(root)/
util-linux-2.39/
libblkid/
src/
dev.c
       1  /*
       2   * dev.c - allocation/initialization/free routines for dev
       3   *
       4   * Copyright (C) 2001 Andreas Dilger
       5   * Copyright (C) 2003 Theodore Ts'o
       6   *
       7   * %Begin-Header%
       8   * This file may be redistributed under the terms of the
       9   * GNU Lesser General Public License.
      10   * %End-Header%
      11   */
      12  
      13  #include <stdlib.h>
      14  #include <string.h>
      15  
      16  #include "blkidP.h"
      17  
      18  /*
      19   * NOTE: reference manual is not structured as code. The following section is a generic
      20   * section for all high-level cache search+iterate routines.
      21   */
      22  
      23  /**
      24   * SECTION:search
      25   * @title: Search and iterate
      26   * @short_description: search devices and iterate over devices in the cache.
      27   *
      28   * Note that high-level probing API provides information about superblocks
      29   * (filesystems/raids) only.  For partitions and topology is necessary to use
      30   * the low-level API.
      31   */
      32  
      33  blkid_dev blkid_new_dev(void)
      34  {
      35  	blkid_dev dev;
      36  
      37  	if (!(dev = calloc(1, sizeof(struct blkid_struct_dev))))
      38  		return NULL;
      39  
      40  	DBG(DEV, ul_debugobj(dev, "alloc"));
      41  	INIT_LIST_HEAD(&dev->bid_devs);
      42  	INIT_LIST_HEAD(&dev->bid_tags);
      43  
      44  	return dev;
      45  }
      46  
      47  void blkid_free_dev(blkid_dev dev)
      48  {
      49  	if (!dev)
      50  		return;
      51  
      52  	DBG(DEV, ul_debugobj(dev, "freeing (%s)", dev->bid_name));
      53  
      54  	list_del(&dev->bid_devs);
      55  	while (!list_empty(&dev->bid_tags)) {
      56  		blkid_tag tag = list_entry(dev->bid_tags.next,
      57  					   struct blkid_struct_tag,
      58  					   bit_tags);
      59  		blkid_free_tag(tag);
      60  	}
      61  	free(dev->bid_xname);
      62  	free(dev->bid_name);
      63  	free(dev);
      64  }
      65  
      66  /*
      67   * Given a blkid device, return its name. The function returns the name
      68   * previously used for blkid_get_dev(). This name does not have to be canonical
      69   * (real path) name, but for example symlink.
      70   */
      71  const char *blkid_dev_devname(blkid_dev dev)
      72  {
      73  	if (!dev)
      74  		return NULL;
      75  	if (dev->bid_xname)
      76  		return dev->bid_xname;
      77  	return dev->bid_name;
      78  }
      79  
      80  void blkid_debug_dump_dev(blkid_dev dev)
      81  {
      82  	struct list_head *p;
      83  
      84  	if (!dev) {
      85  		printf("  dev: NULL\n");
      86  		return;
      87  	}
      88  
      89  	fprintf(stderr, "  dev: name = %s\n", dev->bid_name);
      90  	fprintf(stderr, "  dev: DEVNO=\"0x%0lx\"\n", (unsigned long)dev->bid_devno);
      91  	fprintf(stderr, "  dev: TIME=\"%lld.%lld\"\n", (long long)dev->bid_time, (long long)dev->bid_utime);
      92  	fprintf(stderr, "  dev: PRI=\"%d\"\n", dev->bid_pri);
      93  	fprintf(stderr, "  dev: flags = 0x%08X\n", dev->bid_flags);
      94  
      95  	list_for_each(p, &dev->bid_tags) {
      96  		blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
      97  		if (tag)
      98  			fprintf(stderr, "    tag: %s=\"%s\"\n", tag->bit_name,
      99  			       tag->bit_val);
     100  		else
     101  			fprintf(stderr, "    tag: NULL\n");
     102  	}
     103  }
     104  
     105  /*
     106   * dev iteration routines for the public libblkid interface.
     107   *
     108   * These routines do not expose the list.h implementation, which are a
     109   * contamination of the namespace, and which force us to reveal far, far
     110   * too much of our internal implementation.  I'm not convinced I want
     111   * to keep list.h in the long term, anyway.  It's fine for kernel
     112   * programming, but performance is not the #1 priority for this
     113   * library, and I really don't like the trade-off of type-safety for
     114   * performance for this application.  [tytso:20030125.2007EST]
     115   */
     116  
     117  /*
     118   * This series of functions iterate over all devices in a blkid cache
     119   */
     120  #define DEV_ITERATE_MAGIC	0x01a5284c
     121  
     122  struct blkid_struct_dev_iterate {
     123  	int			magic;
     124  	blkid_cache		cache;
     125  	char			*search_type;
     126  	char			*search_value;
     127  	struct list_head	*p;
     128  };
     129  
     130  blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
     131  {
     132  	blkid_dev_iterate iter;
     133  
     134  	if (!cache) {
     135  		errno = EINVAL;
     136  		return NULL;
     137  	}
     138  
     139  	iter = malloc(sizeof(struct blkid_struct_dev_iterate));
     140  	if (iter) {
     141  		iter->magic = DEV_ITERATE_MAGIC;
     142  		iter->cache = cache;
     143  		iter->p	= cache->bic_devs.next;
     144  		iter->search_type = NULL;
     145  		iter->search_value = NULL;
     146  	}
     147  	return iter;
     148  }
     149  
     150  int blkid_dev_set_search(blkid_dev_iterate iter,
     151  				 const char *search_type, const char *search_value)
     152  {
     153  	char *new_type, *new_value;
     154  
     155  	if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
     156  	    !search_value)
     157  		return -1;
     158  	new_type = malloc(strlen(search_type)+1);
     159  	new_value = malloc(strlen(search_value)+1);
     160  	if (!new_type || !new_value) {
     161  		free(new_type);
     162  		free(new_value);
     163  		return -1;
     164  	}
     165  	strcpy(new_type, search_type);
     166  	strcpy(new_value, search_value);
     167  	free(iter->search_type);
     168  	free(iter->search_value);
     169  	iter->search_type = new_type;
     170  	iter->search_value = new_value;
     171  	return 0;
     172  }
     173  
     174  /*
     175   * Return 0 on success, -1 on error
     176   */
     177  int blkid_dev_next(blkid_dev_iterate iter,
     178  			  blkid_dev *ret_dev)
     179  {
     180  	blkid_dev		dev;
     181  
     182  	if  (!ret_dev || !iter || iter->magic != DEV_ITERATE_MAGIC)
     183  		return -1;
     184  	*ret_dev = NULL;
     185  	while (iter->p != &iter->cache->bic_devs) {
     186  		dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
     187  		iter->p = iter->p->next;
     188  		if (iter->search_type &&
     189  		    !blkid_dev_has_tag(dev, iter->search_type,
     190  				       iter->search_value))
     191  			continue;
     192  		*ret_dev = dev;
     193  		return 0;
     194  	}
     195  	return -1;
     196  }
     197  
     198  void blkid_dev_iterate_end(blkid_dev_iterate iter)
     199  {
     200  	if (!iter || iter->magic != DEV_ITERATE_MAGIC)
     201  		return;
     202  	iter->magic = 0;
     203  	free(iter->search_type);
     204  	free(iter->search_value);
     205  	free(iter);
     206  }
     207  
     208  #ifdef TEST_PROGRAM
     209  #ifdef HAVE_GETOPT_H
     210  #include <getopt.h>
     211  #else
     212  extern char *optarg;
     213  extern int optind;
     214  #endif
     215  
     216  static void __attribute__((__noreturn__)) usage(char *prog)
     217  {
     218  	fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
     219  	fprintf(stderr, "\tList all devices and exit\n");
     220  	exit(1);
     221  }
     222  
     223  int main(int argc, char **argv)
     224  {
     225  	blkid_dev_iterate	iter;
     226  	blkid_cache 		cache = NULL;
     227  	blkid_dev		dev;
     228  	int			c, ret;
     229  	char			*tmp;
     230  	char			*file = NULL;
     231  	char			*search_type = NULL;
     232  	char			*search_value = NULL;
     233  
     234  	while ((c = getopt (argc, argv, "m:f:")) != EOF)
     235  		switch (c) {
     236  		case 'f':
     237  			file = optarg;
     238  			break;
     239  		case 'm':
     240  		{
     241  			int mask = strtoul (optarg, &tmp, 0);
     242  			if (*tmp) {
     243  				fprintf(stderr, "Invalid debug mask: %s\n",
     244  					optarg);
     245  				exit(1);
     246  			}
     247  			blkid_init_debug(mask);
     248  			break;
     249  		}
     250  		case '?':
     251  			usage(argv[0]);
     252  		}
     253  	if (argc >= optind+2) {
     254  		search_type = argv[optind];
     255  		search_value = argv[optind+1];
     256  		optind += 2;
     257  	}
     258  	if (argc != optind)
     259  		usage(argv[0]);
     260  
     261  	if ((ret = blkid_get_cache(&cache, file)) != 0) {
     262  		fprintf(stderr, "%s: error creating cache (%d)\n",
     263  			argv[0], ret);
     264  		exit(1);
     265  	}
     266  
     267  	iter = blkid_dev_iterate_begin(cache);
     268  	if (search_type)
     269  		blkid_dev_set_search(iter, search_type, search_value);
     270  	while (blkid_dev_next(iter, &dev) == 0) {
     271  		printf("Device: %s\n", blkid_dev_devname(dev));
     272  	}
     273  	blkid_dev_iterate_end(iter);
     274  
     275  
     276  	blkid_put_cache(cache);
     277  	return (0);
     278  }
     279  #endif