summaryrefslogblamecommitdiffstats
path: root/fdisks/fdisk.h
blob: 3cb04993e7c547710d07ce1cfba9e44369991bae (plain) (tree)
1
2
3
4
5
6
7
8
9



          

              


                                                            

                          







                            

                            
 





                           


                                                                           

                                                                               
 


                                        
                                        
                                        
                                        




















                                                                                             









                                                                  


                                       










                                                                             
                           
 




                    





                       
 


                                    













                                           



                                                                    
                                                         
                                                                    







                                                                    

  



                                                                                          
  


                            
                           

                           

  
                      

                                                   
                                                                        

                      




                                                                             
                                       
 

                                                               
                       
                                                            
                                                                                      
 

                                                        
                                   


                                              

  

                                                                                 




                            
 

                                           
                                                                                    
 
                              
                                                

                                                

                                                 

                                                 
                           
                                                                                          
                              
                                                                   

                                                                                        

                                                                                               

                                                          










                                          
                                          
 
                                                                                              
                                                             
                                                              
                                                                                     
                                                                  
                                                          
                                                                 



                                                                                  
                                                                          
                                                                                                 
                                                            
                                                             
                                                                               
                                                            
                                                                                               

                                                                           
 






                                                                                               
                                                                                                 

                                                             


                                                                         
                            

                      
                                                           




                                                                                                                        
                                                               
                                                                        
                                                            
                                  
                                  
                                                                             
                                                                         
                                             

                                                                 
                                                                               
                                                                      
                                                                                                               
 
                                                         
 
                                                                           


                                    
                                                    
                                                   

                                                                                                
                                                                                      
                                                                                  
                                                                                                           
                                                                                      


                  
                                   
 
                                                  
 
                  
                             
 

                                                                      
                  






                                                           
                                                                       





                                                                   
                                                                       



                                                 
                                                                               



                                                    
                                                                        
 
                                                        

                                                                               

 
                                                                                            
 






                                                                

 
                                                          



                                              





                                                                            
/*
   fdisk.h
*/

#include "c.h"

#define DEFAULT_SECTOR_SIZE	512
#define MAX_SECTOR_SIZE	2048
#define SECTOR_SIZE	512	/* still used in BSD code */
#define MAXIMUM_PARTS	60

#define ACTIVE_FLAG     0x80

#define EXTENDED        0x05
#define WIN98_EXTENDED  0x0f
#define LINUX_PARTITION 0x81
#define LINUX_SWAP      0x82
#define LINUX_NATIVE    0x83
#define LINUX_EXTENDED  0x85
#define LINUX_LVM       0x8e
#define LINUX_RAID      0xfd

#define ALIGN_UP	1
#define ALIGN_DOWN	2
#define ALIGN_NEAREST	3

#define LINE_LENGTH	800

