import more libs to prep for new e2fsprogs
This commit is contained in:
parent
1fd98e039d
commit
38a33f91c0
105
e2fsprogs/blkid/blkid.h
Normal file
105
e2fsprogs/blkid/blkid.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* blkid.h - Interface for libblkid, a library to identify block devices
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_BLKID_H
|
||||
#define _BLKID_BLKID_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLKID_VERSION "1.0.0"
|
||||
#define BLKID_DATE "12-Feb-2003"
|
||||
|
||||
typedef struct blkid_struct_dev *blkid_dev;
|
||||
typedef struct blkid_struct_cache *blkid_cache;
|
||||
typedef __s64 blkid_loff_t;
|
||||
|
||||
typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
|
||||
typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
|
||||
|
||||
/*
|
||||
* Flags for blkid_get_dev
|
||||
*
|
||||
* BLKID_DEV_CREATE Create an empty device structure if not found
|
||||
* in the cache.
|
||||
* BLKID_DEV_VERIFY Make sure the device structure corresponds
|
||||
* with reality.
|
||||
* BLKID_DEV_FIND Just look up a device entry, and return NULL
|
||||
* if it is not found.
|
||||
* BLKID_DEV_NORMAL Get a valid device structure, either from the
|
||||
* cache or by probing the device.
|
||||
*/
|
||||
#define BLKID_DEV_FIND 0x0000
|
||||
#define BLKID_DEV_CREATE 0x0001
|
||||
#define BLKID_DEV_VERIFY 0x0002
|
||||
#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
|
||||
|
||||
/* cache.c */
|
||||
extern void blkid_put_cache(blkid_cache cache);
|
||||
extern int blkid_get_cache(blkid_cache *cache, const char *filename);
|
||||
|
||||
/* dev.c */
|
||||
extern const char *blkid_dev_devname(blkid_dev dev);
|
||||
|
||||
extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
|
||||
extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
|
||||
extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
|
||||
|
||||
/* devno.c */
|
||||
extern char *blkid_devno_to_devname(dev_t devno);
|
||||
|
||||
/* devname.c */
|
||||
extern int blkid_probe_all(blkid_cache cache);
|
||||
extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
|
||||
int flags);
|
||||
|
||||
/* getsize.c */
|
||||
extern blkid_loff_t blkid_get_dev_size(int fd);
|
||||
|
||||
/* probe.c */
|
||||
int blkid_known_fstype(const char *fstype);
|
||||
extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
|
||||
|
||||
/* read.c */
|
||||
|
||||
/* resolve.c */
|
||||
extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
|
||||
const char *devname);
|
||||
extern char *blkid_get_devname(blkid_cache cache, const char *token,
|
||||
const char *value);
|
||||
|
||||
/* tag.c */
|
||||
extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
|
||||
extern int blkid_tag_next(blkid_tag_iterate iterate,
|
||||
const char **type, const char **value);
|
||||
extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
|
||||
|
||||
extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
|
||||
const char *type,
|
||||
const char *value);
|
||||
extern int blkid_parse_tag_string(const char *token, char **ret_type,
|
||||
char **ret_val);
|
||||
|
||||
/* version.c */
|
||||
extern int blkid_parse_version_string(const char *ver_string);
|
||||
extern int blkid_get_library_version(const char **ver_string,
|
||||
const char **date_string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_BLKID_H */
|
239
e2fsprogs/blkid/blkidP.h
Normal file
239
e2fsprogs/blkid/blkidP.h
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* blkidP.h - Internal interfaces for libblkid
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_BLKIDP_H
|
||||
#define _BLKID_BLKIDP_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <blkid/blkid.h>
|
||||
|
||||
#include <blkid/list.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define __BLKID_ATTR(x) __attribute__(x)
|
||||
#else
|
||||
#define __BLKID_ATTR(x)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This describes the attributes of a specific device.
|
||||
* We can traverse all of the tags by bid_tags (linking to the tag bit_names).
|
||||
* The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
|
||||
* values, if they exist.
|
||||
*/
|
||||
struct blkid_struct_dev
|
||||
{
|
||||
struct list_head bid_devs; /* All devices in the cache */
|
||||
struct list_head bid_tags; /* All tags for this device */
|
||||
blkid_cache bid_cache; /* Dev belongs to this cache */
|
||||
char *bid_name; /* Device inode pathname */
|
||||
char *bid_type; /* Preferred device TYPE */
|
||||
int bid_pri; /* Device priority */
|
||||
dev_t bid_devno; /* Device major/minor number */
|
||||
time_t bid_time; /* Last update time of device */
|
||||
unsigned int bid_flags; /* Device status bitflags */
|
||||
char *bid_label; /* Shortcut to device LABEL */
|
||||
char *bid_uuid; /* Shortcut to binary UUID */
|
||||
};
|
||||
|
||||
#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
|
||||
#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
|
||||
|
||||
/*
|
||||
* Each tag defines a NAME=value pair for a particular device. The tags
|
||||
* are linked via bit_names for a single device, so that traversing the
|
||||
* names list will get you a list of all tags associated with a device.
|
||||
* They are also linked via bit_values for all devices, so one can easily
|
||||
* search all tags with a given NAME for a specific value.
|
||||
*/
|
||||
struct blkid_struct_tag
|
||||
{
|
||||
struct list_head bit_tags; /* All tags for this device */
|
||||
struct list_head bit_names; /* All tags with given NAME */
|
||||
char *bit_name; /* NAME of tag (shared) */
|
||||
char *bit_val; /* value of tag */
|
||||
blkid_dev bit_dev; /* pointer to device */
|
||||
};
|
||||
typedef struct blkid_struct_tag *blkid_tag;
|
||||
|
||||
/*
|
||||
* Minimum number of seconds between device probes, even when reading
|
||||
* from the cache. This is to avoid re-probing all devices which were
|
||||
* just probed by another program that does not share the cache.
|
||||
*/
|
||||
#define BLKID_PROBE_MIN 2
|
||||
|
||||
/*
|
||||
* Time in seconds an entry remains verified in the in-memory cache
|
||||
* before being reverified (in case of long-running processes that
|
||||
* keep a cache in memory and continue to use it for a long time).
|
||||
*/
|
||||
#define BLKID_PROBE_INTERVAL 200
|
||||
|
||||
/* This describes an entire blkid cache file and probed devices.
|
||||
* We can traverse all of the found devices via bic_list.
|
||||
* We can traverse all of the tag types by bic_tags, which hold empty tags
|
||||
* for each tag type. Those tags can be used as list_heads for iterating
|
||||
* through all devices with a specific tag type (e.g. LABEL).
|
||||
*/
|
||||
struct blkid_struct_cache
|
||||
{
|
||||
struct list_head bic_devs; /* List head of all devices */
|
||||
struct list_head bic_tags; /* List head of all tag types */
|
||||
time_t bic_time; /* Last probe time */
|
||||
time_t bic_ftime; /* Mod time of the cachefile */
|
||||
unsigned int bic_flags; /* Status flags of the cache */
|
||||
char *bic_filename; /* filename of cache */
|
||||
};
|
||||
|
||||
#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
|
||||
#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
|
||||
|
||||
extern char *blkid_strdup(const char *s);
|
||||
extern char *blkid_strndup(const char *s, const int length);
|
||||
|
||||
#define BLKID_CACHE_FILE "/etc/blkid.tab"
|
||||
extern const char *blkid_devdirs[];
|
||||
|
||||
#define BLKID_ERR_IO 5
|
||||
#define BLKID_ERR_PROC 9
|
||||
#define BLKID_ERR_MEM 12
|
||||
#define BLKID_ERR_CACHE 14
|
||||
#define BLKID_ERR_DEV 19
|
||||
#define BLKID_ERR_PARAM 22
|
||||
#define BLKID_ERR_BIG 27
|
||||
|
||||
/*
|
||||
* Priority settings for different types of devices
|
||||
*/
|
||||
#define BLKID_PRI_EVMS 30
|
||||
#define BLKID_PRI_LVM 20
|
||||
#define BLKID_PRI_MD 10
|
||||
|
||||
#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
|
||||
#define CONFIG_BLKID_DEBUG
|
||||
#endif
|
||||
|
||||
#define DEBUG_CACHE 0x0001
|
||||
#define DEBUG_DUMP 0x0002
|
||||
#define DEBUG_DEV 0x0004
|
||||
#define DEBUG_DEVNAME 0x0008
|
||||
#define DEBUG_DEVNO 0x0010
|
||||
#define DEBUG_PROBE 0x0020
|
||||
#define DEBUG_READ 0x0040
|
||||
#define DEBUG_RESOLVE 0x0080
|
||||
#define DEBUG_SAVE 0x0100
|
||||
#define DEBUG_TAG 0x0200
|
||||
#define DEBUG_INIT 0x8000
|
||||
#define DEBUG_ALL 0xFFFF
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
#include <stdio.h>
|
||||
extern int blkid_debug_mask;
|
||||
#define DBG(m,x) if ((m) & blkid_debug_mask) x;
|
||||
#else
|
||||
#define DBG(m,x)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
static inline void DEB_DUMP_TAG(int mask, blkid_tag tag)
|
||||
{
|
||||
if (!(mask & blkid_debug_mask))
|
||||
return;
|
||||
|
||||
if (!tag) {
|
||||
printf(" tag: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
|
||||
}
|
||||
|
||||
static inline void DEB_DUMP_DEV(int mask, blkid_dev dev)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!(mask & blkid_debug_mask))
|
||||
return;
|
||||
|
||||
if (!dev) {
|
||||
printf(" dev: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" dev: name = %s\n", dev->bid_name);
|
||||
printf(" dev: DEVNO=\"0x%0Lx\"\n", dev->bid_devno);
|
||||
printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
|
||||
printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
|
||||
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
|
||||
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
DEB_DUMP_TAG(mask, tag);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline void DEB_DUMP_CACHE(int mask, blkid_cache cache)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !(mask & blkid_debug_mask)) {
|
||||
printf("cache: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("cache: time = %lu\n", cache->bic_time);
|
||||
printf("cache: flags = 0x%08X\n", cache->bic_flags);
|
||||
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
|
||||
DEB_DUMP_DEV(mask, dev);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DEB_DUMP_TAG(mask, tag) do {} while (0)
|
||||
#define DEB_DUMP_DEV(mask, dev) do {} while (0)
|
||||
#define DEB_DUMP_CACHE(mask, cache) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* lseek.c */
|
||||
extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
|
||||
|
||||
/* read.c */
|
||||
extern void blkid_read_cache(blkid_cache cache);
|
||||
|
||||
/* save.c */
|
||||
extern int blkid_flush_cache(blkid_cache cache);
|
||||
|
||||
/*
|
||||
* Functions to create and find a specific tag type: tag.c
|
||||
*/
|
||||
extern void blkid_free_tag(blkid_tag tag);
|
||||
extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
|
||||
extern int blkid_set_tag(blkid_dev dev, const char *name,
|
||||
const char *value, const int vlength);
|
||||
|
||||
/*
|
||||
* Functions to create and find a specific tag type: dev.c
|
||||
*/
|
||||
extern blkid_dev blkid_new_dev(void);
|
||||
extern void blkid_free_dev(blkid_dev dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_BLKIDP_H */
|
126
e2fsprogs/blkid/cache.c
Normal file
126
e2fsprogs/blkid/cache.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* cache.c - allocation/initialization/free routines for cache
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "blkidP.h"
|
||||
|
||||
int blkid_debug_mask = 0;
|
||||
|
||||
int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
|
||||
{
|
||||
blkid_cache cache;
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
if (!(blkid_debug_mask & DEBUG_INIT)) {
|
||||
char *dstr = getenv("BLKID_DEBUG");
|
||||
|
||||
if (dstr)
|
||||
blkid_debug_mask = strtoul(dstr, 0, 0);
|
||||
blkid_debug_mask |= DEBUG_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
|
||||
filename ? filename : "default cache"));
|
||||
|
||||
if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
INIT_LIST_HEAD(&cache->bic_devs);
|
||||
INIT_LIST_HEAD(&cache->bic_tags);
|
||||
|
||||
if (filename && !strlen(filename))
|
||||
filename = 0;
|
||||
if (!filename && (getuid() == geteuid()))
|
||||
filename = getenv("BLKID_FILE");
|
||||
if (!filename)
|
||||
filename = BLKID_CACHE_FILE;
|
||||
cache->bic_filename = blkid_strdup(filename);
|
||||
|
||||
blkid_read_cache(cache);
|
||||
|
||||
*ret_cache = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blkid_put_cache(blkid_cache cache)
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
(void) blkid_flush_cache(cache);
|
||||
|
||||
DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
|
||||
|
||||
/* DEB_DUMP_CACHE(cache); */
|
||||
|
||||
while (!list_empty(&cache->bic_devs)) {
|
||||
blkid_dev dev = list_entry(cache->bic_devs.next,
|
||||
struct blkid_struct_dev,
|
||||
bid_devs);
|
||||
blkid_free_dev(dev);
|
||||
}
|
||||
|
||||
while (!list_empty(&cache->bic_tags)) {
|
||||
blkid_tag tag = list_entry(cache->bic_tags.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
|
||||
while (!list_empty(&tag->bit_names)) {
|
||||
blkid_tag bad = list_entry(tag->bit_names.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_names);
|
||||
|
||||
DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
|
||||
bad->bit_name, bad->bit_val));
|
||||
blkid_free_tag(bad);
|
||||
}
|
||||
blkid_free_tag(tag);
|
||||
}
|
||||
if (cache->bic_filename)
|
||||
free(cache->bic_filename);
|
||||
|
||||
free(cache);
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if ((argc > 2)) {
|
||||
fprintf(stderr, "Usage: %s [filename] \n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
|
||||
fprintf(stderr, "error %d parsing cache file %s\n", ret,
|
||||
argv[1] ? argv[1] : BLKID_CACHE_FILE);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_probe_all(cache) < 0))
|
||||
fprintf(stderr, "error probing devices\n");
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
118
e2fsprogs/blkid/dev.c
Normal file
118
e2fsprogs/blkid/dev.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* dev.c - allocation/initialization/free routines for dev
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
blkid_dev blkid_new_dev(void)
|
||||
{
|
||||
blkid_dev dev;
|
||||
|
||||
if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&dev->bid_devs);
|
||||
INIT_LIST_HEAD(&dev->bid_tags);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void blkid_free_dev(blkid_dev dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_DEV,
|
||||
printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
|
||||
DEB_DUMP_DEV(DEBUG_DEV, dev);
|
||||
|
||||
list_del(&dev->bid_devs);
|
||||
while (!list_empty(&dev->bid_tags)) {
|
||||
blkid_tag tag = list_entry(dev->bid_tags.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
blkid_free_tag(tag);
|
||||
}
|
||||
if (dev->bid_name)
|
||||
free(dev->bid_name);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a blkid device, return its name
|
||||
*/
|
||||
extern const char *blkid_dev_devname(blkid_dev dev)
|
||||
{
|
||||
return dev->bid_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* dev iteration routines for the public libblkid interface.
|
||||
*
|
||||
* These routines do not expose the list.h implementation, which are a
|
||||
* contamination of the namespace, and which force us to reveal far, far
|
||||
* too much of our internal implemenation. I'm not convinced I want
|
||||
* to keep list.h in the long term, anyway. It's fine for kernel
|
||||
* programming, but performance is not the #1 priority for this
|
||||
* library, and I really don't like the tradeoff of type-safety for
|
||||
* performance for this application. [tytso:20030125.2007EST]
|
||||
*/
|
||||
|
||||
/*
|
||||
* This series of functions iterate over all devices in a blkid cache
|
||||
*/
|
||||
#define DEV_ITERATE_MAGIC 0x01a5284c
|
||||
|
||||
struct blkid_struct_dev_iterate {
|
||||
int magic;
|
||||
blkid_cache cache;
|
||||
struct list_head *p;
|
||||
};
|
||||
|
||||
extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
|
||||
{
|
||||
blkid_dev_iterate iter;
|
||||
|
||||
iter = malloc(sizeof(struct blkid_struct_dev_iterate));
|
||||
if (iter) {
|
||||
iter->magic = DEV_ITERATE_MAGIC;
|
||||
iter->cache = cache;
|
||||
iter->p = cache->bic_devs.next;
|
||||
}
|
||||
return (iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 on success, -1 on error
|
||||
*/
|
||||
extern int blkid_dev_next(blkid_dev_iterate iter,
|
||||
blkid_dev *dev)
|
||||
{
|
||||
*dev = 0;
|
||||
if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
|
||||
iter->p == &iter->cache->bic_devs)
|
||||
return -1;
|
||||
*dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
|
||||
iter->p = iter->p->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void blkid_dev_iterate_end(blkid_dev_iterate iter)
|
||||
{
|
||||
if (!iter || iter->magic != DEV_ITERATE_MAGIC)
|
||||
return;
|
||||
iter->magic = 0;
|
||||
free(iter);
|
||||
}
|
||||
|
376
e2fsprogs/blkid/devname.c
Normal file
376
e2fsprogs/blkid/devname.c
Normal file
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* devname.c - get a dev by its device inode name
|
||||
*
|
||||
* Copyright (C) Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
/*
|
||||
* Find a dev struct in the cache by device name, if available.
|
||||
*
|
||||
* If there is no entry with the specified device name, and the create
|
||||
* flag is set, then create an empty device entry.
|
||||
*/
|
||||
blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
|
||||
{
|
||||
blkid_dev dev = NULL, tmp;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !devname)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
|
||||
if (strcmp(tmp->bid_name, devname))
|
||||
continue;
|
||||
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("found devname %s in cache\n", tmp->bid_name));
|
||||
dev = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev && (flags & BLKID_DEV_CREATE)) {
|
||||
dev = blkid_new_dev();
|
||||
if (!dev)
|
||||
return NULL;
|
||||
dev->bid_name = blkid_strdup(devname);
|
||||
dev->bid_cache = cache;
|
||||
list_add_tail(&dev->bid_devs, &cache->bic_devs);
|
||||
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
}
|
||||
|
||||
if (flags & BLKID_DEV_VERIFY)
|
||||
dev = blkid_verify(cache, dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe a single block device to add to the device cache.
|
||||
*/
|
||||
static void probe_one(blkid_cache cache, const char *ptname,
|
||||
dev_t devno, int pri)
|
||||
{
|
||||
blkid_dev dev = NULL;
|
||||
struct list_head *p;
|
||||
const char **dir;
|
||||
char *devname = NULL;
|
||||
|
||||
/* See if we already have this device number in the cache. */
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
|
||||
bid_devs);
|
||||
if (tmp->bid_devno == devno) {
|
||||
dev = blkid_verify(cache, tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dev && dev->bid_devno == devno)
|
||||
goto set_pri;
|
||||
|
||||
/*
|
||||
* Take a quick look at /dev/ptname for the device number. We check
|
||||
* all of the likely device directories. If we don't find it, or if
|
||||
* the stat information doesn't check out, use blkid_devno_to_devname()
|
||||
* to find it via an exhaustive search for the device major/minor.
|
||||
*/
|
||||
for (dir = blkid_devdirs; *dir; dir++) {
|
||||
struct stat st;
|
||||
char device[256];
|
||||
|
||||
sprintf(device, "%s/%s", *dir, ptname);
|
||||
if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
|
||||
dev->bid_devno == devno)
|
||||
goto set_pri;
|
||||
|
||||
if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
|
||||
st.st_rdev == devno) {
|
||||
devname = blkid_strdup(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!devname) {
|
||||
devname = blkid_devno_to_devname(devno);
|
||||
if (!devname)
|
||||
return;
|
||||
}
|
||||
dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
|
||||
free(devname);
|
||||
|
||||
set_pri:
|
||||
if (!pri && !strncmp(ptname, "md", 2))
|
||||
pri = BLKID_PRI_MD;
|
||||
if (dev)
|
||||
dev->bid_pri = pri;
|
||||
return;
|
||||
}
|
||||
|
||||
#define PROC_PARTITIONS "/proc/partitions"
|
||||
#define VG_DIR "/proc/lvm/VGs"
|
||||
|
||||
/*
|
||||
* This function initializes the UUID cache with devices from the LVM
|
||||
* proc hierarchy. We currently depend on the names of the LVM
|
||||
* hierarchy giving us the device structure in /dev. (XXX is this a
|
||||
* safe thing to do?)
|
||||
*/
|
||||
#ifdef VG_DIR
|
||||
#include <dirent.h>
|
||||
static dev_t lvm_get_devno(const char *lvm_device)
|
||||
{
|
||||
FILE *lvf;
|
||||
char buf[1024];
|
||||
int ma, mi;
|
||||
dev_t ret = 0;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
|
||||
if ((lvf = fopen(lvm_device, "r")) == NULL) {
|
||||
DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
|
||||
strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), lvf)) {
|
||||
if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
|
||||
ret = makedev(ma, mi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(lvf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lvm_probe_all(blkid_cache cache)
|
||||
{
|
||||
DIR *vg_list;
|
||||
struct dirent *vg_iter;
|
||||
int vg_len = strlen(VG_DIR);
|
||||
dev_t dev;
|
||||
|
||||
if ((vg_list = opendir(VG_DIR)) == NULL)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
|
||||
|
||||
while ((vg_iter = readdir(vg_list)) != NULL) {
|
||||
DIR *lv_list;
|
||||
char *vdirname;
|
||||
char *vg_name;
|
||||
struct dirent *lv_iter;
|
||||
|
||||
vg_name = vg_iter->d_name;
|
||||
if (!strcmp(vg_name, ".") || !strcmp(vg_name, ".."))
|
||||
continue;
|
||||
vdirname = malloc(vg_len + strlen(vg_name) + 8);
|
||||
if (!vdirname)
|
||||
goto exit;
|
||||
sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
|
||||
|
||||
lv_list = opendir(vdirname);
|
||||
free(vdirname);
|
||||
if (lv_list == NULL)
|
||||
continue;
|
||||
|
||||
while ((lv_iter = readdir(lv_list)) != NULL) {
|
||||
char *lv_name, *lvm_device;
|
||||
|
||||
lv_name = lv_iter->d_name;
|
||||
if (!strcmp(lv_name, ".") || !strcmp(lv_name, ".."))
|
||||
continue;
|
||||
|
||||
lvm_device = malloc(vg_len + strlen(vg_name) +
|
||||
strlen(lv_name) + 8);
|
||||
if (!lvm_device) {
|
||||
closedir(lv_list);
|
||||
goto exit;
|
||||
}
|
||||
sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
|
||||
lv_name);
|
||||
dev = lvm_get_devno(lvm_device);
|
||||
sprintf(lvm_device, "%s/%s", vg_name, lv_name);
|
||||
DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
|
||||
lvm_device,
|
||||
(unsigned int) dev));
|
||||
probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
|
||||
free(lvm_device);
|
||||
}
|
||||
closedir(lv_list);
|
||||
}
|
||||
exit:
|
||||
closedir(vg_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
|
||||
|
||||
static int
|
||||
evms_probe_all(blkid_cache cache)
|
||||
{
|
||||
char line[100];
|
||||
int ma, mi, sz, num = 0;
|
||||
FILE *procpt;
|
||||
char device[110];
|
||||
|
||||
procpt = fopen(PROC_EVMS_VOLUMES, "r");
|
||||
if (!procpt)
|
||||
return 0;
|
||||
while (fgets(line, sizeof(line), procpt)) {
|
||||
if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
|
||||
&ma, &mi, &sz, device) != 4)
|
||||
continue;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
|
||||
device, ma, mi));
|
||||
|
||||
probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
|
||||
num++;
|
||||
}
|
||||
fclose(procpt);
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the device data for all available block devices in the system.
|
||||
*/
|
||||
int blkid_probe_all(blkid_cache cache)
|
||||
{
|
||||
FILE *proc;
|
||||
char line[1024];
|
||||
char ptname0[128], ptname1[128], *ptname = 0;
|
||||
char *ptnames[2];
|
||||
dev_t devs[2];
|
||||
int ma, mi;
|
||||
unsigned long long sz;
|
||||
int lens[2] = { 0, 0 };
|
||||
int which = 0, last = 0;
|
||||
|
||||
ptnames[0] = ptname0;
|
||||
ptnames[1] = ptname1;
|
||||
|
||||
if (!cache)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
|
||||
time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
|
||||
return 0;
|
||||
|
||||
blkid_read_cache(cache);
|
||||
evms_probe_all(cache);
|
||||
#ifdef VG_DIR
|
||||
lvm_probe_all(cache);
|
||||
#endif
|
||||
|
||||
proc = fopen(PROC_PARTITIONS, "r");
|
||||
if (!proc)
|
||||
return -BLKID_ERR_PROC;
|
||||
|
||||
while (fgets(line, sizeof(line), proc)) {
|
||||
last = which;
|
||||
which ^= 1;
|
||||
ptname = ptnames[which];
|
||||
|
||||
if (sscanf(line, " %d %d %llu %128[^\n ]",
|
||||
&ma, &mi, &sz, ptname) != 4)
|
||||
continue;
|
||||
devs[which] = makedev(ma, mi);
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
|
||||
|
||||
/* Skip whole disk devs unless they have no partitions
|
||||
* If we don't have a partition on this dev, also
|
||||
* check previous dev to see if it didn't have a partn.
|
||||
* heuristic: partition name ends in a digit.
|
||||
*
|
||||
* Skip extended partitions.
|
||||
* heuristic: size is 1
|
||||
*
|
||||
* FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
|
||||
*/
|
||||
|
||||
lens[which] = strlen(ptname);
|
||||
if (isdigit(ptname[lens[which] - 1])) {
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("partition dev %s, devno 0x%04X\n",
|
||||
ptname, (unsigned int) devs[which]));
|
||||
|
||||
if (sz > 1)
|
||||
probe_one(cache, ptname, devs[which], 0);
|
||||
lens[which] = 0;
|
||||
lens[last] = 0;
|
||||
} else if (lens[last] && strncmp(ptnames[last], ptname,
|
||||
lens[last])) {
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("whole dev %s, devno 0x%04X\n",
|
||||
ptnames[last], (unsigned int) devs[last]));
|
||||
probe_one(cache, ptnames[last], devs[last], 0);
|
||||
lens[last] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the last device if it wasn't partitioned */
|
||||
if (lens[which])
|
||||
probe_one(cache, ptname, devs[which], 0);
|
||||
|
||||
fclose(proc);
|
||||
|
||||
cache->bic_time = time(0);
|
||||
cache->bic_flags |= BLKID_BIC_FL_PROBED;
|
||||
blkid_flush_cache(cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "Usage: %s\n"
|
||||
"Probe all devices and exit\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if (blkid_probe_all(cache) < 0)
|
||||
printf("%s: error probing devices\n", argv[0]);
|
||||
|
||||
blkid_put_cache(cache);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
233
e2fsprogs/blkid/devno.c
Normal file
233
e2fsprogs/blkid/devno.c
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* devno.c - find a particular device by its device number (major/minor)
|
||||
*
|
||||
* Copyright (C) 2000, 2001, 2003 Theodore Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <dirent.h>
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
struct dir_list {
|
||||
char *name;
|
||||
struct dir_list *next;
|
||||
};
|
||||
|
||||
char *blkid_strndup(const char *s, int length)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!length)
|
||||
length = strlen(s);
|
||||
|
||||
ret = malloc(length + 1);
|
||||
if (ret) {
|
||||
strncpy(ret, s, length);
|
||||
ret[length] = '\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *blkid_strdup(const char *s)
|
||||
{
|
||||
return blkid_strndup(s, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adds an entry to the directory list
|
||||
*/
|
||||
static void add_to_dirlist(const char *name, struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp;
|
||||
|
||||
dp = malloc(sizeof(struct dir_list));
|
||||
if (!dp)
|
||||
return;
|
||||
dp->name = blkid_strdup(name);
|
||||
if (!dp->name) {
|
||||
free(dp);
|
||||
return;
|
||||
}
|
||||
dp->next = *list;
|
||||
*list = dp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function frees a directory list
|
||||
*/
|
||||
static void free_dirlist(struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp, *next;
|
||||
|
||||
for (dp = *list; dp; dp = next) {
|
||||
next = dp->next;
|
||||
free(dp->name);
|
||||
free(dp);
|
||||
}
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
|
||||
char **devname)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
char path[1024];
|
||||
int dirlen;
|
||||
struct stat st;
|
||||
|
||||
if ((dir = opendir(dir_name)) == NULL)
|
||||
return;
|
||||
dirlen = strlen(dir_name) + 2;
|
||||
while ((dp = readdir(dir)) != 0) {
|
||||
if (dirlen + strlen(dp->d_name) >= sizeof(path))
|
||||
continue;
|
||||
|
||||
if (dp->d_name[0] == '.' &&
|
||||
((dp->d_name[1] == 0) ||
|
||||
((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
|
||||
continue;
|
||||
|
||||
sprintf(path, "%s/%s", dir_name, dp->d_name);
|
||||
if (stat(path, &st) < 0)
|
||||
continue;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
add_to_dirlist(path, list);
|
||||
else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
|
||||
*devname = blkid_strdup(path);
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("found 0x%Lx at %s (%p)\n", devno,
|
||||
path, *devname));
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Directories where we will try to search for device numbers */
|
||||
const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
|
||||
|
||||
/*
|
||||
* This function finds the pathname to a block device with a given
|
||||
* device number. It returns a pointer to allocated memory to the
|
||||
* pathname on success, and NULL on failure.
|
||||
*/
|
||||
char *blkid_devno_to_devname(dev_t devno)
|
||||
{
|
||||
struct dir_list *list = NULL, *new_list = NULL;
|
||||
char *devname = NULL;
|
||||
const char **dir;
|
||||
|
||||
/*
|
||||
* Add the starting directories to search in reverse order of
|
||||
* importance, since we are using a stack...
|
||||
*/
|
||||
for (dir = blkid_devdirs; *dir; dir++)
|
||||
add_to_dirlist(*dir, &list);
|
||||
|
||||
while (list) {
|
||||
struct dir_list *current = list;
|
||||
|
||||
list = list->next;
|
||||
DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
|
||||
scan_dir(current->name, devno, &new_list, &devname);
|
||||
free(current->name);
|
||||
free(current);
|
||||
if (devname)
|
||||
break;
|
||||
/*
|
||||
* If we're done checking at this level, descend to
|
||||
* the next level of subdirectories. (breadth-first)
|
||||
*/
|
||||
if (list == NULL) {
|
||||
list = new_list;
|
||||
new_list = NULL;
|
||||
}
|
||||
}
|
||||
free_dirlist(&list);
|
||||
free_dirlist(&new_list);
|
||||
|
||||
if (!devname) {
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("blkid: couldn't find devno 0x%04lx\n",
|
||||
(unsigned long) devno));
|
||||
} else {
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("found devno 0x%04Lx as %s\n", devno, devname));
|
||||
}
|
||||
|
||||
|
||||
return devname;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char *devname, *tmp;
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
const char *errmsg = "Couldn't parse %s: %s\n";
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if ((argc != 2) && (argc != 3)) {
|
||||
fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
|
||||
"Resolve a device number to a device name\n",
|
||||
argv[0], argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 2) {
|
||||
devno = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "device number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
major = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "major number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
minor = strtoul(argv[2], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "minor number", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
devno = makedev(major, minor);
|
||||
}
|
||||
printf("Looking for device 0x%04Lx\n", devno);
|
||||
devname = blkid_devno_to_devname(devno);
|
||||
if (devname)
|
||||
free(devname);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
180
e2fsprogs/blkid/getsize.c
Normal file
180
e2fsprogs/blkid/getsize.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* getsize.c --- get the size of a partition.
|
||||
*
|
||||
* Copyright (C) 1995, 1995 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/* include this before sys/queues.h! */
|
||||
#include "blkidP.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_FD_H
|
||||
#include <linux/fd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISK_H
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h> /* for LIST_HEAD */
|
||||
#endif
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
|
||||
#define BLKGETSIZE _IO(0x12,96) /* return device size */
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
|
||||
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
|
||||
#endif
|
||||
|
||||
#ifdef APPLE_DARWIN
|
||||
#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
|
||||
#endif /* APPLE_DARWIN */
|
||||
|
||||
static int valid_offset(int fd, blkid_loff_t offset)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (blkid_llseek(fd, offset, 0) < 0)
|
||||
return 0;
|
||||
if (read(fd, &ch, 1) < 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of blocks in a partition
|
||||
*/
|
||||
blkid_loff_t blkid_get_dev_size(int fd)
|
||||
{
|
||||
int valid_blkgetsize64 = 1;
|
||||
#ifdef __linux__
|
||||
struct utsname ut;
|
||||
#endif
|
||||
unsigned long long size64;
|
||||
unsigned long size;
|
||||
blkid_loff_t high, low;
|
||||
#ifdef FDGETPRM
|
||||
struct floppy_struct this_floppy;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
int part = -1;
|
||||
struct disklabel lab;
|
||||
struct partition *pp;
|
||||
char ch;
|
||||
struct stat st;
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
|
||||
if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
|
||||
if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
|
||||
&& (size64 << 9 > 0xFFFFFFFF))
|
||||
return 0; /* EFBIG */
|
||||
return (blkid_loff_t) size64 << 9;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
#ifdef __linux__
|
||||
if ((uname(&ut) == 0) &&
|
||||
((ut.release[0] == '2') && (ut.release[1] == '.') &&
|
||||
(ut.release[2] < '6') && (ut.release[3] == '.')))
|
||||
valid_blkgetsize64 = 0;
|
||||
#endif
|
||||
if (valid_blkgetsize64 &&
|
||||
ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
|
||||
if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
|
||||
&& ((size64) > 0xFFFFFFFF))
|
||||
return 0; /* EFBIG */
|
||||
return size64;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE
|
||||
if (ioctl(fd, BLKGETSIZE, &size) >= 0)
|
||||
return (blkid_loff_t)size << 9;
|
||||
#endif
|
||||
|
||||
#ifdef FDGETPRM
|
||||
if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
|
||||
return (blkid_loff_t)this_floppy.size << 9;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#if 0
|
||||
/*
|
||||
* This should work in theory but I haven't tested it. Anyone
|
||||
* on a BSD system want to test this for me? In the meantime,
|
||||
* binary search mechanism should work just fine.
|
||||
*/
|
||||
if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
|
||||
part = st.st_rdev & 7;
|
||||
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
|
||||
pp = &lab.d_partitions[part];
|
||||
if (pp->p_size)
|
||||
return pp->p_size << 9;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
/*
|
||||
* OK, we couldn't figure it out by using a specialized ioctl,
|
||||
* which is generally the best way. So do binary search to
|
||||
* find the size of the partition.
|
||||
*/
|
||||
low = 0;
|
||||
for (high = 1024; valid_offset(fd, high); high *= 2)
|
||||
low = high;
|
||||
while (low < high - 1)
|
||||
{
|
||||
const blkid_loff_t mid = (low + high) / 2;
|
||||
|
||||
if (valid_offset(fd, mid))
|
||||
low = mid;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
return low + 1;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_loff_t bytes;
|
||||
int fd;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s device\n"
|
||||
"Determine the size of a device\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY)) < 0)
|
||||
perror(argv[0]);
|
||||
|
||||
bytes = blkid_get_dev_size(fd);
|
||||
printf("Device %s has %Ld 1k blocks.\n", argv[1], bytes >> 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
179
e2fsprogs/blkid/list.h
Normal file
179
e2fsprogs/blkid/list.h
Normal file
@ -0,0 +1,179 @@
|
||||
#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
|
||||
#define _BLKID_LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _INLINE_ static __inline__
|
||||
#else /* For Watcom C */
|
||||
#define _INLINE_ static inline
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
_INLINE_ void __list_add(struct list_head * add,
|
||||
struct list_head * prev,
|
||||
struct list_head * next)
|
||||
{
|
||||
next->prev = add;
|
||||
add->next = next;
|
||||
add->prev = prev;
|
||||
prev->next = add;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @add: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
_INLINE_ void list_add(struct list_head *add, struct list_head *head)
|
||||
{
|
||||
__list_add(add, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @add: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head)
|
||||
{
|
||||
__list_add(add, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
_INLINE_ void __list_del(struct list_head * prev,
|
||||
struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
*
|
||||
* list_empty() on @entry does not return true after this, @entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
_INLINE_ void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
_INLINE_ void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
_INLINE_ int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
_INLINE_ void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
|
||||
if (first != list) {
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over elements in a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over elements in a list, but don't dereference
|
||||
* pos after the body is done (in case it is freed)
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @pnext: the &struct list_head to use as a pointer to the next item.
|
||||
* @head: the head for your list (not included in iteration).
|
||||
*/
|
||||
#define list_for_each_safe(pos, pnext, head) \
|
||||
for (pos = (head)->next, pnext = pos->next; pos != (head); \
|
||||
pos = pnext, pnext = pos->next)
|
||||
|
||||
#undef _INLINE_
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_LIST_H */
|
139
e2fsprogs/blkid/llseek.c
Normal file
139
e2fsprogs/blkid/llseek.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* llseek.c -- stub calling the llseek system call
|
||||
*
|
||||
* Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef __MSDOS__
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
|
||||
|
||||
#define my_llseek lseek64
|
||||
|
||||
#elif defined(HAVE_LLSEEK)
|
||||
#include <syscall.h>
|
||||
|
||||
#ifndef HAVE_LLSEEK_PROTOTYPE
|
||||
extern long long llseek(int fd, long long offset, int origin);
|
||||
#endif
|
||||
|
||||
#define my_llseek llseek
|
||||
|
||||
#else /* ! HAVE_LLSEEK */
|
||||
|
||||
#if defined(__alpha__) || defined(__ia64__)
|
||||
|
||||
#define llseek lseek
|
||||
|
||||
#else /* !__alpha__ && !__ia64__*/
|
||||
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#ifndef __NR__llseek
|
||||
#define __NR__llseek 140
|
||||
#endif
|
||||
|
||||
#ifndef __i386__
|
||||
static int _llseek(unsigned int, unsigned long, unsigned long,
|
||||
blkid_loff_t *, unsigned int);
|
||||
|
||||
static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high,
|
||||
unsigned long, offset_low, blkid_loff_t *, result,
|
||||
unsigned int, origin)
|
||||
#endif
|
||||
|
||||
static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin)
|
||||
{
|
||||
blkid_loff_t result;
|
||||
int retval;
|
||||
|
||||
#ifndef __i386__
|
||||
retval = _llseek(fd, ((unsigned long long) offset) >> 32,
|
||||
((unsigned long long)offset) & 0xffffffff,
|
||||
&result, origin);
|
||||
#else
|
||||
retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32,
|
||||
((unsigned long long)offset) & 0xffffffff,
|
||||
&result, origin);
|
||||
#endif
|
||||
return (retval == -1 ? (blkid_loff_t) retval : result);
|
||||
}
|
||||
|
||||
#endif /* __alpha__ || __ia64__ */
|
||||
|
||||
#endif /* HAVE_LLSEEK */
|
||||
|
||||
blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence)
|
||||
{
|
||||
blkid_loff_t result;
|
||||
static int do_compat = 0;
|
||||
|
||||
if ((sizeof(off_t) >= sizeof(blkid_loff_t)) ||
|
||||
(offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1))))
|
||||
return lseek(fd, (off_t) offset, whence);
|
||||
|
||||
if (do_compat) {
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = my_llseek(fd, offset, whence);
|
||||
if (result == -1 && errno == ENOSYS) {
|
||||
/*
|
||||
* Just in case this code runs on top of an old kernel
|
||||
* which does not support the llseek system call
|
||||
*/
|
||||
do_compat++;
|
||||
errno = EOVERFLOW;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* !linux */
|
||||
|
||||
#ifndef EOVERFLOW
|
||||
#ifdef EXT2_ET_INVALID_ARGUMENT
|
||||
#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT
|
||||
#else
|
||||
#define EOVERFLOW 112
|
||||
#endif
|
||||
#endif
|
||||
|
||||
blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin)
|
||||
{
|
||||
#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
|
||||
return lseek64 (fd, offset, origin);
|
||||
#else
|
||||
if ((sizeof(off_t) < sizeof(blkid_loff_t)) &&
|
||||
(offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) {
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
return lseek(fd, (off_t) offset, origin);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* linux */
|
||||
|
||||
|
704
e2fsprogs/blkid/probe.c
Normal file
704
e2fsprogs/blkid/probe.c
Normal file
@ -0,0 +1,704 @@
|
||||
/*
|
||||
* probe.c - identify a block device by its contents, and return a dev
|
||||
* struct with the details
|
||||
*
|
||||
* Copyright (C) 1999 by Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "blkidP.h"
|
||||
#include "uuid/uuid.h"
|
||||
#include "probe.h"
|
||||
|
||||
/*
|
||||
* This is a special case code to check for an MDRAID device. We do
|
||||
* this special since it requires checking for a superblock at the end
|
||||
* of the device.
|
||||
*/
|
||||
static int check_mdraid(int fd, unsigned char *ret_uuid)
|
||||
{
|
||||
struct mdp_superblock_s *md;
|
||||
blkid_loff_t offset;
|
||||
char buf[4096];
|
||||
|
||||
if (fd < 0)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
|
||||
|
||||
if (blkid_llseek(fd, offset, 0) < 0 ||
|
||||
read(fd, buf, 4096) != 4096)
|
||||
return -BLKID_ERR_IO;
|
||||
|
||||
/* Check for magic number */
|
||||
if (memcmp("\251+N\374", buf, 4))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!ret_uuid)
|
||||
return 0;
|
||||
*ret_uuid = 0;
|
||||
|
||||
/* The MD UUID is not contiguous in the superblock, make it so */
|
||||
md = (struct mdp_superblock_s *)buf;
|
||||
if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
|
||||
memcpy(ret_uuid, &md->set_uuid0, 4);
|
||||
memcpy(ret_uuid, &md->set_uuid1, 12);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_uuid(blkid_dev dev, uuid_t uuid)
|
||||
{
|
||||
char str[37];
|
||||
|
||||
if (!uuid_is_null(uuid)) {
|
||||
uuid_unparse(uuid, str);
|
||||
blkid_set_tag(dev, "UUID", str, sizeof(str));
|
||||
}
|
||||
}
|
||||
|
||||
static void get_ext2_info(blkid_dev dev, unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es = (struct ext2_super_block *) buf;
|
||||
const char *label = 0;
|
||||
|
||||
DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
|
||||
blkid_le32(es->s_feature_compat),
|
||||
blkid_le32(es->s_feature_incompat),
|
||||
blkid_le32(es->s_feature_ro_compat)));
|
||||
|
||||
if (strlen(es->s_volume_name))
|
||||
label = es->s_volume_name;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
|
||||
|
||||
set_uuid(dev, es->s_uuid);
|
||||
}
|
||||
|
||||
static int probe_ext3(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id, unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
|
||||
es = (struct ext2_super_block *)buf;
|
||||
|
||||
/* Distinguish between jbd and ext2/3 fs */
|
||||
if (blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
/* Distinguish between ext3 and ext2 */
|
||||
if (!(blkid_le32(es->s_feature_compat) &
|
||||
EXT3_FEATURE_COMPAT_HAS_JOURNAL))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_ext2(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id, unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
// const char *sec_type = 0, *label = 0;
|
||||
|
||||
es = (struct ext2_super_block *)buf;
|
||||
|
||||
/* Distinguish between jbd and ext2/3 fs */
|
||||
if (blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_jbd(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es = (struct ext2_super_block *) buf;
|
||||
|
||||
if (!(blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_vfat(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct vfat_super_block *vs;
|
||||
char serno[10];
|
||||
const char *label = 0;
|
||||
int label_len = 0;
|
||||
|
||||
vs = (struct vfat_super_block *)buf;
|
||||
|
||||
if (strncmp(vs->vs_label, "NO NAME", 7)) {
|
||||
char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
|
||||
|
||||
while (*end == ' ' && end >= vs->vs_label)
|
||||
--end;
|
||||
if (end >= vs->vs_label) {
|
||||
label = vs->vs_label;
|
||||
label_len = end - vs->vs_label + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can't just print them as %04X, because they are unaligned */
|
||||
sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
|
||||
vs->vs_serno[1], vs->vs_serno[0]);
|
||||
blkid_set_tag(dev, "LABEL", label, label_len);
|
||||
blkid_set_tag(dev, "UUID", serno, sizeof(serno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_msdos(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct msdos_super_block *ms = (struct msdos_super_block *) buf;
|
||||
char serno[10];
|
||||
const char *label = 0;
|
||||
int label_len = 0;
|
||||
|
||||
if (strncmp(ms->ms_label, "NO NAME", 7)) {
|
||||
char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
|
||||
|
||||
while (*end == ' ' && end >= ms->ms_label)
|
||||
--end;
|
||||
if (end >= ms->ms_label) {
|
||||
label = ms->ms_label;
|
||||
label_len = end - ms->ms_label + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can't just print them as %04X, because they are unaligned */
|
||||
sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
|
||||
ms->ms_serno[1], ms->ms_serno[0]);
|
||||
blkid_set_tag(dev, "UUID", serno, 0);
|
||||
blkid_set_tag(dev, "LABEL", label, label_len);
|
||||
blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_xfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct xfs_super_block *xs;
|
||||
const char *label = 0;
|
||||
|
||||
xs = (struct xfs_super_block *)buf;
|
||||
|
||||
if (strlen(xs->xs_fname))
|
||||
label = xs->xs_fname;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
|
||||
set_uuid(dev, xs->xs_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id, unsigned char *buf)
|
||||
{
|
||||
struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
|
||||
unsigned int blocksize;
|
||||
const char *label = 0;
|
||||
|
||||
blocksize = blkid_le16(rs->rs_blocksize);
|
||||
|
||||
/* If the superblock is inside the journal, we have the wrong one */
|
||||
if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
|
||||
return -BLKID_ERR_BIG;
|
||||
|
||||
/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
|
||||
if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
|
||||
!strcmp(id->bim_magic, "ReIsEr3Fs")) {
|
||||
if (strlen(rs->rs_label))
|
||||
label = rs->rs_label;
|
||||
set_uuid(dev, rs->rs_uuid);
|
||||
}
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_jfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct jfs_super_block *js;
|
||||
const char *label = 0;
|
||||
|
||||
js = (struct jfs_super_block *)buf;
|
||||
|
||||
if (strlen((char *) js->js_label))
|
||||
label = (char *) js->js_label;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
|
||||
set_uuid(dev, js->js_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_romfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct romfs_super_block *ros;
|
||||
const char *label = 0;
|
||||
|
||||
ros = (struct romfs_super_block *)buf;
|
||||
|
||||
if (strlen((char *) ros->ros_volume))
|
||||
label = (char *) ros->ros_volume;
|
||||
blkid_set_tag(dev, "LABEL", label, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_swap0(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
blkid_set_tag(dev, "UUID", 0, 0);
|
||||
blkid_set_tag(dev, "LABEL", 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_swap1(int fd,
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
struct swap_id_block *sws;
|
||||
// const char *label = 0;
|
||||
|
||||
probe_swap0(fd, cache, dev, id, buf);
|
||||
/*
|
||||
* Version 1 swap headers are always located at offset of 1024
|
||||
* bytes, although the swap signature itself is located at the
|
||||
* end of the page (which may vary depending on hardware
|
||||
* pagesize).
|
||||
*/
|
||||
if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
|
||||
if (!(sws = (struct swap_id_block *)malloc(1024))) return 1;
|
||||
if (read(fd, sws, 1024) != 1024) {
|
||||
free(sws);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* arbitrary sanity check.. is there any garbage down there? */
|
||||
if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
|
||||
if (sws->sws_volume[0])
|
||||
blkid_set_tag(dev, "LABEL", sws->sws_volume,
|
||||
sizeof(sws->sws_volume));
|
||||
if (sws->sws_uuid[0])
|
||||
set_uuid(dev, sws->sws_uuid);
|
||||
}
|
||||
free(sws);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char
|
||||
*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
|
||||
"NSR03", "TEA01", 0 };
|
||||
|
||||
static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev __BLKID_ATTR((unused)),
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
int j, bs;
|
||||
struct iso_volume_descriptor isosb;
|
||||
const char ** m;
|
||||
|
||||
/* determine the block size by scanning in 2K increments
|
||||
(block sizes larger than 2K will be null padded) */
|
||||
for (bs = 1; bs < 16; bs++) {
|
||||
lseek(fd, bs*2048+32768, SEEK_SET);
|
||||
if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
|
||||
return 1;
|
||||
if (isosb.id[0])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Scan up to another 64 blocks looking for additional VSD's */
|
||||
for (j = 1; j < 64; j++) {
|
||||
if (j > 1) {
|
||||
lseek(fd, j*bs*2048+32768, SEEK_SET);
|
||||
if (read(fd, (char *)&isosb, sizeof(isosb))
|
||||
!= sizeof(isosb))
|
||||
return 1;
|
||||
}
|
||||
/* If we find NSR0x then call it udf:
|
||||
NSR01 for UDF 1.00
|
||||
NSR02 for UDF 1.50
|
||||
NSR03 for UDF 2.00 */
|
||||
if (!strncmp(isosb.id, "NSR0", 4))
|
||||
return 0;
|
||||
for (m = udf_magic; *m; m++)
|
||||
if (!strncmp(*m, isosb.id, 5))
|
||||
break;
|
||||
if (*m == 0)
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int probe_ocfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ocfs_volume_header ovh;
|
||||
struct ocfs_volume_label ovl;
|
||||
__u32 major;
|
||||
|
||||
memcpy(&ovh, buf, sizeof(ovh));
|
||||
memcpy(&ovl, buf+512, sizeof(ovl));
|
||||
|
||||
major = ocfsmajor(ovh);
|
||||
if (major == 1)
|
||||
blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
|
||||
else if (major >= 9)
|
||||
blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
|
||||
|
||||
blkid_set_tag(dev, "LABEL", ovl.label, ocfslabellen(ovl));
|
||||
blkid_set_tag(dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
|
||||
set_uuid(dev, ovl.vol_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ocfs2_super_block *osb;
|
||||
|
||||
osb = (struct ocfs2_super_block *)buf;
|
||||
|
||||
blkid_set_tag(dev, "LABEL", osb->s_label, sizeof(osb->s_label));
|
||||
set_uuid(dev, osb->s_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct oracle_asm_disk_label *dl;
|
||||
|
||||
dl = (struct oracle_asm_disk_label *)buf;
|
||||
|
||||
blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
|
||||
* in the type_array table below + bim_kbalign.
|
||||
*
|
||||
* When probing for a lot of magics, we handle everything in 1kB buffers so
|
||||
* that we don't have to worry about reading each combination of block sizes.
|
||||
*/
|
||||
#define BLKID_BLK_OFFS 64 /* currently reiserfs */
|
||||
|
||||
/*
|
||||
* Various filesystem magics that we can check for. Note that kboff and
|
||||
* sboff are in kilobytes and bytes respectively. All magics are in
|
||||
* byte strings so we don't worry about endian issues.
|
||||
*/
|
||||
static struct blkid_magic type_array[] = {
|
||||
/* type kboff sboff len magic probe */
|
||||
{ "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
|
||||
{ "ntfs", 0, 3, 8, "NTFS ", 0 },
|
||||
{ "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
|
||||
{ "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
|
||||
{ "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
|
||||
{ "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
|
||||
{ "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
|
||||
{ "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
|
||||
{ "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
|
||||
{ "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
|
||||
{ "minix", 1, 0x10, 2, "\177\023", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\217\023", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\150\044", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\170\044", 0 },
|
||||
{ "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
|
||||
{ "xfs", 0, 0, 4, "XFSB", probe_xfs },
|
||||
{ "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
|
||||
{ "bfs", 0, 0, 4, "\316\372\173\033", 0 },
|
||||
{ "cramfs", 0, 0, 4, "E=\315\034", 0 },
|
||||
{ "qnx4", 0, 4, 6, "QNX4FS", 0 },
|
||||
{ "udf", 32, 1, 5, "BEA01", probe_udf },
|
||||
{ "udf", 32, 1, 5, "BOOT2", probe_udf },
|
||||
{ "udf", 32, 1, 5, "CD001", probe_udf },
|
||||
{ "udf", 32, 1, 5, "CDW02", probe_udf },
|
||||
{ "udf", 32, 1, 5, "NSR02", probe_udf },
|
||||
{ "udf", 32, 1, 5, "NSR03", probe_udf },
|
||||
{ "udf", 32, 1, 5, "TEA01", probe_udf },
|
||||
{ "iso9660", 32, 1, 5, "CD001", 0 },
|
||||
{ "iso9660", 32, 9, 5, "CDROM", 0 },
|
||||
{ "jfs", 32, 0, 4, "JFS1", probe_jfs },
|
||||
{ "hfs", 1, 0, 2, "BD", 0 },
|
||||
{ "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
|
||||
{ "hpfs", 8, 0, 4, "I\350\225\371", 0 },
|
||||
{ "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
|
||||
{ "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
|
||||
{ "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Verify that the data in dev is consistent with what is on the actual
|
||||
* block device (using the devname field only). Normally this will be
|
||||
* called when finding items in the cache, but for long running processes
|
||||
* is also desirable to revalidate an item before use.
|
||||
*
|
||||
* If we are unable to revalidate the data, we return the old data and
|
||||
* do not set the BLKID_BID_FL_VERIFIED flag on it.
|
||||
*/
|
||||
blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
|
||||
{
|
||||
struct blkid_magic *id;
|
||||
unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
|
||||
const char *type;
|
||||
struct stat st;
|
||||
time_t diff, now;
|
||||
int fd, idx;
|
||||
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
now = time(0);
|
||||
diff = now - dev->bid_time;
|
||||
|
||||
if ((now < dev->bid_time) ||
|
||||
(diff < BLKID_PROBE_MIN) ||
|
||||
(dev->bid_flags & BLKID_BID_FL_VERIFIED &&
|
||||
diff < BLKID_PROBE_INTERVAL))
|
||||
return dev;
|
||||
|
||||
DBG(DEBUG_PROBE,
|
||||
printf("need to revalidate %s (time since last check %lu)\n",
|
||||
dev->bid_name, diff));
|
||||
|
||||
if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
|
||||
(fstat(fd, &st) < 0)) {
|
||||
if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
|
||||
blkid_free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
/* We don't have read permission, just return cache data. */
|
||||
DBG(DEBUG_PROBE,
|
||||
printf("returning unverified data for %s\n",
|
||||
dev->bid_name));
|
||||
return dev;
|
||||
}
|
||||
|
||||
memset(bufs, 0, sizeof(bufs));
|
||||
|
||||
/*
|
||||
* Iterate over the type array. If we already know the type,
|
||||
* then try that first. If it doesn't work, then blow away
|
||||
* the type information, and try again.
|
||||
*
|
||||
*/
|
||||
try_again:
|
||||
type = 0;
|
||||
if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
|
||||
uuid_t uuid;
|
||||
|
||||
if (check_mdraid(fd, uuid) == 0) {
|
||||
set_uuid(dev, uuid);
|
||||
type = "mdraid";
|
||||
goto found_type;
|
||||
}
|
||||
}
|
||||
for (id = type_array; id->bim_type; id++) {
|
||||
if (dev->bid_type &&
|
||||
strcmp(id->bim_type, dev->bid_type))
|
||||
continue;
|
||||
|
||||
idx = id->bim_kboff + (id->bim_sboff >> 10);
|
||||
if (idx > BLKID_BLK_OFFS || idx < 0)
|
||||
continue;
|
||||
buf = bufs[idx];
|
||||
if (!buf) {
|
||||
if (lseek(fd, idx << 10, SEEK_SET) < 0)
|
||||
continue;
|
||||
|
||||
if (!(buf = (unsigned char *)malloc(1024)))
|
||||
continue;
|
||||
|
||||
if (read(fd, buf, 1024) != 1024) {
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
bufs[idx] = buf;
|
||||
}
|
||||
|
||||
if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
|
||||
id->bim_len))
|
||||
continue;
|
||||
|
||||
if ((id->bim_probe == NULL) ||
|
||||
(id->bim_probe(fd, cache, dev, id, buf) == 0)) {
|
||||
type = id->bim_type;
|
||||
goto found_type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!id->bim_type && dev->bid_type) {
|
||||
/*
|
||||
* Zap the device filesystem type and try again
|
||||
*/
|
||||
blkid_set_tag(dev, "TYPE", 0, 0);
|
||||
blkid_set_tag(dev, "SEC_TYPE", 0, 0);
|
||||
blkid_set_tag(dev, "LABEL", 0, 0);
|
||||
blkid_set_tag(dev, "UUID", 0, 0);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (!dev->bid_type) {
|
||||
blkid_free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
found_type:
|
||||
if (dev && type) {
|
||||
dev->bid_devno = st.st_rdev;
|
||||
dev->bid_time = time(0);
|
||||
dev->bid_flags |= BLKID_BID_FL_VERIFIED;
|
||||
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
|
||||
blkid_set_tag(dev, "TYPE", type, 0);
|
||||
|
||||
DBG(DEBUG_PROBE, printf("%s: devno 0x%04Lx, type %s\n",
|
||||
dev->bid_name, st.st_rdev, type));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
int blkid_known_fstype(const char *fstype)
|
||||
{
|
||||
struct blkid_magic *id;
|
||||
|
||||
for (id = type_array; id->bim_type; id++) {
|
||||
if (strcmp(fstype, id->bim_type) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_dev dev;
|
||||
blkid_cache cache;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s device\n"
|
||||
"Probe a single device to determine type\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
|
||||
if (!dev) {
|
||||
printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
|
||||
return (1);
|
||||
}
|
||||
printf("%s is type %s\n", argv[1], dev->bid_type ?
|
||||
dev->bid_type : "(null)");
|
||||
if (dev->bid_label)
|
||||
printf("\tlabel is '%s'\n", dev->bid_label);
|
||||
if (dev->bid_uuid)
|
||||
printf("\tuuid is %s\n", dev->bid_uuid);
|
||||
|
||||
blkid_free_dev(dev);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
359
e2fsprogs/blkid/probe.h
Normal file
359
e2fsprogs/blkid/probe.h
Normal file
@ -0,0 +1,359 @@
|
||||
/*
|
||||
* probe.h - constants and on-disk structures for extracting device data
|
||||
*
|
||||
* Copyright (C) 1999 by Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_PROBE_H
|
||||
#define _BLKID_PROBE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct blkid_magic;
|
||||
|
||||
typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
|
||||
struct blkid_magic *id, unsigned char *buf);
|
||||
|
||||
struct blkid_magic {
|
||||
const char *bim_type; /* type name for this magic */
|
||||
long bim_kboff; /* kilobyte offset of superblock */
|
||||
unsigned bim_sboff; /* byte offset within superblock */
|
||||
unsigned bim_len; /* length of magic */
|
||||
const char *bim_magic; /* magic string */
|
||||
blkid_probe_t bim_probe; /* probe function */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures for each of the content types we want to extract information
|
||||
* from. We do not necessarily need the magic field here, because we have
|
||||
* already identified the content type before we get this far. It may still
|
||||
* be useful if there are probe functions which handle multiple content types.
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
__u32 s_inodes_count;
|
||||
__u32 s_blocks_count;
|
||||
__u32 s_r_blocks_count;
|
||||
__u32 s_free_blocks_count;
|
||||
__u32 s_free_inodes_count;
|
||||
__u32 s_first_data_block;
|
||||
__u32 s_log_block_size;
|
||||
__u32 s_dummy3[7];
|
||||
unsigned char s_magic[2];
|
||||
__u16 s_state;
|
||||
__u32 s_dummy5[8];
|
||||
__u32 s_feature_compat;
|
||||
__u32 s_feature_incompat;
|
||||
__u32 s_feature_ro_compat;
|
||||
unsigned char s_uuid[16];
|
||||
char s_volume_name[16];
|
||||
};
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
|
||||
|
||||
struct xfs_super_block {
|
||||
unsigned char xs_magic[4];
|
||||
__u32 xs_blocksize;
|
||||
__u64 xs_dblocks;
|
||||
__u64 xs_rblocks;
|
||||
__u32 xs_dummy1[2];
|
||||
unsigned char xs_uuid[16];
|
||||
__u32 xs_dummy2[15];
|
||||
char xs_fname[12];
|
||||
__u32 xs_dummy3[2];
|
||||
__u64 xs_icount;
|
||||
__u64 xs_ifree;
|
||||
__u64 xs_fdblocks;
|
||||
};
|
||||
|
||||
struct reiserfs_super_block {
|
||||
__u32 rs_blocks_count;
|
||||
__u32 rs_free_blocks;
|
||||
__u32 rs_root_block;
|
||||
__u32 rs_journal_block;
|
||||
__u32 rs_journal_dev;
|
||||
__u32 rs_orig_journal_size;
|
||||
__u32 rs_dummy2[5];
|
||||
__u16 rs_blocksize;
|
||||
__u16 rs_dummy3[3];
|
||||
unsigned char rs_magic[12];
|
||||
__u32 rs_dummy4[5];
|
||||
unsigned char rs_uuid[16];
|
||||
char rs_label[16];
|
||||
};
|
||||
|
||||
struct jfs_super_block {
|
||||
unsigned char js_magic[4];
|
||||
__u32 js_version;
|
||||
__u64 js_size;
|
||||
__u32 js_bsize;
|
||||
__u32 js_dummy1;
|
||||
__u32 js_pbsize;
|
||||
__u32 js_dummy2[27];
|
||||
unsigned char js_uuid[16];
|
||||
unsigned char js_label[16];
|
||||
unsigned char js_loguuid[16];
|
||||
};
|
||||
|
||||
struct romfs_super_block {
|
||||
unsigned char ros_magic[8];
|
||||
__u32 ros_dummy1[2];
|
||||
unsigned char ros_volume[16];
|
||||
};
|
||||
|
||||
struct swap_id_block {
|
||||
/* unsigned char sws_boot[1024]; */
|
||||
__u32 sws_version;
|
||||
__u32 sws_lastpage;
|
||||
__u32 sws_nrbad;
|
||||
unsigned char sws_uuid[16];
|
||||
unsigned char sws_volume[16];
|
||||
unsigned char sws_pad[117];
|
||||
__u32 sws_badpg;
|
||||
};
|
||||
|
||||
/* Yucky misaligned values */
|
||||
struct vfat_super_block {
|
||||
/* 00*/ unsigned char vs_ignored[3];
|
||||
/* 03*/ unsigned char vs_sysid[8];
|
||||
/* 0b*/ unsigned char vs_sector_size[2];
|
||||
/* 0d*/ __u8 vs_cluster_size;
|
||||
/* 0e*/ __u16 vs_reserved;
|
||||
/* 10*/ __u8 vs_fats;
|
||||
/* 11*/ unsigned char vs_dir_entries[2];
|
||||
/* 13*/ unsigned char vs_sectors[2];
|
||||
/* 15*/ unsigned char vs_media;
|
||||
/* 16*/ __u16 vs_fat_length;
|
||||
/* 18*/ __u16 vs_secs_track;
|
||||
/* 1a*/ __u16 vs_heads;
|
||||
/* 1c*/ __u32 vs_hidden;
|
||||
/* 20*/ __u32 vs_total_sect;
|
||||
/* 24*/ __u32 vs_fat32_length;
|
||||
/* 28*/ __u16 vs_flags;
|
||||
/* 2a*/ __u8 vs_version[2];
|
||||
/* 2c*/ __u32 vs_root_cluster;
|
||||
/* 30*/ __u16 vs_insfo_sector;
|
||||
/* 32*/ __u16 vs_backup_boot;
|
||||
/* 34*/ __u16 vs_reserved2[6];
|
||||
/* 40*/ unsigned char vs_unknown[3];
|
||||
/* 43*/ unsigned char vs_serno[4];
|
||||
/* 47*/ char vs_label[11];
|
||||
/* 52*/ unsigned char vs_magic[8];
|
||||
/* 5a*/ unsigned char vs_dummy2[164];
|
||||
/*1fe*/ unsigned char vs_pmagic[2];
|
||||
};
|
||||
|
||||
/* Yucky misaligned values */
|
||||
struct msdos_super_block {
|
||||
/* 00*/ unsigned char ms_ignored[3];
|
||||
/* 03*/ unsigned char ms_sysid[8];
|
||||
/* 0b*/ unsigned char ms_sector_size[2];
|
||||
/* 0d*/ __u8 ms_cluster_size;
|
||||
/* 0e*/ __u16 ms_reserved;
|
||||
/* 10*/ __u8 ms_fats;
|
||||
/* 11*/ unsigned char ms_dir_entries[2];
|
||||
/* 13*/ unsigned char ms_sectors[2];
|
||||
/* 15*/ unsigned char ms_media;
|
||||
/* 16*/ __u16 ms_fat_length;
|
||||
/* 18*/ __u16 ms_secs_track;
|
||||
/* 1a*/ __u16 ms_heads;
|
||||
/* 1c*/ __u32 ms_hidden;
|
||||
/* 20*/ __u32 ms_total_sect;
|
||||
/* 24*/ unsigned char ms_unknown[3];
|
||||
/* 27*/ unsigned char ms_serno[4];
|
||||
/* 2b*/ char ms_label[11];
|
||||
/* 36*/ unsigned char ms_magic[8];
|
||||
/* 3d*/ unsigned char ms_dummy2[192];
|
||||
/*1fe*/ unsigned char ms_pmagic[2];
|
||||
};
|
||||
|
||||
struct minix_super_block {
|
||||
__u16 ms_ninodes;
|
||||
__u16 ms_nzones;
|
||||
__u16 ms_imap_blocks;
|
||||
__u16 ms_zmap_blocks;
|
||||
__u16 ms_firstdatazone;
|
||||
__u16 ms_log_zone_size;
|
||||
__u32 ms_max_size;
|
||||
unsigned char ms_magic[2];
|
||||
__u16 ms_state;
|
||||
__u32 ms_zones;
|
||||
};
|
||||
|
||||
struct mdp_superblock_s {
|
||||
__u32 md_magic;
|
||||
__u32 major_version;
|
||||
__u32 minor_version;
|
||||
__u32 patch_version;
|
||||
__u32 gvalid_words;
|
||||
__u32 set_uuid0;
|
||||
__u32 ctime;
|
||||
__u32 level;
|
||||
__u32 size;
|
||||
__u32 nr_disks;
|
||||
__u32 raid_disks;
|
||||
__u32 md_minor;
|
||||
__u32 not_persistent;
|
||||
__u32 set_uuid1;
|
||||
__u32 set_uuid2;
|
||||
__u32 set_uuid3;
|
||||
};
|
||||
|
||||
struct hfs_super_block {
|
||||
char h_magic[2];
|
||||
char h_dummy[18];
|
||||
__u32 h_blksize;
|
||||
};
|
||||
|
||||
struct ocfs_volume_header {
|
||||
unsigned char minor_version[4];
|
||||
unsigned char major_version[4];
|
||||
unsigned char signature[128];
|
||||
unsigned char mount[128];
|
||||
unsigned char mount_len[2];
|
||||
};
|
||||
|
||||
struct ocfs_volume_label {
|
||||
unsigned char disk_lock[48];
|
||||
unsigned char label[64];
|
||||
unsigned char label_len[2];
|
||||
unsigned char vol_id[16];
|
||||
unsigned char vol_id_len[2];
|
||||
};
|
||||
|
||||
#define ocfsmajor(o) ((__u32)o.major_version[0] \
|
||||
+ (((__u32) o.major_version[1]) << 8) \
|
||||
+ (((__u32) o.major_version[2]) << 16) \
|
||||
+ (((__u32) o.major_version[3]) << 24))
|
||||
#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
|
||||
#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
|
||||
|
||||
#define OCFS_MAGIC "OracleCFS"
|
||||
|
||||
struct ocfs2_super_block {
|
||||
unsigned char signature[8];
|
||||
unsigned char s_dummy1[184];
|
||||
unsigned char s_dummy2[80];
|
||||
unsigned char s_label[64];
|
||||
unsigned char s_uuid[16];
|
||||
};
|
||||
|
||||
#define OCFS2_MIN_BLOCKSIZE 512
|
||||
#define OCFS2_MAX_BLOCKSIZE 4096
|
||||
|
||||
#define OCFS2_SUPER_BLOCK_BLKNO 2
|
||||
|
||||
#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
|
||||
|
||||
struct oracle_asm_disk_label {
|
||||
char dummy[32];
|
||||
char dl_tag[8];
|
||||
char dl_id[24];
|
||||
};
|
||||
|
||||
#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
|
||||
#define ORACLE_ASM_DISK_LABEL_OFFSET 32
|
||||
|
||||
#define ISODCL(from, to) (to - from + 1)
|
||||
struct iso_volume_descriptor {
|
||||
char type[ISODCL(1,1)]; /* 711 */
|
||||
char id[ISODCL(2,6)];
|
||||
char version[ISODCL(7,7)];
|
||||
char data[ISODCL(8,2048)];
|
||||
};
|
||||
|
||||
/*
|
||||
* Byte swap functions
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define _INLINE_ static __inline__
|
||||
#else /* For Watcom C */
|
||||
#define _INLINE_ static inline
|
||||
#endif
|
||||
|
||||
static __u16 blkid_swab16(__u16 val);
|
||||
static __u32 blkid_swab32(__u32 val);
|
||||
static __u64 blkid_swab64(__u64 val);
|
||||
|
||||
#if ((defined __GNUC__) && \
|
||||
(defined(__i386__) || defined(__i486__) || defined(__i586__)))
|
||||
|
||||
#define _BLKID_HAVE_ASM_BITOPS_
|
||||
|
||||
_INLINE_ __u32 blkid_swab32(__u32 val)
|
||||
{
|
||||
#ifdef EXT2FS_REQUIRE_486
|
||||
__asm__("bswap %0" : "=r" (val) : "0" (val));
|
||||
#else
|
||||
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
|
||||
"rorl $16,%0\n\t" /* swap words */
|
||||
"xchgb %b0,%h0" /* swap higher bytes */
|
||||
:"=q" (val)
|
||||
: "0" (val));
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
_INLINE_ __u16 blkid_swab16(__u16 val)
|
||||
{
|
||||
__asm__("xchgb %b0,%h0" /* swap bytes */ \
|
||||
: "=q" (val) \
|
||||
: "0" (val)); \
|
||||
return val;
|
||||
}
|
||||
|
||||
_INLINE_ __u64 blkid_swab64(__u64 val)
|
||||
{
|
||||
return (blkid_swab32(val >> 32) |
|
||||
(((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_BLKID_HAVE_ASM_BITOPS_)
|
||||
|
||||
_INLINE_ __u16 blkid_swab16(__u16 val)
|
||||
{
|
||||
return (val >> 8) | (val << 8);
|
||||
}
|
||||
|
||||
_INLINE_ __u32 blkid_swab32(__u32 val)
|
||||
{
|
||||
return ((val>>24) | ((val>>8)&0xFF00) |
|
||||
((val<<8)&0xFF0000) | (val<<24));
|
||||
}
|
||||
|
||||
_INLINE_ __u64 blkid_swab64(__u64 val)
|
||||
{
|
||||
return (blkid_swab32(val >> 32) |
|
||||
(((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define blkid_le16(x) blkid_swab16(x)
|
||||
#define blkid_le32(x) blkid_swab32(x)
|
||||
#define blkid_le64(x) blkid_swab64(x)
|
||||
#define blkid_be16(x) (x)
|
||||
#define blkid_be32(x) (x)
|
||||
#define blkid_be64(x) (x)
|
||||
#else
|
||||
#define blkid_le16(x) (x)
|
||||
#define blkid_le32(x) (x)
|
||||
#define blkid_le64(x) (x)
|
||||
#define blkid_be16(x) blkid_swab16(x)
|
||||
#define blkid_be32(x) blkid_swab32(x)
|
||||
#define blkid_be64(x) blkid_swab64(x)
|
||||
#endif
|
||||
|
||||
#undef _INLINE_
|
||||
|
||||
#endif /* _BLKID_PROBE_H */
|
459
e2fsprogs/blkid/read.c
Normal file
459
e2fsprogs/blkid/read.c
Normal file
@ -0,0 +1,459 @@
|
||||
/*
|
||||
* read.c - read the blkid cache from disk, to avoid scanning all devices
|
||||
*
|
||||
* Copyright (C) 2001, 2003 Theodore Y. Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "blkidP.h"
|
||||
#include "uuid/uuid.h"
|
||||
|
||||
#ifdef HAVE_STRTOULL
|
||||
#define __USE_ISOC9X
|
||||
#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
|
||||
#else
|
||||
/* FIXME: need to support real strtoull here */
|
||||
#define STRTOULL strtoul
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* File format:
|
||||
*
|
||||
* <device [<NAME="value"> ...]>device_name</device>
|
||||
*
|
||||
* The following tags are required for each entry:
|
||||
* <ID="id"> unique (within this file) ID number of this device
|
||||
* <TIME="time"> (ascii time_t) time this entry was last read from disk
|
||||
* <TYPE="type"> (detected) type of filesystem/data for this partition
|
||||
*
|
||||
* The following tags may be present, depending on the device contents
|
||||
* <LABEL="label"> (user supplied) label (volume name, etc)
|
||||
* <UUID="uuid"> (generated) universally unique identifier (serial no)
|
||||
*/
|
||||
|
||||
static char *skip_over_blank(char *cp)
|
||||
{
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *skip_over_word(char *cp)
|
||||
{
|
||||
char ch;
|
||||
|
||||
while ((ch = *cp)) {
|
||||
/* If we see a backslash, skip the next character */
|
||||
if (ch == '\\') {
|
||||
cp++;
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (isspace(ch) || ch == '<' || ch == '>')
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *strip_line(char *line)
|
||||
{
|
||||
char *p;
|
||||
|
||||
line = skip_over_blank(line);
|
||||
|
||||
p = line + strlen(line) - 1;
|
||||
|
||||
while (*line) {
|
||||
if (isspace(*p))
|
||||
*p-- = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *parse_word(char **buf)
|
||||
{
|
||||
char *word, *next;
|
||||
|
||||
word = *buf;
|
||||
if (*word == '\0')
|
||||
return NULL;
|
||||
|
||||
word = skip_over_blank(word);
|
||||
next = skip_over_word(word);
|
||||
if (*next) {
|
||||
char *end = next - 1;
|
||||
if (*end == '"' || *end == '\'')
|
||||
*end = '\0';
|
||||
*next++ = '\0';
|
||||
}
|
||||
*buf = next;
|
||||
|
||||
if (*word == '"' || *word == '\'')
|
||||
word++;
|
||||
return word;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start parsing a new line from the cache.
|
||||
*
|
||||
* line starts with "<device" return 1 -> continue parsing line
|
||||
* line starts with "<foo", empty, or # return 0 -> skip line
|
||||
* line starts with other, return -BLKID_ERR_CACHE -> error
|
||||
*/
|
||||
static int parse_start(char **cp)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strip_line(*cp);
|
||||
|
||||
/* Skip comment or blank lines. We can't just NUL the first '#' char,
|
||||
* in case it is inside quotes, or escaped.
|
||||
*/
|
||||
if (*p == '\0' || *p == '#')
|
||||
return 0;
|
||||
|
||||
if (!strncmp(p, "<device", 7)) {
|
||||
DBG(DEBUG_READ, printf("found device header: %8s\n", p));
|
||||
p += 7;
|
||||
|
||||
*cp = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*p == '<')
|
||||
return 0;
|
||||
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
/* Consume the remaining XML on the line (cosmetic only) */
|
||||
static int parse_end(char **cp)
|
||||
{
|
||||
*cp = skip_over_blank(*cp);
|
||||
|
||||
if (!strncmp(*cp, "</device>", 9)) {
|
||||
DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
|
||||
*cp += 9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new device struct with device name filled in. Will handle
|
||||
* finding the device on lines of the form:
|
||||
* <device foo=bar>devname</device>
|
||||
* <device>devname<foo>bar</foo></device>
|
||||
*/
|
||||
static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
|
||||
{
|
||||
char *start, *tmp, *end, *name;
|
||||
int ret;
|
||||
|
||||
if ((ret = parse_start(cp)) <= 0)
|
||||
return ret;
|
||||
|
||||
start = tmp = strchr(*cp, '>');
|
||||
if (!start) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: short line parsing dev: %s\n", *cp));
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
start = skip_over_blank(start + 1);
|
||||
end = skip_over_word(start);
|
||||
|
||||
DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
|
||||
|
||||
if (**cp == '>')
|
||||
*cp = end;
|
||||
else
|
||||
(*cp)++;
|
||||
|
||||
*tmp = '\0';
|
||||
|
||||
if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: missing </device> ending: %s\n", end));
|
||||
} else if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
if (end - start <= 1) {
|
||||
DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
name = blkid_strndup(start, end-start);
|
||||
if (name == NULL)
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
DBG(DEBUG_READ, printf("found dev %s\n", name));
|
||||
|
||||
if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
free(name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a tag of the form NAME="value" from the line.
|
||||
*/
|
||||
static int parse_token(char **name, char **value, char **cp)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (!name || !value || !cp)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!(*value = strchr(*cp, '=')))
|
||||
return 0;
|
||||
|
||||
**value = '\0';
|
||||
*name = strip_line(*cp);
|
||||
*value = skip_over_blank(*value + 1);
|
||||
|
||||
if (**value == '"') {
|
||||
end = strchr(*value + 1, '"');
|
||||
if (!end) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("unbalanced quotes at: %s\n", *value));
|
||||
*cp = *value;
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
(*value)++;
|
||||
*end = '\0';
|
||||
end++;
|
||||
} else {
|
||||
end = skip_over_word(*value);
|
||||
if (*end) {
|
||||
*end = '\0';
|
||||
end++;
|
||||
}
|
||||
}
|
||||
*cp = end;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a tag of the form <NAME>value</NAME> from the line.
|
||||
*/
|
||||
/*
|
||||
static int parse_xml(char **name, char **value, char **cp)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (!name || !value || !cp)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
*name = strip_line(*cp);
|
||||
|
||||
if ((*name)[0] != '<' || (*name)[1] == '/')
|
||||
return 0;
|
||||
|
||||
FIXME: finish this.
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extract a tag from the line.
|
||||
*
|
||||
* Return 1 if a valid tag was found.
|
||||
* Return 0 if no tag found.
|
||||
* Return -ve error code.
|
||||
*/
|
||||
static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
int ret;
|
||||
|
||||
if (!cache || !dev)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
|
||||
(ret = parse_xml(&name, &value, cp)) <= 0 */)
|
||||
return ret;
|
||||
|
||||
/* Some tags are stored directly in the device struct */
|
||||
if (!strcmp(name, "DEVNO"))
|
||||
dev->bid_devno = STRTOULL(value, 0, 0);
|
||||
else if (!strcmp(name, "PRI"))
|
||||
dev->bid_pri = strtol(value, 0, 0);
|
||||
else if (!strcmp(name, "TIME"))
|
||||
/* FIXME: need to parse a long long eventually */
|
||||
dev->bid_time = strtol(value, 0, 0);
|
||||
else
|
||||
ret = blkid_set_tag(dev, name, value, strlen(value));
|
||||
|
||||
DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a single line of data, and return a newly allocated dev struct.
|
||||
* Add the new device to the cache struct, if one was read.
|
||||
*
|
||||
* Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
|
||||
*
|
||||
* Returns -ve value on error.
|
||||
* Returns 0 otherwise.
|
||||
* If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
|
||||
* (e.g. comment lines, unknown XML content, etc).
|
||||
*/
|
||||
static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
|
||||
{
|
||||
blkid_dev dev;
|
||||
int ret;
|
||||
|
||||
if (!cache || !dev_p)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
*dev_p = NULL;
|
||||
|
||||
DBG(DEBUG_READ, printf("line: %s\n", cp));
|
||||
|
||||
if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
|
||||
return ret;
|
||||
|
||||
dev = *dev_p;
|
||||
|
||||
while ((ret = parse_tag(cache, dev, &cp)) > 0) {
|
||||
;
|
||||
}
|
||||
|
||||
if (dev->bid_type == NULL) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: device %s has no TYPE\n",dev->bid_name));
|
||||
blkid_free_dev(dev);
|
||||
}
|
||||
|
||||
DEB_DUMP_DEV(DEBUG_READ, dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the specified filename, and return the data in the supplied or
|
||||
* a newly allocated cache struct. If the file doesn't exist, return a
|
||||
* new empty cache struct.
|
||||
*/
|
||||
void blkid_read_cache(blkid_cache cache)
|
||||
{
|
||||
FILE *file;
|
||||
char buf[4096];
|
||||
int fd, lineno = 0;
|
||||
struct stat st;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the file doesn't exist, then we just return an empty
|
||||
* struct so that the cache can be populated.
|
||||
*/
|
||||
if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
|
||||
return;
|
||||
if (fstat(fd, &st) < 0)
|
||||
goto errout;
|
||||
if ((st.st_mtime == cache->bic_ftime) ||
|
||||
(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
|
||||
DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
|
||||
cache->bic_filename));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
DBG(DEBUG_CACHE, printf("reading cache file %s\n",
|
||||
cache->bic_filename));
|
||||
|
||||
file = fdopen(fd, "r");
|
||||
if (!file)
|
||||
goto errout;
|
||||
|
||||
while (fgets(buf, sizeof(buf), file)) {
|
||||
blkid_dev dev;
|
||||
unsigned int end;
|
||||
|
||||
lineno++;
|
||||
if (buf[0] == 0)
|
||||
continue;
|
||||
end = strlen(buf) - 1;
|
||||
/* Continue reading next line if it ends with a backslash */
|
||||
while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
|
||||
fgets(buf + end, sizeof(buf) - end, file)) {
|
||||
end = strlen(buf) - 1;
|
||||
lineno++;
|
||||
}
|
||||
|
||||
if (blkid_parse_line(cache, &dev, buf) < 0) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: bad format on line %d\n", lineno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
/*
|
||||
* Initially we do not need to write out the cache file.
|
||||
*/
|
||||
cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
|
||||
cache->bic_ftime = st.st_mtime;
|
||||
|
||||
return;
|
||||
errout:
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [filename]\n"
|
||||
"Test parsing of the cache (filename)\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
|
||||
fprintf(stderr, "error %d reading cache file %s\n", ret,
|
||||
argv[1] ? argv[1] : BLKID_CACHE_FILE);
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
140
e2fsprogs/blkid/resolve.c
Normal file
140
e2fsprogs/blkid/resolve.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* resolve.c - resolve names and tags into specific devices
|
||||
*
|
||||
* Copyright (C) 2001, 2003 Theodore Ts'o.
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "blkidP.h"
|
||||
#include "probe.h"
|
||||
|
||||
/*
|
||||
* Find a tagname (e.g. LABEL or UUID) on a specific device.
|
||||
*/
|
||||
char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
|
||||
const char *devname)
|
||||
{
|
||||
blkid_tag found;
|
||||
blkid_dev dev;
|
||||
blkid_cache c = cache;
|
||||
char *ret = NULL;
|
||||
|
||||
DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
|
||||
if (!cache) {
|
||||
if (blkid_get_cache(&c, NULL) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
|
||||
(found = blkid_find_tag_dev(dev, tagname)))
|
||||
ret = blkid_strdup(found->bit_val);
|
||||
|
||||
if (!cache)
|
||||
blkid_put_cache(c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate a device name from a token (NAME=value string), or (name, value)
|
||||
* pair. In the case of a token, value is ignored. If the "token" is not
|
||||
* of the form "NAME=value" and there is no value given, then it is assumed
|
||||
* to be the actual devname and a copy is returned.
|
||||
*/
|
||||
char *blkid_get_devname(blkid_cache cache, const char *token,
|
||||
const char *value)
|
||||
{
|
||||
blkid_dev dev;
|
||||
blkid_cache c = cache;
|
||||
char *t = 0, *v = 0;
|
||||
char *ret = NULL;
|
||||
|
||||
if (!token)
|
||||
return NULL;
|
||||
|
||||
if (!cache) {
|
||||
if (blkid_get_cache(&c, NULL) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG(DEBUG_RESOLVE,
|
||||
printf("looking for %s%s%s %s\n", token, value ? "=" : "",
|
||||
value ? value : "", cache ? "in cache" : "from disk"));
|
||||
|
||||
if (!value) {
|
||||
if (!strchr(token, '='))
|
||||
return blkid_strdup(token);
|
||||
blkid_parse_tag_string(token, &t, &v);
|
||||
if (!t || !v)
|
||||
goto errout;
|
||||
token = t;
|
||||
value = v;
|
||||
}
|
||||
|
||||
dev = blkid_find_dev_with_tag(c, token, value);
|
||||
if (!dev)
|
||||
goto errout;
|
||||
|
||||
ret = blkid_strdup(blkid_dev_devname(dev));
|
||||
|
||||
errout:
|
||||
if (t)
|
||||
free(t);
|
||||
if (v)
|
||||
free(v);
|
||||
if (!cache) {
|
||||
blkid_put_cache(c);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *value;
|
||||
blkid_cache cache;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage:\t%s tagname=value\n"
|
||||
"\t%s tagname devname\n"
|
||||
"Find which device holds a given token or\n"
|
||||
"Find what the value of a tag is in a device\n",
|
||||
argv[0], argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (blkid_get_cache(&cache, "/dev/null") < 0) {
|
||||
fprintf(stderr, "Couldn't get blkid cache\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argv[2]) {
|
||||
value = blkid_get_tag_value(cache, argv[1], argv[2]);
|
||||
printf("%s has tag %s=%s\n", argv[2], argv[1],
|
||||
value ? value : "<missing>");
|
||||
} else {
|
||||
value = blkid_get_devname(cache, argv[1], NULL);
|
||||
printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
|
||||
}
|
||||
blkid_put_cache(cache);
|
||||
return value ? 0 : 1;
|
||||
}
|
||||
#endif
|
193
e2fsprogs/blkid/save.c
Normal file
193
e2fsprogs/blkid/save.c
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* save.c - write the cache struct to disk
|
||||
*
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "blkidP.h"
|
||||
|
||||
static int save_dev(blkid_dev dev, FILE *file)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev || dev->bid_name[0] != '/')
|
||||
return 0;
|
||||
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
|
||||
|
||||
fprintf(file,
|
||||
"<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
|
||||
(unsigned long) dev->bid_devno, dev->bid_time);
|
||||
if (dev->bid_pri)
|
||||
fprintf(file, " PRI=\"%d\"", dev->bid_pri);
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
|
||||
}
|
||||
fprintf(file, ">%s</device>\n", dev->bid_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the cache struct to the cache file on disk.
|
||||
*/
|
||||
int blkid_flush_cache(blkid_cache cache)
|
||||
{
|
||||
struct list_head *p;
|
||||
char *tmp = NULL;
|
||||
const char *opened = NULL;
|
||||
const char *filename;
|
||||
FILE *file = NULL;
|
||||
int fd, ret = 0;
|
||||
struct stat st;
|
||||
|
||||
if (!cache)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (list_empty(&cache->bic_devs) ||
|
||||
!(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
|
||||
DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
|
||||
|
||||
/* If we can't write to the cache file, then don't even try */
|
||||
if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
|
||||
(ret == 0 && access(filename, W_OK) < 0)) {
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("can't write to cache file %s\n", filename));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and create a temporary file in the same directory so
|
||||
* that in case of error we don't overwrite the cache file.
|
||||
* If the cache file doesn't yet exist, it isn't a regular
|
||||
* file (e.g. /dev/null or a socket), or we couldn't create
|
||||
* a temporary file then we open it directly.
|
||||
*/
|
||||
if (ret == 0 && S_ISREG(st.st_mode)) {
|
||||
tmp = malloc(strlen(filename) + 8);
|
||||
if (tmp) {
|
||||
sprintf(tmp, "%s-XXXXXX", filename);
|
||||
fd = mkstemp(tmp);
|
||||
if (fd >= 0) {
|
||||
file = fdopen(fd, "w");
|
||||
opened = tmp;
|
||||
}
|
||||
fchmod(fd, 0644);
|
||||
}
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
file = fopen(filename, "w");
|
||||
opened = filename;
|
||||
}
|
||||
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("writing cache file %s (really %s)\n",
|
||||
filename, opened));
|
||||
|
||||
if (!file) {
|
||||
ret = errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
|
||||
if (!dev->bid_type)
|
||||
continue;
|
||||
if ((ret = save_dev(dev, file)) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret >= 0) {
|
||||
cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
if (opened != filename) {
|
||||
if (ret < 0) {
|
||||
unlink(opened);
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("unlinked temp cache %s\n", opened));
|
||||
} else {
|
||||
char *backup;
|
||||
|
||||
backup = malloc(strlen(filename) + 5);
|
||||
if (backup) {
|
||||
sprintf(backup, "%s.old", filename);
|
||||
unlink(backup);
|
||||
link(filename, backup);
|
||||
free(backup);
|
||||
}
|
||||
rename(opened, filename);
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("moved temp cache %s\n", opened));
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [filename]\n"
|
||||
"Test loading/saving a cache (filename)\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_probe_all(cache)) < 0) {
|
||||
fprintf(stderr, "error (%d) probing devices\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
cache->bic_filename = blkid_strdup(argv[1]);
|
||||
|
||||
if ((ret = blkid_flush_cache(cache)) < 0) {
|
||||
fprintf(stderr, "error (%d) saving cache\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
340
e2fsprogs/blkid/tag.c
Normal file
340
e2fsprogs/blkid/tag.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* tag.c - allocation/initialization/free routines for tag structs
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
static blkid_tag blkid_new_tag(void)
|
||||
{
|
||||
blkid_tag tag;
|
||||
|
||||
if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&tag->bit_tags);
|
||||
INIT_LIST_HEAD(&tag->bit_names);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
void blkid_free_tag(blkid_tag tag)
|
||||
{
|
||||
if (!tag)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
|
||||
tag->bit_val ? tag->bit_val : "(NULL)"));
|
||||
DEB_DUMP_TAG(DEBUG_TAG, tag);
|
||||
|
||||
list_del(&tag->bit_tags); /* list of tags for this device */
|
||||
list_del(&tag->bit_names); /* list of tags with this type */
|
||||
|
||||
if (tag->bit_name)
|
||||
free(tag->bit_name);
|
||||
if (tag->bit_val)
|
||||
free(tag->bit_val);
|
||||
|
||||
free(tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the desired tag on a device. If value is NULL, then the
|
||||
* first such tag is returned, otherwise return only exact tag if found.
|
||||
*/
|
||||
blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev || !type)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
|
||||
if (!strcmp(tmp->bit_name, type))
|
||||
return tmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the desired tag type in the cache.
|
||||
* We return the head tag for this tag type.
|
||||
*/
|
||||
static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
|
||||
{
|
||||
blkid_tag head = NULL, tmp;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !type)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &cache->bic_tags) {
|
||||
tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
if (!strcmp(tmp->bit_name, type)) {
|
||||
DBG(DEBUG_TAG,
|
||||
printf(" found cache tag head %s\n", type));
|
||||
head = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a tag on an existing device.
|
||||
*
|
||||
* If value is NULL, then delete the tagsfrom the device.
|
||||
*/
|
||||
int blkid_set_tag(blkid_dev dev, const char *name,
|
||||
const char *value, const int vlength)
|
||||
{
|
||||
blkid_tag t = 0, head = 0;
|
||||
char *val = 0;
|
||||
|
||||
if (!dev || !name)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!(val = blkid_strndup(value, vlength)) && value)
|
||||
return -BLKID_ERR_MEM;
|
||||
t = blkid_find_tag_dev(dev, name);
|
||||
if (!value) {
|
||||
if (t)
|
||||
blkid_free_tag(t);
|
||||
} else if (t) {
|
||||
if (!strcmp(t->bit_val, val)) {
|
||||
/* Same thing, exit */
|
||||
free(val);
|
||||
return 0;
|
||||
}
|
||||
free(t->bit_val);
|
||||
t->bit_val = val;
|
||||
} else {
|
||||
/* Existing tag not present, add to device */
|
||||
if (!(t = blkid_new_tag()))
|
||||
goto errout;
|
||||
t->bit_name = blkid_strdup(name);
|
||||
t->bit_val = val;
|
||||
t->bit_dev = dev;
|
||||
|
||||
list_add_tail(&t->bit_tags, &dev->bid_tags);
|
||||
|
||||
if (dev->bid_cache) {
|
||||
head = blkid_find_head_cache(dev->bid_cache,
|
||||
t->bit_name);
|
||||
if (!head) {
|
||||
head = blkid_new_tag();
|
||||
if (!head)
|
||||
goto errout;
|
||||
|
||||
DBG(DEBUG_TAG,
|
||||
printf(" creating new cache tag head %s\n", name));
|
||||
head->bit_name = blkid_strdup(name);
|
||||
if (!head->bit_name)
|
||||
goto errout;
|
||||
list_add_tail(&head->bit_tags,
|
||||
&dev->bid_cache->bic_tags);
|
||||
}
|
||||
list_add_tail(&t->bit_names, &head->bit_names);
|
||||
}
|
||||
}
|
||||
|
||||
/* Link common tags directly to the device struct */
|
||||
if (!strcmp(name, "TYPE"))
|
||||
dev->bid_type = val;
|
||||
else if (!strcmp(name, "LABEL"))
|
||||
dev->bid_label = val;
|
||||
else if (!strcmp(name, "UUID"))
|
||||
dev->bid_uuid = val;
|
||||
|
||||
if (dev->bid_cache)
|
||||
dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (t)
|
||||
blkid_free_tag(t);
|
||||
else if (val)
|
||||
free(val);
|
||||
if (head)
|
||||
blkid_free_tag(head);
|
||||
return -BLKID_ERR_MEM;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse a "NAME=value" string. This is slightly different than
|
||||
* parse_token, because that will end an unquoted value at a space, while
|
||||
* this will assume that an unquoted value is the rest of the token (e.g.
|
||||
* if we are passed an already quoted string from the command-line we don't
|
||||
* have to both quote and escape quote so that the quotes make it to
|
||||
* us).
|
||||
*
|
||||
* Returns 0 on success, and -1 on failure.
|
||||
*/
|
||||
int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
|
||||
{
|
||||
char *name, *value, *cp;
|
||||
|
||||
DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
|
||||
|
||||
if (!token || !(cp = strchr(token, '=')))
|
||||
return -1;
|
||||
|
||||
name = blkid_strdup(token);
|
||||
if (!name)
|
||||
return -1;
|
||||
value = name + (cp - token);
|
||||
*value++ = '\0';
|
||||
if (*value == '"' || *value == '\'') {
|
||||
char c = *value++;
|
||||
if (!(cp = strrchr(value, c)))
|
||||
goto errout; /* missing closing quote */
|
||||
*cp = '\0';
|
||||
}
|
||||
value = blkid_strdup(value);
|
||||
if (!value)
|
||||
goto errout;
|
||||
|
||||
*ret_type = name;
|
||||
*ret_val = value;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tag iteration routines for the public libblkid interface.
|
||||
*
|
||||
* These routines do not expose the list.h implementation, which are a
|
||||
* contamination of the namespace, and which force us to reveal far, far
|
||||
* too much of our internal implemenation. I'm not convinced I want
|
||||
* to keep list.h in the long term, anyway. It's fine for kernel
|
||||
* programming, but performance is not the #1 priority for this
|
||||
* library, and I really don't like the tradeoff of type-safety for
|
||||
* performance for this application. [tytso:20030125.2007EST]
|
||||
*/
|
||||
|
||||
/*
|
||||
* This series of functions iterate over all tags in a device
|
||||
*/
|
||||
#define TAG_ITERATE_MAGIC 0x01a5284c
|
||||
|
||||
struct blkid_struct_tag_iterate {
|
||||
int magic;
|
||||
blkid_dev dev;
|
||||
struct list_head *p;
|
||||
};
|
||||
|
||||
extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
|
||||
{
|
||||
blkid_tag_iterate iter;
|
||||
|
||||
iter = malloc(sizeof(struct blkid_struct_tag_iterate));
|
||||
if (iter) {
|
||||
iter->magic = TAG_ITERATE_MAGIC;
|
||||
iter->dev = dev;
|
||||
iter->p = dev->bid_tags.next;
|
||||
}
|
||||
return (iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 on success, -1 on error
|
||||
*/
|
||||
extern int blkid_tag_next(blkid_tag_iterate iter,
|
||||
const char **type, const char **value)
|
||||
{
|
||||
blkid_tag tag;
|
||||
|
||||
*type = 0;
|
||||
*value = 0;
|
||||
if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
|
||||
iter->p == &iter->dev->bid_tags)
|
||||
return -1;
|
||||
tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
|
||||
*type = tag->bit_name;
|
||||
*value = tag->bit_val;
|
||||
iter->p = iter->p->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void blkid_tag_iterate_end(blkid_tag_iterate iter)
|
||||
{
|
||||
if (!iter || iter->magic != TAG_ITERATE_MAGIC)
|
||||
return;
|
||||
iter->magic = 0;
|
||||
free(iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a device which matches a particular
|
||||
* type/value pair. If there is more than one device that matches the
|
||||
* search specification, it returns the one with the highest priority
|
||||
* value. This allows us to give preference to EVMS or LVM devices.
|
||||
*
|
||||
* XXX there should also be an interface which uses an iterator so we
|
||||
* can get all of the devices which match a type/value search parameter.
|
||||
*/
|
||||
extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
|
||||
const char *type,
|
||||
const char *value)
|
||||
{
|
||||
blkid_tag head;
|
||||
blkid_dev dev;
|
||||
int pri;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !type || !value)
|
||||
return NULL;
|
||||
|
||||
blkid_read_cache(cache);
|
||||
|
||||
DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
|
||||
|
||||
try_again:
|
||||
pri = -1;
|
||||
dev = 0;
|
||||
head = blkid_find_head_cache(cache, type);
|
||||
|
||||
if (head) {
|
||||
list_for_each(p, &head->bit_names) {
|
||||
blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
|
||||
bit_names);
|
||||
|
||||
if (!strcmp(tmp->bit_val, value) &&
|
||||
tmp->bit_dev->bid_pri > pri) {
|
||||
dev = tmp->bit_dev;
|
||||
pri = dev->bid_pri;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
|
||||
dev = blkid_verify(cache, dev);
|
||||
if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
|
||||
if (blkid_probe_all(cache) < 0)
|
||||
return NULL;
|
||||
goto try_again;
|
||||
}
|
||||
return dev;
|
||||
}
|
49
e2fsprogs/blkid/version.c
Normal file
49
e2fsprogs/blkid/version.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* version.c --- Return the version of the blkid library
|
||||
*
|
||||
* Copyright (C) 2004 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "blkid.h"
|
||||
#include "../../version.h"
|
||||
|
||||
static const char *lib_version = E2FSPROGS_VERSION;
|
||||
static const char *lib_date = E2FSPROGS_DATE;
|
||||
|
||||
int blkid_parse_version_string(const char *ver_string)
|
||||
{
|
||||
const char *cp;
|
||||
int version = 0;
|
||||
|
||||
for (cp = ver_string; *cp; cp++) {
|
||||
if (*cp == '.')
|
||||
continue;
|
||||
if (!isdigit(*cp))
|
||||
break;
|
||||
version = (version * 10) + (*cp - '0');
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
int blkid_get_library_version(const char **ver_string,
|
||||
const char **date_string)
|
||||
{
|
||||
if (ver_string)
|
||||
*ver_string = lib_version;
|
||||
if (date_string)
|
||||
*date_string = lib_date;
|
||||
|
||||
return blkid_parse_version_string(lib_version);
|
||||
}
|
207
e2fsprogs/util.c
Normal file
207
e2fsprogs/util.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* util.c --- helper functions used by tune2fs and mke2fs
|
||||
*
|
||||
* Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <linux/major.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "e2fsbb.h"
|
||||
#include "e2p/e2p.h"
|
||||
#include "ext2fs/ext2_fs.h"
|
||||
#include "ext2fs/ext2fs.h"
|
||||
#include "blkid/blkid.h"
|
||||
#include "util.h"
|
||||
|
||||
void proceed_question(void)
|
||||
{
|
||||
fputs("Proceed anyway? (y,n) ", stdout);
|
||||
if (bb_ask_confirmation() == 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void check_plausibility(const char *device)
|
||||
{
|
||||
int val;
|
||||
#ifdef CONFIG_LFS
|
||||
struct stat64 s;
|
||||
val = stat64(device, &s);
|
||||
#else
|
||||
struct stat s;
|
||||
val = stat(device, &s);
|
||||
#endif
|
||||
|
||||
if(val == -1)
|
||||
bb_perror_msg_and_die("Could not stat %s", device);
|
||||
if (!S_ISBLK(s.st_mode)) {
|
||||
printf("%s is not a block special device.\n", device);
|
||||
proceed_question();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_MAJOR_H
|
||||
#ifndef MAJOR
|
||||
#define MAJOR(dev) ((dev)>>8)
|
||||
#define MINOR(dev) ((dev) & 0xff)
|
||||
#endif
|
||||
#ifndef SCSI_BLK_MAJOR
|
||||
#ifdef SCSI_DISK0_MAJOR
|
||||
#ifdef SCSI_DISK8_MAJOR
|
||||
#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
|
||||
((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
|
||||
((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
|
||||
#else
|
||||
#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
|
||||
((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
|
||||
#endif /* defined(SCSI_DISK8_MAJOR) */
|
||||
#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
|
||||
#else
|
||||
#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
|
||||
#endif /* defined(SCSI_DISK0_MAJOR) */
|
||||
#endif /* defined(SCSI_BLK_MAJOR) */
|
||||
if (((MAJOR(s.st_rdev) == HD_MAJOR &&
|
||||
MINOR(s.st_rdev)%64 == 0) ||
|
||||
(SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
|
||||
MINOR(s.st_rdev)%16 == 0))) {
|
||||
printf("%s is entire device, not just one partition!\n", device);
|
||||
proceed_question();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_mount(const char *device, int force, const char *type)
|
||||
{
|
||||
errcode_t retval;
|
||||
int mount_flags;
|
||||
|
||||
retval = ext2fs_check_if_mounted(device, &mount_flags);
|
||||
if (retval) {
|
||||
bb_error_msg("Could not determine if %s is mounted", device);
|
||||
return;
|
||||
}
|
||||
if (!(mount_flags & EXT2_MF_MOUNTED))
|
||||
return;
|
||||
|
||||
bb_error_msg("%s is mounted !", device);
|
||||
if (force)
|
||||
bb_error_msg("forcing anyways and ignoring /etc/mtab status");
|
||||
else
|
||||
bb_error_msg_and_die("will not make a %s here!", type);
|
||||
}
|
||||
|
||||
void parse_journal_opts(char **journal_device, int *journal_flags,
|
||||
int *journal_size, const char *opts)
|
||||
{
|
||||
char *buf, *token, *next, *p, *arg;
|
||||
int journal_usage = 0;
|
||||
#if 0
|
||||
int len;
|
||||
len = strlen(opts);
|
||||
buf = xmalloc(len+1);
|
||||
strcpy(buf, opts);
|
||||
#else
|
||||
buf = bb_xstrdup(opts);
|
||||
#endif
|
||||
for (token = buf; token && *token; token = next) {
|
||||
p = strchr(token, ',');
|
||||
next = 0;
|
||||
if (p) {
|
||||
*p = 0;
|
||||
next = p+1;
|
||||
}
|
||||
arg = strchr(token, '=');
|
||||
if (arg) {
|
||||
*arg = 0;
|
||||
arg++;
|
||||
}
|
||||
if (strcmp(token, "device") == 0) {
|
||||
*journal_device = blkid_get_devname(NULL, arg, NULL);
|
||||
if (!journal_device) {
|
||||
journal_usage++;
|
||||
continue;
|
||||
}
|
||||
} else if (strcmp(token, "size") == 0) {
|
||||
if (!arg) {
|
||||
journal_usage++;
|
||||
continue;
|
||||
}
|
||||
(*journal_size) = strtoul(arg, &p, 0);
|
||||
if (*p)
|
||||
journal_usage++;
|
||||
} else if (strcmp(token, "v1_superblock") == 0) {
|
||||
(*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER;
|
||||
continue;
|
||||
} else
|
||||
journal_usage++;
|
||||
}
|
||||
if (journal_usage)
|
||||
bb_error_msg_and_die(
|
||||
"\nBad journal options specified.\n\n"
|
||||
"Journal options are separated by commas, "
|
||||
"and may take an argument which\n"
|
||||
"\tis set off by an equals ('=') sign.\n\n"
|
||||
"Valid journal options are:\n"
|
||||
"\tsize=<journal size in megabytes>\n"
|
||||
"\tdevice=<journal device>\n\n"
|
||||
"The journal size must be between "
|
||||
"1024 and 102400 filesystem blocks.\n\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the number of journal blocks to use, either via
|
||||
* user-specified # of megabytes, or via some intelligently selected
|
||||
* defaults.
|
||||
*
|
||||
* Find a reasonable journal file size (in blocks) given the number of blocks
|
||||
* in the filesystem. For very small filesystems, it is not reasonable to
|
||||
* have a journal that fills more than half of the filesystem.
|
||||
*/
|
||||
int figure_journal_size(int size, ext2_filsys fs)
|
||||
{
|
||||
blk_t j_blocks;
|
||||
|
||||
if (fs->super->s_blocks_count < 2048) {
|
||||
bb_error_msg("Filesystem too small for a journal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size >= 0) {
|
||||
j_blocks = size * 1024 / (fs->blocksize / 1024);
|
||||
if (j_blocks < 1024 || j_blocks > 102400)
|
||||
bb_error_msg_and_die("\nThe requested journal "
|
||||
"size is %d blocks;\n it must be "
|
||||
"between 1024 and 102400 blocks; Aborting",
|
||||
j_blocks);
|
||||
if (j_blocks > fs->super->s_free_blocks_count)
|
||||
bb_error_msg_and_die("Journal size too big for filesystem");
|
||||
return j_blocks;
|
||||
}
|
||||
|
||||
if (fs->super->s_blocks_count < 32768)
|
||||
j_blocks = 1024;
|
||||
else if (fs->super->s_blocks_count < 262144)
|
||||
j_blocks = 4096;
|
||||
else
|
||||
j_blocks = 8192;
|
||||
|
||||
return j_blocks;
|
||||
}
|
||||
|
||||
void print_check_message(ext2_filsys fs)
|
||||
{
|
||||
printf("This filesystem will be automatically "
|
||||
"checked every %d mounts or\n"
|
||||
"%g days, whichever comes first. "
|
||||
"Use tune2fs -c or -i to override.\n",
|
||||
fs->super->s_max_mnt_count,
|
||||
(double)fs->super->s_checkinterval / (3600 * 24));
|
||||
}
|
18
e2fsprogs/util.h
Normal file
18
e2fsprogs/util.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* util.h --- header file defining prototypes for helper functions
|
||||
* used by tune2fs and mke2fs
|
||||
*
|
||||
* Copyright 2000 by Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
extern void proceed_question(void);
|
||||
extern void check_plausibility(const char *device);
|
||||
extern void parse_journal_opts(char **, int *, int *, const char *opts);
|
||||
extern void check_mount(const char *device, int force, const char *type);
|
||||
extern int figure_journal_size(int size, ext2_filsys fs);
|
||||
extern void print_check_message(ext2_filsys fs);
|
43
e2fsprogs/uuid/clear.c
Normal file
43
e2fsprogs/uuid/clear.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* clear.c -- Clear a UUID
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
void uuid_clear(uuid_t uu)
|
||||
{
|
||||
memset(uu, 0, 16);
|
||||
}
|
||||
|
55
e2fsprogs/uuid/compare.c
Normal file
55
e2fsprogs/uuid/compare.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* compare.c --- compare whether or not two UUID's are the same
|
||||
*
|
||||
* Returns 0 if the two UUID's are different, and 1 if they are the same.
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "uuidP.h"
|
||||
#include <string.h>
|
||||
|
||||
#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
|
||||
|
||||
int uuid_compare(const uuid_t uu1, const uuid_t uu2)
|
||||
{
|
||||
struct uuid uuid1, uuid2;
|
||||
|
||||
uuid_unpack(uu1, &uuid1);
|
||||
uuid_unpack(uu2, &uuid2);
|
||||
|
||||
UUCMP(uuid1.time_low, uuid2.time_low);
|
||||
UUCMP(uuid1.time_mid, uuid2.time_mid);
|
||||
UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
|
||||
UUCMP(uuid1.clock_seq, uuid2.clock_seq);
|
||||
return memcmp(uuid1.node, uuid2.node, 6);
|
||||
}
|
||||
|
45
e2fsprogs/uuid/copy.c
Normal file
45
e2fsprogs/uuid/copy.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* copy.c --- copy UUIDs
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
void uuid_copy(uuid_t dst, const uuid_t src)
|
||||
{
|
||||
unsigned char *cp1;
|
||||
const unsigned char *cp2;
|
||||
int i;
|
||||
|
||||
for (i=0, cp1 = dst, cp2 = src; i < 16; i++)
|
||||
*cp1++ = *cp2++;
|
||||
}
|
310
e2fsprogs/uuid/gen_uuid.c
Normal file
310
e2fsprogs/uuid/gen_uuid.c
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* gen_uuid.c --- generate a DCE-compatible uuid
|
||||
*
|
||||
* Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKIO_H
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_DL_H
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
#ifdef HAVE_SRANDOM
|
||||
#define srand(x) srandom(x)
|
||||
#define rand() random()
|
||||
#endif
|
||||
|
||||
static int get_random_fd(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
static int fd = -2;
|
||||
int i;
|
||||
|
||||
if (fd == -2) {
|
||||
gettimeofday(&tv, 0);
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd == -1)
|
||||
fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
|
||||
srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
|
||||
}
|
||||
/* Crank the random number generator a few times */
|
||||
gettimeofday(&tv, 0);
|
||||
for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
|
||||
rand();
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate a series of random bytes. Use /dev/urandom if possible,
|
||||
* and if not, use srandom/random.
|
||||
*/
|
||||
static void get_random_bytes(void *buf, int nbytes)
|
||||
{
|
||||
int i, n = nbytes, fd = get_random_fd();
|
||||
int lose_counter = 0;
|
||||
unsigned char *cp = (unsigned char *) buf;
|
||||
|
||||
if (fd >= 0) {
|
||||
while (n > 0) {
|
||||
i = read(fd, cp, n);
|
||||
if (i <= 0) {
|
||||
if (lose_counter++ > 16)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
n -= i;
|
||||
cp += i;
|
||||
lose_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We do this all the time, but this is the only source of
|
||||
* randomness if /dev/random/urandom is out to lunch.
|
||||
*/
|
||||
for (cp = buf, i = 0; i < nbytes; i++)
|
||||
*cp++ ^= (rand() >> 7) & 0xFF;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ethernet hardware address, if we can find it...
|
||||
*/
|
||||
static int get_node_id(unsigned char *node_id)
|
||||
{
|
||||
#ifdef HAVE_NET_IF_H
|
||||
int sd;
|
||||
struct ifreq ifr, *ifrp;
|
||||
struct ifconf ifc;
|
||||
char buf[1024];
|
||||
int n, i;
|
||||
unsigned char *a;
|
||||
#ifdef HAVE_NET_IF_DL_H
|
||||
struct sockaddr_dl *sdlp;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BSD 4.4 defines the size of an ifreq to be
|
||||
* max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
|
||||
* However, under earlier systems, sa_len isn't present, so the size is
|
||||
* just sizeof(struct ifreq)
|
||||
*/
|
||||
#ifdef HAVE_SA_LEN
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
#define ifreq_size(i) max(sizeof(struct ifreq),\
|
||||
sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
|
||||
#else
|
||||
#define ifreq_size(i) sizeof(struct ifreq)
|
||||
#endif /* HAVE_SA_LEN*/
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sd < 0) {
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
|
||||
close(sd);
|
||||
return -1;
|
||||
}
|
||||
n = ifc.ifc_len;
|
||||
for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
|
||||
ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
|
||||
strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
|
||||
#ifdef SIOCGIFHWADDR
|
||||
if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
|
||||
continue;
|
||||
a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
|
||||
#else
|
||||
#ifdef SIOCGENADDR
|
||||
if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
|
||||
continue;
|
||||
a = (unsigned char *) ifr.ifr_enaddr;
|
||||
#else
|
||||
#ifdef HAVE_NET_IF_DL_H
|
||||
sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
|
||||
if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
|
||||
continue;
|
||||
a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
|
||||
#else
|
||||
/*
|
||||
* XXX we don't have a way of getting the hardware
|
||||
* address
|
||||
*/
|
||||
close(sd);
|
||||
return 0;
|
||||
#endif /* HAVE_NET_IF_DL_H */
|
||||
#endif /* SIOCGENADDR */
|
||||
#endif /* SIOCGIFHWADDR */
|
||||
if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
|
||||
continue;
|
||||
if (node_id) {
|
||||
memcpy(node_id, a, 6);
|
||||
close(sd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close(sd);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume that the gettimeofday() has microsecond granularity */
|
||||
#define MAX_ADJUSTMENT 10
|
||||
|
||||
static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
|
||||
{
|
||||
static int adjustment = 0;
|
||||
static struct timeval last = {0, 0};
|
||||
static uint16_t clock_seq;
|
||||
struct timeval tv;
|
||||
unsigned long long clock_reg;
|
||||
|
||||
try_again:
|
||||
gettimeofday(&tv, 0);
|
||||
if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
|
||||
get_random_bytes(&clock_seq, sizeof(clock_seq));
|
||||
clock_seq &= 0x3FFF;
|
||||
last = tv;
|
||||
last.tv_sec--;
|
||||
}
|
||||
if ((tv.tv_sec < last.tv_sec) ||
|
||||
((tv.tv_sec == last.tv_sec) &&
|
||||
(tv.tv_usec < last.tv_usec))) {
|
||||
clock_seq = (clock_seq+1) & 0x3FFF;
|
||||
adjustment = 0;
|
||||
last = tv;
|
||||
} else if ((tv.tv_sec == last.tv_sec) &&
|
||||
(tv.tv_usec == last.tv_usec)) {
|
||||
if (adjustment >= MAX_ADJUSTMENT)
|
||||
goto try_again;
|
||||
adjustment++;
|
||||
} else {
|
||||
adjustment = 0;
|
||||
last = tv;
|
||||
}
|
||||
|
||||
clock_reg = tv.tv_usec*10 + adjustment;
|
||||
clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
|
||||
clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
|
||||
|
||||
*clock_high = clock_reg >> 32;
|
||||
*clock_low = clock_reg;
|
||||
*ret_clock_seq = clock_seq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uuid_generate_time(uuid_t out)
|
||||
{
|
||||
static unsigned char node_id[6];
|
||||
static int has_init = 0;
|
||||
struct uuid uu;
|
||||
uint32_t clock_mid;
|
||||
|
||||
if (!has_init) {
|
||||
if (get_node_id(node_id) <= 0) {
|
||||
get_random_bytes(node_id, 6);
|
||||
/*
|
||||
* Set multicast bit, to prevent conflicts
|
||||
* with IEEE 802 addresses obtained from
|
||||
* network cards
|
||||
*/
|
||||
node_id[0] |= 0x01;
|
||||
}
|
||||
has_init = 1;
|
||||
}
|
||||
get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
|
||||
uu.clock_seq |= 0x8000;
|
||||
uu.time_mid = (uint16_t) clock_mid;
|
||||
uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
|
||||
memcpy(uu.node, node_id, 6);
|
||||
uuid_pack(&uu, out);
|
||||
}
|
||||
|
||||
void uuid_generate_random(uuid_t out)
|
||||
{
|
||||
uuid_t buf;
|
||||
struct uuid uu;
|
||||
|
||||
get_random_bytes(buf, sizeof(buf));
|
||||
uuid_unpack(buf, &uu);
|
||||
|
||||
uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
|
||||
uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
|
||||
uuid_pack(&uu, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the generic front-end to uuid_generate_random and
|
||||
* uuid_generate_time. It uses uuid_generate_random only if
|
||||
* /dev/urandom is available, since otherwise we won't have
|
||||
* high-quality randomness.
|
||||
*/
|
||||
void uuid_generate(uuid_t out)
|
||||
{
|
||||
if (get_random_fd() >= 0)
|
||||
uuid_generate_random(out);
|
||||
else
|
||||
uuid_generate_time(out);
|
||||
}
|
48
e2fsprogs/uuid/isnull.c
Normal file
48
e2fsprogs/uuid/isnull.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* isnull.c --- Check whether or not the UUID is null
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
/* Returns 1 if the uuid is the NULL uuid */
|
||||
int uuid_is_null(const uuid_t uu)
|
||||
{
|
||||
const unsigned char *cp;
|
||||
int i;
|
||||
|
||||
for (i=0, cp = uu; i < 16; i++)
|
||||
if (*cp++)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
69
e2fsprogs/uuid/pack.c
Normal file
69
e2fsprogs/uuid/pack.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Internal routine for packing UUID's
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "uuidP.h"
|
||||
|
||||
void uuid_pack(const struct uuid *uu, uuid_t ptr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
unsigned char *out = ptr;
|
||||
|
||||
tmp = uu->time_low;
|
||||
out[3] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[2] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[1] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[0] = (unsigned char) tmp;
|
||||
|
||||
tmp = uu->time_mid;
|
||||
out[5] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[4] = (unsigned char) tmp;
|
||||
|
||||
tmp = uu->time_hi_and_version;
|
||||
out[7] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[6] = (unsigned char) tmp;
|
||||
|
||||
tmp = uu->clock_seq;
|
||||
out[9] = (unsigned char) tmp;
|
||||
tmp >>= 8;
|
||||
out[8] = (unsigned char) tmp;
|
||||
|
||||
memcpy(out+10, uu->node, 6);
|
||||
}
|
||||
|
79
e2fsprogs/uuid/parse.c
Normal file
79
e2fsprogs/uuid/parse.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* parse.c --- UUID parsing
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
int uuid_parse(const char *in, uuid_t uu)
|
||||
{
|
||||
struct uuid uuid;
|
||||
int i;
|
||||
const char *cp;
|
||||
char buf[3];
|
||||
|
||||
if (strlen(in) != 36)
|
||||
return -1;
|
||||
for (i=0, cp = in; i <= 36; i++,cp++) {
|
||||
if ((i == 8) || (i == 13) || (i == 18) ||
|
||||
(i == 23)) {
|
||||
if (*cp == '-')
|
||||
continue;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
if (i== 36)
|
||||
if (*cp == 0)
|
||||
continue;
|
||||
if (!isxdigit(*cp))
|
||||
return -1;
|
||||
}
|
||||
uuid.time_low = strtoul(in, NULL, 16);
|
||||
uuid.time_mid = strtoul(in+9, NULL, 16);
|
||||
uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
|
||||
uuid.clock_seq = strtoul(in+19, NULL, 16);
|
||||
cp = in+24;
|
||||
buf[2] = 0;
|
||||
for (i=0; i < 6; i++) {
|
||||
buf[0] = *cp++;
|
||||
buf[1] = *cp++;
|
||||
uuid.node[i] = strtoul(buf, NULL, 16);
|
||||
}
|
||||
|
||||
uuid_pack(&uuid, uu);
|
||||
return 0;
|
||||
}
|
63
e2fsprogs/uuid/unpack.c
Normal file
63
e2fsprogs/uuid/unpack.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Internal routine for unpacking UUID
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "uuidP.h"
|
||||
|
||||
void uuid_unpack(const uuid_t in, struct uuid *uu)
|
||||
{
|
||||
const uint8_t *ptr = in;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_low = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_mid = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_hi_and_version = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->clock_seq = tmp;
|
||||
|
||||
memcpy(uu->node, ptr, 6);
|
||||
}
|
||||
|
76
e2fsprogs/uuid/unparse.c
Normal file
76
e2fsprogs/uuid/unparse.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* unparse.c -- convert a UUID to string
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
static const char *fmt_lower =
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
|
||||
|
||||
static const char *fmt_upper =
|
||||
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
|
||||
|
||||
#ifdef UUID_UNPARSE_DEFAULT_UPPER
|
||||
#define FMT_DEFAULT fmt_upper
|
||||
#else
|
||||
#define FMT_DEFAULT fmt_lower
|
||||
#endif
|
||||
|
||||
static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
|
||||
{
|
||||
struct uuid uuid;
|
||||
|
||||
uuid_unpack(uu, &uuid);
|
||||
sprintf(out, fmt,
|
||||
uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
|
||||
uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
|
||||
uuid.node[0], uuid.node[1], uuid.node[2],
|
||||
uuid.node[3], uuid.node[4], uuid.node[5]);
|
||||
}
|
||||
|
||||
void uuid_unparse_lower(const uuid_t uu, char *out)
|
||||
{
|
||||
uuid_unparse_x(uu, out, fmt_lower);
|
||||
}
|
||||
|
||||
void uuid_unparse_upper(const uuid_t uu, char *out)
|
||||
{
|
||||
uuid_unparse_x(uu, out, fmt_upper);
|
||||
}
|
||||
|
||||
void uuid_unparse(const uuid_t uu, char *out)
|
||||
{
|
||||
uuid_unparse_x(uu, out, FMT_DEFAULT);
|
||||
}
|
101
e2fsprogs/uuid/uuid.h
Normal file
101
e2fsprogs/uuid/uuid.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Public include file for the UUID library
|
||||
*
|
||||
* Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _UUID_UUID_H
|
||||
#define _UUID_UUID_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef unsigned char uuid_t[16];
|
||||
|
||||
/* UUID Variant definitions */
|
||||
#define UUID_VARIANT_NCS 0
|
||||
#define UUID_VARIANT_DCE 1
|
||||
#define UUID_VARIANT_MICROSOFT 2
|
||||
#define UUID_VARIANT_OTHER 3
|
||||
|
||||
/* UUID Type definitions */
|
||||
#define UUID_TYPE_DCE_TIME 1
|
||||
#define UUID_TYPE_DCE_RANDOM 4
|
||||
|
||||
/* Allow UUID constants to be defined */
|
||||
#ifdef __GNUC__
|
||||
#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
|
||||
static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
|
||||
#else
|
||||
#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
|
||||
static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clear.c */
|
||||
void uuid_clear(uuid_t uu);
|
||||
|
||||
/* compare.c */
|
||||
int uuid_compare(const uuid_t uu1, const uuid_t uu2);
|
||||
|
||||
/* copy.c */
|
||||
void uuid_copy(uuid_t dst, const uuid_t src);
|
||||
|
||||
/* gen_uuid.c */
|
||||
void uuid_generate(uuid_t out);
|
||||
void uuid_generate_random(uuid_t out);
|
||||
void uuid_generate_time(uuid_t out);
|
||||
|
||||
/* isnull.c */
|
||||
int uuid_is_null(const uuid_t uu);
|
||||
|
||||
/* parse.c */
|
||||
int uuid_parse(const char *in, uuid_t uu);
|
||||
|
||||
/* unparse.c */
|
||||
void uuid_unparse(const uuid_t uu, char *out);
|
||||
void uuid_unparse_lower(const uuid_t uu, char *out);
|
||||
void uuid_unparse_upper(const uuid_t uu, char *out);
|
||||
|
||||
/* uuid_time.c */
|
||||
time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
|
||||
int uuid_type(const uuid_t uu);
|
||||
int uuid_variant(const uuid_t uu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UUID_UUID_H */
|
63
e2fsprogs/uuid/uuidP.h
Normal file
63
e2fsprogs/uuid/uuidP.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* uuid.h -- private header file for uuids
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#include <uuid/uuid_types.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "uuid.h"
|
||||
|
||||
/*
|
||||
* Offset between 15-Oct-1582 and 1-Jan-70
|
||||
*/
|
||||
#define TIME_OFFSET_HIGH 0x01B21DD2
|
||||
#define TIME_OFFSET_LOW 0x13814000
|
||||
|
||||
struct uuid {
|
||||
uint32_t time_low;
|
||||
uint16_t time_mid;
|
||||
uint16_t time_hi_and_version;
|
||||
uint16_t clock_seq;
|
||||
uint8_t node[6];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
void uuid_pack(const struct uuid *uu, uuid_t ptr);
|
||||
void uuid_unpack(const uuid_t in, struct uuid *uu);
|
161
e2fsprogs/uuid/uuid_time.c
Normal file
161
e2fsprogs/uuid/uuid_time.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* uuid_time.c --- Interpret the time field from a uuid. This program
|
||||
* violates the UUID abstraction barrier by reaching into the guts
|
||||
* of a UUID and interpreting it.
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, and the entire permission notice in its entirety,
|
||||
* including the disclaimer of warranties.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "uuidP.h"
|
||||
|
||||
time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
|
||||
{
|
||||
struct uuid uuid;
|
||||
uint32_t high;
|
||||
struct timeval tv;
|
||||
unsigned long long clock_reg;
|
||||
|
||||
uuid_unpack(uu, &uuid);
|
||||
|
||||
high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
|
||||
clock_reg = uuid.time_low | ((unsigned long long) high << 32);
|
||||
|
||||
clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
|
||||
tv.tv_sec = clock_reg / 10000000;
|
||||
tv.tv_usec = (clock_reg % 10000000) / 10;
|
||||
|
||||
if (ret_tv)
|
||||
*ret_tv = tv;
|
||||
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
int uuid_type(const uuid_t uu)
|
||||
{
|
||||
struct uuid uuid;
|
||||
|
||||
uuid_unpack(uu, &uuid);
|
||||
return ((uuid.time_hi_and_version >> 12) & 0xF);
|
||||
}
|
||||
|
||||
int uuid_variant(const uuid_t uu)
|
||||
{
|
||||
struct uuid uuid;
|
||||
int var;
|
||||
|
||||
uuid_unpack(uu, &uuid);
|
||||
var = uuid.clock_seq;
|
||||
|
||||
if ((var & 0x8000) == 0)
|
||||
return UUID_VARIANT_NCS;
|
||||
if ((var & 0x4000) == 0)
|
||||
return UUID_VARIANT_DCE;
|
||||
if ((var & 0x2000) == 0)
|
||||
return UUID_VARIANT_MICROSOFT;
|
||||
return UUID_VARIANT_OTHER;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *variant_string(int variant)
|
||||
{
|
||||
switch (variant) {
|
||||
case UUID_VARIANT_NCS:
|
||||
return "NCS";
|
||||
case UUID_VARIANT_DCE:
|
||||
return "DCE";
|
||||
case UUID_VARIANT_MICROSOFT:
|
||||
return "Microsoft";
|
||||
default:
|
||||
return "Other";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
uuid_t buf;
|
||||
time_t time_reg;
|
||||
struct timeval tv;
|
||||
int type, variant;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s uuid\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (uuid_parse(argv[1], buf)) {
|
||||
fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
variant = uuid_variant(buf);
|
||||
type = uuid_type(buf);
|
||||
time_reg = uuid_time(buf, &tv);
|
||||
|
||||
printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
|
||||
if (variant != UUID_VARIANT_DCE) {
|
||||
printf("Warning: This program only knows how to interpret "
|
||||
"DCE UUIDs.\n\tThe rest of the output is likely "
|
||||
"to be incorrect!!\n");
|
||||
}
|
||||
printf("UUID type is %d", type);
|
||||
switch (type) {
|
||||
case 1:
|
||||
printf(" (time based)\n");
|
||||
break;
|
||||
case 2:
|
||||
printf(" (DCE)\n");
|
||||
break;
|
||||
case 3:
|
||||
printf(" (name-based)\n");
|
||||
break;
|
||||
case 4:
|
||||
printf(" (random)\n");
|
||||
break;
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
if (type != 1) {
|
||||
printf("Warning: not a time-based UUID, so UUID time "
|
||||
"decoding will likely not work!\n");
|
||||
}
|
||||
printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
|
||||
ctime(&time_reg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user