aboutsummaryrefslogtreecommitdiff
path: root/e2fsprogs/blkid
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-26 01:25:48 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-26 01:25:48 +0000
commit64c54025842f205ad722675105b88044a5b6845a (patch)
tree9b5361a46d9174b8c4c12947b006acbca33dc24c /e2fsprogs/blkid
parentd63c3a032ade4d7a1953031d787eed044811b78c (diff)
downloadbusybox-w32-64c54025842f205ad722675105b88044a5b6845a.tar.gz
busybox-w32-64c54025842f205ad722675105b88044a5b6845a.tar.bz2
busybox-w32-64c54025842f205ad722675105b88044a5b6845a.zip
remove e2fsprogs. Nobody volunteered to clean up that mess
Diffstat (limited to 'e2fsprogs/blkid')
-rw-r--r--e2fsprogs/blkid/Kbuild23
-rw-r--r--e2fsprogs/blkid/blkid.h105
-rw-r--r--e2fsprogs/blkid/blkidP.h187
-rw-r--r--e2fsprogs/blkid/blkid_getsize.c179
-rw-r--r--e2fsprogs/blkid/cache.c126
-rw-r--r--e2fsprogs/blkid/dev.c214
-rw-r--r--e2fsprogs/blkid/devname.c368
-rw-r--r--e2fsprogs/blkid/devno.c223
-rw-r--r--e2fsprogs/blkid/list.c110
-rw-r--r--e2fsprogs/blkid/list.h73
-rw-r--r--e2fsprogs/blkid/probe.c721
-rw-r--r--e2fsprogs/blkid/probe.h375
-rw-r--r--e2fsprogs/blkid/read.c462
-rw-r--r--e2fsprogs/blkid/resolve.c139
-rw-r--r--e2fsprogs/blkid/save.c189
-rw-r--r--e2fsprogs/blkid/tag.c432
16 files changed, 0 insertions, 3926 deletions
diff --git a/e2fsprogs/blkid/Kbuild b/e2fsprogs/blkid/Kbuild
deleted file mode 100644
index ddcfdfd9a..000000000
--- a/e2fsprogs/blkid/Kbuild
+++ /dev/null
@@ -1,23 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7NEEDED-$(CONFIG_E2FSCK) = y
8NEEDED-$(CONFIG_FSCK) = y
9NEEDED-$(CONFIG_MKE2FS) = y
10NEEDED-$(CONFIG_TUNE2FS) = y
11
12lib-y:=
13lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \
14 probe.o read.o resolve.o save.o tag.o list.o
15
16CFLAGS_dev.o := -include $(srctree)/include/busybox.h
17CFLAGS_devname.o := -include $(srctree)/include/busybox.h
18CFLAGS_devno.o := -include $(srctree)/include/busybox.h
19CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h
20CFLAGS_probe.o := -include $(srctree)/include/busybox.h
21CFLAGS_save.o := -include $(srctree)/include/busybox.h
22CFLAGS_tag.o := -include $(srctree)/include/busybox.h
23CFLAGS_list.o := -include $(srctree)/include/busybox.h
diff --git a/e2fsprogs/blkid/blkid.h b/e2fsprogs/blkid/blkid.h
deleted file mode 100644
index 4fa9f6fdf..000000000
--- a/e2fsprogs/blkid/blkid.h
+++ /dev/null
@@ -1,105 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * blkid.h - Interface for libblkid, a library to identify block devices
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#ifndef _BLKID_BLKID_H
15#define _BLKID_BLKID_H
16
17#include <sys/types.h>
18#include <linux/types.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24#define BLKID_VERSION "1.0.0"
25#define BLKID_DATE "12-Feb-2003"
26
27typedef struct blkid_struct_dev *blkid_dev;
28typedef struct blkid_struct_cache *blkid_cache;
29typedef __s64 blkid_loff_t;
30
31typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
32typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
33
34/*
35 * Flags for blkid_get_dev
36 *
37 * BLKID_DEV_CREATE Create an empty device structure if not found
38 * in the cache.
39 * BLKID_DEV_VERIFY Make sure the device structure corresponds
40 * with reality.
41 * BLKID_DEV_FIND Just look up a device entry, and return NULL
42 * if it is not found.
43 * BLKID_DEV_NORMAL Get a valid device structure, either from the
44 * cache or by probing the device.
45 */
46#define BLKID_DEV_FIND 0x0000
47#define BLKID_DEV_CREATE 0x0001
48#define BLKID_DEV_VERIFY 0x0002
49#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
50
51/* cache.c */
52extern void blkid_put_cache(blkid_cache cache);
53extern int blkid_get_cache(blkid_cache *cache, const char *filename);
54
55/* dev.c */
56extern const char *blkid_dev_devname(blkid_dev dev);
57
58extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
59extern int blkid_dev_set_search(blkid_dev_iterate iter,
60 char *search_type, char *search_value);
61extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
62extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
63
64/* devno.c */
65extern char *blkid_devno_to_devname(dev_t devno);
66
67/* devname.c */
68extern int blkid_probe_all(blkid_cache cache);
69extern int blkid_probe_all_new(blkid_cache cache);
70extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
71 int flags);
72
73/* getsize.c */
74extern blkid_loff_t blkid_get_dev_size(int fd);
75
76/* probe.c */
77int blkid_known_fstype(const char *fstype);
78extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
79
80/* read.c */
81
82/* resolve.c */
83extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
84 const char *devname);
85extern char *blkid_get_devname(blkid_cache cache, const char *token,
86 const char *value);
87
88/* tag.c */
89extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
90extern int blkid_tag_next(blkid_tag_iterate iterate,
91 const char **type, const char **value);
92extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
93extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
94 const char *value);
95extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
96 const char *type,
97 const char *value);
98extern int blkid_parse_tag_string(const char *token, char **ret_type,
99 char **ret_val);
100
101#ifdef __cplusplus
102}
103#endif
104
105#endif /* _BLKID_BLKID_H */
diff --git a/e2fsprogs/blkid/blkidP.h b/e2fsprogs/blkid/blkidP.h
deleted file mode 100644
index c7cb8abe9..000000000
--- a/e2fsprogs/blkid/blkidP.h
+++ /dev/null
@@ -1,187 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * blkidP.h - Internal interfaces for libblkid
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#ifndef _BLKID_BLKIDP_H
15#define _BLKID_BLKIDP_H
16
17#include <sys/types.h>
18#include <stdio.h>
19
20#include "blkid.h"
21#include "list.h"
22
23#ifdef __GNUC__
24#define __BLKID_ATTR(x) __attribute__(x)
25#else
26#define __BLKID_ATTR(x)
27#endif
28
29
30/*
31 * This describes the attributes of a specific device.
32 * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
33 * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
34 * values, if they exist.
35 */
36struct blkid_struct_dev
37{
38 struct list_head bid_devs; /* All devices in the cache */
39 struct list_head bid_tags; /* All tags for this device */
40 blkid_cache bid_cache; /* Dev belongs to this cache */
41 char *bid_name; /* Device inode pathname */
42 char *bid_type; /* Preferred device TYPE */
43 int bid_pri; /* Device priority */
44 dev_t bid_devno; /* Device major/minor number */
45 time_t bid_time; /* Last update time of device */
46 unsigned int bid_flags; /* Device status bitflags */
47 char *bid_label; /* Shortcut to device LABEL */
48 char *bid_uuid; /* Shortcut to binary UUID */
49};
50
51#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
52#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
53
54/*
55 * Each tag defines a NAME=value pair for a particular device. The tags
56 * are linked via bit_names for a single device, so that traversing the
57 * names list will get you a list of all tags associated with a device.
58 * They are also linked via bit_values for all devices, so one can easily
59 * search all tags with a given NAME for a specific value.
60 */
61struct blkid_struct_tag
62{
63 struct list_head bit_tags; /* All tags for this device */
64 struct list_head bit_names; /* All tags with given NAME */
65 char *bit_name; /* NAME of tag (shared) */
66 char *bit_val; /* value of tag */
67 blkid_dev bit_dev; /* pointer to device */
68};
69typedef struct blkid_struct_tag *blkid_tag;
70
71/*
72 * Minimum number of seconds between device probes, even when reading
73 * from the cache. This is to avoid re-probing all devices which were
74 * just probed by another program that does not share the cache.
75 */
76#define BLKID_PROBE_MIN 2
77
78/*
79 * Time in seconds an entry remains verified in the in-memory cache
80 * before being reverified (in case of long-running processes that
81 * keep a cache in memory and continue to use it for a long time).
82 */
83#define BLKID_PROBE_INTERVAL 200
84
85/* This describes an entire blkid cache file and probed devices.
86 * We can traverse all of the found devices via bic_list.
87 * We can traverse all of the tag types by bic_tags, which hold empty tags
88 * for each tag type. Those tags can be used as list_heads for iterating
89 * through all devices with a specific tag type (e.g. LABEL).
90 */
91struct blkid_struct_cache
92{
93 struct list_head bic_devs; /* List head of all devices */
94 struct list_head bic_tags; /* List head of all tag types */
95 time_t bic_time; /* Last probe time */
96 time_t bic_ftime; /* Mod time of the cachefile */
97 unsigned int bic_flags; /* Status flags of the cache */
98 char *bic_filename; /* filename of cache */
99};
100
101#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
102#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
103
104extern char *blkid_strdup(const char *s);
105extern char *blkid_strndup(const char *s, const int length);
106
107#define BLKID_CACHE_FILE "/etc/blkid.tab"
108extern const char *blkid_devdirs[];
109
110#define BLKID_ERR_IO 5
111#define BLKID_ERR_PROC 9
112#define BLKID_ERR_MEM 12
113#define BLKID_ERR_CACHE 14
114#define BLKID_ERR_DEV 19
115#define BLKID_ERR_PARAM 22
116#define BLKID_ERR_BIG 27
117
118/*
119 * Priority settings for different types of devices
120 */
121#define BLKID_PRI_EVMS 30
122#define BLKID_PRI_LVM 20
123#define BLKID_PRI_MD 10
124
125#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
126#define CONFIG_BLKID_DEBUG
127#endif
128
129#define DEBUG_CACHE 0x0001
130#define DEBUG_DUMP 0x0002
131#define DEBUG_DEV 0x0004
132#define DEBUG_DEVNAME 0x0008
133#define DEBUG_DEVNO 0x0010
134#define DEBUG_PROBE 0x0020
135#define DEBUG_READ 0x0040
136#define DEBUG_RESOLVE 0x0080
137#define DEBUG_SAVE 0x0100
138#define DEBUG_TAG 0x0200
139#define DEBUG_INIT 0x8000
140#define DEBUG_ALL 0xFFFF
141
142#ifdef CONFIG_BLKID_DEBUG
143#include <stdio.h>
144extern int blkid_debug_mask;
145#define DBG(m,x) if ((m) & blkid_debug_mask) x;
146#else
147#define DBG(m,x)
148#endif
149
150#ifdef CONFIG_BLKID_DEBUG
151extern void blkid_debug_dump_dev(blkid_dev dev);
152extern void blkid_debug_dump_tag(blkid_tag tag);
153#endif
154
155/* lseek.c */
156/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
157#ifdef CONFIG_LFS
158# define blkid_llseek lseek64
159#else
160# define blkid_llseek lseek
161#endif
162
163/* read.c */
164extern void blkid_read_cache(blkid_cache cache);
165
166/* save.c */
167extern int blkid_flush_cache(blkid_cache cache);
168
169/*
170 * Functions to create and find a specific tag type: tag.c
171 */
172extern void blkid_free_tag(blkid_tag tag);
173extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
174extern int blkid_set_tag(blkid_dev dev, const char *name,
175 const char *value, const int vlength);
176
177/*
178 * Functions to create and find a specific tag type: dev.c
179 */
180extern blkid_dev blkid_new_dev(void);
181extern void blkid_free_dev(blkid_dev dev);
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif /* _BLKID_BLKIDP_H */
diff --git a/e2fsprogs/blkid/blkid_getsize.c b/e2fsprogs/blkid/blkid_getsize.c
deleted file mode 100644
index 941efa42c..000000000
--- a/e2fsprogs/blkid/blkid_getsize.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * getsize.c --- get the size of a partition.
4 *
5 * Copyright (C) 1995, 1995 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 this before sys/queues.h! */
14#include "blkidP.h"
15
16#include <stdio.h>
17#include <unistd.h>
18#ifdef HAVE_ERRNO_H
19#include <errno.h>
20#endif
21#include <fcntl.h>
22#ifdef HAVE_SYS_IOCTL_H
23#include <sys/ioctl.h>
24#endif
25#ifdef HAVE_LINUX_FD_H
26#include <linux/fd.h>
27#endif
28#ifdef HAVE_SYS_DISKLABEL_H
29#include <sys/disklabel.h>
30#include <sys/stat.h>
31#endif
32#ifdef HAVE_SYS_DISK_H
33#ifdef HAVE_SYS_QUEUE_H
34#include <sys/queue.h> /* for LIST_HEAD */
35#endif
36#include <sys/disk.h>
37#endif
38#ifdef __linux__
39#include <sys/utsname.h>
40#endif
41
42#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
43#define BLKGETSIZE _IO(0x12,96) /* return device size */
44#endif
45
46#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
47#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
48#endif
49
50#ifdef APPLE_DARWIN
51#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
52#endif /* APPLE_DARWIN */
53
54static int valid_offset(int fd, blkid_loff_t offset)
55{
56 char ch;
57
58 if (blkid_llseek(fd, offset, 0) < 0)
59 return 0;
60 if (read(fd, &ch, 1) < 1)
61 return 0;
62 return 1;
63}
64
65/*
66 * Returns the number of blocks in a partition
67 */
68blkid_loff_t blkid_get_dev_size(int fd)
69{
70 int valid_blkgetsize64 = 1;
71#ifdef __linux__
72 struct utsname ut;
73#endif
74 unsigned long long size64;
75 unsigned long size;
76 blkid_loff_t high, low;
77#ifdef FDGETPRM
78 struct floppy_struct this_floppy;
79#endif
80#ifdef HAVE_SYS_DISKLABEL_H
81 int part = -1;
82 struct disklabel lab;
83 struct partition *pp;
84 char ch;
85 struct stat st;
86#endif /* HAVE_SYS_DISKLABEL_H */
87
88#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
89 if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
90 if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
91 && (size64 << 9 > 0xFFFFFFFF))
92 return 0; /* EFBIG */
93 return (blkid_loff_t) size64 << 9;
94 }
95#endif
96
97#ifdef BLKGETSIZE64
98#ifdef __linux__
99 if ((uname(&ut) == 0) &&
100 ((ut.release[0] == '2') && (ut.release[1] == '.') &&
101 (ut.release[2] < '6') && (ut.release[3] == '.')))
102 valid_blkgetsize64 = 0;
103#endif
104 if (valid_blkgetsize64 &&
105 ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
106 if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
107 && ((size64) > 0xFFFFFFFF))
108 return 0; /* EFBIG */
109 return size64;
110 }
111#endif
112
113#ifdef BLKGETSIZE
114 if (ioctl(fd, BLKGETSIZE, &size) >= 0)
115 return (blkid_loff_t)size << 9;
116#endif
117
118#ifdef FDGETPRM
119 if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
120 return (blkid_loff_t)this_floppy.size << 9;
121#endif
122#ifdef HAVE_SYS_DISKLABEL_H
123#if 0
124 /*
125 * This should work in theory but I haven't tested it. Anyone
126 * on a BSD system want to test this for me? In the meantime,
127 * binary search mechanism should work just fine.
128 */
129 if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
130 part = st.st_rdev & 7;
131 if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
132 pp = &lab.d_partitions[part];
133 if (pp->p_size)
134 return pp->p_size << 9;
135 }
136#endif
137#endif /* HAVE_SYS_DISKLABEL_H */
138
139 /*
140 * OK, we couldn't figure it out by using a specialized ioctl,
141 * which is generally the best way. So do binary search to
142 * find the size of the partition.
143 */
144 low = 0;
145 for (high = 1024; valid_offset(fd, high); high *= 2)
146 low = high;
147 while (low < high - 1)
148 {
149 const blkid_loff_t mid = (low + high) / 2;
150
151 if (valid_offset(fd, mid))
152 low = mid;
153 else
154 high = mid;
155 }
156 return low + 1;
157}
158
159#ifdef TEST_PROGRAM
160int main(int argc, char **argv)
161{
162 blkid_loff_t bytes;
163 int fd;
164
165 if (argc < 2) {
166 fprintf(stderr, "Usage: %s device\n"
167 "Determine the size of a device\n", argv[0]);
168 return 1;
169 }
170
171 if ((fd = open(argv[1], O_RDONLY)) < 0)
172 perror(argv[0]);
173
174 bytes = blkid_get_dev_size(fd);
175 printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
176
177 return 0;
178}
179#endif
diff --git a/e2fsprogs/blkid/cache.c b/e2fsprogs/blkid/cache.c
deleted file mode 100644
index 9bae6fb67..000000000
--- a/e2fsprogs/blkid/cache.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * cache.c - allocation/initialization/free routines for cache
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17#include "blkidP.h"
18
19int blkid_debug_mask = 0;
20
21int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
22{
23 blkid_cache cache;
24
25#ifdef CONFIG_BLKID_DEBUG
26 if (!(blkid_debug_mask & DEBUG_INIT)) {
27 char *dstr = getenv("BLKID_DEBUG");
28
29 if (dstr)
30 blkid_debug_mask = strtoul(dstr, 0, 0);
31 blkid_debug_mask |= DEBUG_INIT;
32 }
33#endif
34
35 DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
36 filename ? filename : "default cache"));
37
38 if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
39 return -BLKID_ERR_MEM;
40
41 INIT_LIST_HEAD(&cache->bic_devs);
42 INIT_LIST_HEAD(&cache->bic_tags);
43
44 if (filename && !strlen(filename))
45 filename = 0;
46 if (!filename && (getuid() == geteuid()))
47 filename = getenv("BLKID_FILE");
48 if (!filename)
49 filename = BLKID_CACHE_FILE;
50 cache->bic_filename = blkid_strdup(filename);
51
52 blkid_read_cache(cache);
53
54 *ret_cache = cache;
55 return 0;
56}
57
58void blkid_put_cache(blkid_cache cache)
59{
60 if (!cache)
61 return;
62
63 (void) blkid_flush_cache(cache);
64
65 DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
66
67 /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
68
69 while (!list_empty(&cache->bic_devs)) {
70 blkid_dev dev = list_entry(cache->bic_devs.next,
71 struct blkid_struct_dev,
72 bid_devs);
73 blkid_free_dev(dev);
74 }
75
76 while (!list_empty(&cache->bic_tags)) {
77 blkid_tag tag = list_entry(cache->bic_tags.next,
78 struct blkid_struct_tag,
79 bit_tags);
80
81 while (!list_empty(&tag->bit_names)) {
82 blkid_tag bad = list_entry(tag->bit_names.next,
83 struct blkid_struct_tag,
84 bit_names);
85
86 DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
87 bad->bit_name, bad->bit_val));
88 blkid_free_tag(bad);
89 }
90 blkid_free_tag(tag);
91 }
92 free(cache->bic_filename);
93
94 free(cache);
95}
96
97#ifdef TEST_PROGRAM
98int main(int argc, char** argv)
99{
100 blkid_cache cache = NULL;
101 int ret;
102
103 blkid_debug_mask = DEBUG_ALL;
104 if ((argc > 2)) {
105 fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
106 exit(1);
107 }
108
109 if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
110 fprintf(stderr, "error %d parsing cache file %s\n", ret,
111 argv[1] ? argv[1] : BLKID_CACHE_FILE);
112 exit(1);
113 }
114 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
115 fprintf(stderr, "%s: error creating cache (%d)\n",
116 argv[0], ret);
117 exit(1);
118 }
119 if ((ret = blkid_probe_all(cache) < 0))
120 fprintf(stderr, "error probing devices\n");
121
122 blkid_put_cache(cache);
123
124 return ret;
125}
126#endif
diff --git a/e2fsprogs/blkid/dev.c b/e2fsprogs/blkid/dev.c
deleted file mode 100644
index eddbd02b7..000000000
--- a/e2fsprogs/blkid/dev.c
+++ /dev/null
@@ -1,214 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dev.c - allocation/initialization/free routines for dev
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16
17#include "blkidP.h"
18
19blkid_dev blkid_new_dev(void)
20{
21 blkid_dev dev;
22
23 if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
24 return NULL;
25
26 INIT_LIST_HEAD(&dev->bid_devs);
27 INIT_LIST_HEAD(&dev->bid_tags);
28
29 return dev;
30}
31
32void blkid_free_dev(blkid_dev dev)
33{
34 if (!dev)
35 return;
36
37 DBG(DEBUG_DEV,
38 printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
39 DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
40
41 list_del(&dev->bid_devs);
42 while (!list_empty(&dev->bid_tags)) {
43 blkid_tag tag = list_entry(dev->bid_tags.next,
44 struct blkid_struct_tag,
45 bit_tags);
46 blkid_free_tag(tag);
47 }
48 if (dev->bid_name)
49 free(dev->bid_name);
50 free(dev);
51}
52
53/*
54 * Given a blkid device, return its name
55 */
56const char *blkid_dev_devname(blkid_dev dev)
57{
58 return dev->bid_name;
59}
60
61#ifdef CONFIG_BLKID_DEBUG
62void blkid_debug_dump_dev(blkid_dev dev)
63{
64 struct list_head *p;
65
66 if (!dev) {
67 printf(" dev: NULL\n");
68 return;
69 }
70
71 printf(" dev: name = %s\n", dev->bid_name);
72 printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
73 printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
74 printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
75 printf(" dev: flags = 0x%08X\n", dev->bid_flags);
76
77 list_for_each(p, &dev->bid_tags) {
78 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
79 if (tag)
80 printf(" tag: %s=\"%s\"\n", tag->bit_name,
81 tag->bit_val);
82 else
83 printf(" tag: NULL\n");
84 }
85 puts("");
86}
87#endif
88
89/*
90 * dev iteration routines for the public libblkid interface.
91 *
92 * These routines do not expose the list.h implementation, which are a
93 * contamination of the namespace, and which force us to reveal far, far
94 * too much of our internal implemenation. I'm not convinced I want
95 * to keep list.h in the long term, anyway. It's fine for kernel
96 * programming, but performance is not the #1 priority for this
97 * library, and I really don't like the tradeoff of type-safety for
98 * performance for this application. [tytso:20030125.2007EST]
99 */
100
101/*
102 * This series of functions iterate over all devices in a blkid cache
103 */
104#define DEV_ITERATE_MAGIC 0x01a5284c
105
106struct blkid_struct_dev_iterate {
107 int magic;
108 blkid_cache cache;
109 struct list_head *p;
110};
111
112blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
113{
114 blkid_dev_iterate iter;
115
116 iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
117 iter->magic = DEV_ITERATE_MAGIC;
118 iter->cache = cache;
119 iter->p = cache->bic_devs.next;
120 return iter;
121}
122
123/*
124 * Return 0 on success, -1 on error
125 */
126extern int blkid_dev_next(blkid_dev_iterate iter,
127 blkid_dev *dev)
128{
129 *dev = 0;
130 if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
131 iter->p == &iter->cache->bic_devs)
132 return -1;
133 *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
134 iter->p = iter->p->next;
135 return 0;
136}
137
138void blkid_dev_iterate_end(blkid_dev_iterate iter)
139{
140 if (!iter || iter->magic != DEV_ITERATE_MAGIC)
141 return;
142 iter->magic = 0;
143 free(iter);
144}
145
146#ifdef TEST_PROGRAM
147#ifdef HAVE_GETOPT_H
148#include <getopt.h>
149#else
150extern char *optarg;
151extern int optind;
152#endif
153
154void usage(char *prog)
155{
156 fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
157 fprintf(stderr, "\tList all devices and exit\n", prog);
158 exit(1);
159}
160
161int main(int argc, char **argv)
162{
163 blkid_dev_iterate iter;
164 blkid_cache cache = NULL;
165 blkid_dev dev;
166 int c, ret;
167 char *tmp;
168 char *file = NULL;
169 char *search_type = NULL;
170 char *search_value = NULL;
171
172 while ((c = getopt (argc, argv, "m:f:")) != EOF)
173 switch (c) {
174 case 'f':
175 file = optarg;
176 break;
177 case 'm':
178 blkid_debug_mask = strtoul (optarg, &tmp, 0);
179 if (*tmp) {
180 fprintf(stderr, "Invalid debug mask: %d\n",
181 optarg);
182 exit(1);
183 }
184 break;
185 case '?':
186 usage(argv[0]);
187 }
188 if (argc >= optind+2) {
189 search_type = argv[optind];
190 search_value = argv[optind+1];
191 optind += 2;
192 }
193 if (argc != optind)
194 usage(argv[0]);
195
196 if ((ret = blkid_get_cache(&cache, file)) != 0) {
197 fprintf(stderr, "%s: error creating cache (%d)\n",
198 argv[0], ret);
199 exit(1);
200 }
201
202 iter = blkid_dev_iterate_begin(cache);
203 if (search_type)
204 blkid_dev_set_search(iter, search_type, search_value);
205 while (blkid_dev_next(iter, &dev) == 0) {
206 printf("Device: %s\n", blkid_dev_devname(dev));
207 }
208 blkid_dev_iterate_end(iter);
209
210
211 blkid_put_cache(cache);
212 return 0;
213}
214#endif
diff --git a/e2fsprogs/blkid/devname.c b/e2fsprogs/blkid/devname.c
deleted file mode 100644
index 3d11734d5..000000000
--- a/e2fsprogs/blkid/devname.c
+++ /dev/null
@@ -1,368 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * devname.c - get a dev by its device inode name
4 *
5 * Copyright (C) Andries Brouwer
6 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
7 * Copyright (C) 2001 Andreas Dilger
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the
11 * GNU Lesser General Public License.
12 * %End-Header%
13 */
14
15#include <stdio.h>
16#include <string.h>
17#ifdef HAVE_UNISTD_H
18#include <unistd.h>
19#endif
20#include <stdlib.h>
21#include <string.h>
22#include <ctype.h>
23#ifdef HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26#include <sys/stat.h>
27#ifdef HAVE_ERRNO_H
28#include <errno.h>
29#endif
30#ifdef HAVE_SYS_MKDEV_H
31#include <sys/mkdev.h>
32#endif
33#include <time.h>
34
35#include "blkidP.h"
36
37/*
38 * Find a dev struct in the cache by device name, if available.
39 *
40 * If there is no entry with the specified device name, and the create
41 * flag is set, then create an empty device entry.
42 */
43blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
44{
45 blkid_dev dev = NULL, tmp;
46 struct list_head *p;
47
48 if (!cache || !devname)
49 return NULL;
50
51 list_for_each(p, &cache->bic_devs) {
52 tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
53 if (strcmp(tmp->bid_name, devname))
54 continue;
55
56 DBG(DEBUG_DEVNAME,
57 printf("found devname %s in cache\n", tmp->bid_name));
58 dev = tmp;
59 break;
60 }
61
62 if (!dev && (flags & BLKID_DEV_CREATE)) {
63 dev = blkid_new_dev();
64 if (!dev)
65 return NULL;
66 dev->bid_name = blkid_strdup(devname);
67 dev->bid_cache = cache;
68 list_add_tail(&dev->bid_devs, &cache->bic_devs);
69 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
70 }
71
72 if (flags & BLKID_DEV_VERIFY)
73 dev = blkid_verify(cache, dev);
74 return dev;
75}
76
77/*
78 * Probe a single block device to add to the device cache.
79 */
80static void probe_one(blkid_cache cache, const char *ptname,
81 dev_t devno, int pri)
82{
83 blkid_dev dev = NULL;
84 struct list_head *p;
85 const char **dir;
86 char *devname = NULL;
87
88 /* See if we already have this device number in the cache. */
89 list_for_each(p, &cache->bic_devs) {
90 blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
91 bid_devs);
92 if (tmp->bid_devno == devno) {
93 dev = blkid_verify(cache, tmp);
94 break;
95 }
96 }
97 if (dev && dev->bid_devno == devno)
98 goto set_pri;
99
100 /*
101 * Take a quick look at /dev/ptname for the device number. We check
102 * all of the likely device directories. If we don't find it, or if
103 * the stat information doesn't check out, use blkid_devno_to_devname()
104 * to find it via an exhaustive search for the device major/minor.
105 */
106 for (dir = blkid_devdirs; *dir; dir++) {
107 struct stat st;
108 char device[256];
109
110 sprintf(device, "%s/%s", *dir, ptname);
111 if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
112 dev->bid_devno == devno)
113 goto set_pri;
114
115 if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
116 st.st_rdev == devno) {
117 devname = blkid_strdup(device);
118 break;
119 }
120 }
121 if (!devname) {
122 devname = blkid_devno_to_devname(devno);
123 if (!devname)
124 return;
125 }
126 dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
127 free(devname);
128
129set_pri:
130 if (!pri && !strncmp(ptname, "md", 2))
131 pri = BLKID_PRI_MD;
132 if (dev)
133 dev->bid_pri = pri;
134 return;
135}
136
137#define PROC_PARTITIONS "/proc/partitions"
138#define VG_DIR "/proc/lvm/VGs"
139
140/*
141 * This function initializes the UUID cache with devices from the LVM
142 * proc hierarchy. We currently depend on the names of the LVM
143 * hierarchy giving us the device structure in /dev. (XXX is this a
144 * safe thing to do?)
145 */
146#ifdef VG_DIR
147#include <dirent.h>
148static dev_t lvm_get_devno(const char *lvm_device)
149{
150 FILE *lvf;
151 char buf[1024];
152 int ma, mi;
153 dev_t ret = 0;
154
155 DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
156 if ((lvf = fopen(lvm_device, "r")) == NULL) {
157 DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
158 strerror(errno)));
159 return 0;
160 }
161
162 while (fgets(buf, sizeof(buf), lvf)) {
163 if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
164 ret = makedev(ma, mi);
165 break;
166 }
167 }
168 fclose(lvf);
169
170 return ret;
171}
172
173static void lvm_probe_all(blkid_cache cache)
174{
175 DIR *vg_list;
176 struct dirent *vg_iter;
177 int vg_len = strlen(VG_DIR);
178 dev_t dev;
179
180 if ((vg_list = opendir(VG_DIR)) == NULL)
181 return;
182
183 DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
184
185 while ((vg_iter = readdir(vg_list)) != NULL) {
186 DIR *lv_list;
187 char *vdirname;
188 char *vg_name;
189 struct dirent *lv_iter;
190
191 vg_name = vg_iter->d_name;
192 if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
193 continue;
194 vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
195 sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
196
197 lv_list = opendir(vdirname);
198 free(vdirname);
199 if (lv_list == NULL)
200 continue;
201
202 while ((lv_iter = readdir(lv_list)) != NULL) {
203 char *lv_name, *lvm_device;
204
205 lv_name = lv_iter->d_name;
206 if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
207 continue;
208
209 lvm_device = xmalloc(vg_len + strlen(vg_name) +
210 strlen(lv_name) + 8);
211 sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
212 lv_name);
213 dev = lvm_get_devno(lvm_device);
214 sprintf(lvm_device, "%s/%s", vg_name, lv_name);
215 DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
216 lvm_device,
217 (unsigned int) dev));
218 probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
219 free(lvm_device);
220 }
221 closedir(lv_list);
222 }
223 closedir(vg_list);
224}
225#endif
226
227#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
228
229static int
230evms_probe_all(blkid_cache cache)
231{
232 char line[100];
233 int ma, mi, sz, num = 0;
234 FILE *procpt;
235 char device[110];
236
237 procpt = fopen(PROC_EVMS_VOLUMES, "r");
238 if (!procpt)
239 return 0;
240 while (fgets(line, sizeof(line), procpt)) {
241 if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
242 &ma, &mi, &sz, device) != 4)
243 continue;
244
245 DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
246 device, ma, mi));
247
248 probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
249 num++;
250 }
251 fclose(procpt);
252 return num;
253}
254
255/*
256 * Read the device data for all available block devices in the system.
257 */
258int blkid_probe_all(blkid_cache cache)
259{
260 FILE *proc;
261 char line[1024];
262 char ptname0[128], ptname1[128], *ptname = 0;
263 char *ptnames[2];
264 dev_t devs[2];
265 int ma, mi;
266 unsigned long long sz;
267 int lens[2] = { 0, 0 };
268 int which = 0, last = 0;
269
270 ptnames[0] = ptname0;
271 ptnames[1] = ptname1;
272
273 if (!cache)
274 return -BLKID_ERR_PARAM;
275
276 if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
277 time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
278 return 0;
279
280 blkid_read_cache(cache);
281 evms_probe_all(cache);
282#ifdef VG_DIR
283 lvm_probe_all(cache);
284#endif
285
286 proc = fopen(PROC_PARTITIONS, "r");
287 if (!proc)
288 return -BLKID_ERR_PROC;
289
290 while (fgets(line, sizeof(line), proc)) {
291 last = which;
292 which ^= 1;
293 ptname = ptnames[which];
294
295 if (sscanf(line, " %d %d %llu %128[^\n ]",
296 &ma, &mi, &sz, ptname) != 4)
297 continue;
298 devs[which] = makedev(ma, mi);
299
300 DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
301
302 /* Skip whole disk devs unless they have no partitions
303 * If we don't have a partition on this dev, also
304 * check previous dev to see if it didn't have a partn.
305 * heuristic: partition name ends in a digit.
306 *
307 * Skip extended partitions.
308 * heuristic: size is 1
309 *
310 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
311 */
312
313 lens[which] = strlen(ptname);
314 if (isdigit(ptname[lens[which] - 1])) {
315 DBG(DEBUG_DEVNAME,
316 printf("partition dev %s, devno 0x%04X\n",
317 ptname, (unsigned int) devs[which]));
318
319 if (sz > 1)
320 probe_one(cache, ptname, devs[which], 0);
321 lens[which] = 0;
322 lens[last] = 0;
323 } else if (lens[last] && strncmp(ptnames[last], ptname,
324 lens[last])) {
325 DBG(DEBUG_DEVNAME,
326 printf("whole dev %s, devno 0x%04X\n",
327 ptnames[last], (unsigned int) devs[last]));
328 probe_one(cache, ptnames[last], devs[last], 0);
329 lens[last] = 0;
330 }
331 }
332
333 /* Handle the last device if it wasn't partitioned */
334 if (lens[which])
335 probe_one(cache, ptname, devs[which], 0);
336
337 fclose(proc);
338
339 cache->bic_time = time(0);
340 cache->bic_flags |= BLKID_BIC_FL_PROBED;
341 blkid_flush_cache(cache);
342 return 0;
343}
344
345#ifdef TEST_PROGRAM
346int main(int argc, char **argv)
347{
348 blkid_cache cache = NULL;
349 int ret;
350
351 blkid_debug_mask = DEBUG_ALL;
352 if (argc != 1) {
353 fprintf(stderr, "Usage: %s\n"
354 "Probe all devices and exit\n", argv[0]);
355 exit(1);
356 }
357 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
358 fprintf(stderr, "%s: error creating cache (%d)\n",
359 argv[0], ret);
360 exit(1);
361 }
362 if (blkid_probe_all(cache) < 0)
363 printf("%s: error probing devices\n", argv[0]);
364
365 blkid_put_cache(cache);
366 return 0;
367}
368#endif
diff --git a/e2fsprogs/blkid/devno.c b/e2fsprogs/blkid/devno.c
deleted file mode 100644
index 13e7f1a87..000000000
--- a/e2fsprogs/blkid/devno.c
+++ /dev/null
@@ -1,223 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * devno.c - find a particular device by its device number (major/minor)
4 *
5 * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#ifdef HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <stdlib.h>
20#include <string.h>
21#ifdef HAVE_SYS_TYPES_H
22#include <sys/types.h>
23#endif
24#include <sys/stat.h>
25#include <dirent.h>
26#ifdef HAVE_ERRNO_H
27#include <errno.h>
28#endif
29#ifdef HAVE_SYS_MKDEV_H
30#include <sys/mkdev.h>
31#endif
32
33#include "blkidP.h"
34
35struct dir_list {
36 char *name;
37 struct dir_list *next;
38};
39
40char *blkid_strndup(const char *s, int length)
41{
42 char *ret;
43
44 if (!s)
45 return NULL;
46
47 if (!length)
48 length = strlen(s);
49
50 ret = xmalloc(length + 1);
51 strncpy(ret, s, length);
52 ret[length] = '\0';
53 return ret;
54}
55
56char *blkid_strdup(const char *s)
57{
58 return blkid_strndup(s, 0);
59}
60
61/*
62 * This function adds an entry to the directory list
63 */
64static void add_to_dirlist(const char *name, struct dir_list **list)
65{
66 struct dir_list *dp;
67
68 dp = xmalloc(sizeof(struct dir_list));
69 dp->name = blkid_strdup(name);
70 dp->next = *list;
71 *list = dp;
72}
73
74/*
75 * This function frees a directory list
76 */
77static void free_dirlist(struct dir_list **list)
78{
79 struct dir_list *dp, *next;
80
81 for (dp = *list; dp; dp = next) {
82 next = dp->next;
83 free(dp->name);
84 free(dp);
85 }
86 *list = NULL;
87}
88
89static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
90 char **devname)
91{
92 DIR *dir;
93 struct dirent *dp;
94 char path[1024];
95 int dirlen;
96 struct stat st;
97
98 if ((dir = opendir(dir_name)) == NULL)
99 return;
100 dirlen = strlen(dir_name) + 2;
101 while ((dp = readdir(dir)) != 0) {
102 if (dirlen + strlen(dp->d_name) >= sizeof(path))
103 continue;
104
105 if (dp->d_name[0] == '.' &&
106 ((dp->d_name[1] == 0) ||
107 ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
108 continue;
109
110 sprintf(path, "%s/%s", dir_name, dp->d_name);
111 if (stat(path, &st) < 0)
112 continue;
113
114 if (S_ISDIR(st.st_mode))
115 add_to_dirlist(path, list);
116 else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
117 *devname = blkid_strdup(path);
118 DBG(DEBUG_DEVNO,
119 printf("found 0x%llx at %s (%p)\n", devno,
120 path, *devname));
121 break;
122 }
123 }
124 closedir(dir);
125 return;
126}
127
128/* Directories where we will try to search for device numbers */
129const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
130
131/*
132 * This function finds the pathname to a block device with a given
133 * device number. It returns a pointer to allocated memory to the
134 * pathname on success, and NULL on failure.
135 */
136char *blkid_devno_to_devname(dev_t devno)
137{
138 struct dir_list *list = NULL, *new_list = NULL;
139 char *devname = NULL;
140 const char **dir;
141
142 /*
143 * Add the starting directories to search in reverse order of
144 * importance, since we are using a stack...
145 */
146 for (dir = blkid_devdirs; *dir; dir++)
147 add_to_dirlist(*dir, &list);
148
149 while (list) {
150 struct dir_list *current = list;
151
152 list = list->next;
153 DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
154 scan_dir(current->name, devno, &new_list, &devname);
155 free(current->name);
156 free(current);
157 if (devname)
158 break;
159 /*
160 * If we're done checking at this level, descend to
161 * the next level of subdirectories. (breadth-first)
162 */
163 if (list == NULL) {
164 list = new_list;
165 new_list = NULL;
166 }
167 }
168 free_dirlist(&list);
169 free_dirlist(&new_list);
170
171 if (!devname) {
172 DBG(DEBUG_DEVNO,
173 printf("blkid: cannot find devno 0x%04lx\n",
174 (unsigned long) devno));
175 } else {
176 DBG(DEBUG_DEVNO,
177 printf("found devno 0x%04llx as %s\n", devno, devname));
178 }
179
180
181 return devname;
182}
183
184#ifdef TEST_PROGRAM
185int main(int argc, char** argv)
186{
187 char *devname, *tmp;
188 int major, minor;
189 dev_t devno;
190 const char *errmsg = "Cannot parse %s: %s\n";
191
192 blkid_debug_mask = DEBUG_ALL;
193 if ((argc != 2) && (argc != 3)) {
194 fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
195 "Resolve a device number to a device name\n",
196 argv[0], argv[0]);
197 exit(1);
198 }
199 if (argc == 2) {
200 devno = strtoul(argv[1], &tmp, 0);
201 if (*tmp) {
202 fprintf(stderr, errmsg, "device number", argv[1]);
203 exit(1);
204 }
205 } else {
206 major = strtoul(argv[1], &tmp, 0);
207 if (*tmp) {
208 fprintf(stderr, errmsg, "major number", argv[1]);
209 exit(1);
210 }
211 minor = strtoul(argv[2], &tmp, 0);
212 if (*tmp) {
213 fprintf(stderr, errmsg, "minor number", argv[2]);
214 exit(1);
215 }
216 devno = makedev(major, minor);
217 }
218 printf("Looking for device 0x%04Lx\n", devno);
219 devname = blkid_devno_to_devname(devno);
220 free(devname);
221 return 0;
222}
223#endif
diff --git a/e2fsprogs/blkid/list.c b/e2fsprogs/blkid/list.c
deleted file mode 100644
index 04d61a19b..000000000
--- a/e2fsprogs/blkid/list.c
+++ /dev/null
@@ -1,110 +0,0 @@
1/* vi: set sw=4 ts=4: */
2
3#include "list.h"
4
5/*
6 * Insert a new entry between two known consecutive entries.
7 *
8 * This is only for internal list manipulation where we know
9 * the prev/next entries already!
10 */
11void __list_add(struct list_head * add,
12 struct list_head * prev,
13 struct list_head * next)
14{
15 next->prev = add;
16 add->next = next;
17 add->prev = prev;
18 prev->next = add;
19}
20
21/*
22 * list_add - add a new entry
23 * @add: new entry to be added
24 * @head: list head to add it after
25 *
26 * Insert a new entry after the specified head.
27 * This is good for implementing stacks.
28 */
29void list_add(struct list_head *add, struct list_head *head)
30{
31 __list_add(add, head, head->next);
32}
33
34/*
35 * list_add_tail - add a new entry
36 * @add: new entry to be added
37 * @head: list head to add it before
38 *
39 * Insert a new entry before the specified head.
40 * This is useful for implementing queues.
41 */
42void list_add_tail(struct list_head *add, struct list_head *head)
43{
44 __list_add(add, head->prev, head);
45}
46
47/*
48 * Delete a list entry by making the prev/next entries
49 * point to each other.
50 *
51 * This is only for internal list manipulation where we know
52 * the prev/next entries already!
53 */
54void __list_del(struct list_head * prev, struct list_head * next)
55{
56 next->prev = prev;
57 prev->next = next;
58}
59
60/*
61 * list_del - deletes entry from list.
62 * @entry: the element to delete from the list.
63 *
64 * list_empty() on @entry does not return true after this, @entry is
65 * in an undefined state.
66 */
67void list_del(struct list_head *entry)
68{
69 __list_del(entry->prev, entry->next);
70}
71
72/*
73 * list_del_init - deletes entry from list and reinitialize it.
74 * @entry: the element to delete from the list.
75 */
76void list_del_init(struct list_head *entry)
77{
78 __list_del(entry->prev, entry->next);
79 INIT_LIST_HEAD(entry);
80}
81
82/*
83 * list_empty - tests whether a list is empty
84 * @head: the list to test.
85 */
86int list_empty(struct list_head *head)
87{
88 return head->next == head;
89}
90
91/*
92 * list_splice - join two lists
93 * @list: the new list to add.
94 * @head: the place to add it in the first list.
95 */
96void list_splice(struct list_head *list, struct list_head *head)
97{
98 struct list_head *first = list->next;
99
100 if (first != list) {
101 struct list_head *last = list->prev;
102 struct list_head *at = head->next;
103
104 first->prev = head;
105 head->next = first;
106
107 last->next = at;
108 at->prev = last;
109 }
110}
diff --git a/e2fsprogs/blkid/list.h b/e2fsprogs/blkid/list.h
deleted file mode 100644
index 8b06d853b..000000000
--- a/e2fsprogs/blkid/list.h
+++ /dev/null
@@ -1,73 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
3#define _BLKID_LIST_H
4
5#ifdef __cplusplus
6extern "C" {
7#endif
8
9/*
10 * Simple doubly linked list implementation.
11 *
12 * Some of the internal functions ("__xxx") are useful when
13 * manipulating whole lists rather than single entries, as
14 * sometimes we already know the next/prev entries and we can
15 * generate better code by using them directly rather than
16 * using the generic single-entry routines.
17 */
18
19struct list_head {
20 struct list_head *next, *prev;
21};
22
23#define LIST_HEAD_INIT(name) { &(name), &(name) }
24
25#define LIST_HEAD(name) \
26 struct list_head name = LIST_HEAD_INIT(name)
27
28#define INIT_LIST_HEAD(ptr) do { \
29 (ptr)->next = (ptr); (ptr)->prev = (ptr); \
30} while (0)
31
32void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next);
33void list_add(struct list_head *add, struct list_head *head);
34void list_add_tail(struct list_head *add, struct list_head *head);
35void __list_del(struct list_head * prev, struct list_head * next);
36void list_del(struct list_head *entry);
37void list_del_init(struct list_head *entry);
38int list_empty(struct list_head *head);
39void list_splice(struct list_head *list, struct list_head *head);
40
41/**
42 * list_entry - get the struct for this entry
43 * @ptr: the &struct list_head pointer.
44 * @type: the type of the struct this is embedded in.
45 * @member: the name of the list_struct within the struct.
46 */
47#define list_entry(ptr, type, member) \
48 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
49
50/**
51 * list_for_each - iterate over elements in a list
52 * @pos: the &struct list_head to use as a loop counter.
53 * @head: the head for your list.
54 */
55#define list_for_each(pos, head) \
56 for (pos = (head)->next; pos != (head); pos = pos->next)
57
58/**
59 * list_for_each_safe - iterate over elements in a list, but don't dereference
60 * pos after the body is done (in case it is freed)
61 * @pos: the &struct list_head to use as a loop counter.
62 * @pnext: the &struct list_head to use as a pointer to the next item.
63 * @head: the head for your list (not included in iteration).
64 */
65#define list_for_each_safe(pos, pnext, head) \
66 for (pos = (head)->next, pnext = pos->next; pos != (head); \
67 pos = pnext, pnext = pos->next)
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif /* _BLKID_LIST_H */
diff --git a/e2fsprogs/blkid/probe.c b/e2fsprogs/blkid/probe.c
deleted file mode 100644
index 8c6e2aa33..000000000
--- a/e2fsprogs/blkid/probe.c
+++ /dev/null
@@ -1,721 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * probe.c - identify a block device by its contents, and return a dev
4 * struct with the details
5 *
6 * Copyright (C) 1999 by Andries Brouwer
7 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
8 * Copyright (C) 2001 by Andreas Dilger
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the
12 * GNU Lesser General Public License.
13 * %End-Header%
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <sys/types.h>
22#ifdef HAVE_SYS_STAT_H
23#include <sys/stat.h>
24#endif
25#ifdef HAVE_SYS_MKDEV_H
26#include <sys/mkdev.h>
27#endif
28#ifdef HAVE_ERRNO_H
29#include <errno.h>
30#endif
31#include "blkidP.h"
32#include "../uuid/uuid.h"
33#include "probe.h"
34
35/*
36 * This is a special case code to check for an MDRAID device. We do
37 * this special since it requires checking for a superblock at the end
38 * of the device.
39 */
40static int check_mdraid(int fd, unsigned char *ret_uuid)
41{
42 struct mdp_superblock_s *md;
43 blkid_loff_t offset;
44 char buf[4096];
45
46 if (fd < 0)
47 return -BLKID_ERR_PARAM;
48
49 offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
50
51 if (blkid_llseek(fd, offset, 0) < 0 ||
52 read(fd, buf, 4096) != 4096)
53 return -BLKID_ERR_IO;
54
55 /* Check for magic number */
56 if (memcmp("\251+N\374", buf, 4))
57 return -BLKID_ERR_PARAM;
58
59 if (!ret_uuid)
60 return 0;
61 *ret_uuid = 0;
62
63 /* The MD UUID is not contiguous in the superblock, make it so */
64 md = (struct mdp_superblock_s *)buf;
65 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
66 memcpy(ret_uuid, &md->set_uuid0, 4);
67 memcpy(ret_uuid, &md->set_uuid1, 12);
68 }
69 return 0;
70}
71
72static void set_uuid(blkid_dev dev, uuid_t uuid)
73{
74 char str[37];
75
76 if (!uuid_is_null(uuid)) {
77 uuid_unparse(uuid, str);
78 blkid_set_tag(dev, "UUID", str, sizeof(str));
79 }
80}
81
82static void get_ext2_info(blkid_dev dev, unsigned char *buf)
83{
84 struct ext2_super_block *es = (struct ext2_super_block *) buf;
85 const char *label = 0;
86
87 DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
88 blkid_le32(es->s_feature_compat),
89 blkid_le32(es->s_feature_incompat),
90 blkid_le32(es->s_feature_ro_compat)));
91
92 if (strlen(es->s_volume_name))
93 label = es->s_volume_name;
94 blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
95
96 set_uuid(dev, es->s_uuid);
97}
98
99static int probe_ext3(int fd __BLKID_ATTR((unused)),
100 blkid_cache cache __BLKID_ATTR((unused)),
101 blkid_dev dev,
102 const struct blkid_magic *id __BLKID_ATTR((unused)),
103 unsigned char *buf)
104{
105 struct ext2_super_block *es;
106
107 es = (struct ext2_super_block *)buf;
108
109 /* Distinguish between jbd and ext2/3 fs */
110 if (blkid_le32(es->s_feature_incompat) &
111 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
112 return -BLKID_ERR_PARAM;
113
114 /* Distinguish between ext3 and ext2 */
115 if (!(blkid_le32(es->s_feature_compat) &
116 EXT3_FEATURE_COMPAT_HAS_JOURNAL))
117 return -BLKID_ERR_PARAM;
118
119 get_ext2_info(dev, buf);
120
121 blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
122
123 return 0;
124}
125
126static int probe_ext2(int fd __BLKID_ATTR((unused)),
127 blkid_cache cache __BLKID_ATTR((unused)),
128 blkid_dev dev,
129 const struct blkid_magic *id __BLKID_ATTR((unused)),
130 unsigned char *buf)
131{
132 struct ext2_super_block *es;
133
134 es = (struct ext2_super_block *)buf;
135
136 /* Distinguish between jbd and ext2/3 fs */
137 if (blkid_le32(es->s_feature_incompat) &
138 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
139 return -BLKID_ERR_PARAM;
140
141 get_ext2_info(dev, buf);
142
143 return 0;
144}
145
146static int probe_jbd(int fd __BLKID_ATTR((unused)),
147 blkid_cache cache __BLKID_ATTR((unused)),
148 blkid_dev dev,
149 const struct blkid_magic *id __BLKID_ATTR((unused)),
150 unsigned char *buf)
151{
152 struct ext2_super_block *es = (struct ext2_super_block *) buf;
153
154 if (!(blkid_le32(es->s_feature_incompat) &
155 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
156 return -BLKID_ERR_PARAM;
157
158 get_ext2_info(dev, buf);
159
160 return 0;
161}
162
163static int probe_vfat(int fd __BLKID_ATTR((unused)),
164 blkid_cache cache __BLKID_ATTR((unused)),
165 blkid_dev dev,
166 const struct blkid_magic *id __BLKID_ATTR((unused)),
167 unsigned char *buf)
168{
169 struct vfat_super_block *vs;
170 char serno[10];
171 const char *label = 0;
172 int label_len = 0;
173
174 vs = (struct vfat_super_block *)buf;
175
176 if (strncmp(vs->vs_label, "NO NAME", 7)) {
177 char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
178
179 while (*end == ' ' && end >= vs->vs_label)
180 --end;
181 if (end >= vs->vs_label) {
182 label = vs->vs_label;
183 label_len = end - vs->vs_label + 1;
184 }
185 }
186
187 /* We can't just print them as %04X, because they are unaligned */
188 sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
189 vs->vs_serno[1], vs->vs_serno[0]);
190 blkid_set_tag(dev, "LABEL", label, label_len);
191 blkid_set_tag(dev, "UUID", serno, sizeof(serno));
192
193 return 0;
194}
195
196static int probe_msdos(int fd __BLKID_ATTR((unused)),
197 blkid_cache cache __BLKID_ATTR((unused)),
198 blkid_dev dev,
199 const struct blkid_magic *id __BLKID_ATTR((unused)),
200 unsigned char *buf)
201{
202 struct msdos_super_block *ms = (struct msdos_super_block *) buf;
203 char serno[10];
204 const char *label = 0;
205 int label_len = 0;
206
207 if (strncmp(ms->ms_label, "NO NAME", 7)) {
208 char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
209
210 while (*end == ' ' && end >= ms->ms_label)
211 --end;
212 if (end >= ms->ms_label) {
213 label = ms->ms_label;
214 label_len = end - ms->ms_label + 1;
215 }
216 }
217
218 /* We can't just print them as %04X, because they are unaligned */
219 sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
220 ms->ms_serno[1], ms->ms_serno[0]);
221 blkid_set_tag(dev, "UUID", serno, 0);
222 blkid_set_tag(dev, "LABEL", label, label_len);
223 blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
224
225 return 0;
226}
227
228static int probe_xfs(int fd __BLKID_ATTR((unused)),
229 blkid_cache cache __BLKID_ATTR((unused)),
230 blkid_dev dev,
231 const struct blkid_magic *id __BLKID_ATTR((unused)),
232 unsigned char *buf)
233{
234 struct xfs_super_block *xs;
235 const char *label = 0;
236
237 xs = (struct xfs_super_block *)buf;
238
239 if (strlen(xs->xs_fname))
240 label = xs->xs_fname;
241 blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
242 set_uuid(dev, xs->xs_uuid);
243 return 0;
244}
245
246static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
247 blkid_cache cache __BLKID_ATTR((unused)),
248 blkid_dev dev,
249 const struct blkid_magic *id, unsigned char *buf)
250{
251 struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
252 unsigned int blocksize;
253 const char *label = 0;
254
255 blocksize = blkid_le16(rs->rs_blocksize);
256
257 /* If the superblock is inside the journal, we have the wrong one */
258 if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
259 return -BLKID_ERR_BIG;
260
261 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
262 if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
263 !strcmp(id->bim_magic, "ReIsEr3Fs")) {
264 if (strlen(rs->rs_label))
265 label = rs->rs_label;
266 set_uuid(dev, rs->rs_uuid);
267 }
268 blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
269
270 return 0;
271}
272
273static int probe_jfs(int fd __BLKID_ATTR((unused)),
274 blkid_cache cache __BLKID_ATTR((unused)),
275 blkid_dev dev,
276 const struct blkid_magic *id __BLKID_ATTR((unused)),
277 unsigned char *buf)
278{
279 struct jfs_super_block *js;
280 const char *label = 0;
281
282 js = (struct jfs_super_block *)buf;
283
284 if (strlen((char *) js->js_label))
285 label = (char *) js->js_label;
286 blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
287 set_uuid(dev, js->js_uuid);
288 return 0;
289}
290
291static int probe_romfs(int fd __BLKID_ATTR((unused)),
292 blkid_cache cache __BLKID_ATTR((unused)),
293 blkid_dev dev,
294 const struct blkid_magic *id __BLKID_ATTR((unused)),
295 unsigned char *buf)
296{
297 struct romfs_super_block *ros;
298 const char *label = 0;
299
300 ros = (struct romfs_super_block *)buf;
301
302 if (strlen((char *) ros->ros_volume))
303 label = (char *) ros->ros_volume;
304 blkid_set_tag(dev, "LABEL", label, 0);
305 return 0;
306}
307
308static int probe_cramfs(int fd __BLKID_ATTR((unused)),
309 blkid_cache cache __BLKID_ATTR((unused)),
310 blkid_dev dev,
311 const struct blkid_magic *id __BLKID_ATTR((unused)),
312 unsigned char *buf)
313{
314 struct cramfs_super_block *csb;
315 const char *label = 0;
316
317 csb = (struct cramfs_super_block *)buf;
318
319 if (strlen((char *) csb->name))
320 label = (char *) csb->name;
321 blkid_set_tag(dev, "LABEL", label, 0);
322 return 0;
323}
324
325static int probe_swap0(int fd __BLKID_ATTR((unused)),
326 blkid_cache cache __BLKID_ATTR((unused)),
327 blkid_dev dev,
328 const struct blkid_magic *id __BLKID_ATTR((unused)),
329 unsigned char *buf __BLKID_ATTR((unused)))
330{
331 blkid_set_tag(dev, "UUID", 0, 0);
332 blkid_set_tag(dev, "LABEL", 0, 0);
333 return 0;
334}
335
336static int probe_swap1(int fd,
337 blkid_cache cache __BLKID_ATTR((unused)),
338 blkid_dev dev,
339 const struct blkid_magic *id __BLKID_ATTR((unused)),
340 unsigned char *buf __BLKID_ATTR((unused)))
341{
342 struct swap_id_block *sws;
343
344 probe_swap0(fd, cache, dev, id, buf);
345 /*
346 * Version 1 swap headers are always located at offset of 1024
347 * bytes, although the swap signature itself is located at the
348 * end of the page (which may vary depending on hardware
349 * pagesize).
350 */
351 if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
352 sws = xmalloc(1024);
353 if (read(fd, sws, 1024) != 1024) {
354 free(sws);
355 return 1;
356 }
357
358 /* arbitrary sanity check.. is there any garbage down there? */
359 if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
360 if (sws->sws_volume[0])
361 blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
362 sizeof(sws->sws_volume));
363 if (sws->sws_uuid[0])
364 set_uuid(dev, sws->sws_uuid);
365 }
366 free(sws);
367
368 return 0;
369}
370
371static const char
372* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
373 "NSR03", "TEA01", 0 };
374
375static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
376 blkid_dev dev __BLKID_ATTR((unused)),
377 const struct blkid_magic *id __BLKID_ATTR((unused)),
378 unsigned char *buf __BLKID_ATTR((unused)))
379{
380 int j, bs;
381 struct iso_volume_descriptor isosb;
382 const char * const * m;
383
384 /* determine the block size by scanning in 2K increments
385 (block sizes larger than 2K will be null padded) */
386 for (bs = 1; bs < 16; bs++) {
387 lseek(fd, bs*2048+32768, SEEK_SET);
388 if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
389 return 1;
390 if (isosb.id[0])
391 break;
392 }
393
394 /* Scan up to another 64 blocks looking for additional VSD's */
395 for (j = 1; j < 64; j++) {
396 if (j > 1) {
397 lseek(fd, j*bs*2048+32768, SEEK_SET);
398 if (read(fd, (char *)&isosb, sizeof(isosb))
399 != sizeof(isosb))
400 return 1;
401 }
402 /* If we find NSR0x then call it udf:
403 NSR01 for UDF 1.00
404 NSR02 for UDF 1.50
405 NSR03 for UDF 2.00 */
406 if (!strncmp(isosb.id, "NSR0", 4))
407 return 0;
408 for (m = udf_magic; *m; m++)
409 if (!strncmp(*m, isosb.id, 5))
410 break;
411 if (*m == 0)
412 return 1;
413 }
414 return 1;
415}
416
417static int probe_ocfs(int fd __BLKID_ATTR((unused)),
418 blkid_cache cache __BLKID_ATTR((unused)),
419 blkid_dev dev,
420 const struct blkid_magic *id __BLKID_ATTR((unused)),
421 unsigned char *buf)
422{
423 struct ocfs_volume_header ovh;
424 struct ocfs_volume_label ovl;
425 __u32 major;
426
427 memcpy(&ovh, buf, sizeof(ovh));
428 memcpy(&ovl, buf+512, sizeof(ovl));
429
430 major = ocfsmajor(ovh);
431 if (major == 1)
432 blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
433 else if (major >= 9)
434 blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
435
436 blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
437 blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
438 set_uuid(dev, ovl.vol_id);
439 return 0;
440}
441
442static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
443 blkid_cache cache __BLKID_ATTR((unused)),
444 blkid_dev dev,
445 const struct blkid_magic *id __BLKID_ATTR((unused)),
446 unsigned char *buf)
447{
448 struct ocfs2_super_block *osb;
449
450 osb = (struct ocfs2_super_block *)buf;
451
452 blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
453 set_uuid(dev, osb->s_uuid);
454 return 0;
455}
456
457static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
458 blkid_cache cache __BLKID_ATTR((unused)),
459 blkid_dev dev,
460 const struct blkid_magic *id __BLKID_ATTR((unused)),
461 unsigned char *buf)
462{
463 struct oracle_asm_disk_label *dl;
464
465 dl = (struct oracle_asm_disk_label *)buf;
466
467 blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
468 return 0;
469}
470
471/*
472 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
473 * in the type_array table below + bim_kbalign.
474 *
475 * When probing for a lot of magics, we handle everything in 1kB buffers so
476 * that we don't have to worry about reading each combination of block sizes.
477 */
478#define BLKID_BLK_OFFS 64 /* currently reiserfs */
479
480/*
481 * Various filesystem magics that we can check for. Note that kboff and
482 * sboff are in kilobytes and bytes respectively. All magics are in
483 * byte strings so we don't worry about endian issues.
484 */
485static const struct blkid_magic type_array[] = {
486/* type kboff sboff len magic probe */
487 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
488 { "ntfs", 0, 3, 8, "NTFS ", 0 },
489 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
490 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
491 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
492 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
493 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
494 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
495 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
496 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
497 { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
498 { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
499 { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
500 { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
501 { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
502 { "minix", 1, 0x10, 2, "\177\023", 0 },
503 { "minix", 1, 0x10, 2, "\217\023", 0 },
504 { "minix", 1, 0x10, 2, "\150\044", 0 },
505 { "minix", 1, 0x10, 2, "\170\044", 0 },
506 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
507 { "xfs", 0, 0, 4, "XFSB", probe_xfs },
508 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
509 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
510 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
511 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
512 { "udf", 32, 1, 5, "BEA01", probe_udf },
513 { "udf", 32, 1, 5, "BOOT2", probe_udf },
514 { "udf", 32, 1, 5, "CD001", probe_udf },
515 { "udf", 32, 1, 5, "CDW02", probe_udf },
516 { "udf", 32, 1, 5, "NSR02", probe_udf },
517 { "udf", 32, 1, 5, "NSR03", probe_udf },
518 { "udf", 32, 1, 5, "TEA01", probe_udf },
519 { "iso9660", 32, 1, 5, "CD001", 0 },
520 { "iso9660", 32, 9, 5, "CDROM", 0 },
521 { "jfs", 32, 0, 4, "JFS1", probe_jfs },
522 { "hfs", 1, 0, 2, "BD", 0 },
523 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
524 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
525 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
526 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
527 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
528 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
529 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
530 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
531 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
532 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
533 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
534 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
535 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
536 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
537 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
538 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
539 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
540 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
541 { NULL, 0, 0, 0, NULL, NULL }
542};
543
544/*
545 * Verify that the data in dev is consistent with what is on the actual
546 * block device (using the devname field only). Normally this will be
547 * called when finding items in the cache, but for long running processes
548 * is also desirable to revalidate an item before use.
549 *
550 * If we are unable to revalidate the data, we return the old data and
551 * do not set the BLKID_BID_FL_VERIFIED flag on it.
552 */
553blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
554{
555 const struct blkid_magic *id;
556 unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
557 const char *type;
558 struct stat st;
559 time_t diff, now;
560 int fd, idx;
561
562 if (!dev)
563 return NULL;
564
565 now = time(0);
566 diff = now - dev->bid_time;
567
568 if ((now < dev->bid_time) ||
569 (diff < BLKID_PROBE_MIN) ||
570 (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
571 diff < BLKID_PROBE_INTERVAL))
572 return dev;
573
574 DBG(DEBUG_PROBE,
575 printf("need to revalidate %s (time since last check %lu)\n",
576 dev->bid_name, diff));
577
578 if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
579 (fstat(fd, &st) < 0)) {
580 if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
581 blkid_free_dev(dev);
582 return NULL;
583 }
584 /* We don't have read permission, just return cache data. */
585 DBG(DEBUG_PROBE,
586 printf("returning unverified data for %s\n",
587 dev->bid_name));
588 return dev;
589 }
590
591 memset(bufs, 0, sizeof(bufs));
592
593 /*
594 * Iterate over the type array. If we already know the type,
595 * then try that first. If it doesn't work, then blow away
596 * the type information, and try again.
597 *
598 */
599try_again:
600 type = 0;
601 if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
602 uuid_t uuid;
603
604 if (check_mdraid(fd, uuid) == 0) {
605 set_uuid(dev, uuid);
606 type = "mdraid";
607 goto found_type;
608 }
609 }
610 for (id = type_array; id->bim_type; id++) {
611 if (dev->bid_type &&
612 strcmp(id->bim_type, dev->bid_type))
613 continue;
614
615 idx = id->bim_kboff + (id->bim_sboff >> 10);
616 if (idx > BLKID_BLK_OFFS || idx < 0)
617 continue;
618 buf = bufs[idx];
619 if (!buf) {
620 if (lseek(fd, idx << 10, SEEK_SET) < 0)
621 continue;
622
623 buf = xmalloc(1024);
624
625 if (read(fd, buf, 1024) != 1024) {
626 free(buf);
627 continue;
628 }
629 bufs[idx] = buf;
630 }
631
632 if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
633 id->bim_len))
634 continue;
635
636 if ((id->bim_probe == NULL) ||
637 (id->bim_probe(fd, cache, dev, id, buf) == 0)) {
638 type = id->bim_type;
639 goto found_type;
640 }
641 }
642
643 if (!id->bim_type && dev->bid_type) {
644 /*
645 * Zap the device filesystem type and try again
646 */
647 blkid_set_tag(dev, "TYPE", 0, 0);
648 blkid_set_tag(dev, "SEC_TYPE", 0, 0);
649 blkid_set_tag(dev, "LABEL", 0, 0);
650 blkid_set_tag(dev, "UUID", 0, 0);
651 goto try_again;
652 }
653
654 if (!dev->bid_type) {
655 blkid_free_dev(dev);
656 return NULL;
657 }
658
659found_type:
660 if (dev && type) {
661 dev->bid_devno = st.st_rdev;
662 dev->bid_time = time(0);
663 dev->bid_flags |= BLKID_BID_FL_VERIFIED;
664 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
665
666 blkid_set_tag(dev, "TYPE", type, 0);
667
668 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
669 dev->bid_name, st.st_rdev, type));
670 }
671
672 close(fd);
673
674 return dev;
675}
676
677int blkid_known_fstype(const char *fstype)
678{
679 const struct blkid_magic *id;
680
681 for (id = type_array; id->bim_type; id++) {
682 if (strcmp(fstype, id->bim_type) == 0)
683 return 1;
684 }
685 return 0;
686}
687
688#ifdef TEST_PROGRAM
689int main(int argc, char **argv)
690{
691 blkid_dev dev;
692 blkid_cache cache;
693 int ret;
694
695 blkid_debug_mask = DEBUG_ALL;
696 if (argc != 2) {
697 fprintf(stderr, "Usage: %s device\n"
698 "Probe a single device to determine type\n", argv[0]);
699 exit(1);
700 }
701 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
702 fprintf(stderr, "%s: error creating cache (%d)\n",
703 argv[0], ret);
704 exit(1);
705 }
706 dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
707 if (!dev) {
708 printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
709 return 1;
710 }
711 printf("%s is type %s\n", argv[1], dev->bid_type ?
712 dev->bid_type : "(null)");
713 if (dev->bid_label)
714 printf("\tlabel is '%s'\n", dev->bid_label);
715 if (dev->bid_uuid)
716 printf("\tuuid is %s\n", dev->bid_uuid);
717
718 blkid_free_dev(dev);
719 return 0;
720}
721#endif
diff --git a/e2fsprogs/blkid/probe.h b/e2fsprogs/blkid/probe.h
deleted file mode 100644
index 78f796419..000000000
--- a/e2fsprogs/blkid/probe.h
+++ /dev/null
@@ -1,375 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * probe.h - constants and on-disk structures for extracting device data
4 *
5 * Copyright (C) 1999 by Andries Brouwer
6 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
7 * Copyright (C) 2001 by Andreas Dilger
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the
11 * GNU Lesser General Public License.
12 * %End-Header%
13 */
14
15#ifndef _BLKID_PROBE_H
16#define _BLKID_PROBE_H
17
18#include <linux/types.h>
19
20struct blkid_magic;
21
22typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
23 const struct blkid_magic *id, unsigned char *buf);
24
25struct blkid_magic {
26 const char *bim_type; /* type name for this magic */
27 long bim_kboff; /* kilobyte offset of superblock */
28 unsigned bim_sboff; /* byte offset within superblock */
29 unsigned bim_len; /* length of magic */
30 const char *bim_magic; /* magic string */
31 blkid_probe_t bim_probe; /* probe function */
32};
33
34/*
35 * Structures for each of the content types we want to extract information
36 * from. We do not necessarily need the magic field here, because we have
37 * already identified the content type before we get this far. It may still
38 * be useful if there are probe functions which handle multiple content types.
39 */
40struct ext2_super_block {
41 __u32 s_inodes_count;
42 __u32 s_blocks_count;
43 __u32 s_r_blocks_count;
44 __u32 s_free_blocks_count;
45 __u32 s_free_inodes_count;
46 __u32 s_first_data_block;
47 __u32 s_log_block_size;
48 __u32 s_dummy3[7];
49 unsigned char s_magic[2];
50 __u16 s_state;
51 __u32 s_dummy5[8];
52 __u32 s_feature_compat;
53 __u32 s_feature_incompat;
54 __u32 s_feature_ro_compat;
55 unsigned char s_uuid[16];
56 char s_volume_name[16];
57};
58#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
59#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
60#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
61
62struct xfs_super_block {
63 unsigned char xs_magic[4];
64 __u32 xs_blocksize;
65 __u64 xs_dblocks;
66 __u64 xs_rblocks;
67 __u32 xs_dummy1[2];
68 unsigned char xs_uuid[16];
69 __u32 xs_dummy2[15];
70 char xs_fname[12];
71 __u32 xs_dummy3[2];
72 __u64 xs_icount;
73 __u64 xs_ifree;
74 __u64 xs_fdblocks;
75};
76
77struct reiserfs_super_block {
78 __u32 rs_blocks_count;
79 __u32 rs_free_blocks;
80 __u32 rs_root_block;
81 __u32 rs_journal_block;
82 __u32 rs_journal_dev;
83 __u32 rs_orig_journal_size;
84 __u32 rs_dummy2[5];
85 __u16 rs_blocksize;
86 __u16 rs_dummy3[3];
87 unsigned char rs_magic[12];
88 __u32 rs_dummy4[5];
89 unsigned char rs_uuid[16];
90 char rs_label[16];
91};
92
93struct jfs_super_block {
94 unsigned char js_magic[4];
95 __u32 js_version;
96 __u64 js_size;
97 __u32 js_bsize;
98 __u32 js_dummy1;
99 __u32 js_pbsize;
100 __u32 js_dummy2[27];
101 unsigned char js_uuid[16];
102 unsigned char js_label[16];
103 unsigned char js_loguuid[16];
104};
105
106struct romfs_super_block {
107 unsigned char ros_magic[8];
108 __u32 ros_dummy1[2];
109 unsigned char ros_volume[16];
110};
111
112struct cramfs_super_block {
113 __u8 magic[4];
114 __u32 size;
115 __u32 flags;
116 __u32 future;
117 __u8 signature[16];
118 struct cramfs_info {
119 __u32 crc;
120 __u32 edition;
121 __u32 blocks;
122 __u32 files;
123 } info;
124 __u8 name[16];
125};
126
127struct swap_id_block {
128/* unsigned char sws_boot[1024]; */
129 __u32 sws_version;
130 __u32 sws_lastpage;
131 __u32 sws_nrbad;
132 unsigned char sws_uuid[16];
133 char sws_volume[16];
134 unsigned char sws_pad[117];
135 __u32 sws_badpg;
136};
137
138/* Yucky misaligned values */
139struct vfat_super_block {
140/* 00*/ unsigned char vs_ignored[3];
141/* 03*/ unsigned char vs_sysid[8];
142/* 0b*/ unsigned char vs_sector_size[2];
143/* 0d*/ __u8 vs_cluster_size;
144/* 0e*/ __u16 vs_reserved;
145/* 10*/ __u8 vs_fats;
146/* 11*/ unsigned char vs_dir_entries[2];
147/* 13*/ unsigned char vs_sectors[2];
148/* 15*/ unsigned char vs_media;
149/* 16*/ __u16 vs_fat_length;
150/* 18*/ __u16 vs_secs_track;
151/* 1a*/ __u16 vs_heads;
152/* 1c*/ __u32 vs_hidden;
153/* 20*/ __u32 vs_total_sect;
154/* 24*/ __u32 vs_fat32_length;
155/* 28*/ __u16 vs_flags;
156/* 2a*/ __u8 vs_version[2];
157/* 2c*/ __u32 vs_root_cluster;
158/* 30*/ __u16 vs_insfo_sector;
159/* 32*/ __u16 vs_backup_boot;
160/* 34*/ __u16 vs_reserved2[6];
161/* 40*/ unsigned char vs_unknown[3];
162/* 43*/ unsigned char vs_serno[4];
163/* 47*/ char vs_label[11];
164/* 52*/ unsigned char vs_magic[8];
165/* 5a*/ unsigned char vs_dummy2[164];
166/*1fe*/ unsigned char vs_pmagic[2];
167};
168
169/* Yucky misaligned values */
170struct msdos_super_block {
171/* 00*/ unsigned char ms_ignored[3];
172/* 03*/ unsigned char ms_sysid[8];
173/* 0b*/ unsigned char ms_sector_size[2];
174/* 0d*/ __u8 ms_cluster_size;
175/* 0e*/ __u16 ms_reserved;
176/* 10*/ __u8 ms_fats;
177/* 11*/ unsigned char ms_dir_entries[2];
178/* 13*/ unsigned char ms_sectors[2];
179/* 15*/ unsigned char ms_media;
180/* 16*/ __u16 ms_fat_length;
181/* 18*/ __u16 ms_secs_track;
182/* 1a*/ __u16 ms_heads;
183/* 1c*/ __u32 ms_hidden;
184/* 20*/ __u32 ms_total_sect;
185/* 24*/ unsigned char ms_unknown[3];
186/* 27*/ unsigned char ms_serno[4];
187/* 2b*/ char ms_label[11];
188/* 36*/ unsigned char ms_magic[8];
189/* 3d*/ unsigned char ms_dummy2[192];
190/*1fe*/ unsigned char ms_pmagic[2];
191};
192
193struct minix_super_block {
194 __u16 ms_ninodes;
195 __u16 ms_nzones;
196 __u16 ms_imap_blocks;
197 __u16 ms_zmap_blocks;
198 __u16 ms_firstdatazone;
199 __u16 ms_log_zone_size;
200 __u32 ms_max_size;
201 unsigned char ms_magic[2];
202 __u16 ms_state;
203 __u32 ms_zones;
204};
205
206struct mdp_superblock_s {
207 __u32 md_magic;
208 __u32 major_version;
209 __u32 minor_version;
210 __u32 patch_version;
211 __u32 gvalid_words;
212 __u32 set_uuid0;
213 __u32 ctime;
214 __u32 level;
215 __u32 size;
216 __u32 nr_disks;
217 __u32 raid_disks;
218 __u32 md_minor;
219 __u32 not_persistent;
220 __u32 set_uuid1;
221 __u32 set_uuid2;
222 __u32 set_uuid3;
223};
224
225struct hfs_super_block {
226 char h_magic[2];
227 char h_dummy[18];
228 __u32 h_blksize;
229};
230
231struct ocfs_volume_header {
232 unsigned char minor_version[4];
233 unsigned char major_version[4];
234 unsigned char signature[128];
235 char mount[128];
236 unsigned char mount_len[2];
237};
238
239struct ocfs_volume_label {
240 unsigned char disk_lock[48];
241 char label[64];
242 unsigned char label_len[2];
243 unsigned char vol_id[16];
244 unsigned char vol_id_len[2];
245};
246
247#define ocfsmajor(o) ((__u32)o.major_version[0] \
248 + (((__u32) o.major_version[1]) << 8) \
249 + (((__u32) o.major_version[2]) << 16) \
250 + (((__u32) o.major_version[3]) << 24))
251#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
252#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
253
254#define OCFS_MAGIC "OracleCFS"
255
256struct ocfs2_super_block {
257 unsigned char signature[8];
258 unsigned char s_dummy1[184];
259 unsigned char s_dummy2[80];
260 char s_label[64];
261 unsigned char s_uuid[16];
262};
263
264#define OCFS2_MIN_BLOCKSIZE 512
265#define OCFS2_MAX_BLOCKSIZE 4096
266
267#define OCFS2_SUPER_BLOCK_BLKNO 2
268
269#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
270
271struct oracle_asm_disk_label {
272 char dummy[32];
273 char dl_tag[8];
274 char dl_id[24];
275};
276
277#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
278#define ORACLE_ASM_DISK_LABEL_OFFSET 32
279
280#define ISODCL(from, to) (to - from + 1)
281struct iso_volume_descriptor {
282 char type[ISODCL(1,1)]; /* 711 */
283 char id[ISODCL(2,6)];
284 char version[ISODCL(7,7)];
285 char data[ISODCL(8,2048)];
286};
287
288/*
289 * Byte swap functions
290 */
291#ifdef __GNUC__
292#define _INLINE_ static __inline__
293#else /* For Watcom C */
294#define _INLINE_ static inline
295#endif
296
297static __u16 blkid_swab16(__u16 val);
298static __u32 blkid_swab32(__u32 val);
299static __u64 blkid_swab64(__u64 val);
300
301#if ((defined __GNUC__) && \
302 (defined(__i386__) || defined(__i486__) || defined(__i586__)))
303
304#define _BLKID_HAVE_ASM_BITOPS_
305
306_INLINE_ __u32 blkid_swab32(__u32 val)
307{
308#ifdef EXT2FS_REQUIRE_486
309 __asm__("bswap %0" : "=r" (val) : "0" (val));
310#else
311 __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
312 "rorl $16,%0\n\t" /* swap words */
313 "xchgb %b0,%h0" /* swap higher bytes */
314 :"=q" (val)
315 : "0" (val));
316#endif
317 return val;
318}
319
320_INLINE_ __u16 blkid_swab16(__u16 val)
321{
322 __asm__("xchgb %b0,%h0" /* swap bytes */ \
323 : "=q" (val) \
324 : "0" (val)); \
325 return val;
326}
327
328_INLINE_ __u64 blkid_swab64(__u64 val)
329{
330 return blkid_swab32(val >> 32) |
331 ( ((__u64)blkid_swab32((__u32)val)) << 32 );
332}
333#endif
334
335#if !defined(_BLKID_HAVE_ASM_BITOPS_)
336
337_INLINE_ __u16 blkid_swab16(__u16 val)
338{
339 return (val >> 8) | (val << 8);
340}
341
342_INLINE_ __u32 blkid_swab32(__u32 val)
343{
344 return (val>>24) | ((val>>8) & 0xFF00) |
345 ((val<<8) & 0xFF0000) | (val<<24);
346}
347
348_INLINE_ __u64 blkid_swab64(__u64 val)
349{
350 return blkid_swab32(val >> 32) |
351 ( ((__u64)blkid_swab32((__u32)val)) << 32 );
352}
353#endif
354
355
356
357#if __BYTE_ORDER == __BIG_ENDIAN
358#define blkid_le16(x) blkid_swab16(x)
359#define blkid_le32(x) blkid_swab32(x)
360#define blkid_le64(x) blkid_swab64(x)
361#define blkid_be16(x) (x)
362#define blkid_be32(x) (x)
363#define blkid_be64(x) (x)
364#else
365#define blkid_le16(x) (x)
366#define blkid_le32(x) (x)
367#define blkid_le64(x) (x)
368#define blkid_be16(x) blkid_swab16(x)
369#define blkid_be32(x) blkid_swab32(x)
370#define blkid_be64(x) blkid_swab64(x)
371#endif
372
373#undef _INLINE_
374
375#endif /* _BLKID_PROBE_H */
diff --git a/e2fsprogs/blkid/read.c b/e2fsprogs/blkid/read.c
deleted file mode 100644
index bb02a2e21..000000000
--- a/e2fsprogs/blkid/read.c
+++ /dev/null
@@ -1,462 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * read.c - read the blkid cache from disk, to avoid scanning all devices
4 *
5 * Copyright (C) 2001, 2003 Theodore Y. Ts'o
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <ctype.h>
16#include <string.h>
17#include <time.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23
24#include "blkidP.h"
25#include "../uuid/uuid.h"
26
27#ifdef HAVE_STRTOULL
28#define __USE_ISOC9X
29#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
30#else
31/* FIXME: need to support real strtoull here */
32#define STRTOULL strtoul
33#endif
34
35#include <stdlib.h>
36
37#ifdef TEST_PROGRAM
38#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
39static void debug_dump_dev(blkid_dev dev);
40#endif
41
42/*
43 * File format:
44 *
45 * <device [<NAME="value"> ...]>device_name</device>
46 *
47 * The following tags are required for each entry:
48 * <ID="id"> unique (within this file) ID number of this device
49 * <TIME="time"> (ascii time_t) time this entry was last read from disk
50 * <TYPE="type"> (detected) type of filesystem/data for this partition
51 *
52 * The following tags may be present, depending on the device contents
53 * <LABEL="label"> (user supplied) label (volume name, etc)
54 * <UUID="uuid"> (generated) universally unique identifier (serial no)
55 */
56
57static char *skip_over_blank(char *cp)
58{
59 while (*cp && isspace(*cp))
60 cp++;
61 return cp;
62}
63
64static char *skip_over_word(char *cp)
65{
66 char ch;
67
68 while ((ch = *cp)) {
69 /* If we see a backslash, skip the next character */
70 if (ch == '\\') {
71 cp++;
72 if (*cp == '\0')
73 break;
74 cp++;
75 continue;
76 }
77 if (isspace(ch) || ch == '<' || ch == '>')
78 break;
79 cp++;
80 }
81 return cp;
82}
83
84static char *strip_line(char *line)
85{
86 char *p;
87
88 line = skip_over_blank(line);
89
90 p = line + strlen(line) - 1;
91
92 while (*line) {
93 if (isspace(*p))
94 *p-- = '\0';
95 else
96 break;
97 }
98
99 return line;
100}
101
102/*
103 * Start parsing a new line from the cache.
104 *
105 * line starts with "<device" return 1 -> continue parsing line
106 * line starts with "<foo", empty, or # return 0 -> skip line
107 * line starts with other, return -BLKID_ERR_CACHE -> error
108 */
109static int parse_start(char **cp)
110{
111 char *p;
112
113 p = strip_line(*cp);
114
115 /* Skip comment or blank lines. We can't just NUL the first '#' char,
116 * in case it is inside quotes, or escaped.
117 */
118 if (*p == '\0' || *p == '#')
119 return 0;
120
121 if (!strncmp(p, "<device", 7)) {
122 DBG(DEBUG_READ, printf("found device header: %8s\n", p));
123 p += 7;
124
125 *cp = p;
126 return 1;
127 }
128
129 if (*p == '<')
130 return 0;
131
132 return -BLKID_ERR_CACHE;
133}
134
135/* Consume the remaining XML on the line (cosmetic only) */
136static int parse_end(char **cp)
137{
138 *cp = skip_over_blank(*cp);
139
140 if (!strncmp(*cp, "</device>", 9)) {
141 DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
142 *cp += 9;
143 return 0;
144 }
145
146 return -BLKID_ERR_CACHE;
147}
148
149/*
150 * Allocate a new device struct with device name filled in. Will handle
151 * finding the device on lines of the form:
152 * <device foo=bar>devname</device>
153 * <device>devname<foo>bar</foo></device>
154 */
155static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
156{
157 char *start, *tmp, *end, *name;
158 int ret;
159
160 if ((ret = parse_start(cp)) <= 0)
161 return ret;
162
163 start = tmp = strchr(*cp, '>');
164 if (!start) {
165 DBG(DEBUG_READ,
166 printf("blkid: short line parsing dev: %s\n", *cp));
167 return -BLKID_ERR_CACHE;
168 }
169 start = skip_over_blank(start + 1);
170 end = skip_over_word(start);
171
172 DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
173
174 if (**cp == '>')
175 *cp = end;
176 else
177 (*cp)++;
178
179 *tmp = '\0';
180
181 if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
182 DBG(DEBUG_READ,
183 printf("blkid: missing </device> ending: %s\n", end));
184 } else if (tmp)
185 *tmp = '\0';
186
187 if (end - start <= 1) {
188 DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
189 return -BLKID_ERR_CACHE;
190 }
191
192 name = blkid_strndup(start, end-start);
193 if (name == NULL)
194 return -BLKID_ERR_MEM;
195
196 DBG(DEBUG_READ, printf("found dev %s\n", name));
197
198 if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
199 return -BLKID_ERR_MEM;
200
201 free(name);
202 return 1;
203}
204
205/*
206 * Extract a tag of the form NAME="value" from the line.
207 */
208static int parse_token(char **name, char **value, char **cp)
209{
210 char *end;
211
212 if (!name || !value || !cp)
213 return -BLKID_ERR_PARAM;
214
215 if (!(*value = strchr(*cp, '=')))
216 return 0;
217
218 **value = '\0';
219 *name = strip_line(*cp);
220 *value = skip_over_blank(*value + 1);
221
222 if (**value == '"') {
223 end = strchr(*value + 1, '"');
224 if (!end) {
225 DBG(DEBUG_READ,
226 printf("unbalanced quotes at: %s\n", *value));
227 *cp = *value;
228 return -BLKID_ERR_CACHE;
229 }
230 (*value)++;
231 *end = '\0';
232 end++;
233 } else {
234 end = skip_over_word(*value);
235 if (*end) {
236 *end = '\0';
237 end++;
238 }
239 }
240 *cp = end;
241
242 return 1;
243}
244
245/*
246 * Extract a tag of the form <NAME>value</NAME> from the line.
247 */
248/*
249static int parse_xml(char **name, char **value, char **cp)
250{
251 char *end;
252
253 if (!name || !value || !cp)
254 return -BLKID_ERR_PARAM;
255
256 *name = strip_line(*cp);
257
258 if ((*name)[0] != '<' || (*name)[1] == '/')
259 return 0;
260
261 FIXME: finish this.
262}
263*/
264
265/*
266 * Extract a tag from the line.
267 *
268 * Return 1 if a valid tag was found.
269 * Return 0 if no tag found.
270 * Return -ve error code.
271 */
272static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
273{
274 char *name;
275 char *value;
276 int ret;
277
278 if (!cache || !dev)
279 return -BLKID_ERR_PARAM;
280
281 if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
282 (ret = parse_xml(&name, &value, cp)) <= 0 */)
283 return ret;
284
285 /* Some tags are stored directly in the device struct */
286 if (!strcmp(name, "DEVNO"))
287 dev->bid_devno = STRTOULL(value, 0, 0);
288 else if (!strcmp(name, "PRI"))
289 dev->bid_pri = strtol(value, 0, 0);
290 else if (!strcmp(name, "TIME"))
291 /* FIXME: need to parse a long long eventually */
292 dev->bid_time = strtol(value, 0, 0);
293 else
294 ret = blkid_set_tag(dev, name, value, strlen(value));
295
296 DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
297
298 return ret < 0 ? ret : 1;
299}
300
301/*
302 * Parse a single line of data, and return a newly allocated dev struct.
303 * Add the new device to the cache struct, if one was read.
304 *
305 * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
306 *
307 * Returns -ve value on error.
308 * Returns 0 otherwise.
309 * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
310 * (e.g. comment lines, unknown XML content, etc).
311 */
312static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
313{
314 blkid_dev dev;
315 int ret;
316
317 if (!cache || !dev_p)
318 return -BLKID_ERR_PARAM;
319
320 *dev_p = NULL;
321
322 DBG(DEBUG_READ, printf("line: %s\n", cp));
323
324 if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
325 return ret;
326
327 dev = *dev_p;
328
329 while ((ret = parse_tag(cache, dev, &cp)) > 0) {
330 ;
331 }
332
333 if (dev->bid_type == NULL) {
334 DBG(DEBUG_READ,
335 printf("blkid: device %s has no TYPE\n",dev->bid_name));
336 blkid_free_dev(dev);
337 }
338
339 DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
340
341 return ret;
342}
343
344/*
345 * Parse the specified filename, and return the data in the supplied or
346 * a newly allocated cache struct. If the file doesn't exist, return a
347 * new empty cache struct.
348 */
349void blkid_read_cache(blkid_cache cache)
350{
351 FILE *file;
352 char buf[4096];
353 int fd, lineno = 0;
354 struct stat st;
355
356 if (!cache)
357 return;
358
359 /*
360 * If the file doesn't exist, then we just return an empty
361 * struct so that the cache can be populated.
362 */
363 if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
364 return;
365 if (fstat(fd, &st) < 0)
366 goto errout;
367 if ((st.st_mtime == cache->bic_ftime) ||
368 (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
369 DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
370 cache->bic_filename));
371 goto errout;
372 }
373
374 DBG(DEBUG_CACHE, printf("reading cache file %s\n",
375 cache->bic_filename));
376
377 file = fdopen(fd, "r");
378 if (!file)
379 goto errout;
380
381 while (fgets(buf, sizeof(buf), file)) {
382 blkid_dev dev;
383 unsigned int end;
384
385 lineno++;
386 if (buf[0] == 0)
387 continue;
388 end = strlen(buf) - 1;
389 /* Continue reading next line if it ends with a backslash */
390 while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
391 fgets(buf + end, sizeof(buf) - end, file)) {
392 end = strlen(buf) - 1;
393 lineno++;
394 }
395
396 if (blkid_parse_line(cache, &dev, buf) < 0) {
397 DBG(DEBUG_READ,
398 printf("blkid: bad format on line %d\n", lineno));
399 continue;
400 }
401 }
402 fclose(file);
403
404 /*
405 * Initially we do not need to write out the cache file.
406 */
407 cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
408 cache->bic_ftime = st.st_mtime;
409
410 return;
411errout:
412 close(fd);
413 return;
414}
415
416#ifdef TEST_PROGRAM
417static void debug_dump_dev(blkid_dev dev)
418{
419 struct list_head *p;
420
421 if (!dev) {
422 printf(" dev: NULL\n");
423 return;
424 }
425
426 printf(" dev: name = %s\n", dev->bid_name);
427 printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
428 printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
429 printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
430 printf(" dev: flags = 0x%08X\n", dev->bid_flags);
431
432 list_for_each(p, &dev->bid_tags) {
433 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
434 if (tag)
435 printf(" tag: %s=\"%s\"\n", tag->bit_name,
436 tag->bit_val);
437 else
438 printf(" tag: NULL\n");
439 }
440 puts("");
441}
442
443int main(int argc, char**argv)
444{
445 blkid_cache cache = NULL;
446 int ret;
447
448 blkid_debug_mask = DEBUG_ALL;
449 if (argc > 2) {
450 fprintf(stderr, "Usage: %s [filename]\n"
451 "Test parsing of the cache (filename)\n", argv[0]);
452 exit(1);
453 }
454 if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
455 fprintf(stderr, "error %d reading cache file %s\n", ret,
456 argv[1] ? argv[1] : BLKID_CACHE_FILE);
457
458 blkid_put_cache(cache);
459
460 return ret;
461}
462#endif
diff --git a/e2fsprogs/blkid/resolve.c b/e2fsprogs/blkid/resolve.c
deleted file mode 100644
index 7942de2cd..000000000
--- a/e2fsprogs/blkid/resolve.c
+++ /dev/null
@@ -1,139 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * resolve.c - resolve names and tags into specific devices
4 *
5 * Copyright (C) 2001, 2003 Theodore Ts'o.
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#ifdef HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <stdlib.h>
19#include <fcntl.h>
20#include <string.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include "blkidP.h"
24#include "probe.h"
25
26/*
27 * Find a tagname (e.g. LABEL or UUID) on a specific device.
28 */
29char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
30 const char *devname)
31{
32 blkid_tag found;
33 blkid_dev dev;
34 blkid_cache c = cache;
35 char *ret = NULL;
36
37 DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
38
39 if (!devname)
40 return NULL;
41
42 if (!cache) {
43 if (blkid_get_cache(&c, NULL) < 0)
44 return NULL;
45 }
46
47 if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
48 (found = blkid_find_tag_dev(dev, tagname)))
49 ret = blkid_strdup(found->bit_val);
50
51 if (!cache)
52 blkid_put_cache(c);
53
54 return ret;
55}
56
57/*
58 * Locate a device name from a token (NAME=value string), or (name, value)
59 * pair. In the case of a token, value is ignored. If the "token" is not
60 * of the form "NAME=value" and there is no value given, then it is assumed
61 * to be the actual devname and a copy is returned.
62 */
63char *blkid_get_devname(blkid_cache cache, const char *token,
64 const char *value)
65{
66 blkid_dev dev;
67 blkid_cache c = cache;
68 char *t = 0, *v = 0;
69 char *ret = NULL;
70
71 if (!token)
72 return NULL;
73
74 if (!cache) {
75 if (blkid_get_cache(&c, NULL) < 0)
76 return NULL;
77 }
78
79 DBG(DEBUG_RESOLVE,
80 printf("looking for %s%s%s %s\n", token, value ? "=" : "",
81 value ? value : "", cache ? "in cache" : "from disk"));
82
83 if (!value) {
84 if (!strchr(token, '='))
85 return blkid_strdup(token);
86 blkid_parse_tag_string(token, &t, &v);
87 if (!t || !v)
88 goto errout;
89 token = t;
90 value = v;
91 }
92
93 dev = blkid_find_dev_with_tag(c, token, value);
94 if (!dev)
95 goto errout;
96
97 ret = blkid_strdup(blkid_dev_devname(dev));
98
99errout:
100 free(t);
101 free(v);
102 if (!cache) {
103 blkid_put_cache(c);
104 }
105 return ret;
106}
107
108#ifdef TEST_PROGRAM
109int main(int argc, char **argv)
110{
111 char *value;
112 blkid_cache cache;
113
114 blkid_debug_mask = DEBUG_ALL;
115 if (argc != 2 && argc != 3) {
116 fprintf(stderr, "Usage:\t%s tagname=value\n"
117 "\t%s tagname devname\n"
118 "Find which device holds a given token or\n"
119 "Find what the value of a tag is in a device\n",
120 argv[0], argv[0]);
121 exit(1);
122 }
123 if (blkid_get_cache(&cache, bb_dev_null) < 0) {
124 fprintf(stderr, "cannot get blkid cache\n");
125 exit(1);
126 }
127
128 if (argv[2]) {
129 value = blkid_get_tag_value(cache, argv[1], argv[2]);
130 printf("%s has tag %s=%s\n", argv[2], argv[1],
131 value ? value : "<missing>");
132 } else {
133 value = blkid_get_devname(cache, argv[1], NULL);
134 printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
135 }
136 blkid_put_cache(cache);
137 return value ? 0 : 1;
138}
139#endif
diff --git a/e2fsprogs/blkid/save.c b/e2fsprogs/blkid/save.c
deleted file mode 100644
index cdbaabcb1..000000000
--- a/e2fsprogs/blkid/save.c
+++ /dev/null
@@ -1,189 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * save.c - write the cache struct to disk
4 *
5 * Copyright (C) 2001 by Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <sys/types.h>
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif
22#ifdef HAVE_SYS_MKDEV_H
23#include <sys/mkdev.h>
24#endif
25#ifdef HAVE_ERRNO_H
26#include <errno.h>
27#endif
28#include "blkidP.h"
29
30static int save_dev(blkid_dev dev, FILE *file)
31{
32 struct list_head *p;
33
34 if (!dev || dev->bid_name[0] != '/')
35 return 0;
36
37 DBG(DEBUG_SAVE,
38 printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
39
40 fprintf(file,
41 "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
42 (unsigned long) dev->bid_devno, dev->bid_time);
43 if (dev->bid_pri)
44 fprintf(file, " PRI=\"%d\"", dev->bid_pri);
45 list_for_each(p, &dev->bid_tags) {
46 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
47 fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
48 }
49 fprintf(file, ">%s</device>\n", dev->bid_name);
50
51 return 0;
52}
53
54/*
55 * Write out the cache struct to the cache file on disk.
56 */
57int blkid_flush_cache(blkid_cache cache)
58{
59 struct list_head *p;
60 char *tmp = NULL;
61 const char *opened = NULL;
62 const char *filename;
63 FILE *file = NULL;
64 int fd, ret = 0;
65 struct stat st;
66
67 if (!cache)
68 return -BLKID_ERR_PARAM;
69
70 if (list_empty(&cache->bic_devs) ||
71 !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
72 DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
73 return 0;
74 }
75
76 filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
77
78 /* If we can't write to the cache file, then don't even try */
79 if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
80 (ret == 0 && access(filename, W_OK) < 0)) {
81 DBG(DEBUG_SAVE,
82 printf("can't write to cache file %s\n", filename));
83 return 0;
84 }
85
86 /*
87 * Try and create a temporary file in the same directory so
88 * that in case of error we don't overwrite the cache file.
89 * If the cache file doesn't yet exist, it isn't a regular
90 * file (e.g. /dev/null or a socket), or we couldn't create
91 * a temporary file then we open it directly.
92 */
93 if (ret == 0 && S_ISREG(st.st_mode)) {
94 tmp = xmalloc(strlen(filename) + 8);
95 sprintf(tmp, "%s-XXXXXX", filename);
96 fd = mkstemp(tmp);
97 if (fd >= 0) {
98 file = fdopen(fd, "w");
99 opened = tmp;
100 }
101 fchmod(fd, 0644);
102 }
103
104 if (!file) {
105 file = fopen(filename, "w");
106 opened = filename;
107 }
108
109 DBG(DEBUG_SAVE,
110 printf("writing cache file %s (really %s)\n",
111 filename, opened));
112
113 if (!file) {
114 ret = errno;
115 goto errout;
116 }
117
118 list_for_each(p, &cache->bic_devs) {
119 blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
120 if (!dev->bid_type)
121 continue;
122 if ((ret = save_dev(dev, file)) < 0)
123 break;
124 }
125
126 if (ret >= 0) {
127 cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
128 ret = 1;
129 }
130
131 fclose(file);
132 if (opened != filename) {
133 if (ret < 0) {
134 unlink(opened);
135 DBG(DEBUG_SAVE,
136 printf("unlinked temp cache %s\n", opened));
137 } else {
138 char *backup;
139
140 backup = xmalloc(strlen(filename) + 5);
141 sprintf(backup, "%s.old", filename);
142 unlink(backup);
143 link(filename, backup);
144 free(backup);
145 rename(opened, filename);
146 DBG(DEBUG_SAVE,
147 printf("moved temp cache %s\n", opened));
148 }
149 }
150
151errout:
152 free(tmp);
153 return ret;
154}
155
156#ifdef TEST_PROGRAM
157int main(int argc, char **argv)
158{
159 blkid_cache cache = NULL;
160 int ret;
161
162 blkid_debug_mask = DEBUG_ALL;
163 if (argc > 2) {
164 fprintf(stderr, "Usage: %s [filename]\n"
165 "Test loading/saving a cache (filename)\n", argv[0]);
166 exit(1);
167 }
168
169 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
170 fprintf(stderr, "%s: error creating cache (%d)\n",
171 argv[0], ret);
172 exit(1);
173 }
174 if ((ret = blkid_probe_all(cache)) < 0) {
175 fprintf(stderr, "error (%d) probing devices\n", ret);
176 exit(1);
177 }
178 cache->bic_filename = blkid_strdup(argv[1]);
179
180 if ((ret = blkid_flush_cache(cache)) < 0) {
181 fprintf(stderr, "error (%d) saving cache\n", ret);
182 exit(1);
183 }
184
185 blkid_put_cache(cache);
186
187 return ret;
188}
189#endif
diff --git a/e2fsprogs/blkid/tag.c b/e2fsprogs/blkid/tag.c
deleted file mode 100644
index 9e862a50a..000000000
--- a/e2fsprogs/blkid/tag.c
+++ /dev/null
@@ -1,432 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * tag.c - allocation/initialization/free routines for tag structs
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <stdio.h>
17
18#include "blkidP.h"
19
20static blkid_tag blkid_new_tag(void)
21{
22 blkid_tag tag;
23
24 if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
25 return NULL;
26
27 INIT_LIST_HEAD(&tag->bit_tags);
28 INIT_LIST_HEAD(&tag->bit_names);
29
30 return tag;
31}
32
33#ifdef CONFIG_BLKID_DEBUG
34void blkid_debug_dump_tag(blkid_tag tag)
35{
36 if (!tag) {
37 printf(" tag: NULL\n");
38 return;
39 }
40
41 printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
42}
43#endif
44
45void blkid_free_tag(blkid_tag tag)
46{
47 if (!tag)
48 return;
49
50 DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
51 tag->bit_val ? tag->bit_val : "(NULL)"));
52 DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
53
54 list_del(&tag->bit_tags); /* list of tags for this device */
55 list_del(&tag->bit_names); /* list of tags with this type */
56
57 free(tag->bit_name);
58 free(tag->bit_val);
59 free(tag);
60}
61
62/*
63 * Find the desired tag on a device. If value is NULL, then the
64 * first such tag is returned, otherwise return only exact tag if found.
65 */
66blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
67{
68 struct list_head *p;
69
70 if (!dev || !type)
71 return NULL;
72
73 list_for_each(p, &dev->bid_tags) {
74 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
75 bit_tags);
76
77 if (!strcmp(tmp->bit_name, type))
78 return tmp;
79 }
80 return NULL;
81}
82
83/*
84 * Find the desired tag type in the cache.
85 * We return the head tag for this tag type.
86 */
87static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
88{
89 blkid_tag head = NULL, tmp;
90 struct list_head *p;
91
92 if (!cache || !type)
93 return NULL;
94
95 list_for_each(p, &cache->bic_tags) {
96 tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
97 if (!strcmp(tmp->bit_name, type)) {
98 DBG(DEBUG_TAG,
99 printf(" found cache tag head %s\n", type));
100 head = tmp;
101 break;
102 }
103 }
104 return head;
105}
106
107/*
108 * Set a tag on an existing device.
109 *
110 * If value is NULL, then delete the tagsfrom the device.
111 */
112int blkid_set_tag(blkid_dev dev, const char *name,
113 const char *value, const int vlength)
114{
115 blkid_tag t = 0, head = 0;
116 char *val = 0;
117
118 if (!dev || !name)
119 return -BLKID_ERR_PARAM;
120
121 if (!(val = blkid_strndup(value, vlength)) && value)
122 return -BLKID_ERR_MEM;
123 t = blkid_find_tag_dev(dev, name);
124 if (!value) {
125 blkid_free_tag(t);
126 } else if (t) {
127 if (!strcmp(t->bit_val, val)) {
128 /* Same thing, exit */
129 free(val);
130 return 0;
131 }
132 free(t->bit_val);
133 t->bit_val = val;
134 } else {
135 /* Existing tag not present, add to device */
136 if (!(t = blkid_new_tag()))
137 goto errout;
138 t->bit_name = blkid_strdup(name);
139 t->bit_val = val;
140 t->bit_dev = dev;
141
142 list_add_tail(&t->bit_tags, &dev->bid_tags);
143
144 if (dev->bid_cache) {
145 head = blkid_find_head_cache(dev->bid_cache,
146 t->bit_name);
147 if (!head) {
148 head = blkid_new_tag();
149 if (!head)
150 goto errout;
151
152 DBG(DEBUG_TAG,
153 printf(" creating new cache tag head %s\n", name));
154 head->bit_name = blkid_strdup(name);
155 if (!head->bit_name)
156 goto errout;
157 list_add_tail(&head->bit_tags,
158 &dev->bid_cache->bic_tags);
159 }
160 list_add_tail(&t->bit_names, &head->bit_names);
161 }
162 }
163
164 /* Link common tags directly to the device struct */
165 if (!strcmp(name, "TYPE"))
166 dev->bid_type = val;
167 else if (!strcmp(name, "LABEL"))
168 dev->bid_label = val;
169 else if (!strcmp(name, "UUID"))
170 dev->bid_uuid = val;
171
172 if (dev->bid_cache)
173 dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
174 return 0;
175
176errout:
177 blkid_free_tag(t);
178 if (!t)
179 free(val);
180 blkid_free_tag(head);
181 return -BLKID_ERR_MEM;
182}
183
184
185/*
186 * Parse a "NAME=value" string. This is slightly different than
187 * parse_token, because that will end an unquoted value at a space, while
188 * this will assume that an unquoted value is the rest of the token (e.g.
189 * if we are passed an already quoted string from the command-line we don't
190 * have to both quote and escape quote so that the quotes make it to
191 * us).
192 *
193 * Returns 0 on success, and -1 on failure.
194 */
195int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
196{
197 char *name, *value, *cp;
198
199 DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
200
201 if (!token || !(cp = strchr(token, '=')))
202 return -1;
203
204 name = blkid_strdup(token);
205 if (!name)
206 return -1;
207 value = name + (cp - token);
208 *value++ = '\0';
209 if (*value == '"' || *value == '\'') {
210 char c = *value++;
211 if (!(cp = strrchr(value, c)))
212 goto errout; /* missing closing quote */
213 *cp = '\0';
214 }
215 value = blkid_strdup(value);
216 if (!value)
217 goto errout;
218
219 *ret_type = name;
220 *ret_val = value;
221
222 return 0;
223
224errout:
225 free(name);
226 return -1;
227}
228
229/*
230 * Tag iteration routines for the public libblkid interface.
231 *
232 * These routines do not expose the list.h implementation, which are a
233 * contamination of the namespace, and which force us to reveal far, far
234 * too much of our internal implemenation. I'm not convinced I want
235 * to keep list.h in the long term, anyway. It's fine for kernel
236 * programming, but performance is not the #1 priority for this
237 * library, and I really don't like the tradeoff of type-safety for
238 * performance for this application. [tytso:20030125.2007EST]
239 */
240
241/*
242 * This series of functions iterate over all tags in a device
243 */
244#define TAG_ITERATE_MAGIC 0x01a5284c
245
246struct blkid_struct_tag_iterate {
247 int magic;
248 blkid_dev dev;
249 struct list_head *p;
250};
251
252blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
253{
254 blkid_tag_iterate iter;
255
256 iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
257 iter->magic = TAG_ITERATE_MAGIC;
258 iter->dev = dev;
259 iter->p = dev->bid_tags.next;
260 return iter;
261}
262
263/*
264 * Return 0 on success, -1 on error
265 */
266extern int blkid_tag_next(blkid_tag_iterate iter,
267 const char **type, const char **value)
268{
269 blkid_tag tag;
270
271 *type = 0;
272 *value = 0;
273 if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
274 iter->p == &iter->dev->bid_tags)
275 return -1;
276 tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
277 *type = tag->bit_name;
278 *value = tag->bit_val;
279 iter->p = iter->p->next;
280 return 0;
281}
282
283void blkid_tag_iterate_end(blkid_tag_iterate iter)
284{
285 if (!iter || iter->magic != TAG_ITERATE_MAGIC)
286 return;
287 iter->magic = 0;
288 free(iter);
289}
290
291/*
292 * This function returns a device which matches a particular
293 * type/value pair. If there is more than one device that matches the
294 * search specification, it returns the one with the highest priority
295 * value. This allows us to give preference to EVMS or LVM devices.
296 *
297 * XXX there should also be an interface which uses an iterator so we
298 * can get all of the devices which match a type/value search parameter.
299 */
300extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
301 const char *type,
302 const char *value)
303{
304 blkid_tag head;
305 blkid_dev dev;
306 int pri;
307 struct list_head *p;
308
309 if (!cache || !type || !value)
310 return NULL;
311
312 blkid_read_cache(cache);
313
314 DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
315
316try_again:
317 pri = -1;
318 dev = 0;
319 head = blkid_find_head_cache(cache, type);
320
321 if (head) {
322 list_for_each(p, &head->bit_names) {
323 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
324 bit_names);
325
326 if (!strcmp(tmp->bit_val, value) &&
327 tmp->bit_dev->bid_pri > pri) {
328 dev = tmp->bit_dev;
329 pri = dev->bid_pri;
330 }
331 }
332 }
333 if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
334 dev = blkid_verify(cache, dev);
335 if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
336 goto try_again;
337 }
338
339 if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
340 if (blkid_probe_all(cache) < 0)
341 return NULL;
342 goto try_again;
343 }
344 return dev;
345}
346
347#ifdef TEST_PROGRAM
348#ifdef HAVE_GETOPT_H
349#include <getopt.h>
350#else
351extern char *optarg;
352extern int optind;
353#endif
354
355void usage(char *prog)
356{
357 fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
358 "[type value]\n",
359 prog);
360 fprintf(stderr, "\tList all tags for a device and exit\n", prog);
361 exit(1);
362}
363
364int main(int argc, char **argv)
365{
366 blkid_tag_iterate iter;
367 blkid_cache cache = NULL;
368 blkid_dev dev;
369 int c, ret, found;
370 int flags = BLKID_DEV_FIND;
371 char *tmp;
372 char *file = NULL;
373 char *devname = NULL;
374 char *search_type = NULL;
375 char *search_value = NULL;
376 const char *type, *value;
377
378 while ((c = getopt (argc, argv, "m:f:")) != EOF)
379 switch (c) {
380 case 'f':
381 file = optarg;
382 break;
383 case 'm':
384 blkid_debug_mask = strtoul (optarg, &tmp, 0);
385 if (*tmp) {
386 fprintf(stderr, "Invalid debug mask: %d\n",
387 optarg);
388 exit(1);
389 }
390 break;
391 case '?':
392 usage(argv[0]);
393 }
394 if (argc > optind)
395 devname = argv[optind++];
396 if (argc > optind)
397 search_type = argv[optind++];
398 if (argc > optind)
399 search_value = argv[optind++];
400 if (!devname || (argc != optind))
401 usage(argv[0]);
402
403 if ((ret = blkid_get_cache(&cache, file)) != 0) {
404 fprintf(stderr, "%s: error creating cache (%d)\n",
405 argv[0], ret);
406 exit(1);
407 }
408
409 dev = blkid_get_dev(cache, devname, flags);
410 if (!dev) {
411 fprintf(stderr, "%s: cannot find device in blkid cache\n");
412 exit(1);
413 }
414 if (search_type) {
415 found = blkid_dev_has_tag(dev, search_type, search_value);
416 printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
417 search_type, search_value ? search_value : "NULL",
418 found ? "FOUND" : "NOT FOUND");
419 return !found;
420 }
421 printf("Device %s...\n", blkid_dev_devname(dev));
422
423 iter = blkid_tag_iterate_begin(dev);
424 while (blkid_tag_next(iter, &type, &value) == 0) {
425 printf("\tTag %s has value %s\n", type, value);
426 }
427 blkid_tag_iterate_end(iter);
428
429 blkid_put_cache(cache);
430 return 0;
431}
432#endif