#define IS_EXTENDED(i) \
	((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)

#define cround(n)	(display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
#define scround(x)	(((x)+units_per_sector-1)/units_per_sector)

/* fdisk debugging flags/options */
#define FDISK_DEBUG_INIT	(1 << 1)
#define FDISK_DEBUG_CONTEXT	(1 << 2)
#define FDISK_DEBUG_TOPOLOGY    (1 << 3)
#define FDISK_DEBUG_GEOMETRY    (1 << 4)
#define FDISK_DEBUG_LABEL       (1 << 5)
#define FDISK_DEBUG_ALL		0xFFFF

# define ON_DBG(m, x)	do { \
				if ((FDISK_DEBUG_ ## m) & fdisk_debug_mask) { \
					x; \
				}	   \
			} while (0)

# define DBG(m, x)	do { \
				if ((FDISK_DEBUG_ ## m) & fdisk_debug_mask) { \
					fprintf(stderr, "%d: fdisk: %8s: ", getpid(), # m); \
					x;				\
				} \
			} while (0)

# define DBG_FLUSH	do { \
				if (fdisk_debug_mask && \
				    fdisk_debug_mask != FDISK_DEBUG_INIT) \
					fflush(stderr);			\
			} while(0)

static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
dbgprint(const char *mesg, ...)
{
	va_list ap;
	va_start(ap, mesg);
	vfprintf(stderr, mesg, ap);
	va_end(ap);
	fputc('\n', stderr);
}

extern int fdisk_debug_mask;
extern void fdisk_init_debug(int mask);

struct partition {
	unsigned char boot_ind;         /* 0x80 - active */
	unsigned char head;             /* starting head */
	unsigned char sector;           /* starting sector */
	unsigned char cyl;              /* starting cylinder */
	unsigned char sys_ind;          /* What partition type */
	unsigned char end_head;         /* end head */
	unsigned char end_sector;       /* end sector */
	unsigned char end_cyl;          /* end cylinder */
	unsigned char start4[4];        /* starting sector counting from 0 */
	unsigned char size4[4];         /* nr of sectors in partition */
} __attribute__ ((packed));

enum menutype {
	MAIN_MENU,
	EXPERT_MENU,
};

enum failure {
	ioctl_error,
	unable_to_read,
	unable_to_seek,
	unable_to_write
};

typedef unsigned long long sector_t;

/*
 * Supported partition table types (labels)
 */
enum fdisk_labeltype {
	FDISK_DISKLABEL_DOS = 1,
	FDISK_DISKLABEL_SUN = 2,
	FDISK_DISKLABEL_SGI = 4,
	FDISK_DISKLABEL_AIX = 8,
	FDISK_DISKLABEL_OSF = 16,
	FDISK_DISKLABEL_MAC = 32,
	FDISK_DISKLABEL_GPT = 64,
	FDISK_DISKLABEL_ANY = -1
};

/*
 * Partition types
 */
struct fdisk_parttype {
	unsigned int	type;		/* type as number or zero */
	const char	*name;		/* description */
	char		*typestr;	/* type as string or NULL */

	unsigned int	flags;		/* FDISK_PARTTYPE_* flags */
};

enum {
	FDISK_PARTTYPE_UNKNOWN		= (1 << 1),
	FDISK_PARTTYPE_INVISIBLE	= (1 << 2),
	FDISK_PARTTYPE_ALLOCATED	= (1 << 3)
};

#define fdisk_parttype_is_unknown(_x)	((_x) && ((_x)->flags & FDISK_PARTTYPE_UNKNONW))
#define fdisk_parttype_is_invisible(_x)	((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE))
#define fdisk_parttype_is_allocated(_x)	((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED))

/*
 * Legacy CHS based geometry
 */
struct fdisk_geometry {
	unsigned int heads;
	sector_t sectors;
	sector_t cylinders;
};

struct fdisk_context {
	int dev_fd;         /* device descriptor */
	char *dev_path;     /* device path */
	unsigned char *firstsector; /* buffer with master boot record */

	/* topology */
	unsigned long io_size;		/* I/O size used by fdisk */
	unsigned long optimal_io_size;	/* optional I/O returned by device */
	unsigned long min_io_size;	/* minimal I/O size */
	unsigned long phy_sector_size;	/* physical size */
	unsigned long sector_size;	/* logical size */
	unsigned long alignment_offset;

	enum fdisk_labeltype disklabel;	/* current disklabel */

	/* alignment */
	unsigned long grain;		/* alignment unit */
	sector_t first_lba;		/* recommended begin of the first partition */

	/* geometry */
	sector_t total_sectors; /* in logical sectors */
	struct fdisk_geometry geom;

	/* label operations and description */
	const struct fdisk_label *label;
};

#define fdisk_is_disklabel(c, x) fdisk_dev_is_disklabel(c, FDISK_DISKLABEL_ ## x)

/*
 * Label specific operations
 */
struct fdisk_label {
	const char *name;

	/* array with partition types */
	struct fdisk_parttype	*parttypes;
	size_t			nparttypes;	/* number of items in parttypes[] */

	/* probe disk label */
	int (*probe)(struct fdisk_context *cxt);
	/* write in-memory changes to disk */
	int (*write)(struct fdisk_context *cxt);
	/* verify the partition table */
	int (*verify)(struct fdisk_context *cxt);
	/* create new disk label */
	int (*create)(struct fdisk_context *cxt);
	/* new partition */
	int (*part_add)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
	/* delete partition */
	int (*part_delete)(struct fdisk_context *cxt, int partnum);
	/* get partition type */
	struct fdisk_parttype *(*part_get_type)(struct fdisk_context *cxt, int partnum);
	/* set partition type */
	int (*part_set_type)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
	/* refresh alignment setting */
	int (*reset_alignment)(struct fdisk_context *cxt);
};

/*
 * labels
 */
extern const struct fdisk_label aix_label;
extern const struct fdisk_label dos_label;
extern const struct fdisk_label bsd_label;
extern const struct fdisk_label mac_label;
extern const struct fdisk_label sun_label;
extern const struct fdisk_label sgi_label;
extern const struct fdisk_label gpt_label;

extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly);
extern int fdisk_dev_has_topology(struct fdisk_context *cxt);
extern int fdisk_dev_has_disklabel(struct fdisk_context *cxt);
extern int fdisk_dev_is_disklabel(struct fdisk_context *cxt, enum fdisk_labeltype l);
extern int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt);
extern void fdisk_free_context(struct fdisk_context *cxt);
extern void fdisk_zeroize_firstsector(struct fdisk_context *cxt);
extern int fdisk_context_force_sector_size(struct fdisk_context *cxt, sector_t s);
extern int fdisk_context_set_user_geometry(struct fdisk_context *cxt,
			    unsigned int cylinders, unsigned int heads,
			    unsigned int sectors);
