summaryrefslogblamecommitdiffstats
path: root/libfdisk/src/label.c
blob: d04363a1da79305dbd7ede79a10a3447cf809f0e (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                   
  





                                                                          
                          
 
                                            
                                                        

                                                     

                                   
                                 



                                                                                
                                                                 

                                
                                        


                                 



                                                                      
 
                                                      


                         
                                               



                                 







                                                      
                                 










                                                                             
                                                        













                                                          
                                   

                               
                                          

 


                                                     
 

                                                                              



                                                     

               
                    
 
                                            

                                                                




                                                                    

 
   

                      

                                                      

                                          





                                                                               

                                                          
                                                                                    













                                                           

                                                   



                                                                                      




                                                                                    
                                 

                            







                           
                                                  















                                                                       




                                
                                                           




                                                     
                                    
                               

                                        
 
                                           

 
 

   


                        
                                                    

                                                                             
                                                      












                                                          











                                                                       
                         
                               
 


                               

                                                     
                             
     
                             
      

         
                         
                                               

                             
 
                                                
                                
                               
                            

                               


                                              
                                                   

                                                                
                                           
 
 













                                                                               













                                                                
                                                                        

                                               
















                                                                     

   






                                      

                                                       

                                                      
                                
                               

                                           
 

                                                                  














                                                                    
 
   




















                                                                                           
                  

 


                                                        
                                               
 
                   
 


                                       
 



                                                                 







                                                  















                                                                    

#include "fdiskP.h"

/*
 * Don't use this function derectly, use fdisk_new_context_from_filename()
 */
int fdisk_probe_labels(struct fdisk_context *cxt)
{
	size_t i;

	cxt->label = NULL;

	for (i = 0; i < cxt->nlabels; i++) {
		struct fdisk_label *lb = cxt->labels[i];
		struct fdisk_label *org = cxt->label;
		int rc;

		if (!lb->op->probe)
			continue;
		if (lb->disabled) {
			DBG(LABEL, dbgprint("%s disabled -- ignore", lb->name));
			continue;
		}
		DBG(LABEL, dbgprint("probing for %s", lb->name));

		cxt->label = lb;
		rc = lb->op->probe(cxt);
		cxt->label = org;

		if (rc != 1) {
			if (lb->op->deinit)
				lb->op->deinit(lb);	/* for sure */
			continue;
		}

		__fdisk_context_switch_label(cxt, lb);
		return 0;
	}

	DBG(LABEL, dbgprint("no label found"));
	return 1; /* not found */
}


/**
 * fdisk_dev_has_disklabel:
 * @cxt: fdisk context
 *
 * Returns: return 1 if there is label on the device.
 */
int fdisk_dev_has_disklabel(struct fdisk_context *cxt)
{
	return cxt && cxt->label;
}

/**
 * fdisk_dev_is_disklabel:
 * @cxt: fdisk context
 * @l: disklabel type
 *
 * Returns: return 1 if there is @l disklabel on the device.
 */
int fdisk_dev_is_disklabel(struct fdisk_context *cxt, enum fdisk_labeltype l)
{
	return cxt && cxt->label && cxt->label->id == l;
}

/**
 * fdisk_write_disklabel:
 * @cxt: fdisk context
 *
 * Write in-memory changes to disk
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_write_disklabel(struct fdisk_context *cxt)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->write)
		return -ENOSYS;

	return cxt->label->op->write(cxt);
}

int fdisk_require_geometry(struct fdisk_context *cxt)
{
	assert(cxt);

	return cxt->label
	       && cxt->label->flags & FDISK_LABEL_FL_REQUIRE_GEOMETRY ? 1 : 0;
}

int fdisk_missing_geometry(struct fdisk_context *cxt)
{
	int rc;

	assert(cxt);

	rc = (fdisk_require_geometry(cxt) &&
		    (!cxt->geom.heads || !cxt->geom.sectors
				      || !cxt->geom.cylinders));

	if (rc && !fdisk_context_listonly(cxt))
		fdisk_warnx(cxt, _("Incomplete geometry setting."));

	return rc;
}

/**
 * fdisk_get_columns:
 * @cxt: fdisk context
 * @all: 1 or 0
 * @cols: returns allocated array with FDISK_COL_* IDs
 * @ncols: returns number of items in cols
 *
 * This function returns the default or all columns for the current label.  The
 * library uses the columns for list operations (see fdisk_list_disklabel() and
 * fdisk_list_partitions()). Note that the set of the default columns depends
 * on fdisk_context_enable_details() function. If the details are eanable then
 * this function usually returns more columns.
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_get_columns(struct fdisk_context *cxt, int all, int **cols, size_t *ncols)
{
	size_t i, n;
	int *c;

	assert(cxt);

	if (!cxt->label)
		return -EINVAL;
	if (!cxt->label->columns || !cxt->label->ncolumns)
		return -ENOSYS;
	c = calloc(cxt->label->ncolumns, sizeof(int));
	if (!c)
		return -ENOMEM;
	for (n = 0, i = 0; i < cxt->label->ncolumns; i++) {
		int id = cxt->label->columns[i].id;

		if (!all &&
		    ((fdisk_context_display_details(cxt) &&
				(cxt->label->columns[i].flags & FDISK_COLFL_EYECANDY))
		     || (!fdisk_context_display_details(cxt) &&
				(cxt->label->columns[i].flags & FDISK_COLFL_DETAIL))
		     || (id == FDISK_COL_SECTORS &&
			         fdisk_context_use_cylinders(cxt))
		     || (id == FDISK_COL_CYLINDERS &&
			         !fdisk_context_use_cylinders(cxt))))
			continue;

		c[n++] = id;
	}
	if (cols)
		*cols = c;
	if (ncols)
		*ncols = n;
	return 0;
}

const struct fdisk_column *fdisk_label_get_column(
					struct fdisk_label *lb, int id)
{
	size_t i;

	assert(lb);
	assert(id > 0);

	for (i = 0; i < lb->ncolumns; i++) {
		if (lb->columns[i].id == id)
			return &lb->columns[i];
	}

	return NULL;
}

/**
 * fdisk_verify_disklabel:
 * @cxt: fdisk context
 *
 * Verifies the partition table.
 *
 * Returns: 0 on success, otherwise, a corresponding error.
 */
int fdisk_verify_disklabel(struct fdisk_context *cxt)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->verify)
		return -ENOSYS;
	if (fdisk_missing_geometry(cxt))
		return -EINVAL;

	return cxt->label->op->verify(cxt);
}



