aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-05-09 22:13:22 +0000
committerMike Frysinger <vapier@gentoo.org>2005-05-09 22:13:22 +0000
commit38a33f91c0a46f51d07900731245492a3b244ae4 (patch)
treeb86c6e23c1baa56577715cdeef6551d10a4ead2c
parent1fd98e039d146dcff02a5350f509cabca65fd29c (diff)
downloadbusybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.tar.gz
busybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.tar.bz2
busybox-w32-38a33f91c0a46f51d07900731245492a3b244ae4.zip
import more libs to prep for new e2fsprogs
-rw-r--r--e2fsprogs/blkid/blkid.h105
-rw-r--r--e2fsprogs/blkid/blkidP.h239
-rw-r--r--e2fsprogs/blkid/cache.c126
-rw-r--r--e2fsprogs/blkid/dev.c118
-rw-r--r--e2fsprogs/blkid/devname.c376
-rw-r--r--e2fsprogs/blkid/devno.c233
-rw-r--r--e2fsprogs/blkid/getsize.c180
-rw-r--r--e2fsprogs/blkid/list.h179
-rw-r--r--e2fsprogs/blkid/llseek.c139
-rw-r--r--e2fsprogs/blkid/probe.c704
-rw-r--r--e2fsprogs/blkid/probe.h359
-rw-r--r--e2fsprogs/blkid/read.c459
-rw-r--r--e2fsprogs/blkid/resolve.c140
-rw-r--r--e2fsprogs/blkid/save.c193
-rw-r--r--e2fsprogs/blkid/tag.c340
-rw-r--r--e2fsprogs/blkid/version.c49
-rw-r--r--e2fsprogs/util.c207
-rw-r--r--e2fsprogs/util.h18
-rw-r--r--e2fsprogs/uuid/clear.c43
-rw-r--r--e2fsprogs/uuid/compare.c55
-rw-r--r--e2fsprogs/uuid/copy.c45
-rw-r--r--e2fsprogs/uuid/gen_uuid.c310
-rw-r--r--e2fsprogs/uuid/isnull.c48
-rw-r--r--e2fsprogs/uuid/pack.c69
-rw-r--r--e2fsprogs/uuid/parse.c79
-rw-r--r--e2fsprogs/uuid/unpack.c63
-rw-r--r--e2fsprogs/uuid/unparse.c76
-rw-r--r--e2fsprogs/uuid/uuid.h101
-rw-r--r--e2fsprogs/uuid/uuidP.h63
-rw-r--r--e2fsprogs/uuid/uuid_time.c161
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
20extern "C" {
21#endif
22
23#define BLKID_VERSION "1.0.0"
24#define BLKID_DATE "12-Feb-2003"
25
26typedef struct blkid_struct_dev *blkid_dev;
27typedef struct blkid_struct_cache *blkid_cache;
28typedef __s64 blkid_loff_t;
29
30typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
31typedef 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 */
51extern void blkid_put_cache(blkid_cache cache);
52extern int blkid_get_cache(blkid_cache *cache, const char *filename);
53
54/* dev.c */
55extern const char *blkid_dev_devname(blkid_dev dev);
56
57extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
58extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
59extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
60
61/* devno.c */
62extern char *blkid_devno_to_devname(dev_t devno);
63
64/* devname.c */
65extern int blkid_probe_all(blkid_cache cache);
66extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
67 int flags);
68
69/* getsize.c */
70extern blkid_loff_t blkid_get_dev_size(int fd);
71
72/* probe.c */
73int blkid_known_fstype(const char *fstype);
74extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
75
76/* read.c */
77
78/* resolve.c */
79extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
80 const char *devname);
81extern char *blkid_get_devname(blkid_cache cache, const char *token,
82 const char *value);
83
84/* tag.c */
85extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
86extern int blkid_tag_next(blkid_tag_iterate iterate,
87 const char **type, const char **value);
88extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
89
90extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
91 const char *type,
92 const char *value);
93extern int blkid_parse_tag_string(const char *token, char **ret_type,
94 char **ret_val);
95
96/* version.c */
97extern int blkid_parse_version_string(const char *ver_string);
98extern 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 */
36struct blkid_struct_dev
37{
38 struct list_head bid_devs; /* All devices in the cache */
39 struct list_head bid_tags; /* All tags for this device */
40 blkid_cache bid_cache; /* Dev belongs to this cache */
41 char *bid_name; /* Device inode pathname */
42 char *bid_type; /* Preferred device TYPE */
43 int bid_pri; /* Device priority */
44 dev_t bid_devno; /* Device major/minor number */
45 time_t bid_time; /* Last update time of device */
46 unsigned int bid_flags; /* Device status bitflags */
47 char *bid_label; /* Shortcut to device LABEL */
48 char *bid_uuid; /* Shortcut to binary UUID */
49};
50
51#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
52#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
53
54/*
55 * Each tag defines a NAME=value pair for a particular device. The tags
56 * are linked via bit_names for a single device, so that traversing the
57 * names list will get you a list of all tags associated with a device.
58 * They are also linked via bit_values for all devices, so one can easily
59 * search all tags with a given NAME for a specific value.
60 */
61struct blkid_struct_tag
62{
63 struct list_head bit_tags; /* All tags for this device */
64 struct list_head bit_names; /* All tags with given NAME */
65 char *bit_name; /* NAME of tag (shared) */
66 char *bit_val; /* value of tag */
67 blkid_dev bit_dev; /* pointer to device */
68};
69typedef struct blkid_struct_tag *blkid_tag;
70
71/*
72 * Minimum number of seconds between device probes, even when reading
73 * from the cache. This is to avoid re-probing all devices which were
74 * just probed by another program that does not share the cache.
75 */
76#define BLKID_PROBE_MIN 2
77
78/*
79 * Time in seconds an entry remains verified in the in-memory cache
80 * before being reverified (in case of long-running processes that
81 * keep a cache in memory and continue to use it for a long time).
82 */
83#define BLKID_PROBE_INTERVAL 200
84
85/* This describes an entire blkid cache file and probed devices.
86 * We can traverse all of the found devices via bic_list.
87 * We can traverse all of the tag types by bic_tags, which hold empty tags
88 * for each tag type. Those tags can be used as list_heads for iterating
89 * through all devices with a specific tag type (e.g. LABEL).
90 */
91struct blkid_struct_cache
92{
93 struct list_head bic_devs; /* List head of all devices */
94 struct list_head bic_tags; /* List head of all tag types */
95 time_t bic_time; /* Last probe time */
96 time_t bic_ftime; /* Mod time of the cachefile */
97 unsigned int bic_flags; /* Status flags of the cache */
98 char *bic_filename; /* filename of cache */
99};
100
101#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
102#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
103
104extern char *blkid_strdup(const char *s);
105extern char *blkid_strndup(const char *s, const int length);
106
107#define BLKID_CACHE_FILE "/etc/blkid.tab"
108extern const char *blkid_devdirs[];
109
110#define BLKID_ERR_IO 5
111#define BLKID_ERR_PROC 9
112#define BLKID_ERR_MEM 12
113#define BLKID_ERR_CACHE 14
114#define BLKID_ERR_DEV 19
115#define BLKID_ERR_PARAM 22
116#define BLKID_ERR_BIG 27
117
118/*
119 * Priority settings for different types of devices
120 */
121#define BLKID_PRI_EVMS 30
122#define BLKID_PRI_LVM 20
123#define BLKID_PRI_MD 10
124
125#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
126#define CONFIG_BLKID_DEBUG
127#endif
128
129#define DEBUG_CACHE 0x0001
130#define DEBUG_DUMP 0x0002
131#define DEBUG_DEV 0x0004
132#define DEBUG_DEVNAME 0x0008
133#define DEBUG_DEVNO 0x0010
134#define DEBUG_PROBE 0x0020
135#define DEBUG_READ 0x0040
136#define DEBUG_RESOLVE 0x0080
137#define DEBUG_SAVE 0x0100
138#define DEBUG_TAG 0x0200
139#define DEBUG_INIT 0x8000
140#define DEBUG_ALL 0xFFFF
141
142#ifdef CONFIG_BLKID_DEBUG
143#include <stdio.h>
144extern int blkid_debug_mask;
145#define DBG(m,x) if ((m) & blkid_debug_mask) x;
146#else
147#define DBG(m,x)
148#endif
149
150#ifdef CONFIG_BLKID_DEBUG
151static 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
164static 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
189static 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 */
213extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
214
215/* read.c */
216extern void blkid_read_cache(blkid_cache cache);
217
218/* save.c */
219extern int blkid_flush_cache(blkid_cache cache);
220
221/*
222 * Functions to create and find a specific tag type: tag.c
223 */
224extern void blkid_free_tag(blkid_tag tag);
225extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
226extern 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 */
232extern blkid_dev blkid_new_dev(void);
233extern 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
18int blkid_debug_mask = 0;
19
20int 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
57void 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
98int main(int argc, char** argv)
99{
100 blkid_cache cache = NULL;
101 int ret;
102
103 blkid_debug_mask = DEBUG_ALL;
104 if ((argc > 2)) {
105 fprintf(stderr, "Usage: %s [filename] \n", argv[0]);
106 exit(1);
107 }
108
109 if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
110 fprintf(stderr, "error %d parsing cache file %s\n", ret,
111 argv[1] ? argv[1] : BLKID_CACHE_FILE);
112 exit(1);
113 }
114 if ((ret = blkid_get_cache(&cache, "/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
18blkid_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
31void 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 */
55extern 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
77struct blkid_struct_dev_iterate {
78 int magic;
79 blkid_cache cache;
80 struct list_head *p;
81};
82
83extern 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 */
99extern 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
111extern 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 */
44blkid_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 */
81static 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
130set_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>
149static 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
174static 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 }
230exit:
231 closedir(vg_list);
232}
233#endif
234
235#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
236
237static int
238evms_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 */
266int 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
354int 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
36struct dir_list {
37 char *name;
38 struct dir_list *next;
39};
40
41char *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
59char *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 */
67static 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 */
86static 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
98static 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 */
138const 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 */
145char *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
194int 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
55static 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 */
69blkid_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
161int 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
5extern "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
24struct 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
38extern 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__
58static int _llseek(unsigned int, unsigned long, unsigned long,
59 blkid_loff_t *, unsigned int);
60
61static _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
66static 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
87blkid_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
123blkid_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 */
39static 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
71static 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
81static 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
98static 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
124static 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
144static 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
161static 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
194static 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
226static 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
244static 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
271static 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
289static 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
306static 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
317static 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
353static const char
354*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
355 "NSR03", "TEA01", 0 };
356
357static 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
399static 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
424static 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
439static 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 */
467static 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 */
535blkid_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 */
581try_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
642found_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
660int 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
672int 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
19struct blkid_magic;
20
21typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
22 struct blkid_magic *id, unsigned char *buf);
23
24struct 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 */
39struct 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
61struct 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
76struct 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
92struct 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
105struct romfs_super_block {
106 unsigned char ros_magic[8];
107 __u32 ros_dummy1[2];
108 unsigned char ros_volume[16];
109};
110
111struct 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 */
123struct 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 */
154struct 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
177struct 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
190struct 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
209struct hfs_super_block {
210 char h_magic[2];
211 char h_dummy[18];
212 __u32 h_blksize;
213};
214
215struct 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
223struct 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
240struct 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
255struct 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)
265struct 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
281static __u16 blkid_swab16(__u16 val);
282static __u32 blkid_swab32(__u32 val);
283static __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
55static char *skip_over_blank(char *cp)
56{
57 while (*cp && isspace(*cp))
58 cp++;
59 return cp;
60}
61
62static 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
82static 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
101static 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 */
132static 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) */
159static 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 */
178static 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 */
231static 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/*
272static 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 */
295static 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 */
335static 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 */
372void 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;
434errout:
435 close(fd);
436 return;
437}
438
439#ifdef TEST_PROGRAM
440int 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 */
28char *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 */
62char *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
98errout:
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
110int 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
29static 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 */
56int 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
154errout:
155 if (tmp)
156 free(tmp);
157 return ret;
158}
159
160#ifdef TEST_PROGRAM
161int 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
19static 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
32void 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 */
56blkid_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 */
77static 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 */
102int 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
167errout:
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 */
188int 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
217errout:
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
239struct blkid_struct_tag_iterate {
240 int magic;
241 blkid_dev dev;
242 struct list_head *p;
243};
244
245extern 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 */
261extern 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
278extern 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 */
295extern 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
311try_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
22static const char *lib_version = E2FSPROGS_VERSION;
23static const char *lib_date = E2FSPROGS_DATE;
24
25int 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
40int 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
25void proceed_question(void)
26{
27 fputs("Proceed anyway? (y,n) ", stdout);
28 if (bb_ask_confirmation() == 0)
29 exit(1);
30}
31
32void 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
81void 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
101void 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 */
168int 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
199void 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
13extern void proceed_question(void);
14extern void check_plausibility(const char *device);
15extern void parse_journal_opts(char **, int *, int *, const char *opts);
16extern void check_mount(const char *device, int force, const char *type);
17extern int figure_journal_size(int size, ext2_filsys fs);
18extern 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
39void 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
42int 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
37void 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
74static 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 */
99static 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 */
131static 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
216static 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
224try_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
258void 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
285void 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 */
304void 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 */
38int 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
38void 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
42int 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
38void 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
39static const char *fmt_lower =
40 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
41
42static 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
51static 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
63void uuid_unparse_lower(const uuid_t uu, char *out)
64{
65 uuid_unparse_x(uu, out, fmt_lower);
66}
67
68void uuid_unparse_upper(const uuid_t uu, char *out)
69{
70 uuid_unparse_x(uu, out, fmt_upper);
71}
72
73void 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
42typedef 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
64extern "C" {
65#endif
66
67/* clear.c */
68void uuid_clear(uuid_t uu);
69
70/* compare.c */
71int uuid_compare(const uuid_t uu1, const uuid_t uu2);
72
73/* copy.c */
74void uuid_copy(uuid_t dst, const uuid_t src);
75
76/* gen_uuid.c */
77void uuid_generate(uuid_t out);
78void uuid_generate_random(uuid_t out);
79void uuid_generate_time(uuid_t out);
80
81/* isnull.c */
82int uuid_is_null(const uuid_t uu);
83
84/* parse.c */
85int uuid_parse(const char *in, uuid_t uu);
86
87/* unparse.c */
88void uuid_unparse(const uuid_t uu, char *out);
89void uuid_unparse_lower(const uuid_t uu, char *out);
90void uuid_unparse_upper(const uuid_t uu, char *out);
91
92/* uuid_time.c */
93time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
94int uuid_type(const uuid_t uu);
95int 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
50struct 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 */
62void uuid_pack(const struct uuid *uu, uuid_t ptr);
63void 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
46time_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
68int 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
76int 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
94static 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
109int
110main(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