(root)/
util-linux-2.39/
libfdisk/
src/
wipe.c
       1  #include "c.h"
       2  #include "strutils.h"
       3  
       4  #ifdef HAVE_LIBBLKID
       5  # include <blkid.h>
       6  #endif
       7  
       8  #include "fdiskP.h"
       9  
      10  struct fdisk_wipe {
      11  	struct list_head	wipes;
      12  	uint64_t		start;		/* sectors */
      13  	uint64_t		size;		/* sectors */
      14  };
      15  
      16  static struct fdisk_wipe *fdisk_get_wipe_area(
      17  			struct fdisk_context *cxt,
      18  			uint64_t start,
      19  			uint64_t size)
      20  {
      21  	struct list_head *p;
      22  
      23  	if (cxt == NULL || list_empty(&cxt->wipes))
      24  		return NULL;
      25  
      26  	list_for_each(p, &cxt->wipes) {
      27  		struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
      28  		if (wp->start == start && wp->size == size)
      29  			return wp;
      30  	}
      31  	return NULL;
      32  }
      33  
      34  void fdisk_free_wipe_areas(struct fdisk_context *cxt)
      35  {
      36  	while (!list_empty(&cxt->wipes)) {
      37  		struct fdisk_wipe *wp = list_entry(cxt->wipes.next,
      38  				                  struct fdisk_wipe, wipes);
      39  		DBG(WIPE, ul_debugobj(wp, "free [start=%ju, size=%ju]",
      40  				(uintmax_t) wp->start, (uintmax_t) wp->size));
      41  		list_del(&wp->wipes);
      42  		free(wp);
      43  	}
      44  }
      45  
      46  int fdisk_has_wipe_area(struct fdisk_context *cxt,
      47  			uint64_t start,
      48  			uint64_t size)
      49  {
      50  	return fdisk_get_wipe_area(cxt, start, size) != NULL;
      51  }
      52  
      53  /* Add/remove new wiping area
      54   *
      55   * Returns: <0 on error, or old area setting (1: enabled, 0: disabled)
      56   */
      57  int fdisk_set_wipe_area(struct fdisk_context *cxt,
      58  			uint64_t start,
      59  			uint64_t size,
      60  			int enable)
      61  {
      62  	struct fdisk_wipe *wp;
      63  
      64  	if (FDISK_IS_UNDEF(start) || FDISK_IS_UNDEF(size))
      65  		return -EINVAL;
      66  
      67  	wp = fdisk_get_wipe_area(cxt, start, size);
      68  
      69  	/* disable */
      70  	if (!enable) {
      71  		if (wp) {
      72  			DBG(WIPE, ul_debugobj(wp, "disable [start=%ju, size=%ju]",
      73  						(uintmax_t) start, (uintmax_t) size));
      74  			list_del(&wp->wipes);
      75  			free(wp);
      76  			return 1;
      77  		}
      78  		return 0;
      79  	}
      80  
      81  	/* enable */
      82  	if (wp)
      83  		return 1;	/* already enabled */
      84  
      85  	wp = calloc(1, sizeof(*wp));
      86  	if (!wp)
      87  		return -ENOMEM;
      88  
      89  	DBG(WIPE, ul_debugobj(wp, "enable [start=%ju, size=%ju]",
      90  				(uintmax_t) start, (uintmax_t) size));
      91  
      92  	INIT_LIST_HEAD(&wp->wipes);
      93  	wp->start = start;
      94  	wp->size = size;
      95  	list_add_tail(&wp->wipes, &cxt->wipes);
      96  
      97  	return 0;
      98  }
      99  
     100  #ifndef HAVE_LIBBLKID
     101  int fdisk_do_wipe(struct fdisk_context *cxt __attribute__((__unused__)))
     102  {
     103  	return 0;
     104  }
     105  #else
     106  int fdisk_do_wipe(struct fdisk_context *cxt)
     107  {
     108  	struct list_head *p;
     109  	blkid_probe pr;
     110  	int rc;
     111  
     112  	assert(cxt);
     113  	assert(cxt->dev_fd >= 0);
     114  
     115  	if (list_empty(&cxt->wipes))
     116  		return 0;
     117  
     118  	pr = blkid_new_probe();
     119  	if (!pr)
     120  		return -ENOMEM;
     121  
     122  	list_for_each(p, &cxt->wipes) {
     123  		struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
     124  		blkid_loff_t start = (blkid_loff_t) wp->start * cxt->sector_size,
     125  			     size = (blkid_loff_t) wp->size * cxt->sector_size;
     126  
     127  		DBG(WIPE, ul_debugobj(wp, "initialize libblkid prober [start=%ju, size=%ju]",
     128                                              (uintmax_t) start, (uintmax_t) size));
     129  
     130  		rc = blkid_probe_set_device(pr, cxt->dev_fd, start, size);
     131  		if (rc) {
     132  			DBG(WIPE, ul_debugobj(wp, "blkid_probe_set_device() failed [rc=%d]", rc));
     133  			return rc;
     134  		}
     135  
     136  		blkid_probe_enable_superblocks(pr, 1);
     137  		blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |
     138  						      BLKID_SUBLKS_BADCSUM);
     139  		blkid_probe_enable_partitions(pr, 1);
     140  		blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC |
     141  				                     BLKID_PARTS_FORCE_GPT);
     142  
     143  		while (blkid_do_probe(pr) == 0) {
     144  			DBG(WIPE, ul_debugobj(wp, " wiping..."));
     145  			blkid_do_wipe(pr, FALSE);
     146  		}
     147  	}
     148  
     149  	blkid_free_probe(pr);
     150  	return 0;
     151  }
     152  #endif
     153  
     154  
     155  /*
     156   * Please don't call this function if there is already a PT.
     157   *
     158   * Returns: 0 if nothing found, < 0 on error, 1 if found a signature
     159   */
     160  #ifndef HAVE_LIBBLKID
     161  int fdisk_check_collisions(struct fdisk_context *cxt __attribute__((__unused__)))
     162  {
     163  	return 0;
     164  }
     165  #else
     166  int fdisk_check_collisions(struct fdisk_context *cxt)
     167  {
     168  	int rc = 0;
     169  	blkid_probe pr;
     170  
     171  	assert(cxt);
     172  	assert(cxt->dev_fd >= 0);
     173  
     174  	DBG(WIPE, ul_debugobj(cxt, "wipe check: initialize libblkid prober"));
     175  
     176  	pr = blkid_new_probe();
     177  	if (!pr)
     178  		return -ENOMEM;
     179  	rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0);
     180  	if (rc)
     181  		return rc;
     182  
     183  	cxt->pt_collision = 0;
     184  	free(cxt->collision);
     185  	cxt->collision = NULL;
     186  
     187  	blkid_probe_enable_superblocks(pr, 1);
     188  	blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE |
     189  			                      BLKID_SUBLKS_BADCSUM);
     190  	blkid_probe_enable_partitions(pr, 1);
     191  	blkid_probe_set_partitions_flags(pr,  BLKID_PARTS_FORCE_GPT);
     192  
     193  	/* we care about the first found FS/raid, so don't call blkid_do_probe()
     194  	 * in loop or don't use blkid_do_fullprobe() ... */
     195  	rc = blkid_do_probe(pr);
     196  	if (rc == 0) {
     197  		const char *name = NULL;
     198  
     199  		if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0)
     200  			cxt->collision = strdup(name);
     201  		else if (blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) {
     202  			cxt->collision = strdup(name);
     203  			cxt->pt_collision = 1;
     204  		}
     205  
     206  		if (name && !cxt->collision)
     207  			rc = -ENOMEM;
     208  	}
     209  
     210  	blkid_free_probe(pr);
     211  	return rc < 0 ? rc : cxt->collision ? 1 : 0;
     212  }
     213  #endif