/**
 * fdisk_list_disklabel:
 * @cxt: fdisk context
 *
 * Lists details about disklabel, but no partitions.
 *
 * This function uses libfdisk ASK interface to print data. The details about
 * partitions table are printed by FDISK_ASKTYPE_INFO.
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_list_disklabel(struct fdisk_context *cxt)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->list)
		return -ENOSYS;

	return cxt->label->op->list(cxt);
}

/**
 * fdisk_create_disklabel:
 * @cxt: fdisk context
 * @name: label name
 *
 * Creates a new disk label of type @name. If @name is NULL, then it
 * will create a default system label type, either SUN or DOS.
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name)
{
	int haslabel = 0;
	struct fdisk_label *lb;

	if (!cxt)
		return -EINVAL;

	if (!name) { /* use default label creation */
#ifdef __sparc__
		name = "sun";
#else
		name = "dos";
#endif
	}

	if (cxt->label) {
		fdisk_deinit_label(cxt->label);
		haslabel = 1;
	}

	lb = fdisk_context_get_label(cxt, name);
	if (!lb || lb->disabled)
		return -EINVAL;
	if (!lb->op->create)
		return -ENOSYS;

	__fdisk_context_switch_label(cxt, lb);

	if (haslabel && !cxt->parent)
		fdisk_reset_device_properties(cxt);

	DBG(LABEL, dbgprint("create a new %s label", lb->name));
	return cxt->label->op->create(cxt);
}


int fdisk_locate_disklabel(struct fdisk_context *cxt, int n, const char **name,
			   off_t *offset, size_t *size)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->locate)
		return -ENOSYS;

	DBG(LABEL, dbgprint("locating %d chunk of %s.", n, cxt->label->name));
	return cxt->label->op->locate(cxt, n, name, offset, size);
}


/**
 * fdisk_get_disklabel_id:
 * @cxt: fdisk context
 * @id: returns pointer to allocated string
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->get_id)
		return -ENOSYS;

	DBG(LABEL, dbgprint("asking for disk %s ID", cxt->label->name));
	return cxt->label->op->get_id(cxt, id);
}

/**
 * fdisk_get_disklabel_id:
 * @cxt: fdisk context
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_set_disklabel_id(struct fdisk_context *cxt)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->set_id)
		return -ENOSYS;

	DBG(LABEL, dbgprint("setting %s disk ID", cxt->label->name));
	return cxt->label->op->set_id(cxt);
}

/**
 * fdisk_set_partition_type:
 * @cxt: fdisk context
 * @partnum: partition number
 * @t: new type
 *
 * Returns 0 on success, < 0 on error.
 */
int fdisk_set_partition_type(struct fdisk_context *cxt,
			     size_t partnum,
			     struct fdisk_parttype *t)
{
	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->part_set_type)
		return -ENOSYS;

	DBG(LABEL, dbgprint("partition: %zd: set type", partnum));
	return cxt->label->op->part_set_type(cxt, partnum, t);
}

/**
 * fdisk_get_nparttypes:
 * @cxt: fdisk context
 *
 * Returns: number of partition types supported by the current label
 */
size_t fdisk_get_nparttypes(struct fdisk_context *cxt)
{
	if (!cxt || !cxt->label)
		return 0;

	return cxt->label->nparttypes;
}

/**
 * fdisk_partition_taggle_flag:
 * @cxt: fdisk context
 * @partnum: partition number
 * @status: flags
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_partition_toggle_flag(struct fdisk_context *cxt,
			       size_t partnum,
			       unsigned long flag)
{
	int rc;

	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->part_toggle_flag)
		return -ENOSYS;

	rc = cxt->label->op->part_toggle_flag(cxt, partnum, flag);

	DBG(LABEL, dbgprint("partition: %zd: toggle: 0x%04lx [rc=%d]", partnum, flag, rc));
	return rc;
}

/*
 * Resets the current used label driver to initial state
 */
void fdisk_deinit_label(struct fdisk_label *lb)
{
	assert(lb);

	/* private label information */
	if (lb->op->deinit)
		lb->op->deinit(lb);
}

void fdisk_label_set_changed(struct fdisk_label *lb, int changed)
{
	assert(lb);
	lb->changed = changed ? 1 : 0;
}

int fdisk_label_is_changed(struct fdisk_label *lb)
{
	assert(lb);
	return lb ? lb->changed : 0;
}

void fdisk_label_set_disabled(struct fdisk_label *lb, int disabled)
{
	assert(lb);

	DBG(LABEL, dbgprint("%s label %s",
				lb->name,
				disabled ? "DISABLED" : "ENABLED"));
	lb->disabled = disabled ? 1 : 0;
}

int fdisk_label_is_disabled(struct fdisk_label *lb)
{
	assert(lb);
	return lb ? lb->disabled : 0;
}