extern int fdisk_delete_partition(struct fdisk_context *cxt, int partnum);
extern int fdisk_add_partition(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
extern int fdisk_write_disklabel(struct fdisk_context *cxt);
extern int fdisk_verify_disklabel(struct fdisk_context *cxt);
extern int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name);
extern int fdisk_reset_alignment(struct fdisk_context *cxt);
extern struct fdisk_parttype *fdisk_get_partition_type(struct fdisk_context *cxt, int partnum);
extern int fdisk_set_partition_type(struct fdisk_context *cxt, int partnum,
			     struct fdisk_parttype *t);

extern size_t fdisk_get_nparttypes(struct fdisk_context *cxt);
extern struct fdisk_parttype *fdisk_get_parttype_from_code(struct fdisk_context *cxt,
                                unsigned int code);
extern struct fdisk_parttype *fdisk_get_parttype_from_string(struct fdisk_context *cxt,
                                const char *str);
extern struct fdisk_parttype *fdisk_parse_parttype(struct fdisk_context *cxt, const char *str);

extern struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int type, const char *typestr);
extern void fdisk_free_parttype(struct fdisk_parttype *type);

extern sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt);
extern unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt);

/* prototypes for fdisk.c */
extern char *line_ptr;
extern int partitions;
extern unsigned int display_in_cyl_units, units_per_sector;

extern void check_consistency(struct fdisk_context *cxt, struct partition *p, int partition);
extern void check_alignment(struct fdisk_context *cxt, sector_t lba, int partition);
extern void check(struct fdisk_context *cxt, int n, unsigned int h, unsigned int s, unsigned int c, unsigned int start);

extern void fatal(struct fdisk_context *cxt, enum failure why);
extern int  get_partition(struct fdisk_context *cxt, int warn, int max);
extern void list_partition_types(struct fdisk_context *cxt);
extern int read_line (int *asked);
extern char read_char(char *mesg);
extern struct fdisk_parttype *read_partition_type(struct fdisk_context *cxt);
extern void reread_partition_table(struct fdisk_context *cxt, int leave);
extern struct partition *get_part_table(int);
extern unsigned int read_int(struct fdisk_context *cxt,
			     unsigned int low, unsigned int dflt,
			     unsigned int high, unsigned int base, char *mesg);
extern void print_menu(struct fdisk_context *cxt, enum menutype menu);
extern void print_partition_size(struct fdisk_context *cxt, int num, sector_t start, sector_t stop, int sysid);

extern void fill_bounds(sector_t *first, sector_t *last);

extern char *partition_type(struct fdisk_context *cxt, unsigned char type);
extern char read_chars(char *mesg);
extern void set_changed(int);
extern void set_all_unchanged(void);
extern int warn_geometry(struct fdisk_context *cxt);
extern void warn_limits(struct fdisk_context *cxt);
extern unsigned int read_int_with_suffix(struct fdisk_context *cxt,
					 unsigned int low, unsigned int dflt, unsigned int high,
				  unsigned int base, char *mesg, int *is_suffix_used);
extern sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction);
extern sector_t align_lba_in_range(struct fdisk_context *cxt, sector_t lba, sector_t start, sector_t stop);
extern int get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt);

#define PLURAL	0
#define SINGULAR 1
extern const char * str_units(int);

extern sector_t get_nr_sects(struct partition *p);

extern int nowarn;
extern int MBRbuffer_changed;

/* start_sect and nr_sects are stored little endian on all machines */
/* moreover, they are not aligned correctly */
static inline void
store4_little_endian(unsigned char *cp, unsigned int val) {
	cp[0] = (val & 0xff);
	cp[1] = ((val >> 8) & 0xff);
	cp[2] = ((val >> 16) & 0xff);
	cp[3] = ((val >> 24) & 0xff);
}

static inline unsigned int read4_little_endian(const unsigned char *cp)
{
	return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8)
		+ ((unsigned int)(cp[2]) << 16)
		+ ((unsigned int)(cp[3]) << 24);
}

static inline void set_nr_sects(struct partition *p, sector_t nr_sects)
{
	store4_little_endian(p->size4, nr_sects);
}

static inline void set_start_sect(struct partition *p, unsigned int start_sect)
{
	store4_little_endian(p->start4, start_sect);
}

static inline int seek_sector(struct fdisk_context *cxt, sector_t secno)
{
	off_t offset = (off_t) secno * cxt->sector_size;

	return lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1 ? -errno : 0;
}

static inline int read_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf)
{
	int rc = seek_sector(cxt, secno);

	if (rc < 0)
		return rc;

	return read(cxt->dev_fd, buf, cxt->sector_size) !=
			(ssize_t) cxt->sector_size ? -errno : 0;
}

static inline sector_t get_start_sect(struct partition *p)
{
	return read4_little_endian(p->start4);
}

static inline int is_cleared_partition(struct partition *p)
{
	return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
		 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
		 get_start_sect(p) || get_nr_sects(p));
}