diff options
author | Mike Frysinger <vapier@gentoo.org> | 2005-05-09 22:13:22 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2005-05-09 22:13:22 +0000 |
commit | 38a33f91c0a46f51d07900731245492a3b244ae4 (patch) | |
tree | b86c6e23c1baa56577715cdeef6551d10a4ead2c | |
parent | 1fd98e039d146dcff02a5350f509cabca65fd29c (diff) | |
download | busybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.tar.gz busybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.tar.bz2 busybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.zip |
import more libs to prep for new e2fsprogs
30 files changed, 5277 insertions, 0 deletions
diff --git a/e2fsprogs/blkid/blkid.h b/e2fsprogs/blkid/blkid.h new file mode 100644 index 000000000..3ea94ac80 --- /dev/null +++ b/e2fsprogs/blkid/blkid.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * blkid.h - Interface for libblkid, a library to identify block devices | ||
3 | * | ||
4 | * Copyright (C) 2001 Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #ifndef _BLKID_BLKID_H | ||
14 | #define _BLKID_BLKID_H | ||
15 | |||
16 | #include <sys/types.h> | ||
17 | #include <linux/types.h> | ||
18 | |||
19 | #ifdef __cplusplus | ||
20 | extern "C" { | ||
21 | #endif | ||
22 | |||
23 | #define BLKID_VERSION "1.0.0" | ||
24 | #define BLKID_DATE "12-Feb-2003" | ||
25 | |||
26 | typedef struct blkid_struct_dev *blkid_dev; | ||
27 | typedef struct blkid_struct_cache *blkid_cache; | ||
28 | typedef __s64 blkid_loff_t; | ||
29 | |||
30 | typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; | ||
31 | typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; | ||
32 | |||
33 | /* | ||
34 | * Flags for blkid_get_dev | ||
35 | * | ||
36 | * BLKID_DEV_CREATE Create an empty device structure if not found | ||
37 | * in the cache. | ||
38 | * BLKID_DEV_VERIFY Make sure the device structure corresponds | ||
39 | * with reality. | ||
40 | * BLKID_DEV_FIND Just look up a device entry, and return NULL | ||
41 | * if it is not found. | ||
42 | * BLKID_DEV_NORMAL Get a valid device structure, either from the | ||
43 | * cache or by probing the device. | ||
44 | */ | ||
45 | #define BLKID_DEV_FIND 0x0000 | ||
46 | #define BLKID_DEV_CREATE 0x0001 | ||
47 | #define BLKID_DEV_VERIFY 0x0002 | ||
48 | #define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) | ||
49 | |||
50 | /* cache.c */ | ||
51 | extern void blkid_put_cache(blkid_cache cache); | ||
52 | extern int blkid_get_cache(blkid_cache *cache, const char *filename); | ||
53 | |||
54 | /* dev.c */ | ||
55 | extern const char *blkid_dev_devname(blkid_dev dev); | ||
56 | |||
57 | extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); | ||
58 | extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); | ||
59 | extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); | ||
60 | |||
61 | /* devno.c */ | ||
62 | extern char *blkid_devno_to_devname(dev_t devno); | ||
63 | |||
64 | /* devname.c */ | ||
65 | extern int blkid_probe_all(blkid_cache cache); | ||
66 | extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, | ||
67 | int flags); | ||
68 | |||
69 | /* getsize.c */ | ||
70 | extern blkid_loff_t blkid_get_dev_size(int fd); | ||
71 | |||
72 | /* probe.c */ | ||
73 | int blkid_known_fstype(const char *fstype); | ||
74 | extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev); | ||
75 | |||
76 | /* read.c */ | ||
77 | |||
78 | /* resolve.c */ | ||
79 | extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname, | ||
80 | const char *devname); | ||
81 | extern char *blkid_get_devname(blkid_cache cache, const char *token, | ||
82 | const char *value); | ||
83 | |||
84 | /* tag.c */ | ||
85 | extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); | ||
86 | extern int blkid_tag_next(blkid_tag_iterate iterate, | ||
87 | const char **type, const char **value); | ||
88 | extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); | ||
89 | |||
90 | extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, | ||
91 | const char *type, | ||
92 | const char *value); | ||
93 | extern int blkid_parse_tag_string(const char *token, char **ret_type, | ||
94 | char **ret_val); | ||
95 | |||
96 | /* version.c */ | ||
97 | extern int blkid_parse_version_string(const char *ver_string); | ||
98 | extern int blkid_get_library_version(const char **ver_string, | ||
99 | const char **date_string); | ||
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 new file mode 100644 index 000000000..1bb94907e --- /dev/null +++ b/e2fsprogs/blkid/blkidP.h | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * blkidP.h - Internal interfaces for libblkid | ||
3 | * | ||
4 | * Copyright (C) 2001 Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #ifndef _BLKID_BLKIDP_H | ||
14 | #define _BLKID_BLKIDP_H | ||
15 | |||
16 | #include <sys/types.h> | ||
17 | #include <stdio.h> | ||
18 | |||
19 | #include <blkid/blkid.h> | ||
20 | |||
21 | #include <blkid/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 | */ | ||
36 | struct 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 | */ | ||
61 | struct 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 | }; | ||
69 | typedef 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 | */ | ||
91 | struct 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 | |||
104 | extern char *blkid_strdup(const char *s); | ||
105 | extern char *blkid_strndup(const char *s, const int length); | ||
106 | |||
107 | #define BLKID_CACHE_FILE "/etc/blkid.tab" | ||
108 | extern 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> | ||
144 | extern 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 | ||
151 | static inline void DEB_DUMP_TAG(int mask, blkid_tag tag) | ||
152 | { | ||
153 | if (!(mask & blkid_debug_mask)) | ||
154 | return; | ||
155 | |||
156 | if (!tag) { | ||
157 | printf(" tag: NULL\n"); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val); | ||
162 | } | ||
163 | |||
164 | static inline void DEB_DUMP_DEV(int mask, blkid_dev dev) | ||
165 | { | ||
166 | struct list_head *p; | ||
167 | |||
168 | if (!(mask & blkid_debug_mask)) | ||
169 | return; | ||
170 | |||
171 | if (!dev) { | ||
172 | printf(" dev: NULL\n"); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | printf(" dev: name = %s\n", dev->bid_name); | ||
177 | printf(" dev: DEVNO=\"0x%0Lx\"\n", dev->bid_devno); | ||
178 | printf(" dev: TIME=\"%lu\"\n", dev->bid_time); | ||
179 | printf(" dev: PRI=\"%d\"\n", dev->bid_pri); | ||
180 | printf(" dev: flags = 0x%08X\n", dev->bid_flags); | ||
181 | |||
182 | list_for_each(p, &dev->bid_tags) { | ||
183 | blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); | ||
184 | DEB_DUMP_TAG(mask, tag); | ||
185 | } | ||
186 | printf("\n"); | ||
187 | } | ||
188 | |||
189 | static inline void DEB_DUMP_CACHE(int mask, blkid_cache cache) | ||
190 | { | ||
191 | struct list_head *p; | ||
192 | |||
193 | if (!cache || !(mask & blkid_debug_mask)) { | ||
194 | printf("cache: NULL\n"); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | printf("cache: time = %lu\n", cache->bic_time); | ||
199 | printf("cache: flags = 0x%08X\n", cache->bic_flags); | ||
200 | |||
201 | list_for_each(p, &cache->bic_devs) { | ||
202 | blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); | ||
203 | DEB_DUMP_DEV(mask, dev); | ||
204 | } | ||
205 | } | ||
206 | #else | ||
207 | #define DEB_DUMP_TAG(mask, tag) do {} while (0) | ||
208 | #define DEB_DUMP_DEV(mask, dev) do {} while (0) | ||
209 | #define DEB_DUMP_CACHE(mask, cache) do {} while (0) | ||
210 | #endif | ||
211 | |||
212 | /* lseek.c */ | ||
213 | extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); | ||
214 | |||
215 | /* read.c */ | ||
216 | extern void blkid_read_cache(blkid_cache cache); | ||
217 | |||
218 | /* save.c */ | ||
219 | extern int blkid_flush_cache(blkid_cache cache); | ||
220 | |||
221 | /* | ||
222 | * Functions to create and find a specific tag type: tag.c | ||
223 | */ | ||
224 | extern void blkid_free_tag(blkid_tag tag); | ||
225 | extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); | ||
226 | extern int blkid_set_tag(blkid_dev dev, const char *name, | ||
227 | const char *value, const int vlength); | ||
228 | |||
229 | /* | ||
230 | * Functions to create and find a specific tag type: dev.c | ||
231 | */ | ||
232 | extern blkid_dev blkid_new_dev(void); | ||
233 | extern void blkid_free_dev(blkid_dev dev); | ||
234 | |||
235 | #ifdef __cplusplus | ||
236 | } | ||
237 | #endif | ||
238 | |||
239 | #endif /* _BLKID_BLKIDP_H */ | ||
diff --git a/e2fsprogs/blkid/cache.c b/e2fsprogs/blkid/cache.c new file mode 100644 index 000000000..88cc326cc --- /dev/null +++ b/e2fsprogs/blkid/cache.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * cache.c - allocation/initialization/free routines for cache | ||
3 | * | ||
4 | * Copyright (C) 2001 Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include "blkidP.h" | ||
17 | |||
18 | int blkid_debug_mask = 0; | ||
19 | |||
20 | int blkid_get_cache(blkid_cache *ret_cache, const char *filename) | ||
21 | { | ||
22 | blkid_cache cache; | ||
23 | |||
24 | #ifdef CONFIG_BLKID_DEBUG | ||
25 | if (!(blkid_debug_mask & DEBUG_INIT)) { | ||
26 | char *dstr = getenv("BLKID_DEBUG"); | ||
27 | |||
28 | if (dstr) | ||
29 | blkid_debug_mask = strtoul(dstr, 0, 0); | ||
30 | blkid_debug_mask |= DEBUG_INIT; | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", | ||
35 | filename ? filename : "default cache")); | ||
36 | |||
37 | if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache)))) | ||
38 | return -BLKID_ERR_MEM; | ||
39 | |||
40 | INIT_LIST_HEAD(&cache->bic_devs); | ||
41 | INIT_LIST_HEAD(&cache->bic_tags); | ||
42 | |||
43 | if (filename && !strlen(filename)) | ||
44 | filename = 0; | ||
45 | if (!filename && (getuid() == geteuid())) | ||
46 | filename = getenv("BLKID_FILE"); | ||
47 | if (!filename) | ||
48 | filename = BLKID_CACHE_FILE; | ||
49 | cache->bic_filename = blkid_strdup(filename); | ||
50 | |||
51 | blkid_read_cache(cache); | ||
52 | |||
53 | *ret_cache = cache; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | void blkid_put_cache(blkid_cache cache) | ||
58 | { | ||
59 | if (!cache) | ||
60 | return; | ||
61 | |||
62 | (void) blkid_flush_cache(cache); | ||
63 | |||
64 | DBG(DEBUG_CACHE, printf("freeing cache struct\n")); | ||
65 | |||
66 | /* DEB_DUMP_CACHE(cache); */ | ||
67 | |||
68 | while (!list_empty(&cache->bic_devs)) { | ||
69 | blkid_dev dev = list_entry(cache->bic_devs.next, | ||
70 | struct blkid_struct_dev, | ||
71 | bid_devs); | ||
72 | blkid_free_dev(dev); | ||
73 | } | ||
74 | |||
75 | while (!list_empty(&cache->bic_tags)) { | ||
76 | blkid_tag tag = list_entry(cache->bic_tags.next, | ||
77 | struct blkid_struct_tag, | ||
78 | bit_tags); | ||
79 | |||
80 | while (!list_empty(&tag->bit_names)) { | ||
81 | blkid_tag bad = list_entry(tag->bit_names.next, | ||
82 | struct blkid_struct_tag, | ||
83 | bit_names); | ||
84 | |||
85 | DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", | ||
86 | bad->bit_name, bad->bit_val)); | ||
87 | blkid_free_tag(bad); | ||
88 | } | ||
89 | blkid_free_tag(tag); | ||
90 | } | ||
91 | if (cache->bic_filename) | ||
92 | free(cache->bic_filename); | ||
93 | |||
94 | free(cache); | ||
95 | } | ||
96 | |||
97 | #ifdef TEST_PROGRAM | ||
98 | int 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, "/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 new file mode 100644 index 000000000..23af8878d --- /dev/null +++ b/e2fsprogs/blkid/dev.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * dev.c - allocation/initialization/free routines for dev | ||
3 | * | ||
4 | * Copyright (C) 2001 Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | |||
16 | #include "blkidP.h" | ||
17 | |||
18 | blkid_dev blkid_new_dev(void) | ||
19 | { | ||
20 | blkid_dev dev; | ||
21 | |||
22 | if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev)))) | ||
23 | return NULL; | ||
24 | |||
25 | INIT_LIST_HEAD(&dev->bid_devs); | ||
26 | INIT_LIST_HEAD(&dev->bid_tags); | ||
27 | |||
28 | return dev; | ||
29 | } | ||
30 | |||
31 | void blkid_free_dev(blkid_dev dev) | ||
32 | { | ||
33 | if (!dev) | ||
34 | return; | ||
35 | |||
36 | DBG(DEBUG_DEV, | ||
37 | printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type)); | ||
38 | DEB_DUMP_DEV(DEBUG_DEV, dev); | ||
39 | |||
40 | list_del(&dev->bid_devs); | ||
41 | while (!list_empty(&dev->bid_tags)) { | ||
42 | blkid_tag tag = list_entry(dev->bid_tags.next, | ||
43 | struct blkid_struct_tag, | ||
44 | bit_tags); | ||
45 | blkid_free_tag(tag); | ||
46 | } | ||
47 | if (dev->bid_name) | ||
48 | free(dev->bid_name); | ||
49 | free(dev); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Given a blkid device, return its name | ||
54 | */ | ||
55 | extern const char *blkid_dev_devname(blkid_dev dev) | ||
56 | { | ||
57 | return dev->bid_name; | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * dev iteration routines for the public libblkid interface. | ||
62 | * | ||
63 | * These routines do not expose the list.h implementation, which are a | ||
64 | * contamination of the namespace, and which force us to reveal far, far | ||
65 | * too much of our internal implemenation. I'm not convinced I want | ||
66 | * to keep list.h in the long term, anyway. It's fine for kernel | ||
67 | * programming, but performance is not the #1 priority for this | ||
68 | * library, and I really don't like the tradeoff of type-safety for | ||
69 | * performance for this application. [tytso:20030125.2007EST] | ||
70 | */ | ||
71 | |||
72 | /* | ||
73 | * This series of functions iterate over all devices in a blkid cache | ||
74 | */ | ||
75 | #define DEV_ITERATE_MAGIC 0x01a5284c | ||
76 | |||
77 | struct blkid_struct_dev_iterate { | ||
78 | int magic; | ||
79 | blkid_cache cache; | ||
80 | struct list_head *p; | ||
81 | }; | ||
82 | |||
83 | extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) | ||
84 | { | ||
85 | blkid_dev_iterate iter; | ||
86 | |||
87 | iter = malloc(sizeof(struct blkid_struct_dev_iterate)); | ||
88 | if (iter) { | ||
89 | iter->magic = DEV_ITERATE_MAGIC; | ||
90 | iter->cache = cache; | ||
91 | iter->p = cache->bic_devs.next; | ||
92 | } | ||
93 | return (iter); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Return 0 on success, -1 on error | ||
98 | */ | ||
99 | extern int blkid_dev_next(blkid_dev_iterate iter, | ||
100 | blkid_dev *dev) | ||
101 | { | ||
102 | *dev = 0; | ||
103 | if (!iter || iter->magic != DEV_ITERATE_MAGIC || | ||
104 | iter->p == &iter->cache->bic_devs) | ||
105 | return -1; | ||
106 | *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); | ||
107 | iter->p = iter->p->next; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | extern void blkid_dev_iterate_end(blkid_dev_iterate iter) | ||
112 | { | ||
113 | if (!iter || iter->magic != DEV_ITERATE_MAGIC) | ||
114 | return; | ||
115 | iter->magic = 0; | ||
116 | free(iter); | ||
117 | } | ||
118 | |||
diff --git a/e2fsprogs/blkid/devname.c b/e2fsprogs/blkid/devname.c new file mode 100644 index 000000000..87d5cbef3 --- /dev/null +++ b/e2fsprogs/blkid/devname.c | |||
@@ -0,0 +1,376 @@ | |||
1 | /* | ||
2 | * devname.c - get a dev by its device inode name | ||
3 | * | ||
4 | * Copyright (C) Andries Brouwer | ||
5 | * Copyright (C) 1999, 2000, 2001, 2002, 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 | #if HAVE_UNISTD_H | ||
17 | #include <unistd.h> | ||
18 | #endif | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | #include <ctype.h> | ||
22 | #if HAVE_SYS_TYPES_H | ||
23 | #include <sys/types.h> | ||
24 | #endif | ||
25 | #if HAVE_SYS_STAT_H | ||
26 | #include <sys/stat.h> | ||
27 | #endif | ||
28 | #if HAVE_ERRNO_H | ||
29 | #include <errno.h> | ||
30 | #endif | ||
31 | #if HAVE_SYS_MKDEV_H | ||
32 | #include <sys/mkdev.h> | ||
33 | #endif | ||
34 | #include <time.h> | ||
35 | |||
36 | #include "blkidP.h" | ||
37 | |||
38 | /* | ||
39 | * Find a dev struct in the cache by device name, if available. | ||
40 | * | ||
41 | * If there is no entry with the specified device name, and the create | ||
42 | * flag is set, then create an empty device entry. | ||
43 | */ | ||
44 | blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) | ||
45 | { | ||
46 | blkid_dev dev = NULL, tmp; | ||
47 | struct list_head *p; | ||
48 | |||
49 | if (!cache || !devname) | ||
50 | return NULL; | ||
51 | |||
52 | list_for_each(p, &cache->bic_devs) { | ||
53 | tmp = list_entry(p, struct blkid_struct_dev, bid_devs); | ||
54 | if (strcmp(tmp->bid_name, devname)) | ||
55 | continue; | ||
56 | |||
57 | DBG(DEBUG_DEVNAME, | ||
58 | printf("found devname %s in cache\n", tmp->bid_name)); | ||
59 | dev = tmp; | ||
60 | break; | ||
61 | } | ||
62 | |||
63 | if (!dev && (flags & BLKID_DEV_CREATE)) { | ||
64 | dev = blkid_new_dev(); | ||
65 | if (!dev) | ||
66 | return NULL; | ||
67 | dev->bid_name = blkid_strdup(devname); | ||
68 | dev->bid_cache = cache; | ||
69 | list_add_tail(&dev->bid_devs, &cache->bic_devs); | ||
70 | cache->bic_flags |= BLKID_BIC_FL_CHANGED; | ||
71 | } | ||
72 | |||
73 | if (flags & BLKID_DEV_VERIFY) | ||
74 | dev = blkid_verify(cache, dev); | ||
75 | return dev; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Probe a single block device to add to the device cache. | ||
80 | */ | ||
81 | static void probe_one(blkid_cache cache, const char *ptname, | ||
82 | dev_t devno, int pri) | ||
83 | { | ||
84 | blkid_dev dev = NULL; | ||
85 | struct list_head *p; | ||
86 | const char **dir; | ||
87 | char *devname = NULL; | ||
88 | |||
89 | /* See if we already have this device number in the cache. */ | ||
90 | list_for_each(p, &cache->bic_devs) { | ||
91 | blkid_dev tmp = list_entry(p, struct blkid_struct_dev, | ||
92 | bid_devs); | ||
93 | if (tmp->bid_devno == devno) { | ||
94 | dev = blkid_verify(cache, tmp); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | if (dev && dev->bid_devno == devno) | ||
99 | goto set_pri; | ||
100 | |||
101 | /* | ||
102 | * Take a quick look at /dev/ptname for the device number. We check | ||
103 | * all of the likely device directories. If we don't find it, or if | ||
104 | * the stat information doesn't check out, use blkid_devno_to_devname() | ||
105 | * to find it via an exhaustive search for the device major/minor. | ||
106 | */ | ||
107 | for (dir = blkid_devdirs; *dir; dir++) { | ||
108 | struct stat st; | ||
109 | char device[256]; | ||
110 | |||
111 | sprintf(device, "%s/%s", *dir, ptname); | ||
112 | if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && | ||
113 | dev->bid_devno == devno) | ||
114 | goto set_pri; | ||
115 | |||
116 | if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && | ||
117 | st.st_rdev == devno) { | ||
118 | devname = blkid_strdup(device); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | if (!devname) { | ||
123 | devname = blkid_devno_to_devname(devno); | ||
124 | if (!devname) | ||
125 | return; | ||
126 | } | ||
127 | dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); | ||
128 | free(devname); | ||
129 | |||
130 | set_pri: | ||
131 | if (!pri && !strncmp(ptname, "md", 2)) | ||
132 | pri = BLKID_PRI_MD; | ||
133 | if (dev) | ||
134 | dev->bid_pri = pri; | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | #define PROC_PARTITIONS "/proc/partitions" | ||
139 | #define VG_DIR "/proc/lvm/VGs" | ||
140 | |||
141 | /* | ||
142 | * This function initializes the UUID cache with devices from the LVM | ||
143 | * proc hierarchy. We currently depend on the names of the LVM | ||
144 | * hierarchy giving us the device structure in /dev. (XXX is this a | ||
145 | * safe thing to do?) | ||
146 | */ | ||
147 | #ifdef VG_DIR | ||
148 | #include <dirent.h> | ||
149 | static dev_t lvm_get_devno(const char *lvm_device) | ||
150 | { | ||
151 | FILE *lvf; | ||
152 | char buf[1024]; | ||
153 | int ma, mi; | ||
154 | dev_t ret = 0; | ||
155 | |||
156 | DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); | ||
157 | if ((lvf = fopen(lvm_device, "r")) == NULL) { | ||
158 | DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, | ||
159 | strerror(errno))); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | while (fgets(buf, sizeof(buf), lvf)) { | ||
164 | if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { | ||
165 | ret = makedev(ma, mi); | ||
166 | break; | ||
167 | } | ||
168 | } | ||
169 | fclose(lvf); | ||
170 | |||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static void lvm_probe_all(blkid_cache cache) | ||
175 | { | ||
176 | DIR *vg_list; | ||
177 | struct dirent *vg_iter; | ||
178 | int vg_len = strlen(VG_DIR); | ||
179 | dev_t dev; | ||
180 | |||
181 | if ((vg_list = opendir(VG_DIR)) == NULL) | ||
182 | return; | ||
183 | |||
184 | DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); | ||
185 | |||
186 | while ((vg_iter = readdir(vg_list)) != NULL) { | ||
187 | DIR *lv_list; | ||
188 | char *vdirname; | ||
189 | char *vg_name; | ||
190 | struct dirent *lv_iter; | ||
191 | |||
192 | vg_name = vg_iter->d_name; | ||
193 | if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) | ||
194 | continue; | ||
195 | vdirname = malloc(vg_len + strlen(vg_name) + 8); | ||
196 | if (!vdirname) | ||
197 | goto exit; | ||
198 | sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); | ||
199 | |||
200 | lv_list = opendir(vdirname); | ||
201 | free(vdirname); | ||
202 | if (lv_list == NULL) | ||
203 | continue; | ||
204 | |||
205 | while ((lv_iter = readdir(lv_list)) != NULL) { | ||
206 | char *lv_name, *lvm_device; | ||
207 | |||
208 | lv_name = lv_iter->d_name; | ||
209 | if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) | ||
210 | continue; | ||
211 | |||
212 | lvm_device = malloc(vg_len + strlen(vg_name) + | ||
213 | strlen(lv_name) + 8); | ||
214 | if (!lvm_device) { | ||
215 | closedir(lv_list); | ||
216 | goto exit; | ||
217 | } | ||
218 | sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, | ||
219 | lv_name); | ||
220 | dev = lvm_get_devno(lvm_device); | ||
221 | sprintf(lvm_device, "%s/%s", vg_name, lv_name); | ||
222 | DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", | ||
223 | lvm_device, | ||
224 | (unsigned int) dev)); | ||
225 | probe_one(cache, lvm_device, dev, BLKID_PRI_LVM); | ||
226 | free(lvm_device); | ||
227 | } | ||
228 | closedir(lv_list); | ||
229 | } | ||
230 | exit: | ||
231 | closedir(vg_list); | ||
232 | } | ||
233 | #endif | ||
234 | |||
235 | #define PROC_EVMS_VOLUMES "/proc/evms/volumes" | ||
236 | |||
237 | static int | ||
238 | evms_probe_all(blkid_cache cache) | ||
239 | { | ||
240 | char line[100]; | ||
241 | int ma, mi, sz, num = 0; | ||
242 | FILE *procpt; | ||
243 | char device[110]; | ||
244 | |||
245 | procpt = fopen(PROC_EVMS_VOLUMES, "r"); | ||
246 | if (!procpt) | ||
247 | return 0; | ||
248 | while (fgets(line, sizeof(line), procpt)) { | ||
249 | if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", | ||
250 | &ma, &mi, &sz, device) != 4) | ||
251 | continue; | ||
252 | |||
253 | DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", | ||
254 | device, ma, mi)); | ||
255 | |||
256 | probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS); | ||
257 | num++; | ||
258 | } | ||
259 | fclose(procpt); | ||
260 | return num; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Read the device data for all available block devices in the system. | ||
265 | */ | ||
266 | int blkid_probe_all(blkid_cache cache) | ||
267 | { | ||
268 | FILE *proc; | ||
269 | char line[1024]; | ||
270 | char ptname0[128], ptname1[128], *ptname = 0; | ||
271 | char *ptnames[2]; | ||
272 | dev_t devs[2]; | ||
273 | int ma, mi; | ||
274 | unsigned long long sz; | ||
275 | int lens[2] = { 0, 0 }; | ||
276 | int which = 0, last = 0; | ||
277 | |||
278 | ptnames[0] = ptname0; | ||
279 | ptnames[1] = ptname1; | ||
280 | |||
281 | if (!cache) | ||
282 | return -BLKID_ERR_PARAM; | ||
283 | |||
284 | if (cache->bic_flags & BLKID_BIC_FL_PROBED && | ||
285 | time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) | ||
286 | return 0; | ||
287 | |||
288 | blkid_read_cache(cache); | ||
289 | evms_probe_all(cache); | ||
290 | #ifdef VG_DIR | ||
291 | lvm_probe_all(cache); | ||
292 | #endif | ||
293 | |||
294 | proc = fopen(PROC_PARTITIONS, "r"); | ||
295 | if (!proc) | ||
296 | return -BLKID_ERR_PROC; | ||
297 | |||
298 | while (fgets(line, sizeof(line), proc)) { | ||
299 | last = which; | ||
300 | which ^= 1; | ||
301 | ptname = ptnames[which]; | ||
302 | |||
303 | if (sscanf(line, " %d %d %llu %128[^\n ]", | ||
304 | &ma, &mi, &sz, ptname) != 4) | ||
305 | continue; | ||
306 | devs[which] = makedev(ma, mi); | ||
307 | |||
308 | DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); | ||
309 | |||
310 | /* Skip whole disk devs unless they have no partitions | ||
311 | * If we don't have a partition on this dev, also | ||
312 | * check previous dev to see if it didn't have a partn. | ||
313 | * heuristic: partition name ends in a digit. | ||
314 | * | ||
315 | * Skip extended partitions. | ||
316 | * heuristic: size is 1 | ||
317 | * | ||
318 | * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs | ||
319 | */ | ||
320 | |||
321 | lens[which] = strlen(ptname); | ||
322 | if (isdigit(ptname[lens[which] - 1])) { | ||
323 | DBG(DEBUG_DEVNAME, | ||
324 | printf("partition dev %s, devno 0x%04X\n", | ||
325 | ptname, (unsigned int) devs[which])); | ||
326 | |||
327 | if (sz > 1) | ||
328 | probe_one(cache, ptname, devs[which], 0); | ||
329 | lens[which] = 0; | ||
330 | lens[last] = 0; | ||
331 | } else if (lens[last] && strncmp(ptnames[last], ptname, | ||
332 | lens[last])) { | ||
333 | DBG(DEBUG_DEVNAME, | ||
334 | printf("whole dev %s, devno 0x%04X\n", | ||
335 | ptnames[last], (unsigned int) devs[last])); | ||
336 | probe_one(cache, ptnames[last], devs[last], 0); | ||
337 | lens[last] = 0; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* Handle the last device if it wasn't partitioned */ | ||
342 | if (lens[which]) | ||
343 | probe_one(cache, ptname, devs[which], 0); | ||
344 | |||
345 | fclose(proc); | ||
346 | |||
347 | cache->bic_time = time(0); | ||
348 | cache->bic_flags |= BLKID_BIC_FL_PROBED; | ||
349 | blkid_flush_cache(cache); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | #ifdef TEST_PROGRAM | ||
354 | int main(int argc, char **argv) | ||
355 | { | ||
356 | blkid_cache cache = NULL; | ||
357 | int ret; | ||
358 | |||
359 | blkid_debug_mask = DEBUG_ALL; | ||
360 | if (argc != 1) { | ||
361 | fprintf(stderr, "Usage: %s\n" | ||
362 | "Probe all devices and exit\n", argv[0]); | ||
363 | exit(1); | ||
364 | } | ||
365 | if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | ||
366 | fprintf(stderr, "%s: error creating cache (%d)\n", | ||
367 | argv[0], ret); | ||
368 | exit(1); | ||
369 | } | ||
370 | if (blkid_probe_all(cache) < 0) | ||
371 | printf("%s: error probing devices\n", argv[0]); | ||
372 | |||
373 | blkid_put_cache(cache); | ||
374 | return (0); | ||
375 | } | ||
376 | #endif | ||
diff --git a/e2fsprogs/blkid/devno.c b/e2fsprogs/blkid/devno.c new file mode 100644 index 000000000..31aa52bb4 --- /dev/null +++ b/e2fsprogs/blkid/devno.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * devno.c - find a particular device by its device number (major/minor) | ||
3 | * | ||
4 | * Copyright (C) 2000, 2001, 2003 Theodore Ts'o | ||
5 | * Copyright (C) 2001 Andreas Dilger | ||
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 <stdio.h> | ||
14 | #include <string.h> | ||
15 | #if HAVE_UNISTD_H | ||
16 | #include <unistd.h> | ||
17 | #endif | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #if HAVE_SYS_TYPES_H | ||
21 | #include <sys/types.h> | ||
22 | #endif | ||
23 | #if HAVE_SYS_STAT_H | ||
24 | #include <sys/stat.h> | ||
25 | #endif | ||
26 | #include <dirent.h> | ||
27 | #if HAVE_ERRNO_H | ||
28 | #include <errno.h> | ||
29 | #endif | ||
30 | #if HAVE_SYS_MKDEV_H | ||
31 | #include <sys/mkdev.h> | ||
32 | #endif | ||
33 | |||
34 | #include "blkidP.h" | ||
35 | |||
36 | struct dir_list { | ||
37 | char *name; | ||
38 | struct dir_list *next; | ||
39 | }; | ||
40 | |||
41 | char *blkid_strndup(const char *s, int length) | ||
42 | { | ||
43 | char *ret; | ||
44 | |||
45 | if (!s) | ||
46 | return NULL; | ||
47 | |||
48 | if (!length) | ||
49 | length = strlen(s); | ||
50 | |||
51 | ret = malloc(length + 1); | ||
52 | if (ret) { | ||
53 | strncpy(ret, s, length); | ||
54 | ret[length] = '\0'; | ||
55 | } | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | char *blkid_strdup(const char *s) | ||
60 | { | ||
61 | return blkid_strndup(s, 0); | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | * This function adds an entry to the directory list | ||
66 | */ | ||
67 | static void add_to_dirlist(const char *name, struct dir_list **list) | ||
68 | { | ||
69 | struct dir_list *dp; | ||
70 | |||
71 | dp = malloc(sizeof(struct dir_list)); | ||
72 | if (!dp) | ||
73 | return; | ||
74 | dp->name = blkid_strdup(name); | ||
75 | if (!dp->name) { | ||
76 | free(dp); | ||
77 | return; | ||
78 | } | ||
79 | dp->next = *list; | ||
80 | *list = dp; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * This function frees a directory list | ||
85 | */ | ||
86 | static void free_dirlist(struct dir_list **list) | ||
87 | { | ||
88 | struct dir_list *dp, *next; | ||
89 | |||
90 | for (dp = *list; dp; dp = next) { | ||
91 | next = dp->next; | ||
92 | free(dp->name); | ||
93 | free(dp); | ||
94 | } | ||
95 | *list = NULL; | ||
96 | } | ||
97 | |||
98 | static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list, | ||
99 | char **devname) | ||
100 | { | ||
101 | DIR *dir; | ||
102 | struct dirent *dp; | ||
103 | char path[1024]; | ||
104 | int dirlen; | ||
105 | struct stat st; | ||
106 | |||
107 | if ((dir = opendir(dir_name)) == NULL) | ||
108 | return; | ||
109 | dirlen = strlen(dir_name) + 2; | ||
110 | while ((dp = readdir(dir)) != 0) { | ||
111 | if (dirlen + strlen(dp->d_name) >= sizeof(path)) | ||
112 | continue; | ||
113 | |||
114 | if (dp->d_name[0] == '.' && | ||
115 | ((dp->d_name[1] == 0) || | ||
116 | ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) | ||
117 | continue; | ||
118 | |||
119 | sprintf(path, "%s/%s", dir_name, dp->d_name); | ||
120 | if (stat(path, &st) < 0) | ||
121 | continue; | ||
122 | |||
123 | if (S_ISDIR(st.st_mode)) | ||
124 | add_to_dirlist(path, list); | ||
125 | else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { | ||
126 | *devname = blkid_strdup(path); | ||
127 | DBG(DEBUG_DEVNO, | ||
128 | printf("found 0x%Lx at %s (%p)\n", devno, | ||
129 | path, *devname)); | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | closedir(dir); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | /* Directories where we will try to search for device numbers */ | ||
138 | const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL }; | ||
139 | |||
140 | /* | ||
141 | * This function finds the pathname to a block device with a given | ||
142 | * device number. It returns a pointer to allocated memory to the | ||
143 | * pathname on success, and NULL on failure. | ||
144 | */ | ||
145 | char *blkid_devno_to_devname(dev_t devno) | ||
146 | { | ||
147 | struct dir_list *list = NULL, *new_list = NULL; | ||
148 | char *devname = NULL; | ||
149 | const char **dir; | ||
150 | |||
151 | /* | ||
152 | * Add the starting directories to search in reverse order of | ||
153 | * importance, since we are using a stack... | ||
154 | */ | ||
155 | for (dir = blkid_devdirs; *dir; dir++) | ||
156 | add_to_dirlist(*dir, &list); | ||
157 | |||
158 | while (list) { | ||
159 | struct dir_list *current = list; | ||
160 | |||
161 | list = list->next; | ||
162 | DBG(DEBUG_DEVNO, printf("directory %s\n", current->name)); | ||
163 | scan_dir(current->name, devno, &new_list, &devname); | ||
164 | free(current->name); | ||
165 | free(current); | ||
166 | if (devname) | ||
167 | break; | ||
168 | /* | ||
169 | * If we're done checking at this level, descend to | ||
170 | * the next level of subdirectories. (breadth-first) | ||
171 | */ | ||
172 | if (list == NULL) { | ||
173 | list = new_list; | ||
174 | new_list = NULL; | ||
175 | } | ||
176 | } | ||
177 | free_dirlist(&list); | ||
178 | free_dirlist(&new_list); | ||
179 | |||
180 | if (!devname) { | ||
181 | DBG(DEBUG_DEVNO, | ||
182 | printf("blkid: couldn't find devno 0x%04lx\n", | ||
183 | (unsigned long) devno)); | ||
184 | } else { | ||
185 | DBG(DEBUG_DEVNO, | ||
186 | printf("found devno 0x%04Lx as %s\n", devno, devname)); | ||
187 | } | ||
188 | |||
189 | |||
190 | return devname; | ||
191 | } | ||
192 | |||
193 | #ifdef TEST_PROGRAM | ||
194 | int main(int argc, char** argv) | ||
195 | { | ||
196 | char *devname, *tmp; | ||
197 | int major, minor; | ||
198 | dev_t devno; | ||
199 | const char *errmsg = "Couldn't parse %s: %s\n"; | ||
200 | |||
201 | blkid_debug_mask = DEBUG_ALL; | ||
202 | if ((argc != 2) && (argc != 3)) { | ||
203 | fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n" | ||
204 | "Resolve a device number to a device name\n", | ||
205 | argv[0], argv[0]); | ||
206 | exit(1); | ||
207 | } | ||
208 | if (argc == 2) { | ||
209 | devno = strtoul(argv[1], &tmp, 0); | ||
210 | if (*tmp) { | ||
211 | fprintf(stderr, errmsg, "device number", argv[1]); | ||
212 | exit(1); | ||
213 | } | ||
214 | } else { | ||
215 | major = strtoul(argv[1], &tmp, 0); | ||
216 | if (*tmp) { | ||
217 | fprintf(stderr, errmsg, "major number", argv[1]); | ||
218 | exit(1); | ||
219 | } | ||
220 | minor = strtoul(argv[2], &tmp, 0); | ||
221 | if (*tmp) { | ||
222 | fprintf(stderr, errmsg, "minor number", argv[2]); | ||
223 | exit(1); | ||
224 | } | ||
225 | devno = makedev(major, minor); | ||
226 | } | ||
227 | printf("Looking for device 0x%04Lx\n", devno); | ||
228 | devname = blkid_devno_to_devname(devno); | ||
229 | if (devname) | ||
230 | free(devname); | ||
231 | return 0; | ||
232 | } | ||
233 | #endif | ||
diff --git a/e2fsprogs/blkid/getsize.c b/e2fsprogs/blkid/getsize.c new file mode 100644 index 000000000..9458c08bf --- /dev/null +++ b/e2fsprogs/blkid/getsize.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * getsize.c --- get the size of a partition. | ||
3 | * | ||
4 | * Copyright (C) 1995, 1995 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * This file may be redistributed under the terms of the | ||
8 | * GNU Lesser General Public License. | ||
9 | * %End-Header% | ||
10 | */ | ||
11 | |||
12 | /* include this before sys/queues.h! */ | ||
13 | #include "blkidP.h" | ||
14 | |||
15 | #include <stdio.h> | ||
16 | #if HAVE_UNISTD_H | ||
17 | #include <unistd.h> | ||
18 | #endif | ||
19 | #if HAVE_ERRNO_H | ||
20 | #include <errno.h> | ||
21 | #endif | ||
22 | #include <fcntl.h> | ||
23 | #ifdef HAVE_SYS_IOCTL_H | ||
24 | #include <sys/ioctl.h> | ||
25 | #endif | ||
26 | #ifdef HAVE_LINUX_FD_H | ||
27 | #include <linux/fd.h> | ||
28 | #endif | ||
29 | #ifdef HAVE_SYS_DISKLABEL_H | ||
30 | #include <sys/disklabel.h> | ||
31 | #include <sys/stat.h> | ||
32 | #endif | ||
33 | #ifdef HAVE_SYS_DISK_H | ||
34 | #ifdef HAVE_SYS_QUEUE_H | ||
35 | #include <sys/queue.h> /* for LIST_HEAD */ | ||
36 | #endif | ||
37 | #include <sys/disk.h> | ||
38 | #endif | ||
39 | #ifdef __linux__ | ||
40 | #include <sys/utsname.h> | ||
41 | #endif | ||
42 | |||
43 | #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) | ||
44 | #define BLKGETSIZE _IO(0x12,96) /* return device size */ | ||
45 | #endif | ||
46 | |||
47 | #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) | ||
48 | #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ | ||
49 | #endif | ||
50 | |||
51 | #ifdef APPLE_DARWIN | ||
52 | #define BLKGETSIZE DKIOCGETBLOCKCOUNT32 | ||
53 | #endif /* APPLE_DARWIN */ | ||
54 | |||
55 | static int valid_offset(int fd, blkid_loff_t offset) | ||
56 | { | ||
57 | char ch; | ||
58 | |||
59 | if (blkid_llseek(fd, offset, 0) < 0) | ||
60 | return 0; | ||
61 | if (read(fd, &ch, 1) < 1) | ||
62 | return 0; | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Returns the number of blocks in a partition | ||
68 | */ | ||
69 | blkid_loff_t blkid_get_dev_size(int fd) | ||
70 | { | ||
71 | int valid_blkgetsize64 = 1; | ||
72 | #ifdef __linux__ | ||
73 | struct utsname ut; | ||
74 | #endif | ||
75 | unsigned long long size64; | ||
76 | unsigned long size; | ||
77 | blkid_loff_t high, low; | ||
78 | #ifdef FDGETPRM | ||
79 | struct floppy_struct this_floppy; | ||
80 | #endif | ||
81 | #ifdef HAVE_SYS_DISKLABEL_H | ||
82 | int part = -1; | ||
83 | struct disklabel lab; | ||
84 | struct partition *pp; | ||
85 | char ch; | ||
86 | struct stat st; | ||
87 | #endif /* HAVE_SYS_DISKLABEL_H */ | ||
88 | |||
89 | #ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ | ||
90 | if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { | ||
91 | if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) | ||
92 | && (size64 << 9 > 0xFFFFFFFF)) | ||
93 | return 0; /* EFBIG */ | ||
94 | return (blkid_loff_t) size64 << 9; | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | #ifdef BLKGETSIZE64 | ||
99 | #ifdef __linux__ | ||
100 | if ((uname(&ut) == 0) && | ||
101 | ((ut.release[0] == '2') && (ut.release[1] == '.') && | ||
102 | (ut.release[2] < '6') && (ut.release[3] == '.'))) | ||
103 | valid_blkgetsize64 = 0; | ||
104 | #endif | ||
105 | if (valid_blkgetsize64 && | ||
106 | ioctl(fd, BLKGETSIZE64, &size64) >= 0) { | ||
107 | if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) | ||
108 | && ((size64) > 0xFFFFFFFF)) | ||
109 | return 0; /* EFBIG */ | ||
110 | return size64; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | #ifdef BLKGETSIZE | ||
115 | if (ioctl(fd, BLKGETSIZE, &size) >= 0) | ||
116 | return (blkid_loff_t)size << 9; | ||
117 | #endif | ||
118 | |||
119 | #ifdef FDGETPRM | ||
120 | if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) | ||
121 | return (blkid_loff_t)this_floppy.size << 9; | ||
122 | #endif | ||
123 | #ifdef HAVE_SYS_DISKLABEL_H | ||
124 | #if 0 | ||
125 | /* | ||
126 | * This should work in theory but I haven't tested it. Anyone | ||
127 | * on a BSD system want to test this for me? In the meantime, | ||
128 | * binary search mechanism should work just fine. | ||
129 | */ | ||
130 | if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode)) | ||
131 | part = st.st_rdev & 7; | ||
132 | if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { | ||
133 | pp = &lab.d_partitions[part]; | ||
134 | if (pp->p_size) | ||
135 | return pp->p_size << 9; | ||
136 | } | ||
137 | #endif | ||
138 | #endif /* HAVE_SYS_DISKLABEL_H */ | ||
139 | |||
140 | /* | ||
141 | * OK, we couldn't figure it out by using a specialized ioctl, | ||
142 | * which is generally the best way. So do binary search to | ||
143 | * find the size of the partition. | ||
144 | */ | ||
145 | low = 0; | ||
146 | for (high = 1024; valid_offset(fd, high); high *= 2) | ||
147 | low = high; | ||
148 | while (low < high - 1) | ||
149 | { | ||
150 | const blkid_loff_t mid = (low + high) / 2; | ||
151 | |||
152 | if (valid_offset(fd, mid)) | ||
153 | low = mid; | ||
154 | else | ||
155 | high = mid; | ||
156 | } | ||
157 | return low + 1; | ||
158 | } | ||
159 | |||
160 | #ifdef TEST_PROGRAM | ||
161 | int main(int argc, char **argv) | ||
162 | { | ||
163 | blkid_loff_t bytes; | ||
164 | int fd; | ||
165 | |||
166 | if (argc < 2) { | ||
167 | fprintf(stderr, "Usage: %s device\n" | ||
168 | "Determine the size of a device\n", argv[0]); | ||
169 | return 1; | ||
170 | } | ||
171 | |||
172 | if ((fd = open(argv[1], O_RDONLY)) < 0) | ||
173 | perror(argv[0]); | ||
174 | |||
175 | bytes = blkid_get_dev_size(fd); | ||
176 | printf("Device %s has %Ld 1k blocks.\n", argv[1], bytes >> 10); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | #endif | ||
diff --git a/e2fsprogs/blkid/list.h b/e2fsprogs/blkid/list.h new file mode 100644 index 000000000..c1cbfec59 --- /dev/null +++ b/e2fsprogs/blkid/list.h | |||
@@ -0,0 +1,179 @@ | |||
1 | #if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD) | ||
2 | #define _BLKID_LIST_H | ||
3 | |||
4 | #ifdef __cplusplus | ||
5 | extern "C" { | ||
6 | #endif | ||
7 | |||
8 | #ifdef __GNUC__ | ||
9 | #define _INLINE_ static __inline__ | ||
10 | #else /* For Watcom C */ | ||
11 | #define _INLINE_ static inline | ||
12 | #endif | ||
13 | |||
14 | /* | ||
15 | * Simple doubly linked list implementation. | ||
16 | * | ||
17 | * Some of the internal functions ("__xxx") are useful when | ||
18 | * manipulating whole lists rather than single entries, as | ||
19 | * sometimes we already know the next/prev entries and we can | ||
20 | * generate better code by using them directly rather than | ||
21 | * using the generic single-entry routines. | ||
22 | */ | ||
23 | |||
24 | struct list_head { | ||
25 | struct list_head *next, *prev; | ||
26 | }; | ||
27 | |||
28 | #define LIST_HEAD_INIT(name) { &(name), &(name) } | ||
29 | |||
30 | #define LIST_HEAD(name) \ | ||
31 | struct list_head name = LIST_HEAD_INIT(name) | ||
32 | |||
33 | #define INIT_LIST_HEAD(ptr) do { \ | ||
34 | (ptr)->next = (ptr); (ptr)->prev = (ptr); \ | ||
35 | } while (0) | ||
36 | |||
37 | /* | ||
38 | * Insert a new entry between two known consecutive entries. | ||
39 | * | ||
40 | * This is only for internal list manipulation where we know | ||
41 | * the prev/next entries already! | ||
42 | */ | ||
43 | _INLINE_ void __list_add(struct list_head * add, | ||
44 | struct list_head * prev, | ||
45 | struct list_head * next) | ||
46 | { | ||
47 | next->prev = add; | ||
48 | add->next = next; | ||
49 | add->prev = prev; | ||
50 | prev->next = add; | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * list_add - add a new entry | ||
55 | * @add: new entry to be added | ||
56 | * @head: list head to add it after | ||
57 | * | ||
58 | * Insert a new entry after the specified head. | ||
59 | * This is good for implementing stacks. | ||
60 | */ | ||
61 | _INLINE_ void list_add(struct list_head *add, struct list_head *head) | ||
62 | { | ||
63 | __list_add(add, head, head->next); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * list_add_tail - add a new entry | ||
68 | * @add: new entry to be added | ||
69 | * @head: list head to add it before | ||
70 | * | ||
71 | * Insert a new entry before the specified head. | ||
72 | * This is useful for implementing queues. | ||
73 | */ | ||
74 | _INLINE_ void list_add_tail(struct list_head *add, struct list_head *head) | ||
75 | { | ||
76 | __list_add(add, head->prev, head); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * Delete a list entry by making the prev/next entries | ||
81 | * point to each other. | ||
82 | * | ||
83 | * This is only for internal list manipulation where we know | ||
84 | * the prev/next entries already! | ||
85 | */ | ||
86 | _INLINE_ void __list_del(struct list_head * prev, | ||
87 | struct list_head * next) | ||
88 | { | ||
89 | next->prev = prev; | ||
90 | prev->next = next; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * list_del - deletes entry from list. | ||
95 | * @entry: the element to delete from the list. | ||
96 | * | ||
97 | * list_empty() on @entry does not return true after this, @entry is | ||
98 | * in an undefined state. | ||
99 | */ | ||
100 | _INLINE_ void list_del(struct list_head *entry) | ||
101 | { | ||
102 | __list_del(entry->prev, entry->next); | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * list_del_init - deletes entry from list and reinitialize it. | ||
107 | * @entry: the element to delete from the list. | ||
108 | */ | ||
109 | _INLINE_ void list_del_init(struct list_head *entry) | ||
110 | { | ||
111 | __list_del(entry->prev, entry->next); | ||
112 | INIT_LIST_HEAD(entry); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * list_empty - tests whether a list is empty | ||
117 | * @head: the list to test. | ||
118 | */ | ||
119 | _INLINE_ int list_empty(struct list_head *head) | ||
120 | { | ||
121 | return head->next == head; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * list_splice - join two lists | ||
126 | * @list: the new list to add. | ||
127 | * @head: the place to add it in the first list. | ||
128 | */ | ||
129 | _INLINE_ void list_splice(struct list_head *list, struct list_head *head) | ||
130 | { | ||
131 | struct list_head *first = list->next; | ||
132 | |||
133 | if (first != list) { | ||
134 | struct list_head *last = list->prev; | ||
135 | struct list_head *at = head->next; | ||
136 | |||
137 | first->prev = head; | ||
138 | head->next = first; | ||
139 | |||
140 | last->next = at; | ||
141 | at->prev = last; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * list_entry - get the struct for this entry | ||
147 | * @ptr: the &struct list_head pointer. | ||
148 | * @type: the type of the struct this is embedded in. | ||
149 | * @member: the name of the list_struct within the struct. | ||
150 | */ | ||
151 | #define list_entry(ptr, type, member) \ | ||
152 | ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) | ||
153 | |||
154 | /** | ||
155 | * list_for_each - iterate over elements in a list | ||
156 | * @pos: the &struct list_head to use as a loop counter. | ||
157 | * @head: the head for your list. | ||
158 | */ | ||
159 | #define list_for_each(pos, head) \ | ||
160 | for (pos = (head)->next; pos != (head); pos = pos->next) | ||
161 | |||
162 | /** | ||
163 | * list_for_each_safe - iterate over elements in a list, but don't dereference | ||
164 | * pos after the body is done (in case it is freed) | ||
165 | * @pos: the &struct list_head to use as a loop counter. | ||
166 | * @pnext: the &struct list_head to use as a pointer to the next item. | ||
167 | * @head: the head for your list (not included in iteration). | ||
168 | */ | ||
169 | #define list_for_each_safe(pos, pnext, head) \ | ||
170 | for (pos = (head)->next, pnext = pos->next; pos != (head); \ | ||
171 | pos = pnext, pnext = pos->next) | ||
172 | |||
173 | #undef _INLINE_ | ||
174 | |||
175 | #ifdef __cplusplus | ||
176 | } | ||
177 | #endif | ||
178 | |||
179 | #endif /* _BLKID_LIST_H */ | ||
diff --git a/e2fsprogs/blkid/llseek.c b/e2fsprogs/blkid/llseek.c new file mode 100644 index 000000000..b5dde03cf --- /dev/null +++ b/e2fsprogs/blkid/llseek.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * llseek.c -- stub calling the llseek system call | ||
3 | * | ||
4 | * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * This file may be redistributed under the terms of the | ||
8 | * GNU Lesser General Public License. | ||
9 | * %End-Header% | ||
10 | */ | ||
11 | |||
12 | #if HAVE_SYS_TYPES_H | ||
13 | #include <sys/types.h> | ||
14 | #endif | ||
15 | |||
16 | #if HAVE_ERRNO_H | ||
17 | #include <errno.h> | ||
18 | #endif | ||
19 | #if HAVE_UNISTD_H | ||
20 | #include <unistd.h> | ||
21 | #endif | ||
22 | #ifdef __MSDOS__ | ||
23 | #include <io.h> | ||
24 | #endif | ||
25 | |||
26 | #include "blkidP.h" | ||
27 | |||
28 | #ifdef __linux__ | ||
29 | |||
30 | #if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | ||
31 | |||
32 | #define my_llseek lseek64 | ||
33 | |||
34 | #elif defined(HAVE_LLSEEK) | ||
35 | #include <syscall.h> | ||
36 | |||
37 | #ifndef HAVE_LLSEEK_PROTOTYPE | ||
38 | extern long long llseek(int fd, long long offset, int origin); | ||
39 | #endif | ||
40 | |||
41 | #define my_llseek llseek | ||
42 | |||
43 | #else /* ! HAVE_LLSEEK */ | ||
44 | |||
45 | #if defined(__alpha__) || defined(__ia64__) | ||
46 | |||
47 | #define llseek lseek | ||
48 | |||
49 | #else /* !__alpha__ && !__ia64__*/ | ||
50 | |||
51 | #include <linux/unistd.h> | ||
52 | |||
53 | #ifndef __NR__llseek | ||
54 | #define __NR__llseek 140 | ||
55 | #endif | ||
56 | |||
57 | #ifndef __i386__ | ||
58 | static int _llseek(unsigned int, unsigned long, unsigned long, | ||
59 | blkid_loff_t *, unsigned int); | ||
60 | |||
61 | static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high, | ||
62 | unsigned long, offset_low, blkid_loff_t *, result, | ||
63 | unsigned int, origin) | ||
64 | #endif | ||
65 | |||
66 | static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin) | ||
67 | { | ||
68 | blkid_loff_t result; | ||
69 | int retval; | ||
70 | |||
71 | #ifndef __i386__ | ||
72 | retval = _llseek(fd, ((unsigned long long) offset) >> 32, | ||
73 | ((unsigned long long)offset) & 0xffffffff, | ||
74 | &result, origin); | ||
75 | #else | ||
76 | retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32, | ||
77 | ((unsigned long long)offset) & 0xffffffff, | ||
78 | &result, origin); | ||
79 | #endif | ||
80 | return (retval == -1 ? (blkid_loff_t) retval : result); | ||
81 | } | ||
82 | |||
83 | #endif /* __alpha__ || __ia64__ */ | ||
84 | |||
85 | #endif /* HAVE_LLSEEK */ | ||
86 | |||
87 | blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence) | ||
88 | { | ||
89 | blkid_loff_t result; | ||
90 | static int do_compat = 0; | ||
91 | |||
92 | if ((sizeof(off_t) >= sizeof(blkid_loff_t)) || | ||
93 | (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1)))) | ||
94 | return lseek(fd, (off_t) offset, whence); | ||
95 | |||
96 | if (do_compat) { | ||
97 | errno = EOVERFLOW; | ||
98 | return -1; | ||
99 | } | ||
100 | |||
101 | result = my_llseek(fd, offset, whence); | ||
102 | if (result == -1 && errno == ENOSYS) { | ||
103 | /* | ||
104 | * Just in case this code runs on top of an old kernel | ||
105 | * which does not support the llseek system call | ||
106 | */ | ||
107 | do_compat++; | ||
108 | errno = EOVERFLOW; | ||
109 | } | ||
110 | return result; | ||
111 | } | ||
112 | |||
113 | #else /* !linux */ | ||
114 | |||
115 | #ifndef EOVERFLOW | ||
116 | #ifdef EXT2_ET_INVALID_ARGUMENT | ||
117 | #define EOVERFLOW EXT2_ET_INVALID_ARGUMENT | ||
118 | #else | ||
119 | #define EOVERFLOW 112 | ||
120 | #endif | ||
121 | #endif | ||
122 | |||
123 | blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin) | ||
124 | { | ||
125 | #if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | ||
126 | return lseek64 (fd, offset, origin); | ||
127 | #else | ||
128 | if ((sizeof(off_t) < sizeof(blkid_loff_t)) && | ||
129 | (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) { | ||
130 | errno = EOVERFLOW; | ||
131 | return -1; | ||
132 | } | ||
133 | return lseek(fd, (off_t) offset, origin); | ||
134 | #endif | ||
135 | } | ||
136 | |||
137 | #endif /* linux */ | ||
138 | |||
139 | |||
diff --git a/e2fsprogs/blkid/probe.c b/e2fsprogs/blkid/probe.c new file mode 100644 index 000000000..5fa37ad46 --- /dev/null +++ b/e2fsprogs/blkid/probe.c | |||
@@ -0,0 +1,704 @@ | |||
1 | /* | ||
2 | * probe.c - identify a block device by its contents, and return a dev | ||
3 | * struct with the details | ||
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 | #include <stdio.h> | ||
16 | #include <string.h> | ||
17 | #include <stdlib.h> | ||
18 | #include <unistd.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <sys/types.h> | ||
21 | #ifdef HAVE_SYS_STAT_H | ||
22 | #include <sys/stat.h> | ||
23 | #endif | ||
24 | #ifdef HAVE_SYS_MKDEV_H | ||
25 | #include <sys/mkdev.h> | ||
26 | #endif | ||
27 | #ifdef HAVE_ERRNO_H | ||
28 | #include <errno.h> | ||
29 | #endif | ||
30 | #include "blkidP.h" | ||
31 | #include "uuid/uuid.h" | ||
32 | #include "probe.h" | ||
33 | |||
34 | /* | ||
35 | * This is a special case code to check for an MDRAID device. We do | ||
36 | * this special since it requires checking for a superblock at the end | ||
37 | * of the device. | ||
38 | */ | ||
39 | static int check_mdraid(int fd, unsigned char *ret_uuid) | ||
40 | { | ||
41 | struct mdp_superblock_s *md; | ||
42 | blkid_loff_t offset; | ||
43 | char buf[4096]; | ||
44 | |||
45 | if (fd < 0) | ||
46 | return -BLKID_ERR_PARAM; | ||
47 | |||
48 | offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; | ||
49 | |||
50 | if (blkid_llseek(fd, offset, 0) < 0 || | ||
51 | read(fd, buf, 4096) != 4096) | ||
52 | return -BLKID_ERR_IO; | ||
53 | |||
54 | /* Check for magic number */ | ||
55 | if (memcmp("\251+N\374", buf, 4)) | ||
56 | return -BLKID_ERR_PARAM; | ||
57 | |||
58 | if (!ret_uuid) | ||
59 | return 0; | ||
60 | *ret_uuid = 0; | ||
61 | |||
62 | /* The MD UUID is not contiguous in the superblock, make it so */ | ||
63 | md = (struct mdp_superblock_s *)buf; | ||
64 | if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { | ||
65 | memcpy(ret_uuid, &md->set_uuid0, 4); | ||
66 | memcpy(ret_uuid, &md->set_uuid1, 12); | ||
67 | } | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static void set_uuid(blkid_dev dev, uuid_t uuid) | ||
72 | { | ||
73 | char str[37]; | ||
74 | |||
75 | if (!uuid_is_null(uuid)) { | ||
76 | uuid_unparse(uuid, str); | ||
77 | blkid_set_tag(dev, "UUID", str, sizeof(str)); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static void get_ext2_info(blkid_dev dev, unsigned char *buf) | ||
82 | { | ||
83 | struct ext2_super_block *es = (struct ext2_super_block *) buf; | ||
84 | const char *label = 0; | ||
85 | |||
86 | DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", | ||
87 | blkid_le32(es->s_feature_compat), | ||
88 | blkid_le32(es->s_feature_incompat), | ||
89 | blkid_le32(es->s_feature_ro_compat))); | ||
90 | |||
91 | if (strlen(es->s_volume_name)) | ||
92 | label = es->s_volume_name; | ||
93 | blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); | ||
94 | |||
95 | set_uuid(dev, es->s_uuid); | ||
96 | } | ||
97 | |||
98 | static int probe_ext3(int fd __BLKID_ATTR((unused)), | ||
99 | blkid_cache cache __BLKID_ATTR((unused)), | ||
100 | blkid_dev dev, | ||
101 | struct blkid_magic *id, unsigned char *buf) | ||
102 | { | ||
103 | struct ext2_super_block *es; | ||
104 | |||
105 | es = (struct ext2_super_block *)buf; | ||
106 | |||
107 | /* Distinguish between jbd and ext2/3 fs */ | ||
108 | if (blkid_le32(es->s_feature_incompat) & | ||
109 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | ||
110 | return -BLKID_ERR_PARAM; | ||
111 | |||
112 | /* Distinguish between ext3 and ext2 */ | ||
113 | if (!(blkid_le32(es->s_feature_compat) & | ||
114 | EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | ||
115 | return -BLKID_ERR_PARAM; | ||
116 | |||
117 | get_ext2_info(dev, buf); | ||
118 | |||
119 | blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int probe_ext2(int fd __BLKID_ATTR((unused)), | ||
125 | blkid_cache cache __BLKID_ATTR((unused)), | ||
126 | blkid_dev dev, | ||
127 | struct blkid_magic *id, unsigned char *buf) | ||
128 | { | ||
129 | struct ext2_super_block *es; | ||
130 | // const char *sec_type = 0, *label = 0; | ||
131 | |||
132 | es = (struct ext2_super_block *)buf; | ||
133 | |||
134 | /* Distinguish between jbd and ext2/3 fs */ | ||
135 | if (blkid_le32(es->s_feature_incompat) & | ||
136 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | ||
137 | return -BLKID_ERR_PARAM; | ||
138 | |||
139 | get_ext2_info(dev, buf); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int probe_jbd(int fd __BLKID_ATTR((unused)), | ||
145 | blkid_cache cache __BLKID_ATTR((unused)), | ||
146 | blkid_dev dev, | ||
147 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
148 | unsigned char *buf) | ||
149 | { | ||
150 | struct ext2_super_block *es = (struct ext2_super_block *) buf; | ||
151 | |||
152 | if (!(blkid_le32(es->s_feature_incompat) & | ||
153 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) | ||
154 | return -BLKID_ERR_PARAM; | ||
155 | |||
156 | get_ext2_info(dev, buf); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int probe_vfat(int fd __BLKID_ATTR((unused)), | ||
162 | blkid_cache cache __BLKID_ATTR((unused)), | ||
163 | blkid_dev dev, | ||
164 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
165 | unsigned char *buf) | ||
166 | { | ||
167 | struct vfat_super_block *vs; | ||
168 | char serno[10]; | ||
169 | const char *label = 0; | ||
170 | int label_len = 0; | ||
171 | |||
172 | vs = (struct vfat_super_block *)buf; | ||
173 | |||
174 | if (strncmp(vs->vs_label, "NO NAME", 7)) { | ||
175 | char *end = vs->vs_label + sizeof(vs->vs_label) - 1; | ||
176 | |||
177 | while (*end == ' ' && end >= vs->vs_label) | ||
178 | --end; | ||
179 | if (end >= vs->vs_label) { | ||
180 | label = vs->vs_label; | ||
181 | label_len = end - vs->vs_label + 1; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* We can't just print them as %04X, because they are unaligned */ | ||
186 | sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], | ||
187 | vs->vs_serno[1], vs->vs_serno[0]); | ||
188 | blkid_set_tag(dev, "LABEL", label, label_len); | ||
189 | blkid_set_tag(dev, "UUID", serno, sizeof(serno)); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int probe_msdos(int fd __BLKID_ATTR((unused)), | ||
195 | blkid_cache cache __BLKID_ATTR((unused)), | ||
196 | blkid_dev dev, | ||
197 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
198 | unsigned char *buf) | ||
199 | { | ||
200 | struct msdos_super_block *ms = (struct msdos_super_block *) buf; | ||
201 | char serno[10]; | ||
202 | const char *label = 0; | ||
203 | int label_len = 0; | ||
204 | |||
205 | if (strncmp(ms->ms_label, "NO NAME", 7)) { | ||
206 | char *end = ms->ms_label + sizeof(ms->ms_label) - 1; | ||
207 | |||
208 | while (*end == ' ' && end >= ms->ms_label) | ||
209 | --end; | ||
210 | if (end >= ms->ms_label) { | ||
211 | label = ms->ms_label; | ||
212 | label_len = end - ms->ms_label + 1; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* We can't just print them as %04X, because they are unaligned */ | ||
217 | sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], | ||
218 | ms->ms_serno[1], ms->ms_serno[0]); | ||
219 | blkid_set_tag(dev, "UUID", serno, 0); | ||
220 | blkid_set_tag(dev, "LABEL", label, label_len); | ||
221 | blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos")); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int probe_xfs(int fd __BLKID_ATTR((unused)), | ||
227 | blkid_cache cache __BLKID_ATTR((unused)), | ||
228 | blkid_dev dev, | ||
229 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
230 | unsigned char *buf) | ||
231 | { | ||
232 | struct xfs_super_block *xs; | ||
233 | const char *label = 0; | ||
234 | |||
235 | xs = (struct xfs_super_block *)buf; | ||
236 | |||
237 | if (strlen(xs->xs_fname)) | ||
238 | label = xs->xs_fname; | ||
239 | blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname)); | ||
240 | set_uuid(dev, xs->xs_uuid); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int probe_reiserfs(int fd __BLKID_ATTR((unused)), | ||
245 | blkid_cache cache __BLKID_ATTR((unused)), | ||
246 | blkid_dev dev, | ||
247 | struct blkid_magic *id, unsigned char *buf) | ||
248 | { | ||
249 | struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; | ||
250 | unsigned int blocksize; | ||
251 | const char *label = 0; | ||
252 | |||
253 | blocksize = blkid_le16(rs->rs_blocksize); | ||
254 | |||
255 | /* If the superblock is inside the journal, we have the wrong one */ | ||
256 | if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) | ||
257 | return -BLKID_ERR_BIG; | ||
258 | |||
259 | /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ | ||
260 | if (!strcmp(id->bim_magic, "ReIsEr2Fs") || | ||
261 | !strcmp(id->bim_magic, "ReIsEr3Fs")) { | ||
262 | if (strlen(rs->rs_label)) | ||
263 | label = rs->rs_label; | ||
264 | set_uuid(dev, rs->rs_uuid); | ||
265 | } | ||
266 | blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label)); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int probe_jfs(int fd __BLKID_ATTR((unused)), | ||
272 | blkid_cache cache __BLKID_ATTR((unused)), | ||
273 | blkid_dev dev, | ||
274 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
275 | unsigned char *buf) | ||
276 | { | ||
277 | struct jfs_super_block *js; | ||
278 | const char *label = 0; | ||
279 | |||
280 | js = (struct jfs_super_block *)buf; | ||
281 | |||
282 | if (strlen((char *) js->js_label)) | ||
283 | label = (char *) js->js_label; | ||
284 | blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label)); | ||
285 | set_uuid(dev, js->js_uuid); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int probe_romfs(int fd __BLKID_ATTR((unused)), | ||
290 | blkid_cache cache __BLKID_ATTR((unused)), | ||
291 | blkid_dev dev, | ||
292 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
293 | unsigned char *buf) | ||
294 | { | ||
295 | struct romfs_super_block *ros; | ||
296 | const char *label = 0; | ||
297 | |||
298 | ros = (struct romfs_super_block *)buf; | ||
299 | |||
300 | if (strlen((char *) ros->ros_volume)) | ||
301 | label = (char *) ros->ros_volume; | ||
302 | blkid_set_tag(dev, "LABEL", label, 0); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int probe_swap0(int fd __BLKID_ATTR((unused)), | ||
307 | blkid_cache cache __BLKID_ATTR((unused)), | ||
308 | blkid_dev dev, | ||
309 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
310 | unsigned char *buf __BLKID_ATTR((unused))) | ||
311 | { | ||
312 | blkid_set_tag(dev, "UUID", 0, 0); | ||
313 | blkid_set_tag(dev, "LABEL", 0, 0); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int probe_swap1(int fd, | ||
318 | blkid_cache cache __BLKID_ATTR((unused)), | ||
319 | blkid_dev dev, | ||
320 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
321 | unsigned char *buf __BLKID_ATTR((unused))) | ||
322 | { | ||
323 | struct swap_id_block *sws; | ||
324 | // const char *label = 0; | ||
325 | |||
326 | probe_swap0(fd, cache, dev, id, buf); | ||
327 | /* | ||
328 | * Version 1 swap headers are always located at offset of 1024 | ||
329 | * bytes, although the swap signature itself is located at the | ||
330 | * end of the page (which may vary depending on hardware | ||
331 | * pagesize). | ||
332 | */ | ||
333 | if (lseek(fd, 1024, SEEK_SET) < 0) return 1; | ||
334 | if (!(sws = (struct swap_id_block *)malloc(1024))) return 1; | ||
335 | if (read(fd, sws, 1024) != 1024) { | ||
336 | free(sws); | ||
337 | return 1; | ||
338 | } | ||
339 | |||
340 | /* arbitrary sanity check.. is there any garbage down there? */ | ||
341 | if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { | ||
342 | if (sws->sws_volume[0]) | ||
343 | blkid_set_tag(dev, "LABEL", sws->sws_volume, | ||
344 | sizeof(sws->sws_volume)); | ||
345 | if (sws->sws_uuid[0]) | ||
346 | set_uuid(dev, sws->sws_uuid); | ||
347 | } | ||
348 | free(sws); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static const char | ||
354 | *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", | ||
355 | "NSR03", "TEA01", 0 }; | ||
356 | |||
357 | static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)), | ||
358 | blkid_dev dev __BLKID_ATTR((unused)), | ||
359 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
360 | unsigned char *buf __BLKID_ATTR((unused))) | ||
361 | { | ||
362 | int j, bs; | ||
363 | struct iso_volume_descriptor isosb; | ||
364 | const char ** m; | ||
365 | |||
366 | /* determine the block size by scanning in 2K increments | ||
367 | (block sizes larger than 2K will be null padded) */ | ||
368 | for (bs = 1; bs < 16; bs++) { | ||
369 | lseek(fd, bs*2048+32768, SEEK_SET); | ||
370 | if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb)) | ||
371 | return 1; | ||
372 | if (isosb.id[0]) | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | /* Scan up to another 64 blocks looking for additional VSD's */ | ||
377 | for (j = 1; j < 64; j++) { | ||
378 | if (j > 1) { | ||
379 | lseek(fd, j*bs*2048+32768, SEEK_SET); | ||
380 | if (read(fd, (char *)&isosb, sizeof(isosb)) | ||
381 | != sizeof(isosb)) | ||
382 | return 1; | ||
383 | } | ||
384 | /* If we find NSR0x then call it udf: | ||
385 | NSR01 for UDF 1.00 | ||
386 | NSR02 for UDF 1.50 | ||
387 | NSR03 for UDF 2.00 */ | ||
388 | if (!strncmp(isosb.id, "NSR0", 4)) | ||
389 | return 0; | ||
390 | for (m = udf_magic; *m; m++) | ||
391 | if (!strncmp(*m, isosb.id, 5)) | ||
392 | break; | ||
393 | if (*m == 0) | ||
394 | return 1; | ||
395 | } | ||
396 | return 1; | ||
397 | } | ||
398 | |||
399 | static int probe_ocfs(int fd __BLKID_ATTR((unused)), | ||
400 | blkid_cache cache __BLKID_ATTR((unused)), | ||
401 | blkid_dev dev, | ||
402 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
403 | unsigned char *buf) | ||
404 | { | ||
405 | struct ocfs_volume_header ovh; | ||
406 | struct ocfs_volume_label ovl; | ||
407 | __u32 major; | ||
408 | |||
409 | memcpy(&ovh, buf, sizeof(ovh)); | ||
410 | memcpy(&ovl, buf+512, sizeof(ovl)); | ||
411 | |||
412 | major = ocfsmajor(ovh); | ||
413 | if (major == 1) | ||
414 | blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); | ||
415 | else if (major >= 9) | ||
416 | blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); | ||
417 | |||
418 | blkid_set_tag(dev, "LABEL", ovl.label, ocfslabellen(ovl)); | ||
419 | blkid_set_tag(dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); | ||
420 | set_uuid(dev, ovl.vol_id); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int probe_ocfs2(int fd __BLKID_ATTR((unused)), | ||
425 | blkid_cache cache __BLKID_ATTR((unused)), | ||
426 | blkid_dev dev, | ||
427 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
428 | unsigned char *buf) | ||
429 | { | ||
430 | struct ocfs2_super_block *osb; | ||
431 | |||
432 | osb = (struct ocfs2_super_block *)buf; | ||
433 | |||
434 | blkid_set_tag(dev, "LABEL", osb->s_label, sizeof(osb->s_label)); | ||
435 | set_uuid(dev, osb->s_uuid); | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int probe_oracleasm(int fd __BLKID_ATTR((unused)), | ||
440 | blkid_cache cache __BLKID_ATTR((unused)), | ||
441 | blkid_dev dev, | ||
442 | struct blkid_magic *id __BLKID_ATTR((unused)), | ||
443 | unsigned char *buf) | ||
444 | { | ||
445 | struct oracle_asm_disk_label *dl; | ||
446 | |||
447 | dl = (struct oracle_asm_disk_label *)buf; | ||
448 | |||
449 | blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined | ||
455 | * in the type_array table below + bim_kbalign. | ||
456 | * | ||
457 | * When probing for a lot of magics, we handle everything in 1kB buffers so | ||
458 | * that we don't have to worry about reading each combination of block sizes. | ||
459 | */ | ||
460 | #define BLKID_BLK_OFFS 64 /* currently reiserfs */ | ||
461 | |||
462 | /* | ||
463 | * Various filesystem magics that we can check for. Note that kboff and | ||
464 | * sboff are in kilobytes and bytes respectively. All magics are in | ||
465 | * byte strings so we don't worry about endian issues. | ||
466 | */ | ||
467 | static struct blkid_magic type_array[] = { | ||
468 | /* type kboff sboff len magic probe */ | ||
469 | { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, | ||
470 | { "ntfs", 0, 3, 8, "NTFS ", 0 }, | ||
471 | { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, | ||
472 | { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, | ||
473 | { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, | ||
474 | { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, | ||
475 | { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, | ||
476 | { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, | ||
477 | { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, | ||
478 | { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, | ||
479 | { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, | ||
480 | { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, | ||
481 | { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos }, | ||
482 | { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos }, | ||
483 | { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos }, | ||
484 | { "minix", 1, 0x10, 2, "\177\023", 0 }, | ||
485 | { "minix", 1, 0x10, 2, "\217\023", 0 }, | ||
486 | { "minix", 1, 0x10, 2, "\150\044", 0 }, | ||
487 | { "minix", 1, 0x10, 2, "\170\044", 0 }, | ||
488 | { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, | ||
489 | { "xfs", 0, 0, 4, "XFSB", probe_xfs }, | ||
490 | { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, | ||
491 | { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, | ||
492 | { "cramfs", 0, 0, 4, "E=\315\034", 0 }, | ||
493 | { "qnx4", 0, 4, 6, "QNX4FS", 0 }, | ||
494 | { "udf", 32, 1, 5, "BEA01", probe_udf }, | ||
495 | { "udf", 32, 1, 5, "BOOT2", probe_udf }, | ||
496 | { "udf", 32, 1, 5, "CD001", probe_udf }, | ||
497 | { "udf", 32, 1, 5, "CDW02", probe_udf }, | ||
498 | { "udf", 32, 1, 5, "NSR02", probe_udf }, | ||
499 | { "udf", 32, 1, 5, "NSR03", probe_udf }, | ||
500 | { "udf", 32, 1, 5, "TEA01", probe_udf }, | ||
501 | { "iso9660", 32, 1, 5, "CD001", 0 }, | ||
502 | { "iso9660", 32, 9, 5, "CDROM", 0 }, | ||
503 | { "jfs", 32, 0, 4, "JFS1", probe_jfs }, | ||
504 | { "hfs", 1, 0, 2, "BD", 0 }, | ||
505 | { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, | ||
506 | { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, | ||
507 | { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, | ||
508 | { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
509 | { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
510 | { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
511 | { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
512 | { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
513 | { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
514 | { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
515 | { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
516 | { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
517 | { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
518 | { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, | ||
519 | { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
520 | { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
521 | { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
522 | { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
523 | { NULL, 0, 0, 0, NULL, NULL } | ||
524 | }; | ||
525 | |||
526 | /* | ||
527 | * Verify that the data in dev is consistent with what is on the actual | ||
528 | * block device (using the devname field only). Normally this will be | ||
529 | * called when finding items in the cache, but for long running processes | ||
530 | * is also desirable to revalidate an item before use. | ||
531 | * | ||
532 | * If we are unable to revalidate the data, we return the old data and | ||
533 | * do not set the BLKID_BID_FL_VERIFIED flag on it. | ||
534 | */ | ||
535 | blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) | ||
536 | { | ||
537 | struct blkid_magic *id; | ||
538 | unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; | ||
539 | const char *type; | ||
540 | struct stat st; | ||
541 | time_t diff, now; | ||
542 | int fd, idx; | ||
543 | |||
544 | if (!dev) | ||
545 | return NULL; | ||
546 | |||
547 | now = time(0); | ||
548 | diff = now - dev->bid_time; | ||
549 | |||
550 | if ((now < dev->bid_time) || | ||
551 | (diff < BLKID_PROBE_MIN) || | ||
552 | (dev->bid_flags & BLKID_BID_FL_VERIFIED && | ||
553 | diff < BLKID_PROBE_INTERVAL)) | ||
554 | return dev; | ||
555 | |||
556 | DBG(DEBUG_PROBE, | ||
557 | printf("need to revalidate %s (time since last check %lu)\n", | ||
558 | dev->bid_name, diff)); | ||
559 | |||
560 | if (((fd = open(dev->bid_name, O_RDONLY)) < 0) || | ||
561 | (fstat(fd, &st) < 0)) { | ||
562 | if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { | ||
563 | blkid_free_dev(dev); | ||
564 | return NULL; | ||
565 | } | ||
566 | /* We don't have read permission, just return cache data. */ | ||
567 | DBG(DEBUG_PROBE, | ||
568 | printf("returning unverified data for %s\n", | ||
569 | dev->bid_name)); | ||
570 | return dev; | ||
571 | } | ||
572 | |||
573 | memset(bufs, 0, sizeof(bufs)); | ||
574 | |||
575 | /* | ||
576 | * Iterate over the type array. If we already know the type, | ||
577 | * then try that first. If it doesn't work, then blow away | ||
578 | * the type information, and try again. | ||
579 | * | ||
580 | */ | ||
581 | try_again: | ||
582 | type = 0; | ||
583 | if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { | ||
584 | uuid_t uuid; | ||
585 | |||
586 | if (check_mdraid(fd, uuid) == 0) { | ||
587 | set_uuid(dev, uuid); | ||
588 | type = "mdraid"; | ||
589 | goto found_type; | ||
590 | } | ||
591 | } | ||
592 | for (id = type_array; id->bim_type; id++) { | ||
593 | if (dev->bid_type && | ||
594 | strcmp(id->bim_type, dev->bid_type)) | ||
595 | continue; | ||
596 | |||
597 | idx = id->bim_kboff + (id->bim_sboff >> 10); | ||
598 | if (idx > BLKID_BLK_OFFS || idx < 0) | ||
599 | continue; | ||
600 | buf = bufs[idx]; | ||
601 | if (!buf) { | ||
602 | if (lseek(fd, idx << 10, SEEK_SET) < 0) | ||
603 | continue; | ||
604 | |||
605 | if (!(buf = (unsigned char *)malloc(1024))) | ||
606 | continue; | ||
607 | |||
608 | if (read(fd, buf, 1024) != 1024) { | ||
609 | free(buf); | ||
610 | continue; | ||
611 | } | ||
612 | bufs[idx] = buf; | ||
613 | } | ||
614 | |||
615 | if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), | ||
616 | id->bim_len)) | ||
617 | continue; | ||
618 | |||
619 | if ((id->bim_probe == NULL) || | ||
620 | (id->bim_probe(fd, cache, dev, id, buf) == 0)) { | ||
621 | type = id->bim_type; | ||
622 | goto found_type; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | if (!id->bim_type && dev->bid_type) { | ||
627 | /* | ||
628 | * Zap the device filesystem type and try again | ||
629 | */ | ||
630 | blkid_set_tag(dev, "TYPE", 0, 0); | ||
631 | blkid_set_tag(dev, "SEC_TYPE", 0, 0); | ||
632 | blkid_set_tag(dev, "LABEL", 0, 0); | ||
633 | blkid_set_tag(dev, "UUID", 0, 0); | ||
634 | goto try_again; | ||
635 | } | ||
636 | |||
637 | if (!dev->bid_type) { | ||
638 | blkid_free_dev(dev); | ||
639 | return NULL; | ||
640 | } | ||
641 | |||
642 | found_type: | ||
643 | if (dev && type) { | ||
644 | dev->bid_devno = st.st_rdev; | ||
645 | dev->bid_time = time(0); | ||
646 | dev->bid_flags |= BLKID_BID_FL_VERIFIED; | ||
647 | cache->bic_flags |= BLKID_BIC_FL_CHANGED; | ||
648 | |||
649 | blkid_set_tag(dev, "TYPE", type, 0); | ||
650 | |||
651 | DBG(DEBUG_PROBE, printf("%s: devno 0x%04Lx, type %s\n", | ||
652 | dev->bid_name, st.st_rdev, type)); | ||
653 | } | ||
654 | |||
655 | close(fd); | ||
656 | |||
657 | return dev; | ||
658 | } | ||
659 | |||
660 | int blkid_known_fstype(const char *fstype) | ||
661 | { | ||
662 | struct blkid_magic *id; | ||
663 | |||
664 | for (id = type_array; id->bim_type; id++) { | ||
665 | if (strcmp(fstype, id->bim_type) == 0) | ||
666 | return 1; | ||
667 | } | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | #ifdef TEST_PROGRAM | ||
672 | int main(int argc, char **argv) | ||
673 | { | ||
674 | blkid_dev dev; | ||
675 | blkid_cache cache; | ||
676 | int ret; | ||
677 | |||
678 | blkid_debug_mask = DEBUG_ALL; | ||
679 | if (argc != 2) { | ||
680 | fprintf(stderr, "Usage: %s device\n" | ||
681 | "Probe a single device to determine type\n", argv[0]); | ||
682 | exit(1); | ||
683 | } | ||
684 | if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | ||
685 | fprintf(stderr, "%s: error creating cache (%d)\n", | ||
686 | argv[0], ret); | ||
687 | exit(1); | ||
688 | } | ||
689 | dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); | ||
690 | if (!dev) { | ||
691 | printf("%s: %s has an unsupported type\n", argv[0], argv[1]); | ||
692 | return (1); | ||
693 | } | ||
694 | printf("%s is type %s\n", argv[1], dev->bid_type ? | ||
695 | dev->bid_type : "(null)"); | ||
696 | if (dev->bid_label) | ||
697 | printf("\tlabel is '%s'\n", dev->bid_label); | ||
698 | if (dev->bid_uuid) | ||
699 | printf("\tuuid is %s\n", dev->bid_uuid); | ||
700 | |||
701 | blkid_free_dev(dev); | ||
702 | return (0); | ||
703 | } | ||
704 | #endif | ||
diff --git a/e2fsprogs/blkid/probe.h b/e2fsprogs/blkid/probe.h new file mode 100644 index 000000000..85234e84f --- /dev/null +++ b/e2fsprogs/blkid/probe.h | |||
@@ -0,0 +1,359 @@ | |||
1 | /* | ||
2 | * probe.h - constants and on-disk structures for extracting device data | ||
3 | * | ||
4 | * Copyright (C) 1999 by Andries Brouwer | ||
5 | * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o | ||
6 | * Copyright (C) 2001 by 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 | #ifndef _BLKID_PROBE_H | ||
15 | #define _BLKID_PROBE_H | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | |||
19 | struct blkid_magic; | ||
20 | |||
21 | typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, | ||
22 | struct blkid_magic *id, unsigned char *buf); | ||
23 | |||
24 | struct blkid_magic { | ||
25 | const char *bim_type; /* type name for this magic */ | ||
26 | long bim_kboff; /* kilobyte offset of superblock */ | ||
27 | unsigned bim_sboff; /* byte offset within superblock */ | ||
28 | unsigned bim_len; /* length of magic */ | ||
29 | const char *bim_magic; /* magic string */ | ||
30 | blkid_probe_t bim_probe; /* probe function */ | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * Structures for each of the content types we want to extract information | ||
35 | * from. We do not necessarily need the magic field here, because we have | ||
36 | * already identified the content type before we get this far. It may still | ||
37 | * be useful if there are probe functions which handle multiple content types. | ||
38 | */ | ||
39 | struct ext2_super_block { | ||
40 | __u32 s_inodes_count; | ||
41 | __u32 s_blocks_count; | ||
42 | __u32 s_r_blocks_count; | ||
43 | __u32 s_free_blocks_count; | ||
44 | __u32 s_free_inodes_count; | ||
45 | __u32 s_first_data_block; | ||
46 | __u32 s_log_block_size; | ||
47 | __u32 s_dummy3[7]; | ||
48 | unsigned char s_magic[2]; | ||
49 | __u16 s_state; | ||
50 | __u32 s_dummy5[8]; | ||
51 | __u32 s_feature_compat; | ||
52 | __u32 s_feature_incompat; | ||
53 | __u32 s_feature_ro_compat; | ||
54 | unsigned char s_uuid[16]; | ||
55 | char s_volume_name[16]; | ||
56 | }; | ||
57 | #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004 | ||
58 | #define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004 | ||
59 | #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008 | ||
60 | |||
61 | struct xfs_super_block { | ||
62 | unsigned char xs_magic[4]; | ||
63 | __u32 xs_blocksize; | ||
64 | __u64 xs_dblocks; | ||
65 | __u64 xs_rblocks; | ||
66 | __u32 xs_dummy1[2]; | ||
67 | unsigned char xs_uuid[16]; | ||
68 | __u32 xs_dummy2[15]; | ||
69 | char xs_fname[12]; | ||
70 | __u32 xs_dummy3[2]; | ||
71 | __u64 xs_icount; | ||
72 | __u64 xs_ifree; | ||
73 | __u64 xs_fdblocks; | ||
74 | }; | ||
75 | |||
76 | struct reiserfs_super_block { | ||
77 | __u32 rs_blocks_count; | ||
78 | __u32 rs_free_blocks; | ||
79 | __u32 rs_root_block; | ||
80 | __u32 rs_journal_block; | ||
81 | __u32 rs_journal_dev; | ||
82 | __u32 rs_orig_journal_size; | ||
83 | __u32 rs_dummy2[5]; | ||
84 | __u16 rs_blocksize; | ||
85 | __u16 rs_dummy3[3]; | ||
86 | unsigned char rs_magic[12]; | ||
87 | __u32 rs_dummy4[5]; | ||
88 | unsigned char rs_uuid[16]; | ||
89 | char rs_label[16]; | ||
90 | }; | ||
91 | |||
92 | struct jfs_super_block { | ||
93 | unsigned char js_magic[4]; | ||
94 | __u32 js_version; | ||
95 | __u64 js_size; | ||
96 | __u32 js_bsize; | ||
97 | __u32 js_dummy1; | ||
98 | __u32 js_pbsize; | ||
99 | __u32 js_dummy2[27]; | ||
100 | unsigned char js_uuid[16]; | ||
101 | unsigned char js_label[16]; | ||
102 | unsigned char js_loguuid[16]; | ||
103 | }; | ||
104 | |||
105 | struct romfs_super_block { | ||
106 | unsigned char ros_magic[8]; | ||
107 | __u32 ros_dummy1[2]; | ||
108 | unsigned char ros_volume[16]; | ||
109 | }; | ||
110 | |||
111 | struct swap_id_block { | ||
112 | /* unsigned char sws_boot[1024]; */ | ||
113 | __u32 sws_version; | ||
114 | __u32 sws_lastpage; | ||
115 | __u32 sws_nrbad; | ||
116 | unsigned char sws_uuid[16]; | ||
117 | unsigned char sws_volume[16]; | ||
118 | unsigned char sws_pad[117]; | ||
119 | __u32 sws_badpg; | ||
120 | }; | ||
121 | |||
122 | /* Yucky misaligned values */ | ||
123 | struct vfat_super_block { | ||
124 | /* 00*/ unsigned char vs_ignored[3]; | ||
125 | /* 03*/ unsigned char vs_sysid[8]; | ||
126 | /* 0b*/ unsigned char vs_sector_size[2]; | ||
127 | /* 0d*/ __u8 vs_cluster_size; | ||
128 | /* 0e*/ __u16 vs_reserved; | ||
129 | /* 10*/ __u8 vs_fats; | ||
130 | /* 11*/ unsigned char vs_dir_entries[2]; | ||
131 | /* 13*/ unsigned char vs_sectors[2]; | ||
132 | /* 15*/ unsigned char vs_media; | ||
133 | /* 16*/ __u16 vs_fat_length; | ||
134 | /* 18*/ __u16 vs_secs_track; | ||
135 | /* 1a*/ __u16 vs_heads; | ||
136 | /* 1c*/ __u32 vs_hidden; | ||
137 | /* 20*/ __u32 vs_total_sect; | ||
138 | /* 24*/ __u32 vs_fat32_length; | ||
139 | /* 28*/ __u16 vs_flags; | ||
140 | /* 2a*/ __u8 vs_version[2]; | ||
141 | /* 2c*/ __u32 vs_root_cluster; | ||
142 | /* 30*/ __u16 vs_insfo_sector; | ||
143 | /* 32*/ __u16 vs_backup_boot; | ||
144 | /* 34*/ __u16 vs_reserved2[6]; | ||
145 | /* 40*/ unsigned char vs_unknown[3]; | ||
146 | /* 43*/ unsigned char vs_serno[4]; | ||
147 | /* 47*/ char vs_label[11]; | ||
148 | /* 52*/ unsigned char vs_magic[8]; | ||
149 | /* 5a*/ unsigned char vs_dummy2[164]; | ||
150 | /*1fe*/ unsigned char vs_pmagic[2]; | ||
151 | }; | ||
152 | |||
153 | /* Yucky misaligned values */ | ||
154 | struct msdos_super_block { | ||
155 | /* 00*/ unsigned char ms_ignored[3]; | ||
156 | /* 03*/ unsigned char ms_sysid[8]; | ||
157 | /* 0b*/ unsigned char ms_sector_size[2]; | ||
158 | /* 0d*/ __u8 ms_cluster_size; | ||
159 | /* 0e*/ __u16 ms_reserved; | ||
160 | /* 10*/ __u8 ms_fats; | ||
161 | /* 11*/ unsigned char ms_dir_entries[2]; | ||
162 | /* 13*/ unsigned char ms_sectors[2]; | ||
163 | /* 15*/ unsigned char ms_media; | ||
164 | /* 16*/ __u16 ms_fat_length; | ||
165 | /* 18*/ __u16 ms_secs_track; | ||
166 | /* 1a*/ __u16 ms_heads; | ||
167 | /* 1c*/ __u32 ms_hidden; | ||
168 | /* 20*/ __u32 ms_total_sect; | ||
169 | /* 24*/ unsigned char ms_unknown[3]; | ||
170 | /* 27*/ unsigned char ms_serno[4]; | ||
171 | /* 2b*/ char ms_label[11]; | ||
172 | /* 36*/ unsigned char ms_magic[8]; | ||
173 | /* 3d*/ unsigned char ms_dummy2[192]; | ||
174 | /*1fe*/ unsigned char ms_pmagic[2]; | ||
175 | }; | ||
176 | |||
177 | struct minix_super_block { | ||
178 | __u16 ms_ninodes; | ||
179 | __u16 ms_nzones; | ||
180 | __u16 ms_imap_blocks; | ||
181 | __u16 ms_zmap_blocks; | ||
182 | __u16 ms_firstdatazone; | ||
183 | __u16 ms_log_zone_size; | ||
184 | __u32 ms_max_size; | ||
185 | unsigned char ms_magic[2]; | ||
186 | __u16 ms_state; | ||
187 | __u32 ms_zones; | ||
188 | }; | ||
189 | |||
190 | struct mdp_superblock_s { | ||
191 | __u32 md_magic; | ||
192 | __u32 major_version; | ||
193 | __u32 minor_version; | ||
194 | __u32 patch_version; | ||
195 | __u32 gvalid_words; | ||
196 | __u32 set_uuid0; | ||
197 | __u32 ctime; | ||
198 | __u32 level; | ||
199 | __u32 size; | ||
200 | __u32 nr_disks; | ||
201 | __u32 raid_disks; | ||
202 | __u32 md_minor; | ||
203 | __u32 not_persistent; | ||
204 | __u32 set_uuid1; | ||
205 | __u32 set_uuid2; | ||
206 | __u32 set_uuid3; | ||
207 | }; | ||
208 | |||
209 | struct hfs_super_block { | ||
210 | char h_magic[2]; | ||
211 | char h_dummy[18]; | ||
212 | __u32 h_blksize; | ||
213 | }; | ||
214 | |||
215 | struct ocfs_volume_header { | ||
216 | unsigned char minor_version[4]; | ||
217 | unsigned char major_version[4]; | ||
218 | unsigned char signature[128]; | ||
219 | unsigned char mount[128]; | ||
220 | unsigned char mount_len[2]; | ||
221 | }; | ||
222 | |||
223 | struct ocfs_volume_label { | ||
224 | unsigned char disk_lock[48]; | ||
225 | unsigned char label[64]; | ||
226 | unsigned char label_len[2]; | ||
227 | unsigned char vol_id[16]; | ||
228 | unsigned char vol_id_len[2]; | ||
229 | }; | ||
230 | |||
231 | #define ocfsmajor(o) ((__u32)o.major_version[0] \ | ||
232 | + (((__u32) o.major_version[1]) << 8) \ | ||
233 | + (((__u32) o.major_version[2]) << 16) \ | ||
234 | + (((__u32) o.major_version[3]) << 24)) | ||
235 | #define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8)) | ||
236 | #define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8)) | ||
237 | |||
238 | #define OCFS_MAGIC "OracleCFS" | ||
239 | |||
240 | struct ocfs2_super_block { | ||
241 | unsigned char signature[8]; | ||
242 | unsigned char s_dummy1[184]; | ||
243 | unsigned char s_dummy2[80]; | ||
244 | unsigned char s_label[64]; | ||
245 | unsigned char s_uuid[16]; | ||
246 | }; | ||
247 | |||
248 | #define OCFS2_MIN_BLOCKSIZE 512 | ||
249 | #define OCFS2_MAX_BLOCKSIZE 4096 | ||
250 | |||
251 | #define OCFS2_SUPER_BLOCK_BLKNO 2 | ||
252 | |||
253 | #define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2" | ||
254 | |||
255 | struct oracle_asm_disk_label { | ||
256 | char dummy[32]; | ||
257 | char dl_tag[8]; | ||
258 | char dl_id[24]; | ||
259 | }; | ||
260 | |||
261 | #define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK" | ||
262 | #define ORACLE_ASM_DISK_LABEL_OFFSET 32 | ||
263 | |||
264 | #define ISODCL(from, to) (to - from + 1) | ||
265 | struct iso_volume_descriptor { | ||
266 | char type[ISODCL(1,1)]; /* 711 */ | ||
267 | char id[ISODCL(2,6)]; | ||
268 | char version[ISODCL(7,7)]; | ||
269 | char data[ISODCL(8,2048)]; | ||
270 | }; | ||
271 | |||
272 | /* | ||
273 | * Byte swap functions | ||
274 | */ | ||
275 | #ifdef __GNUC__ | ||
276 | #define _INLINE_ static __inline__ | ||
277 | #else /* For Watcom C */ | ||
278 | #define _INLINE_ static inline | ||
279 | #endif | ||
280 | |||
281 | static __u16 blkid_swab16(__u16 val); | ||
282 | static __u32 blkid_swab32(__u32 val); | ||
283 | static __u64 blkid_swab64(__u64 val); | ||
284 | |||
285 | #if ((defined __GNUC__) && \ | ||
286 | (defined(__i386__) || defined(__i486__) || defined(__i586__))) | ||
287 | |||
288 | #define _BLKID_HAVE_ASM_BITOPS_ | ||
289 | |||
290 | _INLINE_ __u32 blkid_swab32(__u32 val) | ||
291 | { | ||
292 | #ifdef EXT2FS_REQUIRE_486 | ||
293 | __asm__("bswap %0" : "=r" (val) : "0" (val)); | ||
294 | #else | ||
295 | __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ | ||
296 | "rorl $16,%0\n\t" /* swap words */ | ||
297 | "xchgb %b0,%h0" /* swap higher bytes */ | ||
298 | :"=q" (val) | ||
299 | : "0" (val)); | ||
300 | #endif | ||
301 | return val; | ||
302 | } | ||
303 | |||
304 | _INLINE_ __u16 blkid_swab16(__u16 val) | ||
305 | { | ||
306 | __asm__("xchgb %b0,%h0" /* swap bytes */ \ | ||
307 | : "=q" (val) \ | ||
308 | : "0" (val)); \ | ||
309 | return val; | ||
310 | } | ||
311 | |||
312 | _INLINE_ __u64 blkid_swab64(__u64 val) | ||
313 | { | ||
314 | return (blkid_swab32(val >> 32) | | ||
315 | (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | #if !defined(_BLKID_HAVE_ASM_BITOPS_) | ||
320 | |||
321 | _INLINE_ __u16 blkid_swab16(__u16 val) | ||
322 | { | ||
323 | return (val >> 8) | (val << 8); | ||
324 | } | ||
325 | |||
326 | _INLINE_ __u32 blkid_swab32(__u32 val) | ||
327 | { | ||
328 | return ((val>>24) | ((val>>8)&0xFF00) | | ||
329 | ((val<<8)&0xFF0000) | (val<<24)); | ||
330 | } | ||
331 | |||
332 | _INLINE_ __u64 blkid_swab64(__u64 val) | ||
333 | { | ||
334 | return (blkid_swab32(val >> 32) | | ||
335 | (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); | ||
336 | } | ||
337 | #endif | ||
338 | |||
339 | |||
340 | |||
341 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
342 | #define blkid_le16(x) blkid_swab16(x) | ||
343 | #define blkid_le32(x) blkid_swab32(x) | ||
344 | #define blkid_le64(x) blkid_swab64(x) | ||
345 | #define blkid_be16(x) (x) | ||
346 | #define blkid_be32(x) (x) | ||
347 | #define blkid_be64(x) (x) | ||
348 | #else | ||
349 | #define blkid_le16(x) (x) | ||
350 | #define blkid_le32(x) (x) | ||
351 | #define blkid_le64(x) (x) | ||
352 | #define blkid_be16(x) blkid_swab16(x) | ||
353 | #define blkid_be32(x) blkid_swab32(x) | ||
354 | #define blkid_be64(x) blkid_swab64(x) | ||
355 | #endif | ||
356 | |||
357 | #undef _INLINE_ | ||
358 | |||
359 | #endif /* _BLKID_PROBE_H */ | ||
diff --git a/e2fsprogs/blkid/read.c b/e2fsprogs/blkid/read.c new file mode 100644 index 000000000..358554cb5 --- /dev/null +++ b/e2fsprogs/blkid/read.c | |||
@@ -0,0 +1,459 @@ | |||
1 | /* | ||
2 | * read.c - read the blkid cache from disk, to avoid scanning all devices | ||
3 | * | ||
4 | * Copyright (C) 2001, 2003 Theodore Y. Ts'o | ||
5 | * Copyright (C) 2001 Andreas Dilger | ||
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 <stdio.h> | ||
14 | #include <ctype.h> | ||
15 | #include <string.h> | ||
16 | #include <time.h> | ||
17 | #include <sys/types.h> | ||
18 | #include <sys/stat.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <unistd.h> | ||
21 | #if HAVE_ERRNO_H | ||
22 | #include <errno.h> | ||
23 | #endif | ||
24 | |||
25 | #include "blkidP.h" | ||
26 | #include "uuid/uuid.h" | ||
27 | |||
28 | #ifdef HAVE_STRTOULL | ||
29 | #define __USE_ISOC9X | ||
30 | #define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */ | ||
31 | #else | ||
32 | /* FIXME: need to support real strtoull here */ | ||
33 | #define STRTOULL strtoul | ||
34 | #endif | ||
35 | |||
36 | #if HAVE_STDLIB_H | ||
37 | #include <stdlib.h> | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | * File format: | ||
42 | * | ||
43 | * <device [<NAME="value"> ...]>device_name</device> | ||
44 | * | ||
45 | * The following tags are required for each entry: | ||
46 | * <ID="id"> unique (within this file) ID number of this device | ||
47 | * <TIME="time"> (ascii time_t) time this entry was last read from disk | ||
48 | * <TYPE="type"> (detected) type of filesystem/data for this partition | ||
49 | * | ||
50 | * The following tags may be present, depending on the device contents | ||
51 | * <LABEL="label"> (user supplied) label (volume name, etc) | ||
52 | * <UUID="uuid"> (generated) universally unique identifier (serial no) | ||
53 | */ | ||
54 | |||
55 | static char *skip_over_blank(char *cp) | ||
56 | { | ||
57 | while (*cp && isspace(*cp)) | ||
58 | cp++; | ||
59 | return cp; | ||
60 | } | ||
61 | |||
62 | static char *skip_over_word(char *cp) | ||
63 | { | ||
64 | char ch; | ||
65 | |||
66 | while ((ch = *cp)) { | ||
67 | /* If we see a backslash, skip the next character */ | ||
68 | if (ch == '\\') { | ||
69 | cp++; | ||
70 | if (*cp == '\0') | ||
71 | break; | ||
72 | cp++; | ||
73 | continue; | ||
74 | } | ||
75 | if (isspace(ch) || ch == '<' || ch == '>') | ||
76 | break; | ||
77 | cp++; | ||
78 | } | ||
79 | return cp; | ||
80 | } | ||
81 | |||
82 | static char *strip_line(char *line) | ||
83 | { | ||
84 | char *p; | ||
85 | |||
86 | line = skip_over_blank(line); | ||
87 | |||
88 | p = line + strlen(line) - 1; | ||
89 | |||
90 | while (*line) { | ||
91 | if (isspace(*p)) | ||
92 | *p-- = '\0'; | ||
93 | else | ||
94 | break; | ||
95 | } | ||
96 | |||
97 | return line; | ||
98 | } | ||
99 | |||
100 | #if 0 | ||
101 | static char *parse_word(char **buf) | ||
102 | { | ||
103 | char *word, *next; | ||
104 | |||
105 | word = *buf; | ||
106 | if (*word == '\0') | ||
107 | return NULL; | ||
108 | |||
109 | word = skip_over_blank(word); | ||
110 | next = skip_over_word(word); | ||
111 | if (*next) { | ||
112 | char *end = next - 1; | ||
113 | if (*end == '"' || *end == '\'') | ||
114 | *end = '\0'; | ||
115 | *next++ = '\0'; | ||
116 | } | ||
117 | *buf = next; | ||
118 | |||
119 | if (*word == '"' || *word == '\'') | ||
120 | word++; | ||
121 | return word; | ||
122 | } | ||
123 | #endif | ||
124 | |||
125 | /* | ||
126 | * Start parsing a new line from the cache. | ||
127 | * | ||
128 | * line starts with "<device" return 1 -> continue parsing line | ||
129 | * line starts with "<foo", empty, or # return 0 -> skip line | ||
130 | * line starts with other, return -BLKID_ERR_CACHE -> error | ||
131 | */ | ||
132 | static int parse_start(char **cp) | ||
133 | { | ||
134 | char *p; | ||
135 | |||
136 | p = strip_line(*cp); | ||
137 | |||
138 | /* Skip comment or blank lines. We can't just NUL the first '#' char, | ||
139 | * in case it is inside quotes, or escaped. | ||
140 | */ | ||
141 | if (*p == '\0' || *p == '#') | ||
142 | return 0; | ||
143 | |||
144 | if (!strncmp(p, "<device", 7)) { | ||
145 | DBG(DEBUG_READ, printf("found device header: %8s\n", p)); | ||
146 | p += 7; | ||
147 | |||
148 | *cp = p; | ||
149 | return 1; | ||
150 | } | ||
151 | |||
152 | if (*p == '<') | ||
153 | return 0; | ||
154 | |||
155 | return -BLKID_ERR_CACHE; | ||
156 | } | ||
157 | |||
158 | /* Consume the remaining XML on the line (cosmetic only) */ | ||
159 | static int parse_end(char **cp) | ||
160 | { | ||
161 | *cp = skip_over_blank(*cp); | ||
162 | |||
163 | if (!strncmp(*cp, "</device>", 9)) { | ||
164 | DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp)); | ||
165 | *cp += 9; | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | return -BLKID_ERR_CACHE; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Allocate a new device struct with device name filled in. Will handle | ||
174 | * finding the device on lines of the form: | ||
175 | * <device foo=bar>devname</device> | ||
176 | * <device>devname<foo>bar</foo></device> | ||
177 | */ | ||
178 | static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) | ||
179 | { | ||
180 | char *start, *tmp, *end, *name; | ||
181 | int ret; | ||
182 | |||
183 | if ((ret = parse_start(cp)) <= 0) | ||
184 | return ret; | ||
185 | |||
186 | start = tmp = strchr(*cp, '>'); | ||
187 | if (!start) { | ||
188 | DBG(DEBUG_READ, | ||
189 | printf("blkid: short line parsing dev: %s\n", *cp)); | ||
190 | return -BLKID_ERR_CACHE; | ||
191 | } | ||
192 | start = skip_over_blank(start + 1); | ||
193 | end = skip_over_word(start); | ||
194 | |||
195 | DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start)); | ||
196 | |||
197 | if (**cp == '>') | ||
198 | *cp = end; | ||
199 | else | ||
200 | (*cp)++; | ||
201 | |||
202 | *tmp = '\0'; | ||
203 | |||
204 | if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { | ||
205 | DBG(DEBUG_READ, | ||
206 | printf("blkid: missing </device> ending: %s\n", end)); | ||
207 | } else if (tmp) | ||
208 | *tmp = '\0'; | ||
209 | |||
210 | if (end - start <= 1) { | ||
211 | DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp)); | ||
212 | return -BLKID_ERR_CACHE; | ||
213 | } | ||
214 | |||
215 | name = blkid_strndup(start, end-start); | ||
216 | if (name == NULL) | ||
217 | return -BLKID_ERR_MEM; | ||
218 | |||
219 | DBG(DEBUG_READ, printf("found dev %s\n", name)); | ||
220 | |||
221 | if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) | ||
222 | return -BLKID_ERR_MEM; | ||
223 | |||
224 | free(name); | ||
225 | return 1; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Extract a tag of the form NAME="value" from the line. | ||
230 | */ | ||
231 | static int parse_token(char **name, char **value, char **cp) | ||
232 | { | ||
233 | char *end; | ||
234 | |||
235 | if (!name || !value || !cp) | ||
236 | return -BLKID_ERR_PARAM; | ||
237 | |||
238 | if (!(*value = strchr(*cp, '='))) | ||
239 | return 0; | ||
240 | |||
241 | **value = '\0'; | ||
242 | *name = strip_line(*cp); | ||
243 | *value = skip_over_blank(*value + 1); | ||
244 | |||
245 | if (**value == '"') { | ||
246 | end = strchr(*value + 1, '"'); | ||
247 | if (!end) { | ||
248 | DBG(DEBUG_READ, | ||
249 | printf("unbalanced quotes at: %s\n", *value)); | ||
250 | *cp = *value; | ||
251 | return -BLKID_ERR_CACHE; | ||
252 | } | ||
253 | (*value)++; | ||
254 | *end = '\0'; | ||
255 | end++; | ||
256 | } else { | ||
257 | end = skip_over_word(*value); | ||
258 | if (*end) { | ||
259 | *end = '\0'; | ||
260 | end++; | ||
261 | } | ||
262 | } | ||
263 | *cp = end; | ||
264 | |||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Extract a tag of the form <NAME>value</NAME> from the line. | ||
270 | */ | ||
271 | /* | ||
272 | static int parse_xml(char **name, char **value, char **cp) | ||
273 | { | ||
274 | char *end; | ||
275 | |||
276 | if (!name || !value || !cp) | ||
277 | return -BLKID_ERR_PARAM; | ||
278 | |||
279 | *name = strip_line(*cp); | ||
280 | |||
281 | if ((*name)[0] != '<' || (*name)[1] == '/') | ||
282 | return 0; | ||
283 | |||
284 | FIXME: finish this. | ||
285 | } | ||
286 | */ | ||
287 | |||
288 | /* | ||
289 | * Extract a tag from the line. | ||
290 | * | ||
291 | * Return 1 if a valid tag was found. | ||
292 | * Return 0 if no tag found. | ||
293 | * Return -ve error code. | ||
294 | */ | ||
295 | static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) | ||
296 | { | ||
297 | char *name; | ||
298 | char *value; | ||
299 | int ret; | ||
300 | |||
301 | if (!cache || !dev) | ||
302 | return -BLKID_ERR_PARAM; | ||
303 | |||
304 | if ((ret = parse_token(&name, &value, cp)) <= 0 /* && | ||
305 | (ret = parse_xml(&name, &value, cp)) <= 0 */) | ||
306 | return ret; | ||
307 | |||
308 | /* Some tags are stored directly in the device struct */ | ||
309 | if (!strcmp(name, "DEVNO")) | ||
310 | dev->bid_devno = STRTOULL(value, 0, 0); | ||
311 | else if (!strcmp(name, "PRI")) | ||
312 | dev->bid_pri = strtol(value, 0, 0); | ||
313 | else if (!strcmp(name, "TIME")) | ||
314 | /* FIXME: need to parse a long long eventually */ | ||
315 | dev->bid_time = strtol(value, 0, 0); | ||
316 | else | ||
317 | ret = blkid_set_tag(dev, name, value, strlen(value)); | ||
318 | |||
319 | DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); | ||
320 | |||
321 | return ret < 0 ? ret : 1; | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Parse a single line of data, and return a newly allocated dev struct. | ||
326 | * Add the new device to the cache struct, if one was read. | ||
327 | * | ||
328 | * Lines are of the form <device [TAG="value" ...]>/dev/foo</device> | ||
329 | * | ||
330 | * Returns -ve value on error. | ||
331 | * Returns 0 otherwise. | ||
332 | * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL | ||
333 | * (e.g. comment lines, unknown XML content, etc). | ||
334 | */ | ||
335 | static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) | ||
336 | { | ||
337 | blkid_dev dev; | ||
338 | int ret; | ||
339 | |||
340 | if (!cache || !dev_p) | ||
341 | return -BLKID_ERR_PARAM; | ||
342 | |||
343 | *dev_p = NULL; | ||
344 | |||
345 | DBG(DEBUG_READ, printf("line: %s\n", cp)); | ||
346 | |||
347 | if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) | ||
348 | return ret; | ||
349 | |||
350 | dev = *dev_p; | ||
351 | |||
352 | while ((ret = parse_tag(cache, dev, &cp)) > 0) { | ||
353 | ; | ||
354 | } | ||
355 | |||
356 | if (dev->bid_type == NULL) { | ||
357 | DBG(DEBUG_READ, | ||
358 | printf("blkid: device %s has no TYPE\n",dev->bid_name)); | ||
359 | blkid_free_dev(dev); | ||
360 | } | ||
361 | |||
362 | DEB_DUMP_DEV(DEBUG_READ, dev); | ||
363 | |||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Parse the specified filename, and return the data in the supplied or | ||
369 | * a newly allocated cache struct. If the file doesn't exist, return a | ||
370 | * new empty cache struct. | ||
371 | */ | ||
372 | void blkid_read_cache(blkid_cache cache) | ||
373 | { | ||
374 | FILE *file; | ||
375 | char buf[4096]; | ||
376 | int fd, lineno = 0; | ||
377 | struct stat st; | ||
378 | |||
379 | if (!cache) | ||
380 | return; | ||
381 | |||
382 | /* | ||
383 | * If the file doesn't exist, then we just return an empty | ||
384 | * struct so that the cache can be populated. | ||
385 | */ | ||
386 | if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) | ||
387 | return; | ||
388 | if (fstat(fd, &st) < 0) | ||
389 | goto errout; | ||
390 | if ((st.st_mtime == cache->bic_ftime) || | ||
391 | (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { | ||
392 | DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", | ||
393 | cache->bic_filename)); | ||
394 | goto errout; | ||
395 | } | ||
396 | |||
397 | DBG(DEBUG_CACHE, printf("reading cache file %s\n", | ||
398 | cache->bic_filename)); | ||
399 | |||
400 | file = fdopen(fd, "r"); | ||
401 | if (!file) | ||
402 | goto errout; | ||
403 | |||
404 | while (fgets(buf, sizeof(buf), file)) { | ||
405 | blkid_dev dev; | ||
406 | unsigned int end; | ||
407 | |||
408 | lineno++; | ||
409 | if (buf[0] == 0) | ||
410 | continue; | ||
411 | end = strlen(buf) - 1; | ||
412 | /* Continue reading next line if it ends with a backslash */ | ||
413 | while (buf[end] == '\\' && end < sizeof(buf) - 2 && | ||
414 | fgets(buf + end, sizeof(buf) - end, file)) { | ||
415 | end = strlen(buf) - 1; | ||
416 | lineno++; | ||
417 | } | ||
418 | |||
419 | if (blkid_parse_line(cache, &dev, buf) < 0) { | ||
420 | DBG(DEBUG_READ, | ||
421 | printf("blkid: bad format on line %d\n", lineno)); | ||
422 | continue; | ||
423 | } | ||
424 | } | ||
425 | fclose(file); | ||
426 | |||
427 | /* | ||
428 | * Initially we do not need to write out the cache file. | ||
429 | */ | ||
430 | cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; | ||
431 | cache->bic_ftime = st.st_mtime; | ||
432 | |||
433 | return; | ||
434 | errout: | ||
435 | close(fd); | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | #ifdef TEST_PROGRAM | ||
440 | int main(int argc, char**argv) | ||
441 | { | ||
442 | blkid_cache cache = NULL; | ||
443 | int ret; | ||
444 | |||
445 | blkid_debug_mask = DEBUG_ALL; | ||
446 | if (argc > 2) { | ||
447 | fprintf(stderr, "Usage: %s [filename]\n" | ||
448 | "Test parsing of the cache (filename)\n", argv[0]); | ||
449 | exit(1); | ||
450 | } | ||
451 | if ((ret = blkid_get_cache(&cache, argv[1])) < 0) | ||
452 | fprintf(stderr, "error %d reading cache file %s\n", ret, | ||
453 | argv[1] ? argv[1] : BLKID_CACHE_FILE); | ||
454 | |||
455 | blkid_put_cache(cache); | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | #endif | ||
diff --git a/e2fsprogs/blkid/resolve.c b/e2fsprogs/blkid/resolve.c new file mode 100644 index 000000000..3dca74ff4 --- /dev/null +++ b/e2fsprogs/blkid/resolve.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * resolve.c - resolve names and tags into specific devices | ||
3 | * | ||
4 | * Copyright (C) 2001, 2003 Theodore Ts'o. | ||
5 | * Copyright (C) 2001 Andreas Dilger | ||
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 <stdio.h> | ||
14 | #if HAVE_UNISTD_H | ||
15 | #include <unistd.h> | ||
16 | #endif | ||
17 | #include <stdlib.h> | ||
18 | #include <fcntl.h> | ||
19 | #include <string.h> | ||
20 | #include <sys/types.h> | ||
21 | #include <sys/stat.h> | ||
22 | #include "blkidP.h" | ||
23 | #include "probe.h" | ||
24 | |||
25 | /* | ||
26 | * Find a tagname (e.g. LABEL or UUID) on a specific device. | ||
27 | */ | ||
28 | char *blkid_get_tag_value(blkid_cache cache, const char *tagname, | ||
29 | const char *devname) | ||
30 | { | ||
31 | blkid_tag found; | ||
32 | blkid_dev dev; | ||
33 | blkid_cache c = cache; | ||
34 | char *ret = NULL; | ||
35 | |||
36 | DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname)); | ||
37 | |||
38 | if (!devname) | ||
39 | return NULL; | ||
40 | |||
41 | if (!cache) { | ||
42 | if (blkid_get_cache(&c, NULL) < 0) | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) && | ||
47 | (found = blkid_find_tag_dev(dev, tagname))) | ||
48 | ret = blkid_strdup(found->bit_val); | ||
49 | |||
50 | if (!cache) | ||
51 | blkid_put_cache(c); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Locate a device name from a token (NAME=value string), or (name, value) | ||
58 | * pair. In the case of a token, value is ignored. If the "token" is not | ||
59 | * of the form "NAME=value" and there is no value given, then it is assumed | ||
60 | * to be the actual devname and a copy is returned. | ||
61 | */ | ||
62 | char *blkid_get_devname(blkid_cache cache, const char *token, | ||
63 | const char *value) | ||
64 | { | ||
65 | blkid_dev dev; | ||
66 | blkid_cache c = cache; | ||
67 | char *t = 0, *v = 0; | ||
68 | char *ret = NULL; | ||
69 | |||
70 | if (!token) | ||
71 | return NULL; | ||
72 | |||
73 | if (!cache) { | ||
74 | if (blkid_get_cache(&c, NULL) < 0) | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | DBG(DEBUG_RESOLVE, | ||
79 | printf("looking for %s%s%s %s\n", token, value ? "=" : "", | ||
80 | value ? value : "", cache ? "in cache" : "from disk")); | ||
81 | |||
82 | if (!value) { | ||
83 | if (!strchr(token, '=')) | ||
84 | return blkid_strdup(token); | ||
85 | blkid_parse_tag_string(token, &t, &v); | ||
86 | if (!t || !v) | ||
87 | goto errout; | ||
88 | token = t; | ||
89 | value = v; | ||
90 | } | ||
91 | |||
92 | dev = blkid_find_dev_with_tag(c, token, value); | ||
93 | if (!dev) | ||
94 | goto errout; | ||
95 | |||
96 | ret = blkid_strdup(blkid_dev_devname(dev)); | ||
97 | |||
98 | errout: | ||
99 | if (t) | ||
100 | free(t); | ||
101 | if (v) | ||
102 | free(v); | ||
103 | if (!cache) { | ||
104 | blkid_put_cache(c); | ||
105 | } | ||
106 | return (ret); | ||
107 | } | ||
108 | |||
109 | #ifdef TEST_PROGRAM | ||
110 | int main(int argc, char **argv) | ||
111 | { | ||
112 | char *value; | ||
113 | blkid_cache cache; | ||
114 | |||
115 | blkid_debug_mask = DEBUG_ALL; | ||
116 | if (argc != 2 && argc != 3) { | ||
117 | fprintf(stderr, "Usage:\t%s tagname=value\n" | ||
118 | "\t%s tagname devname\n" | ||
119 | "Find which device holds a given token or\n" | ||
120 | "Find what the value of a tag is in a device\n", | ||
121 | argv[0], argv[0]); | ||
122 | exit(1); | ||
123 | } | ||
124 | if (blkid_get_cache(&cache, "/dev/null") < 0) { | ||
125 | fprintf(stderr, "Couldn't get blkid cache\n"); | ||
126 | exit(1); | ||
127 | } | ||
128 | |||
129 | if (argv[2]) { | ||
130 | value = blkid_get_tag_value(cache, argv[1], argv[2]); | ||
131 | printf("%s has tag %s=%s\n", argv[2], argv[1], | ||
132 | value ? value : "<missing>"); | ||
133 | } else { | ||
134 | value = blkid_get_devname(cache, argv[1], NULL); | ||
135 | printf("%s has tag %s\n", value ? value : "<none>", argv[1]); | ||
136 | } | ||
137 | blkid_put_cache(cache); | ||
138 | return value ? 0 : 1; | ||
139 | } | ||
140 | #endif | ||
diff --git a/e2fsprogs/blkid/save.c b/e2fsprogs/blkid/save.c new file mode 100644 index 000000000..a2fbd7b45 --- /dev/null +++ b/e2fsprogs/blkid/save.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * save.c - write the cache struct to disk | ||
3 | * | ||
4 | * Copyright (C) 2001 by Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdio.h> | ||
14 | #include <string.h> | ||
15 | #include <stdlib.h> | ||
16 | #include <unistd.h> | ||
17 | #include <sys/types.h> | ||
18 | #ifdef HAVE_SYS_STAT_H | ||
19 | #include <sys/stat.h> | ||
20 | #endif | ||
21 | #ifdef HAVE_SYS_MKDEV_H | ||
22 | #include <sys/mkdev.h> | ||
23 | #endif | ||
24 | #ifdef HAVE_ERRNO_H | ||
25 | #include <errno.h> | ||
26 | #endif | ||
27 | #include "blkidP.h" | ||
28 | |||
29 | static int save_dev(blkid_dev dev, FILE *file) | ||
30 | { | ||
31 | struct list_head *p; | ||
32 | |||
33 | if (!dev || dev->bid_name[0] != '/') | ||
34 | return 0; | ||
35 | |||
36 | DBG(DEBUG_SAVE, | ||
37 | printf("device %s, type %s\n", dev->bid_name, dev->bid_type)); | ||
38 | |||
39 | fprintf(file, | ||
40 | "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"", | ||
41 | (unsigned long) dev->bid_devno, dev->bid_time); | ||
42 | if (dev->bid_pri) | ||
43 | fprintf(file, " PRI=\"%d\"", dev->bid_pri); | ||
44 | list_for_each(p, &dev->bid_tags) { | ||
45 | blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); | ||
46 | fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); | ||
47 | } | ||
48 | fprintf(file, ">%s</device>\n", dev->bid_name); | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Write out the cache struct to the cache file on disk. | ||
55 | */ | ||
56 | int blkid_flush_cache(blkid_cache cache) | ||
57 | { | ||
58 | struct list_head *p; | ||
59 | char *tmp = NULL; | ||
60 | const char *opened = NULL; | ||
61 | const char *filename; | ||
62 | FILE *file = NULL; | ||
63 | int fd, ret = 0; | ||
64 | struct stat st; | ||
65 | |||
66 | if (!cache) | ||
67 | return -BLKID_ERR_PARAM; | ||
68 | |||
69 | if (list_empty(&cache->bic_devs) || | ||
70 | !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { | ||
71 | DBG(DEBUG_SAVE, printf("skipping cache file write\n")); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; | ||
76 | |||
77 | /* If we can't write to the cache file, then don't even try */ | ||
78 | if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || | ||
79 | (ret == 0 && access(filename, W_OK) < 0)) { | ||
80 | DBG(DEBUG_SAVE, | ||
81 | printf("can't write to cache file %s\n", filename)); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Try and create a temporary file in the same directory so | ||
87 | * that in case of error we don't overwrite the cache file. | ||
88 | * If the cache file doesn't yet exist, it isn't a regular | ||
89 | * file (e.g. /dev/null or a socket), or we couldn't create | ||
90 | * a temporary file then we open it directly. | ||
91 | */ | ||
92 | if (ret == 0 && S_ISREG(st.st_mode)) { | ||
93 | tmp = malloc(strlen(filename) + 8); | ||
94 | if (tmp) { | ||
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 | |||
105 | if (!file) { | ||
106 | file = fopen(filename, "w"); | ||
107 | opened = filename; | ||
108 | } | ||
109 | |||
110 | DBG(DEBUG_SAVE, | ||
111 | printf("writing cache file %s (really %s)\n", | ||
112 | filename, opened)); | ||
113 | |||
114 | if (!file) { | ||
115 | ret = errno; | ||
116 | goto errout; | ||
117 | } | ||
118 | |||
119 | list_for_each(p, &cache->bic_devs) { | ||
120 | blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); | ||
121 | if (!dev->bid_type) | ||
122 | continue; | ||
123 | if ((ret = save_dev(dev, file)) < 0) | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | if (ret >= 0) { | ||
128 | cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; | ||
129 | ret = 1; | ||
130 | } | ||
131 | |||
132 | fclose(file); | ||
133 | if (opened != filename) { | ||
134 | if (ret < 0) { | ||
135 | unlink(opened); | ||
136 | DBG(DEBUG_SAVE, | ||
137 | printf("unlinked temp cache %s\n", opened)); | ||
138 | } else { | ||
139 | char *backup; | ||
140 | |||
141 | backup = malloc(strlen(filename) + 5); | ||
142 | if (backup) { | ||
143 | sprintf(backup, "%s.old", filename); | ||
144 | unlink(backup); | ||
145 | link(filename, backup); | ||
146 | free(backup); | ||
147 | } | ||
148 | rename(opened, filename); | ||
149 | DBG(DEBUG_SAVE, | ||
150 | printf("moved temp cache %s\n", opened)); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | errout: | ||
155 | if (tmp) | ||
156 | free(tmp); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | #ifdef TEST_PROGRAM | ||
161 | int main(int argc, char **argv) | ||
162 | { | ||
163 | blkid_cache cache = NULL; | ||
164 | int ret; | ||
165 | |||
166 | blkid_debug_mask = DEBUG_ALL; | ||
167 | if (argc > 2) { | ||
168 | fprintf(stderr, "Usage: %s [filename]\n" | ||
169 | "Test loading/saving a cache (filename)\n", argv[0]); | ||
170 | exit(1); | ||
171 | } | ||
172 | |||
173 | if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | ||
174 | fprintf(stderr, "%s: error creating cache (%d)\n", | ||
175 | argv[0], ret); | ||
176 | exit(1); | ||
177 | } | ||
178 | if ((ret = blkid_probe_all(cache)) < 0) { | ||
179 | fprintf(stderr, "error (%d) probing devices\n", ret); | ||
180 | exit(1); | ||
181 | } | ||
182 | cache->bic_filename = blkid_strdup(argv[1]); | ||
183 | |||
184 | if ((ret = blkid_flush_cache(cache)) < 0) { | ||
185 | fprintf(stderr, "error (%d) saving cache\n", ret); | ||
186 | exit(1); | ||
187 | } | ||
188 | |||
189 | blkid_put_cache(cache); | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | #endif | ||
diff --git a/e2fsprogs/blkid/tag.c b/e2fsprogs/blkid/tag.c new file mode 100644 index 000000000..63e5e7b4d --- /dev/null +++ b/e2fsprogs/blkid/tag.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * tag.c - allocation/initialization/free routines for tag structs | ||
3 | * | ||
4 | * Copyright (C) 2001 Andreas Dilger | ||
5 | * Copyright (C) 2003 Theodore Ts'o | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the | ||
9 | * GNU Lesser General Public License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <stdio.h> | ||
16 | |||
17 | #include "blkidP.h" | ||
18 | |||
19 | static blkid_tag blkid_new_tag(void) | ||
20 | { | ||
21 | blkid_tag tag; | ||
22 | |||
23 | if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag)))) | ||
24 | return NULL; | ||
25 | |||
26 | INIT_LIST_HEAD(&tag->bit_tags); | ||
27 | INIT_LIST_HEAD(&tag->bit_names); | ||
28 | |||
29 | return tag; | ||
30 | } | ||
31 | |||
32 | void blkid_free_tag(blkid_tag tag) | ||
33 | { | ||
34 | if (!tag) | ||
35 | return; | ||
36 | |||
37 | DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name, | ||
38 | tag->bit_val ? tag->bit_val : "(NULL)")); | ||
39 | DEB_DUMP_TAG(DEBUG_TAG, tag); | ||
40 | |||
41 | list_del(&tag->bit_tags); /* list of tags for this device */ | ||
42 | list_del(&tag->bit_names); /* list of tags with this type */ | ||
43 | |||
44 | if (tag->bit_name) | ||
45 | free(tag->bit_name); | ||
46 | if (tag->bit_val) | ||
47 | free(tag->bit_val); | ||
48 | |||
49 | free(tag); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Find the desired tag on a device. If value is NULL, then the | ||
54 | * first such tag is returned, otherwise return only exact tag if found. | ||
55 | */ | ||
56 | blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) | ||
57 | { | ||
58 | struct list_head *p; | ||
59 | |||
60 | if (!dev || !type) | ||
61 | return NULL; | ||
62 | |||
63 | list_for_each(p, &dev->bid_tags) { | ||
64 | blkid_tag tmp = list_entry(p, struct blkid_struct_tag, | ||
65 | bit_tags); | ||
66 | |||
67 | if (!strcmp(tmp->bit_name, type)) | ||
68 | return tmp; | ||
69 | } | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Find the desired tag type in the cache. | ||
75 | * We return the head tag for this tag type. | ||
76 | */ | ||
77 | static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) | ||
78 | { | ||
79 | blkid_tag head = NULL, tmp; | ||
80 | struct list_head *p; | ||
81 | |||
82 | if (!cache || !type) | ||
83 | return NULL; | ||
84 | |||
85 | list_for_each(p, &cache->bic_tags) { | ||
86 | tmp = list_entry(p, struct blkid_struct_tag, bit_tags); | ||
87 | if (!strcmp(tmp->bit_name, type)) { | ||
88 | DBG(DEBUG_TAG, | ||
89 | printf(" found cache tag head %s\n", type)); | ||
90 | head = tmp; | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | return head; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Set a tag on an existing device. | ||
99 | * | ||
100 | * If value is NULL, then delete the tagsfrom the device. | ||
101 | */ | ||
102 | int blkid_set_tag(blkid_dev dev, const char *name, | ||
103 | const char *value, const int vlength) | ||
104 | { | ||
105 | blkid_tag t = 0, head = 0; | ||
106 | char *val = 0; | ||
107 | |||
108 | if (!dev || !name) | ||
109 | return -BLKID_ERR_PARAM; | ||
110 | |||
111 | if (!(val = blkid_strndup(value, vlength)) && value) | ||
112 | return -BLKID_ERR_MEM; | ||
113 | t = blkid_find_tag_dev(dev, name); | ||
114 | if (!value) { | ||
115 | if (t) | ||
116 | blkid_free_tag(t); | ||
117 | } else if (t) { | ||
118 | if (!strcmp(t->bit_val, val)) { | ||
119 | /* Same thing, exit */ | ||
120 | free(val); | ||
121 | return 0; | ||
122 | } | ||
123 | free(t->bit_val); | ||
124 | t->bit_val = val; | ||
125 | } else { | ||
126 | /* Existing tag not present, add to device */ | ||
127 | if (!(t = blkid_new_tag())) | ||
128 | goto errout; | ||
129 | t->bit_name = blkid_strdup(name); | ||
130 | t->bit_val = val; | ||
131 | t->bit_dev = dev; | ||
132 | |||
133 | list_add_tail(&t->bit_tags, &dev->bid_tags); | ||
134 | |||
135 | if (dev->bid_cache) { | ||
136 | head = blkid_find_head_cache(dev->bid_cache, | ||
137 | t->bit_name); | ||
138 | if (!head) { | ||
139 | head = blkid_new_tag(); | ||
140 | if (!head) | ||
141 | goto errout; | ||
142 | |||
143 | DBG(DEBUG_TAG, | ||
144 | printf(" creating new cache tag head %s\n", name)); | ||
145 | head->bit_name = blkid_strdup(name); | ||
146 | if (!head->bit_name) | ||
147 | goto errout; | ||
148 | list_add_tail(&head->bit_tags, | ||
149 | &dev->bid_cache->bic_tags); | ||
150 | } | ||
151 | list_add_tail(&t->bit_names, &head->bit_names); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* Link common tags directly to the device struct */ | ||
156 | if (!strcmp(name, "TYPE")) | ||
157 | dev->bid_type = val; | ||
158 | else if (!strcmp(name, "LABEL")) | ||
159 | dev->bid_label = val; | ||
160 | else if (!strcmp(name, "UUID")) | ||
161 | dev->bid_uuid = val; | ||
162 | |||
163 | if (dev->bid_cache) | ||
164 | dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; | ||
165 | return 0; | ||
166 | |||
167 | errout: | ||
168 | if (t) | ||
169 | blkid_free_tag(t); | ||
170 | else if (val) | ||
171 | free(val); | ||
172 | if (head) | ||
173 | blkid_free_tag(head); | ||
174 | return -BLKID_ERR_MEM; | ||
175 | } | ||
176 | |||
177 | |||
178 | /* | ||
179 | * Parse a "NAME=value" string. This is slightly different than | ||
180 | * parse_token, because that will end an unquoted value at a space, while | ||
181 | * this will assume that an unquoted value is the rest of the token (e.g. | ||
182 | * if we are passed an already quoted string from the command-line we don't | ||
183 | * have to both quote and escape quote so that the quotes make it to | ||
184 | * us). | ||
185 | * | ||
186 | * Returns 0 on success, and -1 on failure. | ||
187 | */ | ||
188 | int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) | ||
189 | { | ||
190 | char *name, *value, *cp; | ||
191 | |||
192 | DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token)); | ||
193 | |||
194 | if (!token || !(cp = strchr(token, '='))) | ||
195 | return -1; | ||
196 | |||
197 | name = blkid_strdup(token); | ||
198 | if (!name) | ||
199 | return -1; | ||
200 | value = name + (cp - token); | ||
201 | *value++ = '\0'; | ||
202 | if (*value == '"' || *value == '\'') { | ||
203 | char c = *value++; | ||
204 | if (!(cp = strrchr(value, c))) | ||
205 | goto errout; /* missing closing quote */ | ||
206 | *cp = '\0'; | ||
207 | } | ||
208 | value = blkid_strdup(value); | ||
209 | if (!value) | ||
210 | goto errout; | ||
211 | |||
212 | *ret_type = name; | ||
213 | *ret_val = value; | ||
214 | |||
215 | return 0; | ||
216 | |||
217 | errout: | ||
218 | free(name); | ||
219 | return -1; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Tag iteration routines for the public libblkid interface. | ||
224 | * | ||
225 | * These routines do not expose the list.h implementation, which are a | ||
226 | * contamination of the namespace, and which force us to reveal far, far | ||
227 | * too much of our internal implemenation. I'm not convinced I want | ||
228 | * to keep list.h in the long term, anyway. It's fine for kernel | ||
229 | * programming, but performance is not the #1 priority for this | ||
230 | * library, and I really don't like the tradeoff of type-safety for | ||
231 | * performance for this application. [tytso:20030125.2007EST] | ||
232 | */ | ||
233 | |||
234 | /* | ||
235 | * This series of functions iterate over all tags in a device | ||
236 | */ | ||
237 | #define TAG_ITERATE_MAGIC 0x01a5284c | ||
238 | |||
239 | struct blkid_struct_tag_iterate { | ||
240 | int magic; | ||
241 | blkid_dev dev; | ||
242 | struct list_head *p; | ||
243 | }; | ||
244 | |||
245 | extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev) | ||
246 | { | ||
247 | blkid_tag_iterate iter; | ||
248 | |||
249 | iter = malloc(sizeof(struct blkid_struct_tag_iterate)); | ||
250 | if (iter) { | ||
251 | iter->magic = TAG_ITERATE_MAGIC; | ||
252 | iter->dev = dev; | ||
253 | iter->p = dev->bid_tags.next; | ||
254 | } | ||
255 | return (iter); | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * Return 0 on success, -1 on error | ||
260 | */ | ||
261 | extern int blkid_tag_next(blkid_tag_iterate iter, | ||
262 | const char **type, const char **value) | ||
263 | { | ||
264 | blkid_tag tag; | ||
265 | |||
266 | *type = 0; | ||
267 | *value = 0; | ||
268 | if (!iter || iter->magic != TAG_ITERATE_MAGIC || | ||
269 | iter->p == &iter->dev->bid_tags) | ||
270 | return -1; | ||
271 | tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags); | ||
272 | *type = tag->bit_name; | ||
273 | *value = tag->bit_val; | ||
274 | iter->p = iter->p->next; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | extern void blkid_tag_iterate_end(blkid_tag_iterate iter) | ||
279 | { | ||
280 | if (!iter || iter->magic != TAG_ITERATE_MAGIC) | ||
281 | return; | ||
282 | iter->magic = 0; | ||
283 | free(iter); | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * This function returns a device which matches a particular | ||
288 | * type/value pair. If there is more than one device that matches the | ||
289 | * search specification, it returns the one with the highest priority | ||
290 | * value. This allows us to give preference to EVMS or LVM devices. | ||
291 | * | ||
292 | * XXX there should also be an interface which uses an iterator so we | ||
293 | * can get all of the devices which match a type/value search parameter. | ||
294 | */ | ||
295 | extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, | ||
296 | const char *type, | ||
297 | const char *value) | ||
298 | { | ||
299 | blkid_tag head; | ||
300 | blkid_dev dev; | ||
301 | int pri; | ||
302 | struct list_head *p; | ||
303 | |||
304 | if (!cache || !type || !value) | ||
305 | return NULL; | ||
306 | |||
307 | blkid_read_cache(cache); | ||
308 | |||
309 | DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); | ||
310 | |||
311 | try_again: | ||
312 | pri = -1; | ||
313 | dev = 0; | ||
314 | head = blkid_find_head_cache(cache, type); | ||
315 | |||
316 | if (head) { | ||
317 | list_for_each(p, &head->bit_names) { | ||
318 | blkid_tag tmp = list_entry(p, struct blkid_struct_tag, | ||
319 | bit_names); | ||
320 | |||
321 | if (!strcmp(tmp->bit_val, value) && | ||
322 | tmp->bit_dev->bid_pri > pri) { | ||
323 | dev = tmp->bit_dev; | ||
324 | pri = dev->bid_pri; | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { | ||
329 | dev = blkid_verify(cache, dev); | ||
330 | if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) | ||
331 | goto try_again; | ||
332 | } | ||
333 | |||
334 | if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { | ||
335 | if (blkid_probe_all(cache) < 0) | ||
336 | return NULL; | ||
337 | goto try_again; | ||
338 | } | ||
339 | return dev; | ||
340 | } | ||
diff --git a/e2fsprogs/blkid/version.c b/e2fsprogs/blkid/version.c new file mode 100644 index 000000000..772291641 --- /dev/null +++ b/e2fsprogs/blkid/version.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * version.c --- Return the version of the blkid library | ||
3 | * | ||
4 | * Copyright (C) 2004 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * This file may be redistributed under the terms of the GNU Public | ||
8 | * License. | ||
9 | * %End-Header% | ||
10 | */ | ||
11 | |||
12 | #if HAVE_UNISTD_H | ||
13 | #include <unistd.h> | ||
14 | #endif | ||
15 | #include <string.h> | ||
16 | #include <stdio.h> | ||
17 | #include <ctype.h> | ||
18 | |||
19 | #include "blkid.h" | ||
20 | #include "../../version.h" | ||
21 | |||
22 | static const char *lib_version = E2FSPROGS_VERSION; | ||
23 | static const char *lib_date = E2FSPROGS_DATE; | ||
24 | |||
25 | int blkid_parse_version_string(const char *ver_string) | ||
26 | { | ||
27 | const char *cp; | ||
28 | int version = 0; | ||
29 | |||
30 | for (cp = ver_string; *cp; cp++) { | ||
31 | if (*cp == '.') | ||
32 | continue; | ||
33 | if (!isdigit(*cp)) | ||
34 | break; | ||
35 | version = (version * 10) + (*cp - '0'); | ||
36 | } | ||
37 | return version; | ||
38 | } | ||
39 | |||
40 | int blkid_get_library_version(const char **ver_string, | ||
41 | const char **date_string) | ||
42 | { | ||
43 | if (ver_string) | ||
44 | *ver_string = lib_version; | ||
45 | if (date_string) | ||
46 | *date_string = lib_date; | ||
47 | |||
48 | return blkid_parse_version_string(lib_version); | ||
49 | } | ||
diff --git a/e2fsprogs/util.c b/e2fsprogs/util.c new file mode 100644 index 000000000..d4d77b63b --- /dev/null +++ b/e2fsprogs/util.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * util.c --- helper functions used by tune2fs and mke2fs | ||
3 | * | ||
4 | * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * This file may be redistributed under the terms of the GNU Public | ||
8 | * License. | ||
9 | * %End-Header% | ||
10 | */ | ||
11 | |||
12 | #include <stdio.h> | ||
13 | #include <string.h> | ||
14 | #include <errno.h> | ||
15 | #include <linux/major.h> | ||
16 | #include <sys/stat.h> | ||
17 | |||
18 | #include "e2fsbb.h" | ||
19 | #include "e2p/e2p.h" | ||
20 | #include "ext2fs/ext2_fs.h" | ||
21 | #include "ext2fs/ext2fs.h" | ||
22 | #include "blkid/blkid.h" | ||
23 | #include "util.h" | ||
24 | |||
25 | void proceed_question(void) | ||
26 | { | ||
27 | fputs("Proceed anyway? (y,n) ", stdout); | ||
28 | if (bb_ask_confirmation() == 0) | ||
29 | exit(1); | ||
30 | } | ||
31 | |||
32 | void check_plausibility(const char *device) | ||
33 | { | ||
34 | int val; | ||
35 | #ifdef CONFIG_LFS | ||
36 | struct stat64 s; | ||
37 | val = stat64(device, &s); | ||
38 | #else | ||
39 | struct stat s; | ||
40 | val = stat(device, &s); | ||
41 | #endif | ||
42 | |||
43 | if(val == -1) | ||
44 | bb_perror_msg_and_die("Could not stat %s", device); | ||
45 | if (!S_ISBLK(s.st_mode)) { | ||
46 | printf("%s is not a block special device.\n", device); | ||
47 | proceed_question(); | ||
48 | return; | ||
49 | } | ||
50 | |||
51 | #ifdef HAVE_LINUX_MAJOR_H | ||
52 | #ifndef MAJOR | ||
53 | #define MAJOR(dev) ((dev)>>8) | ||
54 | #define MINOR(dev) ((dev) & 0xff) | ||
55 | #endif | ||
56 | #ifndef SCSI_BLK_MAJOR | ||
57 | #ifdef SCSI_DISK0_MAJOR | ||
58 | #ifdef SCSI_DISK8_MAJOR | ||
59 | #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | ||
60 | ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \ | ||
61 | ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR)) | ||
62 | #else | ||
63 | #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | ||
64 | ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR)) | ||
65 | #endif /* defined(SCSI_DISK8_MAJOR) */ | ||
66 | #define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR) | ||
67 | #else | ||
68 | #define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) | ||
69 | #endif /* defined(SCSI_DISK0_MAJOR) */ | ||
70 | #endif /* defined(SCSI_BLK_MAJOR) */ | ||
71 | if (((MAJOR(s.st_rdev) == HD_MAJOR && | ||
72 | MINOR(s.st_rdev)%64 == 0) || | ||
73 | (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) && | ||
74 | MINOR(s.st_rdev)%16 == 0))) { | ||
75 | printf("%s is entire device, not just one partition!\n", device); | ||
76 | proceed_question(); | ||
77 | } | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | void check_mount(const char *device, int force, const char *type) | ||
82 | { | ||
83 | errcode_t retval; | ||
84 | int mount_flags; | ||
85 | |||
86 | retval = ext2fs_check_if_mounted(device, &mount_flags); | ||
87 | if (retval) { | ||
88 | bb_error_msg("Could not determine if %s is mounted", device); | ||
89 | return; | ||
90 | } | ||
91 | if (!(mount_flags & EXT2_MF_MOUNTED)) | ||
92 | return; | ||
93 | |||
94 | bb_error_msg("%s is mounted !", device); | ||
95 | if (force) | ||
96 | bb_error_msg("forcing anyways and ignoring /etc/mtab status"); | ||
97 | else | ||
98 | bb_error_msg_and_die("will not make a %s here!", type); | ||
99 | } | ||
100 | |||
101 | void parse_journal_opts(char **journal_device, int *journal_flags, | ||
102 | int *journal_size, const char *opts) | ||
103 | { | ||
104 | char *buf, *token, *next, *p, *arg; | ||
105 | int journal_usage = 0; | ||
106 | #if 0 | ||
107 | int len; | ||
108 | len = strlen(opts); | ||
109 | buf = xmalloc(len+1); | ||
110 | strcpy(buf, opts); | ||
111 | #else | ||
112 | buf = bb_xstrdup(opts); | ||
113 | #endif | ||
114 | for (token = buf; token && *token; token = next) { | ||
115 | p = strchr(token, ','); | ||
116 | next = 0; | ||
117 | if (p) { | ||
118 | *p = 0; | ||
119 | next = p+1; | ||
120 | } | ||
121 | arg = strchr(token, '='); | ||
122 | if (arg) { | ||
123 | *arg = 0; | ||
124 | arg++; | ||
125 | } | ||
126 | if (strcmp(token, "device") == 0) { | ||
127 | *journal_device = blkid_get_devname(NULL, arg, NULL); | ||
128 | if (!journal_device) { | ||
129 | journal_usage++; | ||
130 | continue; | ||
131 | } | ||
132 | } else if (strcmp(token, "size") == 0) { | ||
133 | if (!arg) { | ||
134 | journal_usage++; | ||
135 | continue; | ||
136 | } | ||
137 | (*journal_size) = strtoul(arg, &p, 0); | ||
138 | if (*p) | ||
139 | journal_usage++; | ||
140 | } else if (strcmp(token, "v1_superblock") == 0) { | ||
141 | (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER; | ||
142 | continue; | ||
143 | } else | ||
144 | journal_usage++; | ||
145 | } | ||
146 | if (journal_usage) | ||
147 | bb_error_msg_and_die( | ||
148 | "\nBad journal options specified.\n\n" | ||
149 | "Journal options are separated by commas, " | ||
150 | "and may take an argument which\n" | ||
151 | "\tis set off by an equals ('=') sign.\n\n" | ||
152 | "Valid journal options are:\n" | ||
153 | "\tsize=<journal size in megabytes>\n" | ||
154 | "\tdevice=<journal device>\n\n" | ||
155 | "The journal size must be between " | ||
156 | "1024 and 102400 filesystem blocks.\n\n"); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Determine the number of journal blocks to use, either via | ||
161 | * user-specified # of megabytes, or via some intelligently selected | ||
162 | * defaults. | ||
163 | * | ||
164 | * Find a reasonable journal file size (in blocks) given the number of blocks | ||
165 | * in the filesystem. For very small filesystems, it is not reasonable to | ||
166 | * have a journal that fills more than half of the filesystem. | ||
167 | */ | ||
168 | int figure_journal_size(int size, ext2_filsys fs) | ||
169 | { | ||
170 | blk_t j_blocks; | ||
171 | |||
172 | if (fs->super->s_blocks_count < 2048) { | ||
173 | bb_error_msg("Filesystem too small for a journal"); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | if (size >= 0) { | ||
178 | j_blocks = size * 1024 / (fs->blocksize / 1024); | ||
179 | if (j_blocks < 1024 || j_blocks > 102400) | ||
180 | bb_error_msg_and_die("\nThe requested journal " | ||
181 | "size is %d blocks;\n it must be " | ||
182 | "between 1024 and 102400 blocks; Aborting", | ||
183 | j_blocks); | ||
184 | if (j_blocks > fs->super->s_free_blocks_count) | ||
185 | bb_error_msg_and_die("Journal size too big for filesystem"); | ||
186 | return j_blocks; | ||
187 | } | ||
188 | |||
189 | if (fs->super->s_blocks_count < 32768) | ||
190 | j_blocks = 1024; | ||
191 | else if (fs->super->s_blocks_count < 262144) | ||
192 | j_blocks = 4096; | ||
193 | else | ||
194 | j_blocks = 8192; | ||
195 | |||
196 | return j_blocks; | ||
197 | } | ||
198 | |||
199 | void print_check_message(ext2_filsys fs) | ||
200 | { | ||
201 | printf("This filesystem will be automatically " | ||
202 | "checked every %d mounts or\n" | ||
203 | "%g days, whichever comes first. " | ||
204 | "Use tune2fs -c or -i to override.\n", | ||
205 | fs->super->s_max_mnt_count, | ||
206 | (double)fs->super->s_checkinterval / (3600 * 24)); | ||
207 | } | ||
diff --git a/e2fsprogs/util.h b/e2fsprogs/util.h new file mode 100644 index 000000000..55cb84937 --- /dev/null +++ b/e2fsprogs/util.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * util.h --- header file defining prototypes for helper functions | ||
3 | * used by tune2fs and mke2fs | ||
4 | * | ||
5 | * Copyright 2000 by Theodore Ts'o. | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the GNU Public | ||
9 | * License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | extern void proceed_question(void); | ||
14 | extern void check_plausibility(const char *device); | ||
15 | extern void parse_journal_opts(char **, int *, int *, const char *opts); | ||
16 | extern void check_mount(const char *device, int force, const char *type); | ||
17 | extern int figure_journal_size(int size, ext2_filsys fs); | ||
18 | extern void print_check_message(ext2_filsys fs); | ||
diff --git a/e2fsprogs/uuid/clear.c b/e2fsprogs/uuid/clear.c new file mode 100644 index 000000000..f3a1005b3 --- /dev/null +++ b/e2fsprogs/uuid/clear.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * clear.c -- Clear a UUID | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include "string.h" | ||
36 | |||
37 | #include "uuidP.h" | ||
38 | |||
39 | void uuid_clear(uuid_t uu) | ||
40 | { | ||
41 | memset(uu, 0, 16); | ||
42 | } | ||
43 | |||
diff --git a/e2fsprogs/uuid/compare.c b/e2fsprogs/uuid/compare.c new file mode 100644 index 000000000..a9c505c74 --- /dev/null +++ b/e2fsprogs/uuid/compare.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * compare.c --- compare whether or not two UUID's are the same | ||
3 | * | ||
4 | * Returns 0 if the two UUID's are different, and 1 if they are the same. | ||
5 | * | ||
6 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
7 | * | ||
8 | * %Begin-Header% | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, and the entire permission notice in its entirety, | ||
14 | * including the disclaimer of warranties. | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in the | ||
17 | * documentation and/or other materials provided with the distribution. | ||
18 | * 3. The name of the author may not be used to endorse or promote | ||
19 | * products derived from this software without specific prior | ||
20 | * written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
25 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
28 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
30 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
32 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
33 | * DAMAGE. | ||
34 | * %End-Header% | ||
35 | */ | ||
36 | |||
37 | #include "uuidP.h" | ||
38 | #include <string.h> | ||
39 | |||
40 | #define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1); | ||
41 | |||
42 | int uuid_compare(const uuid_t uu1, const uuid_t uu2) | ||
43 | { | ||
44 | struct uuid uuid1, uuid2; | ||
45 | |||
46 | uuid_unpack(uu1, &uuid1); | ||
47 | uuid_unpack(uu2, &uuid2); | ||
48 | |||
49 | UUCMP(uuid1.time_low, uuid2.time_low); | ||
50 | UUCMP(uuid1.time_mid, uuid2.time_mid); | ||
51 | UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); | ||
52 | UUCMP(uuid1.clock_seq, uuid2.clock_seq); | ||
53 | return memcmp(uuid1.node, uuid2.node, 6); | ||
54 | } | ||
55 | |||
diff --git a/e2fsprogs/uuid/copy.c b/e2fsprogs/uuid/copy.c new file mode 100644 index 000000000..963bc818d --- /dev/null +++ b/e2fsprogs/uuid/copy.c | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * copy.c --- copy UUIDs | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include "uuidP.h" | ||
36 | |||
37 | void uuid_copy(uuid_t dst, const uuid_t src) | ||
38 | { | ||
39 | unsigned char *cp1; | ||
40 | const unsigned char *cp2; | ||
41 | int i; | ||
42 | |||
43 | for (i=0, cp1 = dst, cp2 = src; i < 16; i++) | ||
44 | *cp1++ = *cp2++; | ||
45 | } | ||
diff --git a/e2fsprogs/uuid/gen_uuid.c b/e2fsprogs/uuid/gen_uuid.c new file mode 100644 index 000000000..489cdd2b9 --- /dev/null +++ b/e2fsprogs/uuid/gen_uuid.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /* | ||
2 | * gen_uuid.c --- generate a DCE-compatible uuid | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #ifdef HAVE_UNISTD_H | ||
36 | #include <unistd.h> | ||
37 | #endif | ||
38 | #ifdef HAVE_STDLIB_H | ||
39 | #include <stdlib.h> | ||
40 | #endif | ||
41 | #include <string.h> | ||
42 | #include <fcntl.h> | ||
43 | #include <errno.h> | ||
44 | #include <sys/types.h> | ||
45 | #include <sys/time.h> | ||
46 | #include <sys/stat.h> | ||
47 | #include <sys/file.h> | ||
48 | #ifdef HAVE_SYS_IOCTL_H | ||
49 | #include <sys/ioctl.h> | ||
50 | #endif | ||
51 | #ifdef HAVE_SYS_SOCKET_H | ||
52 | #include <sys/socket.h> | ||
53 | #endif | ||
54 | #ifdef HAVE_SYS_SOCKIO_H | ||
55 | #include <sys/sockio.h> | ||
56 | #endif | ||
57 | #ifdef HAVE_NET_IF_H | ||
58 | #include <net/if.h> | ||
59 | #endif | ||
60 | #ifdef HAVE_NETINET_IN_H | ||
61 | #include <netinet/in.h> | ||
62 | #endif | ||
63 | #ifdef HAVE_NET_IF_DL_H | ||
64 | #include <net/if_dl.h> | ||
65 | #endif | ||
66 | |||
67 | #include "uuidP.h" | ||
68 | |||
69 | #ifdef HAVE_SRANDOM | ||
70 | #define srand(x) srandom(x) | ||
71 | #define rand() random() | ||
72 | #endif | ||
73 | |||
74 | static int get_random_fd(void) | ||
75 | { | ||
76 | struct timeval tv; | ||
77 | static int fd = -2; | ||
78 | int i; | ||
79 | |||
80 | if (fd == -2) { | ||
81 | gettimeofday(&tv, 0); | ||
82 | fd = open("/dev/urandom", O_RDONLY); | ||
83 | if (fd == -1) | ||
84 | fd = open("/dev/random", O_RDONLY | O_NONBLOCK); | ||
85 | srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); | ||
86 | } | ||
87 | /* Crank the random number generator a few times */ | ||
88 | gettimeofday(&tv, 0); | ||
89 | for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) | ||
90 | rand(); | ||
91 | return fd; | ||
92 | } | ||
93 | |||
94 | |||
95 | /* | ||
96 | * Generate a series of random bytes. Use /dev/urandom if possible, | ||
97 | * and if not, use srandom/random. | ||
98 | */ | ||
99 | static void get_random_bytes(void *buf, int nbytes) | ||
100 | { | ||
101 | int i, n = nbytes, fd = get_random_fd(); | ||
102 | int lose_counter = 0; | ||
103 | unsigned char *cp = (unsigned char *) buf; | ||
104 | |||
105 | if (fd >= 0) { | ||
106 | while (n > 0) { | ||
107 | i = read(fd, cp, n); | ||
108 | if (i <= 0) { | ||
109 | if (lose_counter++ > 16) | ||
110 | break; | ||
111 | continue; | ||
112 | } | ||
113 | n -= i; | ||
114 | cp += i; | ||
115 | lose_counter = 0; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * We do this all the time, but this is the only source of | ||
121 | * randomness if /dev/random/urandom is out to lunch. | ||
122 | */ | ||
123 | for (cp = buf, i = 0; i < nbytes; i++) | ||
124 | *cp++ ^= (rand() >> 7) & 0xFF; | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Get the ethernet hardware address, if we can find it... | ||
130 | */ | ||
131 | static int get_node_id(unsigned char *node_id) | ||
132 | { | ||
133 | #ifdef HAVE_NET_IF_H | ||
134 | int sd; | ||
135 | struct ifreq ifr, *ifrp; | ||
136 | struct ifconf ifc; | ||
137 | char buf[1024]; | ||
138 | int n, i; | ||
139 | unsigned char *a; | ||
140 | #ifdef HAVE_NET_IF_DL_H | ||
141 | struct sockaddr_dl *sdlp; | ||
142 | #endif | ||
143 | |||
144 | /* | ||
145 | * BSD 4.4 defines the size of an ifreq to be | ||
146 | * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len | ||
147 | * However, under earlier systems, sa_len isn't present, so the size is | ||
148 | * just sizeof(struct ifreq) | ||
149 | */ | ||
150 | #ifdef HAVE_SA_LEN | ||
151 | #ifndef max | ||
152 | #define max(a,b) ((a) > (b) ? (a) : (b)) | ||
153 | #endif | ||
154 | #define ifreq_size(i) max(sizeof(struct ifreq),\ | ||
155 | sizeof((i).ifr_name)+(i).ifr_addr.sa_len) | ||
156 | #else | ||
157 | #define ifreq_size(i) sizeof(struct ifreq) | ||
158 | #endif /* HAVE_SA_LEN*/ | ||
159 | |||
160 | sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); | ||
161 | if (sd < 0) { | ||
162 | return -1; | ||
163 | } | ||
164 | memset(buf, 0, sizeof(buf)); | ||
165 | ifc.ifc_len = sizeof(buf); | ||
166 | ifc.ifc_buf = buf; | ||
167 | if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { | ||
168 | close(sd); | ||
169 | return -1; | ||
170 | } | ||
171 | n = ifc.ifc_len; | ||
172 | for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { | ||
173 | ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); | ||
174 | strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); | ||
175 | #ifdef SIOCGIFHWADDR | ||
176 | if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) | ||
177 | continue; | ||
178 | a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; | ||
179 | #else | ||
180 | #ifdef SIOCGENADDR | ||
181 | if (ioctl(sd, SIOCGENADDR, &ifr) < 0) | ||
182 | continue; | ||
183 | a = (unsigned char *) ifr.ifr_enaddr; | ||
184 | #else | ||
185 | #ifdef HAVE_NET_IF_DL_H | ||
186 | sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; | ||
187 | if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) | ||
188 | continue; | ||
189 | a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; | ||
190 | #else | ||
191 | /* | ||
192 | * XXX we don't have a way of getting the hardware | ||
193 | * address | ||
194 | */ | ||
195 | close(sd); | ||
196 | return 0; | ||
197 | #endif /* HAVE_NET_IF_DL_H */ | ||
198 | #endif /* SIOCGENADDR */ | ||
199 | #endif /* SIOCGIFHWADDR */ | ||
200 | if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) | ||
201 | continue; | ||
202 | if (node_id) { | ||
203 | memcpy(node_id, a, 6); | ||
204 | close(sd); | ||
205 | return 1; | ||
206 | } | ||
207 | } | ||
208 | close(sd); | ||
209 | #endif | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /* Assume that the gettimeofday() has microsecond granularity */ | ||
214 | #define MAX_ADJUSTMENT 10 | ||
215 | |||
216 | static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq) | ||
217 | { | ||
218 | static int adjustment = 0; | ||
219 | static struct timeval last = {0, 0}; | ||
220 | static uint16_t clock_seq; | ||
221 | struct timeval tv; | ||
222 | unsigned long long clock_reg; | ||
223 | |||
224 | try_again: | ||
225 | gettimeofday(&tv, 0); | ||
226 | if ((last.tv_sec == 0) && (last.tv_usec == 0)) { | ||
227 | get_random_bytes(&clock_seq, sizeof(clock_seq)); | ||
228 | clock_seq &= 0x3FFF; | ||
229 | last = tv; | ||
230 | last.tv_sec--; | ||
231 | } | ||
232 | if ((tv.tv_sec < last.tv_sec) || | ||
233 | ((tv.tv_sec == last.tv_sec) && | ||
234 | (tv.tv_usec < last.tv_usec))) { | ||
235 | clock_seq = (clock_seq+1) & 0x3FFF; | ||
236 | adjustment = 0; | ||
237 | last = tv; | ||
238 | } else if ((tv.tv_sec == last.tv_sec) && | ||
239 | (tv.tv_usec == last.tv_usec)) { | ||
240 | if (adjustment >= MAX_ADJUSTMENT) | ||
241 | goto try_again; | ||
242 | adjustment++; | ||
243 | } else { | ||
244 | adjustment = 0; | ||
245 | last = tv; | ||
246 | } | ||
247 | |||
248 | clock_reg = tv.tv_usec*10 + adjustment; | ||
249 | clock_reg += ((unsigned long long) tv.tv_sec)*10000000; | ||
250 | clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; | ||
251 | |||
252 | *clock_high = clock_reg >> 32; | ||
253 | *clock_low = clock_reg; | ||
254 | *ret_clock_seq = clock_seq; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | void uuid_generate_time(uuid_t out) | ||
259 | { | ||
260 | static unsigned char node_id[6]; | ||
261 | static int has_init = 0; | ||
262 | struct uuid uu; | ||
263 | uint32_t clock_mid; | ||
264 | |||
265 | if (!has_init) { | ||
266 | if (get_node_id(node_id) <= 0) { | ||
267 | get_random_bytes(node_id, 6); | ||
268 | /* | ||
269 | * Set multicast bit, to prevent conflicts | ||
270 | * with IEEE 802 addresses obtained from | ||
271 | * network cards | ||
272 | */ | ||
273 | node_id[0] |= 0x01; | ||
274 | } | ||
275 | has_init = 1; | ||
276 | } | ||
277 | get_clock(&clock_mid, &uu.time_low, &uu.clock_seq); | ||
278 | uu.clock_seq |= 0x8000; | ||
279 | uu.time_mid = (uint16_t) clock_mid; | ||
280 | uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; | ||
281 | memcpy(uu.node, node_id, 6); | ||
282 | uuid_pack(&uu, out); | ||
283 | } | ||
284 | |||
285 | void uuid_generate_random(uuid_t out) | ||
286 | { | ||
287 | uuid_t buf; | ||
288 | struct uuid uu; | ||
289 | |||
290 | get_random_bytes(buf, sizeof(buf)); | ||
291 | uuid_unpack(buf, &uu); | ||
292 | |||
293 | uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; | ||
294 | uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; | ||
295 | uuid_pack(&uu, out); | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * This is the generic front-end to uuid_generate_random and | ||
300 | * uuid_generate_time. It uses uuid_generate_random only if | ||
301 | * /dev/urandom is available, since otherwise we won't have | ||
302 | * high-quality randomness. | ||
303 | */ | ||
304 | void uuid_generate(uuid_t out) | ||
305 | { | ||
306 | if (get_random_fd() >= 0) | ||
307 | uuid_generate_random(out); | ||
308 | else | ||
309 | uuid_generate_time(out); | ||
310 | } | ||
diff --git a/e2fsprogs/uuid/isnull.c b/e2fsprogs/uuid/isnull.c new file mode 100644 index 000000000..54a830038 --- /dev/null +++ b/e2fsprogs/uuid/isnull.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * isnull.c --- Check whether or not the UUID is null | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include "uuidP.h" | ||
36 | |||
37 | /* Returns 1 if the uuid is the NULL uuid */ | ||
38 | int uuid_is_null(const uuid_t uu) | ||
39 | { | ||
40 | const unsigned char *cp; | ||
41 | int i; | ||
42 | |||
43 | for (i=0, cp = uu; i < 16; i++) | ||
44 | if (*cp++) | ||
45 | return 0; | ||
46 | return 1; | ||
47 | } | ||
48 | |||
diff --git a/e2fsprogs/uuid/pack.c b/e2fsprogs/uuid/pack.c new file mode 100644 index 000000000..348d43213 --- /dev/null +++ b/e2fsprogs/uuid/pack.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Internal routine for packing UUID's | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include <string.h> | ||
36 | #include "uuidP.h" | ||
37 | |||
38 | void uuid_pack(const struct uuid *uu, uuid_t ptr) | ||
39 | { | ||
40 | uint32_t tmp; | ||
41 | unsigned char *out = ptr; | ||
42 | |||
43 | tmp = uu->time_low; | ||
44 | out[3] = (unsigned char) tmp; | ||
45 | tmp >>= 8; | ||
46 | out[2] = (unsigned char) tmp; | ||
47 | tmp >>= 8; | ||
48 | out[1] = (unsigned char) tmp; | ||
49 | tmp >>= 8; | ||
50 | out[0] = (unsigned char) tmp; | ||
51 | |||
52 | tmp = uu->time_mid; | ||
53 | out[5] = (unsigned char) tmp; | ||
54 | tmp >>= 8; | ||
55 | out[4] = (unsigned char) tmp; | ||
56 | |||
57 | tmp = uu->time_hi_and_version; | ||
58 | out[7] = (unsigned char) tmp; | ||
59 | tmp >>= 8; | ||
60 | out[6] = (unsigned char) tmp; | ||
61 | |||
62 | tmp = uu->clock_seq; | ||
63 | out[9] = (unsigned char) tmp; | ||
64 | tmp >>= 8; | ||
65 | out[8] = (unsigned char) tmp; | ||
66 | |||
67 | memcpy(out+10, uu->node, 6); | ||
68 | } | ||
69 | |||
diff --git a/e2fsprogs/uuid/parse.c b/e2fsprogs/uuid/parse.c new file mode 100644 index 000000000..07b894d11 --- /dev/null +++ b/e2fsprogs/uuid/parse.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * parse.c --- UUID parsing | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include <stdlib.h> | ||
36 | #include <stdio.h> | ||
37 | #include <ctype.h> | ||
38 | #include <string.h> | ||
39 | |||
40 | #include "uuidP.h" | ||
41 | |||
42 | int uuid_parse(const char *in, uuid_t uu) | ||
43 | { | ||
44 | struct uuid uuid; | ||
45 | int i; | ||
46 | const char *cp; | ||
47 | char buf[3]; | ||
48 | |||
49 | if (strlen(in) != 36) | ||
50 | return -1; | ||
51 | for (i=0, cp = in; i <= 36; i++,cp++) { | ||
52 | if ((i == 8) || (i == 13) || (i == 18) || | ||
53 | (i == 23)) { | ||
54 | if (*cp == '-') | ||
55 | continue; | ||
56 | else | ||
57 | return -1; | ||
58 | } | ||
59 | if (i== 36) | ||
60 | if (*cp == 0) | ||
61 | continue; | ||
62 | if (!isxdigit(*cp)) | ||
63 | return -1; | ||
64 | } | ||
65 | uuid.time_low = strtoul(in, NULL, 16); | ||
66 | uuid.time_mid = strtoul(in+9, NULL, 16); | ||
67 | uuid.time_hi_and_version = strtoul(in+14, NULL, 16); | ||
68 | uuid.clock_seq = strtoul(in+19, NULL, 16); | ||
69 | cp = in+24; | ||
70 | buf[2] = 0; | ||
71 | for (i=0; i < 6; i++) { | ||
72 | buf[0] = *cp++; | ||
73 | buf[1] = *cp++; | ||
74 | uuid.node[i] = strtoul(buf, NULL, 16); | ||
75 | } | ||
76 | |||
77 | uuid_pack(&uuid, uu); | ||
78 | return 0; | ||
79 | } | ||
diff --git a/e2fsprogs/uuid/unpack.c b/e2fsprogs/uuid/unpack.c new file mode 100644 index 000000000..9502fc2a6 --- /dev/null +++ b/e2fsprogs/uuid/unpack.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Internal routine for unpacking UUID | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include <string.h> | ||
36 | #include "uuidP.h" | ||
37 | |||
38 | void uuid_unpack(const uuid_t in, struct uuid *uu) | ||
39 | { | ||
40 | const uint8_t *ptr = in; | ||
41 | uint32_t tmp; | ||
42 | |||
43 | tmp = *ptr++; | ||
44 | tmp = (tmp << 8) | *ptr++; | ||
45 | tmp = (tmp << 8) | *ptr++; | ||
46 | tmp = (tmp << 8) | *ptr++; | ||
47 | uu->time_low = tmp; | ||
48 | |||
49 | tmp = *ptr++; | ||
50 | tmp = (tmp << 8) | *ptr++; | ||
51 | uu->time_mid = tmp; | ||
52 | |||
53 | tmp = *ptr++; | ||
54 | tmp = (tmp << 8) | *ptr++; | ||
55 | uu->time_hi_and_version = tmp; | ||
56 | |||
57 | tmp = *ptr++; | ||
58 | tmp = (tmp << 8) | *ptr++; | ||
59 | uu->clock_seq = tmp; | ||
60 | |||
61 | memcpy(uu->node, ptr, 6); | ||
62 | } | ||
63 | |||
diff --git a/e2fsprogs/uuid/unparse.c b/e2fsprogs/uuid/unparse.c new file mode 100644 index 000000000..c0e08ef49 --- /dev/null +++ b/e2fsprogs/uuid/unparse.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * unparse.c -- convert a UUID to string | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #include <stdio.h> | ||
36 | |||
37 | #include "uuidP.h" | ||
38 | |||
39 | static const char *fmt_lower = | ||
40 | "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; | ||
41 | |||
42 | static const char *fmt_upper = | ||
43 | "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; | ||
44 | |||
45 | #ifdef UUID_UNPARSE_DEFAULT_UPPER | ||
46 | #define FMT_DEFAULT fmt_upper | ||
47 | #else | ||
48 | #define FMT_DEFAULT fmt_lower | ||
49 | #endif | ||
50 | |||
51 | static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) | ||
52 | { | ||
53 | struct uuid uuid; | ||
54 | |||
55 | uuid_unpack(uu, &uuid); | ||
56 | sprintf(out, fmt, | ||
57 | uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, | ||
58 | uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, | ||
59 | uuid.node[0], uuid.node[1], uuid.node[2], | ||
60 | uuid.node[3], uuid.node[4], uuid.node[5]); | ||
61 | } | ||
62 | |||
63 | void uuid_unparse_lower(const uuid_t uu, char *out) | ||
64 | { | ||
65 | uuid_unparse_x(uu, out, fmt_lower); | ||
66 | } | ||
67 | |||
68 | void uuid_unparse_upper(const uuid_t uu, char *out) | ||
69 | { | ||
70 | uuid_unparse_x(uu, out, fmt_upper); | ||
71 | } | ||
72 | |||
73 | void uuid_unparse(const uuid_t uu, char *out) | ||
74 | { | ||
75 | uuid_unparse_x(uu, out, FMT_DEFAULT); | ||
76 | } | ||
diff --git a/e2fsprogs/uuid/uuid.h b/e2fsprogs/uuid/uuid.h new file mode 100644 index 000000000..e9cf889ae --- /dev/null +++ b/e2fsprogs/uuid/uuid.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Public include file for the UUID library | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #ifndef _UUID_UUID_H | ||
36 | #define _UUID_UUID_H | ||
37 | |||
38 | #include <sys/types.h> | ||
39 | #include <sys/time.h> | ||
40 | #include <time.h> | ||
41 | |||
42 | typedef unsigned char uuid_t[16]; | ||
43 | |||
44 | /* UUID Variant definitions */ | ||
45 | #define UUID_VARIANT_NCS 0 | ||
46 | #define UUID_VARIANT_DCE 1 | ||
47 | #define UUID_VARIANT_MICROSOFT 2 | ||
48 | #define UUID_VARIANT_OTHER 3 | ||
49 | |||
50 | /* UUID Type definitions */ | ||
51 | #define UUID_TYPE_DCE_TIME 1 | ||
52 | #define UUID_TYPE_DCE_RANDOM 4 | ||
53 | |||
54 | /* Allow UUID constants to be defined */ | ||
55 | #ifdef __GNUC__ | ||
56 | #define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ | ||
57 | static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} | ||
58 | #else | ||
59 | #define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ | ||
60 | static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} | ||
61 | #endif | ||
62 | |||
63 | #ifdef __cplusplus | ||
64 | extern "C" { | ||
65 | #endif | ||
66 | |||
67 | /* clear.c */ | ||
68 | void uuid_clear(uuid_t uu); | ||
69 | |||
70 | /* compare.c */ | ||
71 | int uuid_compare(const uuid_t uu1, const uuid_t uu2); | ||
72 | |||
73 | /* copy.c */ | ||
74 | void uuid_copy(uuid_t dst, const uuid_t src); | ||
75 | |||
76 | /* gen_uuid.c */ | ||
77 | void uuid_generate(uuid_t out); | ||
78 | void uuid_generate_random(uuid_t out); | ||
79 | void uuid_generate_time(uuid_t out); | ||
80 | |||
81 | /* isnull.c */ | ||
82 | int uuid_is_null(const uuid_t uu); | ||
83 | |||
84 | /* parse.c */ | ||
85 | int uuid_parse(const char *in, uuid_t uu); | ||
86 | |||
87 | /* unparse.c */ | ||
88 | void uuid_unparse(const uuid_t uu, char *out); | ||
89 | void uuid_unparse_lower(const uuid_t uu, char *out); | ||
90 | void uuid_unparse_upper(const uuid_t uu, char *out); | ||
91 | |||
92 | /* uuid_time.c */ | ||
93 | time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); | ||
94 | int uuid_type(const uuid_t uu); | ||
95 | int uuid_variant(const uuid_t uu); | ||
96 | |||
97 | #ifdef __cplusplus | ||
98 | } | ||
99 | #endif | ||
100 | |||
101 | #endif /* _UUID_UUID_H */ | ||
diff --git a/e2fsprogs/uuid/uuidP.h b/e2fsprogs/uuid/uuidP.h new file mode 100644 index 000000000..adf233da9 --- /dev/null +++ b/e2fsprogs/uuid/uuidP.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * uuid.h -- private header file for uuids | ||
3 | * | ||
4 | * Copyright (C) 1996, 1997 Theodore Ts'o. | ||
5 | * | ||
6 | * %Begin-Header% | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, and the entire permission notice in its entirety, | ||
12 | * including the disclaimer of warranties. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The name of the author may not be used to endorse or promote | ||
17 | * products derived from this software without specific prior | ||
18 | * written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
23 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
27 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
30 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
31 | * DAMAGE. | ||
32 | * %End-Header% | ||
33 | */ | ||
34 | |||
35 | #ifdef HAVE_INTTYPES_H | ||
36 | #include <inttypes.h> | ||
37 | #else | ||
38 | #include <uuid/uuid_types.h> | ||
39 | #endif | ||
40 | #include <sys/types.h> | ||
41 | |||
42 | #include "uuid.h" | ||
43 | |||
44 | /* | ||
45 | * Offset between 15-Oct-1582 and 1-Jan-70 | ||
46 | */ | ||
47 | #define TIME_OFFSET_HIGH 0x01B21DD2 | ||
48 | #define TIME_OFFSET_LOW 0x13814000 | ||
49 | |||
50 | struct uuid { | ||
51 | uint32_t time_low; | ||
52 | uint16_t time_mid; | ||
53 | uint16_t time_hi_and_version; | ||
54 | uint16_t clock_seq; | ||
55 | uint8_t node[6]; | ||
56 | }; | ||
57 | |||
58 | |||
59 | /* | ||
60 | * prototypes | ||
61 | */ | ||
62 | void uuid_pack(const struct uuid *uu, uuid_t ptr); | ||
63 | void uuid_unpack(const uuid_t in, struct uuid *uu); | ||
diff --git a/e2fsprogs/uuid/uuid_time.c b/e2fsprogs/uuid/uuid_time.c new file mode 100644 index 000000000..d5f992b39 --- /dev/null +++ b/e2fsprogs/uuid/uuid_time.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * uuid_time.c --- Interpret the time field from a uuid. This program | ||
3 | * violates the UUID abstraction barrier by reaching into the guts | ||
4 | * of a UUID and interpreting it. | ||
5 | * | ||
6 | * Copyright (C) 1998, 1999 Theodore Ts'o. | ||
7 | * | ||
8 | * %Begin-Header% | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, and the entire permission notice in its entirety, | ||
14 | * including the disclaimer of warranties. | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in the | ||
17 | * documentation and/or other materials provided with the distribution. | ||
18 | * 3. The name of the author may not be used to endorse or promote | ||
19 | * products derived from this software without specific prior | ||
20 | * written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | ||
25 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | ||
26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | ||
28 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
30 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
32 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | ||
33 | * DAMAGE. | ||
34 | * %End-Header% | ||
35 | */ | ||
36 | |||
37 | #include <stdio.h> | ||
38 | #include <unistd.h> | ||
39 | #include <stdlib.h> | ||
40 | #include <sys/types.h> | ||
41 | #include <sys/time.h> | ||
42 | #include <time.h> | ||
43 | |||
44 | #include "uuidP.h" | ||
45 | |||
46 | time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) | ||
47 | { | ||
48 | struct uuid uuid; | ||
49 | uint32_t high; | ||
50 | struct timeval tv; | ||
51 | unsigned long long clock_reg; | ||
52 | |||
53 | uuid_unpack(uu, &uuid); | ||
54 | |||
55 | high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); | ||
56 | clock_reg = uuid.time_low | ((unsigned long long) high << 32); | ||
57 | |||
58 | clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; | ||
59 | tv.tv_sec = clock_reg / 10000000; | ||
60 | tv.tv_usec = (clock_reg % 10000000) / 10; | ||
61 | |||
62 | if (ret_tv) | ||
63 | *ret_tv = tv; | ||
64 | |||
65 | return tv.tv_sec; | ||
66 | } | ||
67 | |||
68 | int uuid_type(const uuid_t uu) | ||
69 | { | ||
70 | struct uuid uuid; | ||
71 | |||
72 | uuid_unpack(uu, &uuid); | ||
73 | return ((uuid.time_hi_and_version >> 12) & 0xF); | ||
74 | } | ||
75 | |||
76 | int uuid_variant(const uuid_t uu) | ||
77 | { | ||
78 | struct uuid uuid; | ||
79 | int var; | ||
80 | |||
81 | uuid_unpack(uu, &uuid); | ||
82 | var = uuid.clock_seq; | ||
83 | |||
84 | if ((var & 0x8000) == 0) | ||
85 | return UUID_VARIANT_NCS; | ||
86 | if ((var & 0x4000) == 0) | ||
87 | return UUID_VARIANT_DCE; | ||
88 | if ((var & 0x2000) == 0) | ||
89 | return UUID_VARIANT_MICROSOFT; | ||
90 | return UUID_VARIANT_OTHER; | ||
91 | } | ||
92 | |||
93 | #ifdef DEBUG | ||
94 | static const char *variant_string(int variant) | ||
95 | { | ||
96 | switch (variant) { | ||
97 | case UUID_VARIANT_NCS: | ||
98 | return "NCS"; | ||
99 | case UUID_VARIANT_DCE: | ||
100 | return "DCE"; | ||
101 | case UUID_VARIANT_MICROSOFT: | ||
102 | return "Microsoft"; | ||
103 | default: | ||
104 | return "Other"; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | |||
109 | int | ||
110 | main(int argc, char **argv) | ||
111 | { | ||
112 | uuid_t buf; | ||
113 | time_t time_reg; | ||
114 | struct timeval tv; | ||
115 | int type, variant; | ||
116 | |||
117 | if (argc != 2) { | ||
118 | fprintf(stderr, "Usage: %s uuid\n", argv[0]); | ||
119 | exit(1); | ||
120 | } | ||
121 | if (uuid_parse(argv[1], buf)) { | ||
122 | fprintf(stderr, "Invalid UUID: %s\n", argv[1]); | ||
123 | exit(1); | ||
124 | } | ||
125 | variant = uuid_variant(buf); | ||
126 | type = uuid_type(buf); | ||
127 | time_reg = uuid_time(buf, &tv); | ||
128 | |||
129 | printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); | ||
130 | if (variant != UUID_VARIANT_DCE) { | ||
131 | printf("Warning: This program only knows how to interpret " | ||
132 | "DCE UUIDs.\n\tThe rest of the output is likely " | ||
133 | "to be incorrect!!\n"); | ||
134 | } | ||
135 | printf("UUID type is %d", type); | ||
136 | switch (type) { | ||
137 | case 1: | ||
138 | printf(" (time based)\n"); | ||
139 | break; | ||
140 | case 2: | ||
141 | printf(" (DCE)\n"); | ||
142 | break; | ||
143 | case 3: | ||
144 | printf(" (name-based)\n"); | ||
145 | break; | ||
146 | case 4: | ||
147 | printf(" (random)\n"); | ||
148 | break; | ||
149 | default: | ||
150 | printf("\n"); | ||
151 | } | ||
152 | if (type != 1) { | ||
153 | printf("Warning: not a time-based UUID, so UUID time " | ||
154 | "decoding will likely not work!\n"); | ||
155 | } | ||
156 | printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, | ||
157 | ctime(&time_reg)); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | #endif | ||