use libblkid to get filesystem type

we can now use libblkid to detect exfat
This commit is contained in:
bigbiff bigbiff
2013-02-22 20:55:50 -05:00
parent 43681d4497
commit e60683a0d5
169 changed files with 31042 additions and 60 deletions
+3 -2
View File
@@ -66,7 +66,7 @@ LOCAL_SHARED_LIBRARIES :=
LOCAL_STATIC_LIBRARIES += libmtdutils libcrecovery
LOCAL_STATIC_LIBRARIES += libminadbd libminzip libunz
LOCAL_STATIC_LIBRARIES += libminuitwrp libpixelflinger_static libpng libjpegtwrp libgui
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libmincrypt libext4_utils libtar
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libmincrypt libext4_utils libtar libblkid
ifneq ($(wildcard system/core/libsparse/Android.mk),)
LOCAL_SHARED_LIBRARIES += libsparse
@@ -297,7 +297,8 @@ include $(commands_recovery_local_path)/libjpegtwrp/Android.mk \
$(commands_recovery_local_path)/crypto/cryptsettings/Android.mk \
$(commands_recovery_local_path)/crypto/cryptfs/Android.mk \
$(commands_recovery_local_path)/libcrecovery/Android.mk \
$(commands_recovery_local_path)/twmincrypt/Android.mk
$(commands_recovery_local_path)/twmincrypt/Android.mk \
$(commands_recovery_local_path)/libblkid/Android.mk
ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true)
include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk
+13
View File
@@ -0,0 +1,13 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libblkid
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64
LOCAL_SRC_FILES = aix.c at.c befs.c bfs.c blkdev.c bsd.c btrfs.c cache.c canonicalize.c colors.c config.c cramfs.c crc32.c ddf_raid.c dev.c devname.c devno.c dm.c dos.c drbd.c drbdproxy_datalog.c encode.c env.c evaluate.c evms.c exec_shell.c exfat.c ext.c f2fs.c fileutils.c getsize.c gfs.c gpt.c hfs.c highpoint_raid.c hpfs.c ioctl.c ismounted.c iso9660.c isw_raid.c jfs.c jmicron_raid.c langinfo.c linux_raid.c linux_version.c llseek.c loopdev.c lsi_raid.c luks.c lvm1.c lvm2.c mac.c mangle.c match.c mbsalign.c md5.c md.c minix1.c minix2.c netware.c nilfs.c ntfs.c nvidia_raid.c ocfs.c pager.c partitions.c path.c probe.c procutils.c promise_raid.c randutils.c read.c reiserfs.c resolve.c romfs.c save.c setproctitle.c sgi.c silicon_raid.c solaris_x86.c squashfs.c sun.c superblocks.c swap.c sysfs1.c sysfs2.c sysv.c tag.c topology.c ubifs.c udf.c ufs.c ultrix.c unixware.c verify.c version.c vfat.c via_raid.c vmfs.c vxfs.c wholedisk.c xfs.c zfs.c adaptec_raid.c
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
LOCAL_SHARED_LIBRARIES += libc
include $(BUILD_SHARED_LIBRARY)
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct adaptec_metadata {
uint32_t b0idcode;
uint8_t lunsave[8];
uint16_t sdtype;
uint16_t ssavecyl;
uint8_t ssavehed;
uint8_t ssavesec;
uint8_t sb0flags;
uint8_t jbodEnable;
uint8_t lundsave;
uint8_t svpdirty;
uint16_t biosInfo;
uint16_t svwbskip;
uint16_t svwbcln;
uint16_t svwbmax;
uint16_t res3;
uint16_t svwbmin;
uint16_t res4;
uint16_t svrcacth;
uint16_t svwcacth;
uint16_t svwbdly;
uint8_t svsdtime;
uint8_t res5;
uint16_t firmval;
uint16_t firmbln;
uint32_t firmblk;
uint32_t fstrsvrb;
uint16_t svBlockStorageTid;
uint16_t svtid;
uint8_t svseccfl;
uint8_t res6;
uint8_t svhbanum;
uint8_t resver;
uint32_t drivemagic;
uint8_t reserved[20];
uint8_t testnum;
uint8_t testflags;
uint16_t maxErrorCount;
uint32_t count;
uint32_t startTime;
uint32_t interval;
uint8_t tstxt0;
uint8_t tstxt1;
uint8_t serNum[32];
uint8_t res8[102];
uint32_t fwTestMagic;
uint32_t fwTestSeqNum;
uint8_t fwTestRes[8];
uint32_t smagic;
uint32_t raidtbl;
uint16_t raidline;
uint8_t res9[0xF6];
} __attribute__((packed));
#define AD_SIGNATURE 0x4450544D /* "DPTM" */
#define AD_MAGIC 0x37FC4D1E
static int probe_adraid(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
uint64_t off;
struct adaptec_metadata *ad;
if (pr->size < 0x10000)
return -1;
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
off = ((pr->size / 0x200)-1) * 0x200;
ad = (struct adaptec_metadata *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct adaptec_metadata));
if (!ad)
return -1;
if (ad->smagic != be32_to_cpu(AD_SIGNATURE))
return -1;
if (ad->b0idcode != be32_to_cpu(AD_MAGIC))
return -1;
if (blkid_probe_sprintf_version(pr, "%u", ad->resver) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(ad->b0idcode),
(unsigned char *) &ad->b0idcode))
return -1;
return 0;
}
const struct blkid_idinfo adraid_idinfo = {
.name = "adaptec_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_adraid,
.magics = BLKID_NONE_MAGIC
};
+59
View File
@@ -0,0 +1,59 @@
/*
* aix partitions
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "partitions.h"
#include "aix.h"
static int probe_aix_pt(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
blkid_partlist ls;
blkid_parttable tab;
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
ls = blkid_probe_get_partlist(pr);
if (!ls)
goto err;
tab = blkid_partlist_new_parttable(ls, "aix", 0);
if (!tab)
goto err;
return 0;
err:
return -1;
}
/*
* We know nothing about AIX on-disk structures. Everything what we know is the
* magic number at begin of the disk.
*
* Note, Linux kernel is tring to be smart and AIX signature is ignored when
* there is a valid DOS partitions table. We don't support such behaviour. All
* fdisk-like programs has to properly wipe the fist sector. Everything other
* is a bug.
*/
const struct blkid_idinfo aix_pt_idinfo =
{
.name = "aix",
.probefunc = probe_aix_pt,
.magics =
{
{ .magic = BLKID_AIX_MAGIC_STRING, .len = BLKID_AIX_MAGIC_STRLEN },
{ NULL }
}
};
+7
View File
@@ -0,0 +1,7 @@
#ifndef BLKID_PARTITIONS_AIX_H
#define BLKID_PARTITIONS_AIX_H
#define BLKID_AIX_MAGIC_STRING "\xC9\xC2\xD4\xC1"
#define BLKID_AIX_MAGIC_STRLEN (sizeof(BLKID_AIX_MAGIC_STRING) - 1)
#endif
+82
View File
@@ -0,0 +1,82 @@
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
* Petr Uzel <petr.uzel@suse.cz>
*/
#ifndef UTIL_LINUX_ALL_IO_H
#define UTIL_LINUX_ALL_IO_H
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "c.h"
static inline int write_all(int fd, const void *buf, size_t count)
{
while (count) {
ssize_t tmp;
errno = 0;
tmp = write(fd, buf, count);
if (tmp > 0) {
count -= tmp;
if (count)
buf = (void *) ((char *) buf + tmp);
} else if (errno != EINTR && errno != EAGAIN)
return -1;
if (errno == EAGAIN) /* Try later, *sigh* */
usleep(10000);
}
return 0;
}
static inline int fwrite_all(const void *ptr, size_t size,
size_t nmemb, FILE *stream)
{
while (nmemb) {
size_t tmp;
errno = 0;
tmp = fwrite(ptr, size, nmemb, stream);
if (tmp > 0) {
nmemb -= tmp;
if (nmemb)
ptr = (void *) ((char *) ptr + (tmp * size));
} else if (errno != EINTR && errno != EAGAIN)
return -1;
if (errno == EAGAIN) /* Try later, *sigh* */
usleep(10000);
}
return 0;
}
static inline ssize_t read_all(int fd, char *buf, size_t count)
{
ssize_t ret;
ssize_t c = 0;
int tries = 0;
memset(buf, 0, count);
while (count > 0) {
ret = read(fd, buf, count);
if (ret <= 0) {
if ((errno == EAGAIN || errno == EINTR || ret == 0) &&
(tries++ < 5))
continue;
return c ? c : -1;
}
if (ret > 0)
tries = 0;
count -= ret;
buf += ret;
c += ret;
}
return c;
}
#endif /* UTIL_LINUX_ALL_IO_H */
+143
View File
@@ -0,0 +1,143 @@
/*
* Portable xxxat() functions.
*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "at.h"
#include "c.h"
#ifdef HAVE_FSTATAT
int fstat_at(int dir, const char *dirname __attribute__ ((__unused__)),
const char *filename, struct stat *st, int nofollow)
{
return fstatat(dir, filename, st,
nofollow ? AT_SYMLINK_NOFOLLOW : 0);
}
#else
int fstat_at(int dir, const char *dirname, const char *filename,
struct stat *st, int nofollow)
{
if (*filename != '/') {
char path[PATH_MAX];
int len;
len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
if (len < 0 || len + 1 > sizeof(path))
return -1;
return nofollow ? lstat(path, st) : stat(path, st);
}
return nofollow ? lstat(filename, st) : stat(filename, st);
}
#endif
#ifdef HAVE_FSTATAT
int open_at(int dir, const char *dirname __attribute__ ((__unused__)),
const char *filename, int flags)
{
return openat(dir, filename, flags);
}
#else
int open_at(int dir, const char *dirname, const char *filename, int flags)
{
if (*filename != '/') {
char path[PATH_MAX];
int len;
len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
if (len < 0 || len + 1 > sizeof(path))
return -1;
return open(path, flags);
}
return open(filename, flags);
}
#endif
FILE *fopen_at(int dir, const char *dirname, const char *filename, int flags,
const char *mode)
{
int fd = open_at(dir, dirname, filename, flags);
if (fd < 0)
return NULL;
return fdopen(fd, mode);
}
#ifdef HAVE_FSTATAT
ssize_t readlink_at(int dir, const char *dirname __attribute__ ((__unused__)),
const char *pathname, char *buf, size_t bufsiz)
{
return readlinkat(dir, pathname, buf, bufsiz);
}
#else
ssize_t readlink_at(int dir, const char *dirname, const char *pathname,
char *buf, size_t bufsiz)
{
if (*pathname != '/') {
char path[PATH_MAX];
int len;
len = snprintf(path, sizeof(path), "%s/%s", dirname, pathname);
if (len < 0 || len + 1 > sizeof(path))
return -1;
return readlink(path, buf, bufsiz);
}
return readlink(pathname, buf, bufsiz);
}
#endif
#ifdef TEST_PROGRAM_AT
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
int main(int argc, char *argv[])
{
DIR *dir;
struct dirent *d;
char *dirname;
if (argc != 2) {
fprintf(stderr, "usage: %s <directory>\n", argv[0]);
exit(EXIT_FAILURE);
}
dirname = argv[1];
dir = opendir(dirname);
if (!dir)
err(EXIT_FAILURE, "cannot open %s", dirname);
while ((d = readdir(dir))) {
struct stat st;
FILE *f;
printf("%32s ", d->d_name);
if (fstat_at(dirfd(dir), dirname, d->d_name, &st, 0) == 0)
printf("%16jd bytes ", st.st_size);
else
printf("%16s bytes ", "???");
f = fopen_at(dirfd(dir), dirname, d->d_name, O_RDONLY, "r");
printf(" %s\n", f ? "OK" : strerror(errno));
if (f)
fclose(f);
}
closedir(dir);
return EXIT_SUCCESS;
}
#endif
+32
View File
@@ -0,0 +1,32 @@
/*
* wrappers for "at" functions.
*
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#ifndef UTIL_LINUX_AT_H
#define UTIL_LINUX_AT_H
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "c.h"
extern int fstat_at(int dir, const char *dirname,
const char *filename, struct stat *st, int nofollow);
extern int open_at(int dir, const char *dirname,
const char *filename, int flags);
extern FILE *fopen_at(int dir, const char *dirname, const char *filename,
int flags, const char *mode);
extern ssize_t readlink_at(int dir, const char *dirname, const char *pathname,
char *buf, size_t bufsiz);
#endif /* UTIL_LINUX_AT_H */
+480
View File
@@ -0,0 +1,480 @@
/*
* Copyright (C) 2010 Jeroen Oortwijn <oortwijn@gmail.com>
*
* Partly based on the Haiku BFS driver by
* Axel Dörfler <axeld@pinc-software.de>
*
* Also inspired by the Linux BeFS driver by
* Will Dyson <will_dyson@pobox.com>, et al.
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <byteswap.h>
#include "bitops.h"
#include "superblocks.h"
#define B_OS_NAME_LENGTH 0x20
#define SUPER_BLOCK_MAGIC1 0x42465331 /* BFS1 */
#define SUPER_BLOCK_MAGIC2 0xdd121031
#define SUPER_BLOCK_MAGIC3 0x15b6830e
#define SUPER_BLOCK_FS_ENDIAN 0x42494745 /* BIGE */
#define INODE_MAGIC1 0x3bbe0ad9
#define BPLUSTREE_MAGIC 0x69f6c2e8
#define BPLUSTREE_NULL -1LL
#define NUM_DIRECT_BLOCKS 12
#define B_UINT64_TYPE 0x554c4c47 /* ULLG */
#define KEY_NAME "be:volume_id"
#define KEY_SIZE 8
#define FS16_TO_CPU(value, fs_is_le) (fs_is_le ? le16_to_cpu(value) \
: be16_to_cpu(value))
#define FS32_TO_CPU(value, fs_is_le) (fs_is_le ? le32_to_cpu(value) \
: be32_to_cpu(value))
#define FS64_TO_CPU(value, fs_is_le) (fs_is_le ? le64_to_cpu(value) \
: be64_to_cpu(value))
typedef struct block_run {
int32_t allocation_group;
uint16_t start;
uint16_t len;
} __attribute__((packed)) block_run, inode_addr;
struct befs_super_block {
char name[B_OS_NAME_LENGTH];
int32_t magic1;
int32_t fs_byte_order;
uint32_t block_size;
uint32_t block_shift;
int64_t num_blocks;
int64_t used_blocks;
int32_t inode_size;
int32_t magic2;
int32_t blocks_per_ag;
int32_t ag_shift;
int32_t num_ags;
int32_t flags;
block_run log_blocks;
int64_t log_start;
int64_t log_end;
int32_t magic3;
inode_addr root_dir;
inode_addr indices;
int32_t pad[8];
} __attribute__((packed));
typedef struct data_stream {
block_run direct[NUM_DIRECT_BLOCKS];
int64_t max_direct_range;
block_run indirect;
int64_t max_indirect_range;
block_run double_indirect;
int64_t max_double_indirect_range;
int64_t size;
} __attribute__((packed)) data_stream;
struct befs_inode {
int32_t magic1;
inode_addr inode_num;
int32_t uid;
int32_t gid;
int32_t mode;
int32_t flags;
int64_t create_time;
int64_t last_modified_time;
inode_addr parent;
inode_addr attributes;
uint32_t type;
int32_t inode_size;
uint32_t etc;
data_stream data;
int32_t pad[4];
int32_t small_data[0];
} __attribute__((packed));
struct small_data {
uint32_t type;
uint16_t name_size;
uint16_t data_size;
char name[0];
} __attribute__((packed));
struct bplustree_header {
uint32_t magic;
uint32_t node_size;
uint32_t max_number_of_levels;
uint32_t data_type;
int64_t root_node_pointer;
int64_t free_node_pointer;
int64_t maximum_size;
} __attribute__((packed));
struct bplustree_node {
int64_t left_link;
int64_t right_link;
int64_t overflow_link;
uint16_t all_key_count;
uint16_t all_key_length;
char name[0];
} __attribute__((packed));
static unsigned char *get_block_run(blkid_probe pr, const struct befs_super_block *bs,
const struct block_run *br, int fs_le)
{
return blkid_probe_get_buffer(pr,
((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
<< FS32_TO_CPU(bs->ag_shift, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le))
+ ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le)),
(blkid_loff_t) FS16_TO_CPU(br->len, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le));
}
static unsigned char *get_custom_block_run(blkid_probe pr,
const struct befs_super_block *bs,
const struct block_run *br,
int64_t offset, uint32_t length, int fs_le)
{
if (offset + length > (int64_t) FS16_TO_CPU(br->len, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le))
return NULL;
return blkid_probe_get_buffer(pr,
((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
<< FS32_TO_CPU(bs->ag_shift, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le))
+ ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le))
+ offset,
length);
}
static unsigned char *get_tree_node(blkid_probe pr, const struct befs_super_block *bs,
const struct data_stream *ds,
int64_t start, uint32_t length, int fs_le)
{
if (start < (int64_t) FS64_TO_CPU(ds->max_direct_range, fs_le)) {
int64_t br_len;
size_t i;
for (i = 0; i < NUM_DIRECT_BLOCKS; i++) {
br_len = (int64_t) FS16_TO_CPU(ds->direct[i].len, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le);
if (start < br_len)
return get_custom_block_run(pr, bs,
&ds->direct[i],
start, length, fs_le);
else
start -= br_len;
}
} else if (start < (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le)) {
struct block_run *br;
int64_t max_br, br_len, i;
start -= FS64_TO_CPU(ds->max_direct_range, fs_le);
max_br = ((int64_t) FS16_TO_CPU(ds->indirect.len, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le))
/ sizeof(struct block_run);
br = (struct block_run *) get_block_run(pr, bs, &ds->indirect,
fs_le);
if (!br)
return NULL;
for (i = 0; i < max_br; i++) {
br_len = (int64_t) FS16_TO_CPU(br[i].len, fs_le)
<< FS32_TO_CPU(bs->block_shift, fs_le);
if (start < br_len)
return get_custom_block_run(pr, bs, &br[i],
start, length, fs_le);
else
start -= br_len;
}
} else if (start < (int64_t) FS64_TO_CPU(ds->max_double_indirect_range, fs_le)) {
struct block_run *br;
int64_t di_br_size, br_per_di_br, di_index, i_index;
start -= (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le);
di_br_size = (int64_t) FS16_TO_CPU(ds->double_indirect.len,
fs_le) << FS32_TO_CPU(bs->block_shift, fs_le);
if (di_br_size == 0)
return NULL;
br_per_di_br = di_br_size / sizeof(struct block_run);
if (br_per_di_br == 0)
return NULL;
di_index = start / (br_per_di_br * di_br_size);
i_index = (start % (br_per_di_br * di_br_size)) / di_br_size;
start = (start % (br_per_di_br * di_br_size)) % di_br_size;
br = (struct block_run *) get_block_run(pr, bs,
&ds->double_indirect, fs_le);
if (!br)
return NULL;
br = (struct block_run *) get_block_run(pr, bs, &br[di_index],
fs_le);
if (!br)
return NULL;
return get_custom_block_run(pr, bs, &br[i_index], start, length,
fs_le);
}
return NULL;
}
static int32_t compare_keys(const char keys1[], uint16_t keylengths1[], int32_t index,
const char *key2, uint16_t keylength2, int fs_le)
{
const char *key1;
uint16_t keylength1;
int32_t result;
key1 = &keys1[index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
fs_le)];
keylength1 = FS16_TO_CPU(keylengths1[index], fs_le)
- (index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
fs_le));
result = strncmp(key1, key2, min(keylength1, keylength2));
if (result == 0)
return keylength1 - keylength2;
return result;
}
static int64_t get_key_value(blkid_probe pr, const struct befs_super_block *bs,
const struct befs_inode *bi, const char *key, int fs_le)
{
struct bplustree_header *bh;
struct bplustree_node *bn;
uint16_t *keylengths;
int64_t *values;
int64_t node_pointer;
int32_t first, last, mid, cmp;
bh = (struct bplustree_header *) get_tree_node(pr, bs, &bi->data, 0,
sizeof(struct bplustree_header), fs_le);
if (!bh)
return -1;
if ((int32_t) FS32_TO_CPU(bh->magic, fs_le) != BPLUSTREE_MAGIC)
return -1;
node_pointer = FS64_TO_CPU(bh->root_node_pointer, fs_le);
do {
bn = (struct bplustree_node *) get_tree_node(pr, bs, &bi->data,
node_pointer, FS32_TO_CPU(bh->node_size, fs_le), fs_le);
if (!bn)
return -1;
keylengths = (uint16_t *) ((uint8_t *) bn
+ ((sizeof(struct bplustree_node)
+ FS16_TO_CPU(bn->all_key_length, fs_le)
+ sizeof(int64_t) - 1)
& ~(sizeof(int64_t) - 1)));
values = (int64_t *) ((uint8_t *) keylengths
+ FS16_TO_CPU(bn->all_key_count, fs_le)
* sizeof(uint16_t));
first = 0;
mid = 0;
last = FS16_TO_CPU(bn->all_key_count, fs_le) - 1;
cmp = compare_keys(bn->name, keylengths, last, key, strlen(key),
fs_le);
if (cmp == 0) {
if ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
== BPLUSTREE_NULL)
return FS64_TO_CPU(values[last], fs_le);
else
node_pointer = FS64_TO_CPU(values[last], fs_le);
} else if (cmp < 0)
node_pointer = FS64_TO_CPU(bn->overflow_link, fs_le);
else {
while (first <= last) {
mid = (first + last) / 2;
cmp = compare_keys(bn->name, keylengths, mid,
key, strlen(key), fs_le);
if (cmp == 0) {
if ((int64_t) FS64_TO_CPU(bn->overflow_link,
fs_le) == BPLUSTREE_NULL)
return FS64_TO_CPU(values[mid],
fs_le);
else
break;
} else if (cmp < 0)
first = mid + 1;
else
last = mid - 1;
}
if (cmp < 0)
node_pointer = FS64_TO_CPU(values[mid + 1],
fs_le);
else
node_pointer = FS64_TO_CPU(values[mid], fs_le);
}
} while ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
!= BPLUSTREE_NULL);
return 0;
}
static int get_uuid(blkid_probe pr, const struct befs_super_block *bs,
uint64_t * const uuid, int fs_le)
{
struct befs_inode *bi;
struct small_data *sd;
bi = (struct befs_inode *) get_block_run(pr, bs, &bs->root_dir, fs_le);
if (!bi)
return -1;
if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
return -1;
sd = (struct small_data *) bi->small_data;
do {
if (FS32_TO_CPU(sd->type, fs_le) == B_UINT64_TYPE
&& FS16_TO_CPU(sd->name_size, fs_le) == strlen(KEY_NAME)
&& FS16_TO_CPU(sd->data_size, fs_le) == KEY_SIZE
&& strcmp(sd->name, KEY_NAME) == 0) {
memcpy(uuid,
sd->name + FS16_TO_CPU(sd->name_size, fs_le) + 3,
sizeof(uint64_t));
break;
} else if (FS32_TO_CPU(sd->type, fs_le) == 0
&& FS16_TO_CPU(sd->name_size, fs_le) == 0
&& FS16_TO_CPU(sd->data_size, fs_le) == 0)
break;
sd = (struct small_data *) ((uint8_t *) sd
+ sizeof(struct small_data)
+ FS16_TO_CPU(sd->name_size, fs_le) + 3
+ FS16_TO_CPU(sd->data_size, fs_le) + 1);
} while ((intptr_t) sd < (intptr_t) bi
+ (int32_t) FS32_TO_CPU(bi->inode_size, fs_le)
- (int32_t) sizeof(struct small_data));
if (*uuid == 0
&& (FS32_TO_CPU(bi->attributes.allocation_group, fs_le) != 0
|| FS16_TO_CPU(bi->attributes.start, fs_le) != 0
|| FS16_TO_CPU(bi->attributes.len, fs_le) != 0)) {
int64_t value;
bi = (struct befs_inode *) get_block_run(pr, bs,
&bi->attributes, fs_le);
if (!bi)
return -1;
if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
return -1;
value = get_key_value(pr, bs, bi, KEY_NAME, fs_le);
if (value < 0)
return value;
else if (value > 0) {
bi = (struct befs_inode *) blkid_probe_get_buffer(pr,
value << FS32_TO_CPU(bs->block_shift, fs_le),
FS32_TO_CPU(bs->block_size, fs_le));
if (!bi)
return -1;
if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
return -1;
if (FS32_TO_CPU(bi->type, fs_le) == B_UINT64_TYPE
&& FS64_TO_CPU(bi->data.size, fs_le) == KEY_SIZE
&& FS16_TO_CPU(bi->data.direct[0].len, fs_le)
== 1) {
uint64_t *attr_data;
attr_data = (uint64_t *) get_block_run(pr, bs,
&bi->data.direct[0], fs_le);
if (!attr_data)
return -1;
*uuid = *attr_data;
}
}
}
return 0;
}
static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct befs_super_block *bs;
const char *version = NULL;
uint64_t volume_id = 0;
int fs_le, ret;
bs = (struct befs_super_block *) blkid_probe_get_buffer(pr,
mag->sboff - B_OS_NAME_LENGTH,
sizeof(struct befs_super_block));
if (!bs)
return -1;
if (le32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
&& le32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
&& le32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
&& le32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
fs_le = 1;
version = "little-endian";
} else if (be32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
&& be32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
&& be32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
&& be32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
fs_le = 0;
version = "big-endian";
} else
return -1;
ret = get_uuid(pr, bs, &volume_id, fs_le);
if (ret < 0)
return ret;
/*
* all checks pass, set LABEL, VERSION and UUID
*/
if (strlen(bs->name))
blkid_probe_set_label(pr, (unsigned char *) bs->name,
sizeof(bs->name));
if (version)
blkid_probe_set_version(pr, version);
if (volume_id)
blkid_probe_sprintf_uuid(pr, (unsigned char *) &volume_id,
sizeof(volume_id), "%016" PRIx64,
FS64_TO_CPU(volume_id, fs_le));
return 0;
}
const struct blkid_idinfo befs_idinfo =
{
.name = "befs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_befs,
.minsz = 1024 * 1440,
.magics = {
{ .magic = "BFS1", .len = 4, .sboff = B_OS_NAME_LENGTH },
{ .magic = "1SFB", .len = 4, .sboff = B_OS_NAME_LENGTH },
{ .magic = "BFS1", .len = 4, .sboff = 0x200 +
B_OS_NAME_LENGTH },
{ .magic = "1SFB", .len = 4, .sboff = 0x200 +
B_OS_NAME_LENGTH },
{ NULL }
}
};
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include "superblocks.h"
/*
* BFS actually has two different labels in the superblock, each
* of them only 6 bytes long. Until we find out what their use
* we just ignore them.
*/
const struct blkid_idinfo bfs_idinfo =
{
.name = "bfs",
.usage = BLKID_USAGE_FILESYSTEM,
.magics = {
{ .magic = "\xce\xfa\xad\x1b", .len = 4 },
{ NULL }
}
};
+126
View File
@@ -0,0 +1,126 @@
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
*/
#ifndef BITOPS_H
#define BITOPS_H
#include <stdint.h>
#include <sys/param.h>
#if defined(HAVE_BYTESWAP_H)
# include <byteswap.h>
#endif
#define HAVE_SYS_ENDIAN_H
#if defined(HAVE_ENDIAN_H)
# include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H) /* BSDs have them here */
# include <sys/endian.h>
#endif
#if defined(__OpenBSD__)
# include <sys/types.h>
# define be16toh(x) betoh16(x)
# define be32toh(x) betoh32(x)
# define be64toh(x) betoh64(x)
#endif
/*
* Fallbacks
*/
#ifndef bswap_16
# define bswap_16(x) ((((x) & 0x00FF) << 8) | \
(((x) & 0xFF00) >> 8))
#endif
#ifndef bswap_32
# define bswap_32(x) ((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8) | \
(((x) & 0x00FF0000) >> 8) | \
(((x) & 0xFF000000) >> 24))
#endif
#ifndef bswap_64
# define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \
(((x) & 0x000000000000FF00ULL) << 40) | \
(((x) & 0x0000000000FF0000ULL) << 24) | \
(((x) & 0x00000000FF000000ULL) << 8) | \
(((x) & 0x000000FF00000000ULL) >> 8) | \
(((x) & 0x0000FF0000000000ULL) >> 24) | \
(((x) & 0x00FF000000000000ULL) >> 40) | \
(((x) & 0xFF00000000000000ULL) >> 56))
#endif
//#ifndef htobe16
//# if !defined(WORDS_BIGENDIAN)
# define htobe16(x) bswap_16 (x)
# define htole16(x) (x)
# define be16toh(x) bswap_16 (x)
# define le16toh(x) (x)
# define htobe32(x) bswap_32 (x)
# define htole32(x) (x)
# define be32toh(x) bswap_32 (x)
# define le32toh(x) (x)
# define htobe64(x) bswap_64 (x)
# define htole64(x) (x)
# define be64toh(x) bswap_64 (x)
# define le64toh(x) (x)
/*
# else
# define htobe16(x) (x)
# define htole16(x) bswap_16 (x)
# define be16toh(x) (x)
# define le16toh(x) bswap_16 (x)
# define htobe32(x) (x)
# define htole32(x) bswap_32 (x)
# define be32toh(x) (x)
# define le32toh(x) bswap_32 (x)
# define htobe64(x) (x)
# define htole64(x) bswap_64 (x)
# define be64toh(x) (x)
# define le64toh(x) bswap_64 (x)
# endif
#endif
*/
/*
* Byte swab macros (based on linux/byteorder/swab.h)
*/
#define swab16(x) bswap_16(x)
#define swab32(x) bswap_32(x)
#define swab64(x) bswap_64(x)
#define cpu_to_le16(x) ((uint16_t) htole16(x))
#define cpu_to_le32(x) ((uint32_t) htole32(x))
#define cpu_to_le64(x) ((uint64_t) htole64(x))
#define cpu_to_be16(x) ((uint16_t) htobe16(x))
#define cpu_to_be32(x) ((uint32_t) htobe32(x))
#define cpu_to_be64(x) ((uint64_t) htobe64(x))
#define le16_to_cpu(x) ((uint16_t) le16toh(x))
#define le32_to_cpu(x) ((uint32_t) le32toh(x))
#define le64_to_cpu(x) ((uint64_t) le64toh(x))
#define be16_to_cpu(x) ((uint16_t) be16toh(x))
#define be32_to_cpu(x) ((uint32_t) be32toh(x))
#define be64_to_cpu(x) ((uint64_t) be64toh(x))
/*
* Bit map related macros. Usually provided by libc.
*/
#ifndef NBBY
# define NBBY CHAR_BIT
#endif
#ifndef setbit
# define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
# define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
# define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
# define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
#endif
#endif /* BITOPS_H */
+375
View File
@@ -0,0 +1,375 @@
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdint.h>
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
#endif
#ifdef HAVE_SYS_DISKLABEL_H
#include <sys/disklabel.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
#include "blkdev.h"
#include "c.h"
#include "linux_version.h"
#include "xalloc.h"
static long
blkdev_valid_offset (int fd, off_t offset) {
char ch;
if (lseek (fd, offset, 0) < 0)
return 0;
if (read (fd, &ch, 1) < 1)
return 0;
return 1;
}
int is_blkdev(int fd)
{
struct stat st;
return (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode));
}
off_t
blkdev_find_size (int fd) {
uintmax_t high, low = 0;
for (high = 1024; blkdev_valid_offset (fd, high); ) {
if (high == UINTMAX_MAX)
return -1;
low = high;
if (high >= UINTMAX_MAX/2)
high = UINTMAX_MAX;
else
high *= 2;
}
while (low < high - 1)
{
uintmax_t mid = (low + high) / 2;
if (blkdev_valid_offset (fd, mid))
low = mid;
else
high = mid;
}
blkdev_valid_offset (fd, 0);
return (low + 1);
}
/* get size in bytes */
int
blkdev_get_size(int fd, unsigned long long *bytes)
{
#ifdef DKIOCGETBLOCKCOUNT
/* Apple Darwin */
if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
*bytes <<= 9;
return 0;
}
#endif
#ifdef BLKGETSIZE64
{
#ifdef __linux__
int ver = get_linux_version();
/* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
if (ver >= KERNEL_VERSION (2,6,0) ||
(ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
#endif
if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
return 0;
}
#endif /* BLKGETSIZE64 */
#ifdef BLKGETSIZE
{
unsigned long size;
if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
*bytes = ((unsigned long long)size << 9);
return 0;
}
}
#endif /* BLKGETSIZE */
#ifdef DIOCGMEDIASIZE
/* FreeBSD */
if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
return 0;
#endif
#ifdef FDGETPRM
{
struct floppy_struct this_floppy;
if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
*bytes = this_floppy.size << 9;
return 0;
}
}
#endif /* FDGETPRM */
#ifdef HAVE_SYS_DISKLABEL_H
{
/*
* This code works for FreeBSD 4.11 i386, except for the full device
* (such as /dev/ad0). It doesn't work properly for newer FreeBSD
* though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
* above however.
*
* Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
* character) devices, so we need to check for S_ISCHR, too.
*/
int part = -1;
struct disklabel lab;
struct partition *pp;
char ch;
struct stat st;
if ((fstat(fd, &st) >= 0) &&
(S_ISBLK(st.st_mode) || S_ISCHR(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) {
*bytes = pp->p_size << 9;
return 0;
}
}
}
#endif /* HAVE_SYS_DISKLABEL_H */
{
struct stat st;
if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
*bytes = st.st_size;
return 0;
}
if (!S_ISBLK(st.st_mode))
return -1;
}
*bytes = blkdev_find_size(fd);
return 0;
}
/* get 512-byte sector count */
int
blkdev_get_sectors(int fd, unsigned long long *sectors)
{
unsigned long long bytes;
if (blkdev_get_size(fd, &bytes) == 0) {
*sectors = (bytes >> 9);
return 0;
}
return -1;
}
/*
* Get logical sector size.
*
* This is the smallest unit the storage device can
* address. It is typically 512 bytes.
*/
int blkdev_get_sector_size(int fd, int *sector_size)
{
#ifdef BLKSSZGET
if (ioctl(fd, BLKSSZGET, sector_size) >= 0)
return 0;
return -1;
#else
*sector_size = DEFAULT_SECTOR_SIZE;
return 0;
#endif
}
/*
* Get physical block device size. The BLKPBSZGET is supported since Linux
* 2.6.32. For old kernels is probably the best to assume that physical sector
* size is the same as logical sector size.
*
* Example:
*
* rc = blkdev_get_physector_size(fd, &physec);
* if (rc || physec == 0) {
* rc = blkdev_get_sector_size(fd, &physec);
* if (rc)
* physec = DEFAULT_SECTOR_SIZE;
* }
*/
int blkdev_get_physector_size(int fd, int *sector_size)
{
#ifdef BLKPBSZGET
if (ioctl(fd, BLKPBSZGET, &sector_size) >= 0)
return 0;
return -1;
#else
*sector_size = DEFAULT_SECTOR_SIZE;
return 0;
#endif
}
/*
* Return the alignment status of a device
*/
int blkdev_is_misaligned(int fd)
{
#ifdef BLKALIGNOFF
int aligned;
if (ioctl(fd, BLKALIGNOFF, &aligned) < 0)
return 0; /* probably kernel < 2.6.32 */
/*
* Note that kernel returns -1 as alignement offset if no compatible
* sizes and alignments exist for stacked devices
*/
return aligned != 0 ? 1 : 0;
#else
return 0;
#endif
}
int blkdev_is_cdrom(int fd)
{
#ifdef CDROM_GET_CAPABILITY
int ret;
if ((ret = ioctl(fd, CDROM_GET_CAPABILITY, NULL)) < 0)
return 0;
else
return ret;
#else
return 0;
#endif
}
/*
* Get kernel's interpretation of the device's geometry.
*
* Returns the heads and sectors - but not cylinders
* as it's truncated for disks with more than 65535 tracks.
*
* Note that this is deprecated in favor of LBA addressing.
*/
int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s)
{
#ifdef HDIO_GETGEO
struct hd_geometry geometry;
if (ioctl(fd, HDIO_GETGEO, &geometry) == 0) {
*h = geometry.heads;
*s = geometry.sectors;
return 0;
}
#else
*h = 0;
*s = 0;
#endif
return -1;
}
/*
* Convert scsi type to human readable string.
*/
const char *blkdev_scsi_type_to_name(int type)
{
switch (type) {
case SCSI_TYPE_DISK:
return "disk";
case SCSI_TYPE_TAPE:
return "tape";
case SCSI_TYPE_PRINTER:
return "printer";
case SCSI_TYPE_PROCESSOR:
return "processor";
case SCSI_TYPE_WORM:
return "worm";
case SCSI_TYPE_ROM:
return "rom";
case SCSI_TYPE_SCANNER:
return "scanner";
case SCSI_TYPE_MOD:
return "mo-disk";
case SCSI_TYPE_MEDIUM_CHANGER:
return "changer";
case SCSI_TYPE_COMM:
return "comm";
case SCSI_TYPE_RAID:
return "raid";
case SCSI_TYPE_ENCLOSURE:
return "enclosure";
case SCSI_TYPE_RBC:
return "rbc";
case SCSI_TYPE_OSD:
return "osd";
case SCSI_TYPE_NO_LUN:
return "no-lun";
default:
break;
}
return NULL;
}
#ifdef TEST_PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int
main(int argc, char **argv)
{
unsigned long long bytes;
unsigned long long sectors;
int sector_size, phy_sector_size;
int fd;
if (argc != 2) {
fprintf(stderr, "usage: %s device\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fd = open(argv[1], O_RDONLY)) < 0)
err(EXIT_FAILURE, "open %s failed", argv[1]);
if (blkdev_get_size(fd, &bytes) < 0)
err(EXIT_FAILURE, "blkdev_get_size() failed");
if (blkdev_get_sectors(fd, &sectors) < 0)
err(EXIT_FAILURE, "blkdev_get_sectors() failed");
if (blkdev_get_sector_size(fd, &sector_size) < 0)
err(EXIT_FAILURE, "blkdev_get_sector_size() failed");
if (blkdev_get_physector_size(fd, &phy_sector_size) < 0)
err(EXIT_FAILURE, "blkdev_get_physector_size() failed");
printf(" bytes: %llu\n", bytes);
printf(" sectors: %llu\n", sectors);
printf(" sector size: %d\n", sector_size);
printf("phy-sector size: %d\n", phy_sector_size);
return EXIT_SUCCESS;
}
#endif /* TEST_PROGRAM */
+146
View File
@@ -0,0 +1,146 @@
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
*/
#ifndef BLKDEV_H
#define BLKDEV_H
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_IOCCOM_H
# include <sys/ioccom.h> /* for _IO macro on e.g. Solaris */
#endif
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_SYS_MKDEV_H
# include <sys/mkdev.h> /* major and minor on Solaris */
#endif
#define DEFAULT_SECTOR_SIZE 512
#ifdef __linux__
/* very basic ioclts, should be available everywhere */
# ifndef BLKROSET
# define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
# define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
# define BLKRRPART _IO(0x12,95) /* re-read partition table */
# define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
# define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
# define BLKRASET _IO(0x12,98) /* set read ahead for block device */
# define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
# define BLKFRASET _IO(0x12,100) /* set filesystem (mm/filemap.c) read-ahead */
# define BLKFRAGET _IO(0x12,101) /* get filesystem (mm/filemap.c) read-ahead */
# define BLKSECTSET _IO(0x12,102) /* set max sectors per request (ll_rw_blk.c) */
# define BLKSECTGET _IO(0x12,103) /* get max sectors per request (ll_rw_blk.c) */
# define BLKSSZGET _IO(0x12,104) /* get block device sector size */
/* ioctls introduced in 2.2.16, removed in 2.5.58 */
# define BLKELVGET _IOR(0x12,106,size_t) /* elevator get */
# define BLKELVSET _IOW(0x12,107,size_t) /* elevator set */
# define BLKBSZGET _IOR(0x12,112,size_t)
# define BLKBSZSET _IOW(0x12,113,size_t)
# endif /* !BLKROSET */
# ifndef BLKGETSIZE64
# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
# endif
/* block device topology ioctls, introduced in 2.6.32 (commit ac481c20) */
# ifndef BLKIOMIN
# define BLKIOMIN _IO(0x12,120)
# define BLKIOOPT _IO(0x12,121)
# define BLKALIGNOFF _IO(0x12,122)
# define BLKPBSZGET _IO(0x12,123)
# endif
/* discard zeroes support, introduced in 2.6.33 (commit 98262f27) */
# ifndef BLKDISCARDZEROES
# define BLKDISCARDZEROES _IO(0x12,124)
# endif
/* filesystem freeze, introduced in 2.6.29 (commit fcccf502) */
# ifndef FIFREEZE
# define FIFREEZE _IOWR('X', 119, int) /* Freeze */
# define FITHAW _IOWR('X', 120, int) /* Thaw */
# endif
/* uniform CD-ROM information */
# ifndef CDROM_GET_CAPABILITY
# define CDROM_GET_CAPABILITY 0x5331
# endif
#endif /* __linux */
#ifdef APPLE_DARWIN
# define BLKGETSIZE DKIOCGETBLOCKCOUNT32
#endif
#ifndef HDIO_GETGEO
# ifdef __linux__
# define HDIO_GETGEO 0x0301
# endif
struct hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders; /* truncated */
unsigned long start;
};
#endif /* HDIO_GETGEO */
/* are we working with block device? */
int is_blkdev(int fd);
/* Determine size in bytes */
off_t blkdev_find_size (int fd);
/* get size in bytes */
int blkdev_get_size(int fd, unsigned long long *bytes);
/* get 512-byte sector count */
int blkdev_get_sectors(int fd, unsigned long long *sectors);
/* get hardware sector size */
int blkdev_get_sector_size(int fd, int *sector_size);
/* specifies whether or not the device is misaligned */
int blkdev_is_misaligned(int fd);
/* get physical block device size */
int blkdev_get_physector_size(int fd, int *sector_size);
/* is the device cdrom capable? */
int blkdev_is_cdrom(int fd);
/* get device's geometry - legacy */
int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s);
/* SCSI device types. Copied almost as-is from kernel header.
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/scsi/scsi.h */
#define SCSI_TYPE_DISK 0x00
#define SCSI_TYPE_TAPE 0x01
#define SCSI_TYPE_PRINTER 0x02
#define SCSI_TYPE_PROCESSOR 0x03 /* HP scanners use this */
#define SCSI_TYPE_WORM 0x04 /* Treated as ROM by our system */
#define SCSI_TYPE_ROM 0x05
#define SCSI_TYPE_SCANNER 0x06
#define SCSI_TYPE_MOD 0x07 /* Magneto-optical disk - treated as SCSI_TYPE_DISK */
#define SCSI_TYPE_MEDIUM_CHANGER 0x08
#define SCSI_TYPE_COMM 0x09 /* Communications device */
#define SCSI_TYPE_RAID 0x0c
#define SCSI_TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define SCSI_TYPE_RBC 0x0e
#define SCSI_TYPE_OSD 0x11
#define SCSI_TYPE_NO_LUN 0x7f
/* convert scsi type code to name */
const char *blkdev_scsi_type_to_name(int type);
#endif /* BLKDEV_H */
+458
View File
@@ -0,0 +1,458 @@
/*
* blkid.h - Interface for libblkid, a library to identify block devices
*
* Copyright (C) 2001 Andreas Dilger
* Copyright (C) 2003 Theodore Ts'o
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BLKID_BLKID_H
#define _BLKID_BLKID_H
#include <stdint.h>
#include <sys/types.h>
#define _SC_HOST_NAME_MAX 255
#ifdef __cplusplus
extern "C" {
#endif
#define BLKID_VERSION "2.22.0"
#define BLKID_DATE "04-Sep-2012"
/**
* blkid_dev:
*
* The device object keeps information about one device
*/
typedef struct blkid_struct_dev *blkid_dev;
/**
* blkid_cache:
*
* information about all system devices
*/
typedef struct blkid_struct_cache *blkid_cache;
/**
* blkid_probe:
*
* low-level probing setting
*/
typedef struct blkid_struct_probe *blkid_probe;
/**
* blkid_topology:
*
* device topology information
*/
typedef struct blkid_struct_topology *blkid_topology;
/**
* blkid_partlist
*
* list of all detected partitions and partitions tables
*/
typedef struct blkid_struct_partlist *blkid_partlist;
/**
* blkid_partition:
*
* information about a partition
*/
typedef struct blkid_struct_partition *blkid_partition;
/**
* blkid_parttable:
*
* information about a partition table
*/
typedef struct blkid_struct_parttable *blkid_parttable;
/**
* blkid_loff_t:
*
* 64-bit signed number for offsets and sizes
*/
typedef int64_t blkid_loff_t;
/**
* blkid_tag_iterate:
*
* tags iterator for high-level (blkid_cache) API
*/
typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
/**
* blkid_dev_iterate:
*
* devices iterator for high-level (blkid_cache) API
*/
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)
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
#ifndef __ul_attribute__
# if __GNUC_PREREQ (3, 4)
# define __ul_attribute__(_a_) __attribute__(_a_)
# else
# define __ul_attribute__(_a_)
# endif
#endif
/* cache.c */
extern void blkid_put_cache(blkid_cache cache);
extern int blkid_get_cache(blkid_cache *cache, const char *filename);
extern void blkid_gc_cache(blkid_cache cache);
/* dev.c */
extern const char *blkid_dev_devname(blkid_dev dev)
__ul_attribute__((warn_unused_result));
extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
__ul_attribute__((nonnull));
extern int blkid_dev_set_search(blkid_dev_iterate iter,
char *search_type, char *search_value);
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)
__ul_attribute__((warn_unused_result));
extern int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
size_t len, dev_t *diskdevno)
__ul_attribute__((warn_unused_result));
/* devname.c */
extern int blkid_probe_all(blkid_cache cache);
extern int blkid_probe_all_new(blkid_cache cache);
extern int blkid_probe_all_removable(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)
__ul_attribute__((warn_unused_result));
/* verify.c */
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)
__ul_attribute__((warn_unused_result));
extern char *blkid_get_devname(blkid_cache cache, const char *token,
const char *value)
__ul_attribute__((warn_unused_result));
/* tag.c */
extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
__ul_attribute__((warn_unused_result));
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 int blkid_dev_has_tag(blkid_dev dev, const char *type, const char *value)
__ul_attribute__((nonnull(1,2)));
extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
const char *type,
const char *value)
__ul_attribute__((warn_unused_result));
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)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_get_library_version(const char **ver_string,
const char **date_string);
/* encode.c */
extern int blkid_encode_string(const char *str, char *str_enc, size_t len);
extern int blkid_safe_string(const char *str, char *str_safe, size_t len);
/* evaluate.c */
extern int blkid_send_uevent(const char *devname, const char *action);
extern char *blkid_evaluate_tag(const char *token, const char *value,
blkid_cache *cache)
__ul_attribute__((warn_unused_result));
extern char *blkid_evaluate_spec(const char *spec, blkid_cache *cache)
__ul_attribute__((warn_unused_result));
/* probe.c */
extern blkid_probe blkid_new_probe(void)
__ul_attribute__((warn_unused_result));
extern blkid_probe blkid_new_probe_from_filename(const char *filename)
__ul_attribute__((warn_unused_result));
extern void blkid_free_probe(blkid_probe pr);
extern void blkid_reset_probe(blkid_probe pr);
extern int blkid_probe_set_device(blkid_probe pr, int fd,
blkid_loff_t off, blkid_loff_t size);
extern dev_t blkid_probe_get_devno(blkid_probe pr)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_probe_is_wholedisk(blkid_probe pr)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_probe_get_size(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern int blkid_probe_get_fd(blkid_probe pr)
__ul_attribute__((warn_unused_result));
/*
* superblocks probing
*/
extern int blkid_known_fstype(const char *fstype)
__ul_attribute__((warn_unused_result));
extern int blkid_superblocks_get_name(size_t idx, const char **name, int *usage);
extern int blkid_probe_enable_superblocks(blkid_probe pr, int enable);
#define BLKID_SUBLKS_LABEL (1 << 1) /* read LABEL from superblock */
#define BLKID_SUBLKS_LABELRAW (1 << 2) /* read and define LABEL_RAW result value*/
#define BLKID_SUBLKS_UUID (1 << 3) /* read UUID from superblock */
#define BLKID_SUBLKS_UUIDRAW (1 << 4) /* read and define UUID_RAW result value */
#define BLKID_SUBLKS_TYPE (1 << 5) /* define TYPE result value */
#define BLKID_SUBLKS_SECTYPE (1 << 6) /* define compatible fs type (second type) */
#define BLKID_SUBLKS_USAGE (1 << 7) /* define USAGE result value */
#define BLKID_SUBLKS_VERSION (1 << 8) /* read FS type from superblock */
#define BLKID_SUBLKS_MAGIC (1 << 9) /* define SBMAGIC and SBMAGIC_OFFSET */
#define BLKID_SUBLKS_DEFAULT (BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | \
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE)
extern int blkid_probe_set_superblocks_flags(blkid_probe pr, int flags);
extern int blkid_probe_reset_superblocks_filter(blkid_probe pr);
extern int blkid_probe_invert_superblocks_filter(blkid_probe pr);
/**
* BLKID_FLTR_NOTIN
*/
#define BLKID_FLTR_NOTIN 1
/**
* BLKID_FLTR_ONLYIN
*/
#define BLKID_FLTR_ONLYIN 2
extern int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *names[]);
#define BLKID_USAGE_FILESYSTEM (1 << 1)
#define BLKID_USAGE_RAID (1 << 2)
#define BLKID_USAGE_CRYPTO (1 << 3)
#define BLKID_USAGE_OTHER (1 << 4)
extern int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage);
/*
* topology probing
*/
extern int blkid_probe_enable_topology(blkid_probe pr, int enable);
/* binary interface */
extern blkid_topology blkid_probe_get_topology(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern unsigned long blkid_topology_get_alignment_offset(blkid_topology tp)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern unsigned long blkid_topology_get_logical_sector_size(blkid_topology tp)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern unsigned long blkid_topology_get_physical_sector_size(blkid_topology tp)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
/*
* partitions probing
*/
extern int blkid_known_pttype(const char *pttype)
__ul_attribute__((warn_unused_result));
extern int blkid_probe_enable_partitions(blkid_probe pr, int enable);
extern int blkid_probe_reset_partitions_filter(blkid_probe pr);
extern int blkid_probe_invert_partitions_filter(blkid_probe pr);
extern int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[]);
/* partitions probing flags */
#define BLKID_PARTS_FORCE_GPT (1 << 1)
#define BLKID_PARTS_ENTRY_DETAILS (1 << 2)
#define BLKID_PARTS_MAGIC (1 << 3)
extern int blkid_probe_set_partitions_flags(blkid_probe pr, int flags);
/* binary interface */
extern blkid_partlist blkid_probe_get_partitions(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern int blkid_partlist_numof_partitions(blkid_partlist ls)
__ul_attribute__((warn_unused_result));
extern blkid_parttable blkid_partlist_get_table(blkid_partlist ls)
__ul_attribute__((warn_unused_result));
extern blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
__ul_attribute__((warn_unused_result));
extern blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno)
__ul_attribute__((warn_unused_result));
extern blkid_parttable blkid_partition_get_table(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern const char *blkid_partition_get_name(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern const char *blkid_partition_get_uuid(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern int blkid_partition_get_partno(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_partition_get_start(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_partition_get_size(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern int blkid_partition_get_type(blkid_partition par)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern const char *blkid_partition_get_type_string(blkid_partition par)
__ul_attribute__((warn_unused_result));
extern unsigned long long blkid_partition_get_flags(blkid_partition par)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_partition_is_logical(blkid_partition par)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_partition_is_extended(blkid_partition par)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_partition_is_primary(blkid_partition par)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern const char *blkid_parttable_get_type(blkid_parttable tab)
__ul_attribute__((warn_unused_result));
extern const char *blkid_parttable_get_id(blkid_parttable tab)
__ul_attribute__((warn_unused_result));
extern blkid_loff_t blkid_parttable_get_offset(blkid_parttable tab)
__ul_attribute__((warn_unused_result));
extern blkid_partition blkid_parttable_get_parent(blkid_parttable tab)
__ul_attribute__((warn_unused_result));
/*
* NAME=value low-level interface
*/
extern int blkid_do_probe(blkid_probe pr);
extern int blkid_do_safeprobe(blkid_probe pr);
extern int blkid_do_fullprobe(blkid_probe pr);
extern int blkid_probe_numof_values(blkid_probe pr)
__ul_attribute__((warn_unused_result));
extern int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
const char **data, size_t *len);
extern int blkid_probe_lookup_value(blkid_probe pr, const char *name,
const char **data, size_t *len);
extern int blkid_probe_has_value(blkid_probe pr, const char *name)
__ul_attribute__((nonnull))
__ul_attribute__((warn_unused_result));
extern int blkid_do_wipe(blkid_probe pr, int dryrun);
extern int blkid_probe_step_back(blkid_probe pr);
/*
* Deprecated functions/macros
*/
#ifndef BLKID_DISABLE_DEPRECATED
#define BLKID_PROBREQ_LABEL BLKID_SUBLKS_LABEL
#define BLKID_PROBREQ_LABELRAW BLKID_SUBLKS_LABELRAW
#define BLKID_PROBREQ_UUID BLKID_SUBLKS_UUID
#define BLKID_PROBREQ_UUIDRAW BLKID_SUBLKS_UUIDRAW
#define BLKID_PROBREQ_TYPE BLKID_SUBLKS_TYPE
#define BLKID_PROBREQ_SECTYPE BLKID_SUBLKS_SECTYPE
#define BLKID_PROBREQ_USAGE BLKID_SUBLKS_USAGE
#define BLKID_PROBREQ_VERSION BLKID_SUBLKS_VERSION
extern int blkid_probe_set_request(blkid_probe pr, int flags)
__ul_attribute__((deprecated));
extern int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
__ul_attribute__((deprecated));
extern int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
__ul_attribute__((deprecated));
extern int blkid_probe_invert_filter(blkid_probe pr)
__ul_attribute__((deprecated));
extern int blkid_probe_reset_filter(blkid_probe pr)
__ul_attribute__((deprecated));
#endif /* BLKID_DISABLE_DEPRECATED */
#ifdef __cplusplus
}
#endif
#endif /* _BLKID_BLKID_H */
+551
View File
@@ -0,0 +1,551 @@
/*
* 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
/* support debug output if LIBBLKID_DEBUG env. variable is set */
#define CONFIG_BLKID_DEBUG 1
/* Always confirm that /dev/disk-by symlinks match with LABEL/UUID on device */
/* #define CONFIG_BLKID_VERIFY_UDEV 1 */
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include "c.h"
#include "bitops.h" /* $(top_srcdir)/include/ */
#include "blkdev.h"
#include "blkid.h"
#include "list.h"
/*
* 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 */
suseconds_t bid_utime; /* Last update time (microseconds) */
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 */
#define BLKID_BID_FL_REMOVABLE 0x0008 /* Device added by blkid_probe_all_removable() */
/*
* 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;
/*
* Chain IDs
*/
enum {
BLKID_CHAIN_SUBLKS, /* FS/RAID superblocks (enabled by default) */
BLKID_CHAIN_TOPLGY, /* Block device topology */
BLKID_CHAIN_PARTS, /* Partition tables */
BLKID_NCHAINS /* number of chains */
};
struct blkid_chain {
const struct blkid_chaindrv *driver; /* chain driver */
int enabled; /* boolean */
int flags; /* BLKID_<chain>_* */
int binary; /* boolean */
int idx; /* index of the current prober (or -1) */
unsigned long *fltr; /* filter or NULL */
void *data; /* private chain data or NULL */
};
/*
* Chain driver
*/
struct blkid_chaindrv {
const size_t id; /* BLKID_CHAIN_* */
const char *name; /* name of chain (for debug purpose) */
const int dflt_flags; /* default chain flags */
const int dflt_enabled; /* default enabled boolean */
int has_fltr; /* boolean */
const struct blkid_idinfo **idinfos; /* description of probing functions */
const size_t nidinfos; /* number of idinfos */
/* driver operations */
int (*probe)(blkid_probe, struct blkid_chain *);
int (*safeprobe)(blkid_probe, struct blkid_chain *);
void (*free_data)(blkid_probe, void *);
};
/*
* Low-level probe result
*/
#define BLKID_PROBVAL_BUFSIZ 128
#define BLKID_NVALS_SUBLKS 18
#define BLKID_NVALS_TOPLGY 5
#define BLKID_NVALS_PARTS 13
/* Max number of all values in probing result */
#define BLKID_NVALS (BLKID_NVALS_SUBLKS + \
BLKID_NVALS_TOPLGY + \
BLKID_NVALS_PARTS)
struct blkid_prval
{
const char *name; /* value name */
unsigned char data[BLKID_PROBVAL_BUFSIZ]; /* value data */
size_t len; /* length of value data */
struct blkid_chain *chain; /* owner */
};
/*
* Filesystem / Raid magic strings
*/
struct blkid_idmag
{
const char *magic; /* magic string */
unsigned int len; /* length of magic */
long kboff; /* kilobyte offset of superblock */
unsigned int sboff; /* byte offset within superblock */
};
/*
* Filesystem / Raid description
*/
struct blkid_idinfo
{
const char *name; /* fs, raid or partition table name */
int usage; /* BLKID_USAGE_* flag */
int flags; /* BLKID_IDINFO_* flags */
int minsz; /* minimal device size */
/* probe function */
int (*probefunc)(blkid_probe pr, const struct blkid_idmag *mag);
struct blkid_idmag magics[]; /* NULL or array with magic strings */
};
#define BLKID_NONE_MAGIC {{ NULL }}
/*
* tolerant FS - can share the same device with more filesystems (e.g. typical
* on CD-ROMs). We need this flag to detect ambivalent results (e.g. valid fat
* and valid linux swap on the same device).
*/
#define BLKID_IDINFO_TOLERANT (1 << 1)
struct blkid_bufinfo {
unsigned char *data;
blkid_loff_t off;
blkid_loff_t len;
struct list_head bufs; /* list of buffers */
};
/*
* Low-level probing control struct
*/
struct blkid_struct_probe
{
int fd; /* device file descriptor */
blkid_loff_t off; /* begin of data on the device */
blkid_loff_t size; /* end of data on the device */
dev_t devno; /* device number (st.st_rdev) */
dev_t disk_devno; /* devno of the whole-disk or 0 */
unsigned int blkssz; /* sector size (BLKSSZGET ioctl) */
mode_t mode; /* struct stat.sb_mode */
int flags; /* private libray flags */
int prob_flags; /* always zeroized by blkid_do_*() */
blkid_loff_t wipe_off; /* begin of the wiped area */
blkid_loff_t wipe_size; /* size of the wiped area */
struct blkid_chain *wipe_chain; /* superblock, partition, ... */
struct list_head buffers; /* list of buffers */
struct blkid_chain chains[BLKID_NCHAINS]; /* array of chains */
struct blkid_chain *cur_chain; /* current chain */
struct blkid_prval vals[BLKID_NVALS]; /* results */
int nvals; /* number of assigned vals */
struct blkid_struct_probe *parent; /* for clones */
struct blkid_struct_probe *disk_probe; /* whole-disk probing */
};
/* private flags library flags */
#define BLKID_FL_PRIVATE_FD (1 << 1) /* see blkid_new_probe_from_filename() */
#define BLKID_FL_TINY_DEV (1 << 2) /* <= 1.47MiB (floppy or so) */
#define BLKID_FL_CDROM_DEV (1 << 3) /* is a CD/DVD drive */
/* private per-probing flags */
#define BLKID_PROBE_FL_IGNORE_PT (1 << 1) /* ignore partition table */
#define BLKID_PROBE_FL_IGNORE_BACKUP (1 << 2) /* ignore backup superblocks or PT */
extern int blkid_probe_ignore_backup(blkid_probe pr);
extern blkid_probe blkid_clone_probe(blkid_probe parent);
extern blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr);
/*
* Evaluation methods (for blkid_eval_* API)
*/
enum {
BLKID_EVAL_UDEV = 0,
BLKID_EVAL_SCAN,
__BLKID_EVAL_LAST
};
/*
* Library config options
*/
struct blkid_config {
int eval[__BLKID_EVAL_LAST]; /* array with EVALUATION=<udev,cache> options */
int nevals; /* number of elems in eval array */
int uevent; /* SEND_UEVENT=<yes|not> option */
char *cachefile; /* CACHE_FILE=<path> option */
};
extern struct blkid_config *blkid_read_config(const char *filename)
__ul_attribute__((warn_unused_result));
extern void blkid_free_config(struct blkid_config *conf);
/*
* 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 */
blkid_probe probe; /* low-level probing stuff */
};
#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
/* config file */
#define BLKID_CONFIG_FILE "/etc/blkid.conf"
/* cache file on systemds with /run */
#define BLKID_RUNTIME_TOPDIR "/run"
#define BLKID_RUNTIME_DIR BLKID_RUNTIME_TOPDIR "/blkid"
#define BLKID_CACHE_FILE BLKID_RUNTIME_DIR "/blkid.tab"
/* old systems */
#define BLKID_CACHE_FILE_OLD "/etc/blkid.tab"
#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_UBI 50
#define BLKID_PRI_DM 40
#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_LOWPROBE 0x0400
#define DEBUG_CONFIG 0x0800
#define DEBUG_EVALUATE 0x1000
#define DEBUG_INIT 0x8000
#define DEBUG_ALL 0xFFFF
#ifdef CONFIG_BLKID_DEBUG
extern int blkid_debug_mask;
extern void blkid_init_debug(int mask);
extern void blkid_debug_dump_dev(blkid_dev dev);
extern void blkid_debug_dump_tag(blkid_tag tag);
#define DBG(m,x) do { if ((m) & blkid_debug_mask) x; } while (0)
#else /* !CONFIG_BLKID_DEBUG */
#define DBG(m,x)
#define blkid_init_debug(x)
#endif /* CONFIG_BLKID_DEBUG */
/* devno.c */
struct dir_list {
char *name;
struct dir_list *next;
};
extern void blkid__scan_dir(char *, dev_t, struct dir_list **, char **)
__attribute__((nonnull(1,4)));
extern int blkid_driver_has_major(const char *drvname, int major)
__attribute__((warn_unused_result));
/* 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)
__attribute__((nonnull));
/* save.c */
extern int blkid_flush_cache(blkid_cache cache)
__attribute__((nonnull));
/* cache */
extern char *blkid_safe_getenv(const char *arg)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern char *blkid_get_cache_filename(struct blkid_config *conf)
__attribute__((warn_unused_result));
/*
* 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)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_set_tag(blkid_dev dev, const char *name,
const char *value, const int vlength)
__attribute__((nonnull(1,2)));
/*
* Functions to create and find a specific tag type: dev.c
*/
extern blkid_dev blkid_new_dev(void)
__attribute__((warn_unused_result));
extern void blkid_free_dev(blkid_dev dev);
/* probe.c */
extern int blkid_probe_is_tiny(blkid_probe pr)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_probe_is_cdrom(blkid_probe pr)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern unsigned char *blkid_probe_get_buffer(blkid_probe pr,
blkid_loff_t off, blkid_loff_t len)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_probe_get_dimension(blkid_probe pr,
blkid_loff_t *off, blkid_loff_t *size)
__attribute__((nonnull));
extern int blkid_probe_set_dimension(blkid_probe pr,
blkid_loff_t off, blkid_loff_t size)
__attribute__((nonnull));
extern int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
blkid_loff_t *offset, const struct blkid_idmag **res)
__attribute__((nonnull(1)));
/* returns superblok according to 'struct blkid_idmag' */
#define blkid_probe_get_sb(_pr, _mag, type) \
((type *) blkid_probe_get_buffer((_pr),\
(_mag)->kboff << 10, sizeof(type)))
extern blkid_partlist blkid_probe_get_partlist(blkid_probe pr)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_probe_is_covered_by_pt(blkid_probe pr,
blkid_loff_t offset, blkid_loff_t size)
__attribute__((warn_unused_result));
extern void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
__attribute__((nonnull));
extern int blkid_probe_chain_copy_vals(blkid_probe pr,
struct blkid_chain *chn,
struct blkid_prval *vals,
int nvals)
__attribute__((nonnull));
extern struct blkid_prval *blkid_probe_assign_value(blkid_probe pr,
const char *name)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_probe_reset_last_value(blkid_probe pr)
__attribute__((nonnull));
extern void blkid_probe_append_vals(blkid_probe pr,
struct blkid_prval *vals,
int nvals)
__attribute__((nonnull));
extern struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int __blkid_probe_invert_filter(blkid_probe pr, int chain)
__attribute__((nonnull));
extern int __blkid_probe_reset_filter(blkid_probe pr, int chain)
__attribute__((nonnull));
extern int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
__attribute__((nonnull));
extern void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern int blkid_probe_set_value(blkid_probe pr, const char *name,
unsigned char *data, size_t len)
__attribute__((nonnull));
extern int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
const char *fmt, va_list ap)
__attribute__((nonnull));
extern int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
const char *fmt, ...)
__attribute__((nonnull))
__attribute__ ((__format__ (__printf__, 3, 4)));
extern int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
size_t len, unsigned char *magic)
__attribute__((nonnull));
extern void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
__attribute__((nonnull));
extern size_t blkid_rtrim_whitespace(unsigned char *str)
__attribute__((nonnull));
extern size_t blkid_ltrim_whitespace(unsigned char *str)
__attribute__((nonnull));
extern void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off,
blkid_loff_t size)
__attribute__((nonnull));
extern int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
blkid_loff_t off, blkid_loff_t size)
__attribute__((nonnull))
__attribute__((warn_unused_result));
extern void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
__attribute__((nonnull));
/* filter bitmap macros */
#define blkid_bmp_wordsize (8 * sizeof(unsigned long))
#define blkid_bmp_idx_bit(item) (1UL << ((item) % blkid_bmp_wordsize))
#define blkid_bmp_idx_byte(item) ((item) / blkid_bmp_wordsize)
#define blkid_bmp_set_item(bmp, item) \
((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item))
#define blkid_bmp_unset_item(bmp, item) \
((bmp)[ blkid_bmp_idx_byte(item) ] &= ~blkid_bmp_idx_bit(item))
#define blkid_bmp_get_item(bmp, item) \
((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item))
#define blkid_bmp_nwords(max_items) \
(((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize)
#define blkid_bmp_nbytes(max_items) \
(blkid_bmp_nwords(max_items) * sizeof(unsigned long))
/* encode.c */
extern size_t blkid_encode_to_utf8(int enc, unsigned char *dest, size_t len,
const unsigned char *src, size_t count)
__attribute__((nonnull));
#define BLKID_ENC_UTF16BE 0
#define BLKID_ENC_UTF16LE 1
#endif /* _BLKID_BLKIDP_H */
+121
View File
@@ -0,0 +1,121 @@
/*
* Partition types
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Note, _L32M means <32M (less), for example FAT16_L32M */
enum {
BLKID_EMPTY_PARTITION = 0x00,
BLKID_FAT12_PARTITION = 0x01,
BLKID_XENIX_ROOT_PARTITION = 0x02,
BLKID_XENIX_USR_PARTITION = 0x03,
BLKID_FAT16_LESS32M_PARTITION = 0x04,
BLKID_DOS_EXTENDED_PARTITION = 0x05,
BLKID_FAT16_PARTITION = 0x06, /* DOS 16-bit >=32M */
BLKID_HPFS_NTFS_PARTITION = 0x07, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
BLKID_AIX_PARTITION = 0x08, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
BLKID_AIX_BOOTABLE_PARTITION = 0x09, /* AIX data or Coherent */
BLKID_OS2_BOOTMNGR_PARTITION = 0x0a, /* OS/2 Boot Manager */
BLKID_W95_FAT32_PARTITION = 0x0b,
BLKID_W95_FAT32_LBA_PARTITION = 0x0c, /* LBA really is `Extended Int 13h' */
BLKID_W95_FAT16_LBA_PARTITION = 0x0e,
BLKID_W95_EXTENDED_PARTITION = 0x0f,
BLKID_OPUS_PARTITION = 0x10,
BLKID_HIDDEN_FAT12_PARTITION = 0x11,
BLKID_COMPAQ_DIAGNOSTICS_PARTITION = 0x12,
BLKID_HIDDEN_FAT16_L32M_PARTITION = 0x14,
BLKID_HIDDEN_FAT16_PARTITION = 0x16,
BLKID_HIDDEN_HPFS_NTFS_PARTITION = 0x17,
BLKID_AST_SMARTSLEEP_PARTITION = 0x18,
BLKID_HIDDEN_W95_FAT32_PARTITION = 0x1b,
BLKID_HIDDEN_W95_FAT32LBA_PARTITION = 0x1c,
BLKID_HIDDEN_W95_FAT16LBA_PARTITION = 0x1e,
BLKID_NEC_DOS_PARTITION = 0x24,
BLKID_PLAN9_PARTITION = 0x39,
BLKID_PARTITIONMAGIC_PARTITION = 0x3c,
BLKID_VENIX80286_PARTITION = 0x40,
BLKID_PPC_PREP_BOOT_PARTITION = 0x41,
BLKID_SFS_PARTITION = 0x42,
BLKID_QNX_4X_PARTITION = 0x4d,
BLKID_QNX_4X_2ND_PARTITION = 0x4e,
BLKID_QNX_4X_3RD_PARTITION = 0x4f,
BLKID_DM_PARTITION = 0x50,
BLKID_DM6_AUX1_PARTITION = 0x51, /* (or Novell) */
BLKID_CPM_PARTITION = 0x52, /* CP/M or Microport SysV/AT */
BLKID_DM6_AUX3_PARTITION = 0x53,
BLKID_DM6_PARTITION = 0x54,
BLKID_EZ_DRIVE_PARTITION = 0x55,
BLKID_GOLDEN_BOW_PARTITION = 0x56,
BLKID_PRIAM_EDISK_PARTITION = 0x5c,
BLKID_SPEEDSTOR_PARTITION = 0x61,
BLKID_GNU_HURD_PARTITION = 0x63, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
BLKID_UNIXWARE_PARTITION = BLKID_GNU_HURD_PARTITION,
BLKID_NETWARE_286_PARTITION = 0x64,
BLKID_NETWARE_386_PARTITION = 0x65,
BLKID_DISKSECURE_MULTIBOOT_PARTITION = 0x70,
BLKID_PC_IX_PARTITION = 0x75,
BLKID_OLD_MINIX_PARTITION = 0x80, /* Minix 1.4a and earlier */
BLKID_MINIX_PARTITION = 0x81, /* Minix 1.4b and later */
BLKID_LINUX_SWAP_PARTITION = 0x82,
BLKID_SOLARIS_X86_PARTITION = BLKID_LINUX_SWAP_PARTITION,
BLKID_LINUX_DATA_PARTITION = 0x83,
BLKID_OS2_HIDDEN_DRIVE_PARTITION = 0x84,
BLKID_LINUX_EXTENDED_PARTITION = 0x85,
BLKID_NTFS_VOL_SET1_PARTITION = 0x86,
BLKID_NTFS_VOL_SET2_PARTITION = 0x87,
BLKID_LINUX_PLAINTEXT_PARTITION = 0x88,
BLKID_LINUX_LVM_PARTITION = 0x8e,
BLKID_AMOEBA_PARTITION = 0x93,
BLKID_AMOEBA_BBT_PARTITION = 0x94, /* (bad block table) */
BLKID_BSD_OS_PARTITION = 0x9f, /* BSDI */
BLKID_THINKPAD_HIBERNATION_PARTITION = 0xa0,
BLKID_FREEBSD_PARTITION = 0xa5, /* various BSD flavours */
BLKID_OPENBSD_PARTITION = 0xa6,
BLKID_NEXTSTEP_PARTITION = 0xa7,
BLKID_DARWIN_UFS_PARTITION = 0xa8,
BLKID_NETBSD_PARTITION = 0xa9,
BLKID_DARWIN_BOOT_PARTITION = 0xab,
BLKID_HFS_HFS_PARTITION = 0xaf,
BLKID_BSDI_FS_PARTITION = 0xb7,
BLKID_BSDI_SWAP_PARTITION = 0xb8,
BLKID_BOOTWIZARD_HIDDEN_PARTITION = 0xbb,
BLKID_SOLARIS_BOOT_PARTITION = 0xbe,
BLKID_SOLARIS_PARTITION = 0xbf,
BLKID_DRDOS_FAT12_PARTITION = 0xc1,
BLKID_DRDOS_FAT16_L32M_PARTITION = 0xc4,
BLKID_DRDOS_FAT16_PARTITION = 0xc6,
BLKID_SYRINX_PARTITION = 0xc7,
BLKID_NONFS_DATA_PARTITION = 0xda,
BLKID_CPM_CTOS_PARTITION = 0xdb, /* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
BLKID_DELL_UTILITY_PARTITION = 0xde, /* Dell PowerEdge Server utilities */
BLKID_BOOTIT_PARTITION = 0xdf, /* BootIt EMBRM */
BLKID_DOS_ACCESS_PARTITION = 0xe1, /* DOS access or SpeedStor 12-bit FAT extended partition */
BLKID_DOS_RO_PARTITION = 0xe3, /* DOS R/O or SpeedStor */
BLKID_SPEEDSTOR_EXTENDED_PARTITION = 0xe4, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
BLKID_BEOS_FS_PARTITION = 0xeb,
BLKID_GPT_PARTITION = 0xee, /* Intel EFI GUID Partition Table */
BLKID_EFI_SYSTEM_PARTITION = 0xef, /* Intel EFI System Partition */
BLKID_LINUX_PARISC_BOOT_PARTITION = 0xf0, /* Linux/PA-RISC boot loader */
BLKID_SPEEDSTOR1_PARTITION = 0xf1,
BLKID_SPEEDSTOR2_PARTITION = 0xf4, /* SpeedStor large partition */
BLKID_DOS_SECONDARY_PARTITION = 0xf2, /* DOS 3.3+ secondary */
BLKID_VMWARE_VMFS_PARTITION = 0xfb,
BLKID_VMWARE_VMKCORE_PARTITION = 0xfc, /* VMware kernel dump partition */
BLKID_LINUX_RAID_PARTITION = 0xfd, /* New (2.2.x) raid partition with autodetect using persistent superblock */
BLKID_LANSTEP_PARTITION = 0xfe, /* SpeedStor >1024 cyl. or LANstep */
BLKID_XENIX_BBT_PARTITION = 0xff, /* Xenix Bad Block Table */
};
+243
View File
@@ -0,0 +1,243 @@
/*
* BSD/OSF partition parsing code
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* Inspired by fdisk, partx, Linux kernel, libparted and openbsd header files.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "partitions.h"
#define BSD_MAXPARTITIONS 16
#define BSD_FS_UNUSED 0
struct bsd_disklabel {
uint32_t d_magic; /* the magic number */
int16_t d_type; /* drive type */
int16_t d_subtype; /* controller/d_type specific */
char d_typename[16]; /* type name, e.g. "eagle" */
char d_packname[16]; /* pack identifier */
/* disk geometry: */
uint32_t d_secsize; /* # of bytes per sector */
uint32_t d_nsectors; /* # of data sectors per track */
uint32_t d_ntracks; /* # of tracks per cylinder */
uint32_t d_ncylinders; /* # of data cylinders per unit */
uint32_t d_secpercyl; /* # of data sectors per cylinder */
uint32_t d_secperunit; /* # of data sectors per unit */
/*
* Spares (bad sector replacements) below
* are not counted in d_nsectors or d_secpercyl.
* Spare sectors are assumed to be physical sectors
* which occupy space at the end of each track and/or cylinder.
*/
uint16_t d_sparespertrack; /* # of spare sectors per track */
uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
/*
* Alternate cylinders include maintenance, replacement,
* configuration description areas, etc.
*/
uint32_t d_acylinders; /* # of alt. cylinders per unit */
/* hardware characteristics: */
/*
* d_interleave, d_trackskew and d_cylskew describe perturbations
* in the media format used to compensate for a slow controller.
* Interleave is physical sector interleave, set up by the formatter
* or controller when formatting. When interleaving is in use,
* logically adjacent sectors are not physically contiguous,
* but instead are separated by some number of sectors.
* It is specified as the ratio of physical sectors traversed
* per logical sector. Thus an interleave of 1:1 implies contiguous
* layout, while 2:1 implies that logical sector 0 is separated
* by one sector from logical sector 1.
* d_trackskew is the offset of sector 0 on track N
* relative to sector 0 on track N-1 on the same cylinder.
* Finally, d_cylskew is the offset of sector 0 on cylinder N
* relative to sector 0 on cylinder N-1.
*/
uint16_t d_rpm; /* rotational speed */
uint16_t d_interleave; /* hardware sector interleave */
uint16_t d_trackskew; /* sector 0 skew, per track */
uint16_t d_cylskew; /* sector 0 skew, per cylinder */
uint32_t d_headswitch; /* head switch time, usec */
uint32_t d_trkseek; /* track-to-track seek, usec */
uint32_t d_flags; /* generic flags */
uint32_t d_drivedata[5]; /* drive-type specific information */
uint32_t d_spare[5]; /* reserved for future use */
uint32_t d_magic2; /* the magic number (again) */
uint16_t d_checksum; /* xor of data incl. partitions */
/* filesystem and partition information: */
uint16_t d_npartitions; /* number of partitions in following */
uint32_t d_bbsize; /* size of boot area at sn0, bytes */
uint32_t d_sbsize; /* max size of fs superblock, bytes */
struct bsd_partition { /* the partition table */
uint32_t p_size; /* number of sectors in partition */
uint32_t p_offset; /* starting sector */
uint32_t p_fsize; /* filesystem basic fragment size */
uint8_t p_fstype; /* filesystem type, see below */
uint8_t p_frag; /* filesystem fragments per block */
uint16_t p_cpg; /* filesystem cylinders per group */
} __attribute__((packed)) d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
} __attribute__((packed));
/* Returns 'blkid_idmag' in 512-sectors */
#define BLKID_MAG_SECTOR(_mag) (((_mag)->kboff * 2) + ((_mag)->sboff >> 9))
/* Returns 'blkid_idmag' in bytes */
#define BLKID_MAG_OFFSET(_mag) ((_mag)->kboff >> 10) + ((_mag)->sboff)
/* Returns 'blkid_idmag' offset in bytes within the last sector */
#define BLKID_MAG_LASTOFFSET(_mag) \
(BLKID_MAG_OFFSET(_mag) - (BLKID_MAG_SECTOR(_mag) << 9))
static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag)
{
struct bsd_disklabel *l;
struct bsd_partition *p;
const char *name = "bsd" ;
blkid_parttable tab = NULL;
blkid_partition parent;
blkid_partlist ls;
int i, nparts = BSD_MAXPARTITIONS;
unsigned char *data;
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
data = blkid_probe_get_sector(pr, BLKID_MAG_SECTOR(mag));
if (!data)
goto nothing;
l = (struct bsd_disklabel *) data + BLKID_MAG_LASTOFFSET(mag);
ls = blkid_probe_get_partlist(pr);
if (!ls)
goto err;
/* try to determine the real type of BSD system according to
* (parental) primary partition */
parent = blkid_partlist_get_parent(ls);
if (parent) {
switch(blkid_partition_get_type(parent)) {
case BLKID_FREEBSD_PARTITION:
name = "freebsd";
break;
case BLKID_NETBSD_PARTITION:
name = "netbsd";
break;
case BLKID_OPENBSD_PARTITION:
name = "openbsd";
break;
default:
DBG(DEBUG_LOWPROBE, printf(
"WARNING: BSD label detected on unknown (0x%x) "
"primary partition\n",
blkid_partition_get_type(parent)));
break;
}
}
tab = blkid_partlist_new_parttable(ls, name, BLKID_MAG_OFFSET(mag));
if (!tab)
goto err;
if (le16_to_cpu(l->d_npartitions) < BSD_MAXPARTITIONS)
nparts = le16_to_cpu(l->d_npartitions);
else if (le16_to_cpu(l->d_npartitions) > BSD_MAXPARTITIONS)
DBG(DEBUG_LOWPROBE, printf(
"WARNING: ignore %d more BSD partitions\n",
le16_to_cpu(l->d_npartitions) - BSD_MAXPARTITIONS));
for (i = 0, p = l->d_partitions; i < nparts; i++, p++) {
blkid_partition par;
uint32_t start, size;
/* TODO: in fdisk-mode returns all non-zero (p_size) partitions */
if (p->p_fstype == BSD_FS_UNUSED)
continue;
start = le32_to_cpu(p->p_offset);
size = le32_to_cpu(p->p_size);
if (parent && !blkid_is_nested_dimension(parent, start, size)) {
DBG(DEBUG_LOWPROBE, printf(
"WARNING: BSD partition (%d) overflow "
"detected, ignore\n", i));
continue;
}
par = blkid_partlist_add_partition(ls, tab, start, size);
if (!par)
goto err;
blkid_partition_set_type(par, p->p_fstype);
}
return 0;
nothing:
return 1;
err:
return -1;
}
/*
* All BSD variants use the same magic string (little-endian),
* and the same disklabel.
*
* The difference between {Free,Open,...}BSD is in the (parental)
* primary partition type.
*
* See also: http://en.wikipedia.org/wiki/BSD_disklabel
*
* The location of BSD disk label is architecture specific and in defined by
* LABELSECTOR and LABELOFFSET macros in the disklabel.h file. The location
* also depends on BSD variant, FreeBSD uses only one location, NetBSD and
* OpenBSD are more creative...
*
* The basic overview:
*
* arch | LABELSECTOR | LABELOFFSET
* ------------------------+-------------+------------
* amd64 arm hppa hppa64 | |
* i386, macppc, mvmeppc | 1 | 0
* sgi, aviion, sh, socppc | |
* ------------------------+-------------+------------
* alpha luna88k mac68k | 0 | 64
* sparc(OpenBSD) vax | |
* ------------------------+-------------+------------
* spark64 sparc(NetBSD) | 0 | 128
* ------------------------+-------------+------------
*
* ...and more (see http://fxr.watson.org/fxr/ident?v=NETBSD;i=LABELSECTOR)
*
*/
const struct blkid_idinfo bsd_pt_idinfo =
{
.name = "bsd",
.probefunc = probe_bsd_pt,
.magics =
{
{ .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 512 },
{ .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 64 },
{ .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 128 },
{ NULL }
}
};
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct btrfs_super_block {
uint8_t csum[32];
uint8_t fsid[16];
uint64_t bytenr;
uint64_t flags;
uint8_t magic[8];
uint64_t generation;
uint64_t root;
uint64_t chunk_root;
uint64_t log_root;
uint64_t log_root_transid;
uint64_t total_bytes;
uint64_t bytes_used;
uint64_t root_dir_objectid;
uint64_t num_devices;
uint32_t sectorsize;
uint32_t nodesize;
uint32_t leafsize;
uint32_t stripesize;
uint32_t sys_chunk_array_size;
uint64_t chunk_root_generation;
uint64_t compat_flags;
uint64_t compat_ro_flags;
uint64_t incompat_flags;
uint16_t csum_type;
uint8_t root_level;
uint8_t chunk_root_level;
uint8_t log_root_level;
struct btrfs_dev_item {
uint64_t devid;
uint64_t total_bytes;
uint64_t bytes_used;
uint32_t io_align;
uint32_t io_width;
uint32_t sector_size;
uint64_t type;
uint64_t generation;
uint64_t start_offset;
uint32_t dev_group;
uint8_t seek_speed;
uint8_t bandwidth;
uint8_t uuid[16];
uint8_t fsid[16];
} __attribute__ ((__packed__)) dev_item;
uint8_t label[256];
} __attribute__ ((__packed__));
static int probe_btrfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct btrfs_super_block *bfs;
if (mag->kboff > 64 && blkid_probe_ignore_backup(pr)) {
DBG(DEBUG_LOWPROBE, printf("btrfs: found backup superblock, ignore\n"));
return 1;
}
bfs = blkid_probe_get_sb(pr, mag, struct btrfs_super_block);
if (!bfs)
return -1;
if (*bfs->label)
blkid_probe_set_label(pr,
(unsigned char *) bfs->label,
sizeof(bfs->label));
blkid_probe_set_uuid(pr, bfs->fsid);
blkid_probe_set_uuid_as(pr, bfs->dev_item.uuid, "UUID_SUB");
return 0;
}
const struct blkid_idinfo btrfs_idinfo =
{
.name = "btrfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_btrfs,
.minsz = 1024 * 1024,
.magics =
{
{ .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 64 },
{ .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 64 * 1024 },
{ .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 256 * 1024 * 1024 },
{ NULL }
}
};
+280
View File
@@ -0,0 +1,280 @@
/*
* Fundamental C definitions.
*/
#ifndef UTIL_LINUX_C_H
#define UTIL_LINUX_C_H
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "blkid.h"
#ifdef HAVE_ERR_H
# include <err.h>
#endif
#ifndef HAVE_USLEEP
# include <time.h>
#endif
/*
* Compiler specific stuff
*/
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
#ifdef __GNUC__
/* &a[0] degrades to a pointer: a different type from an array */
# define __must_be_array(a) \
UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
# define ignore_result(x) ({ \
__typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \
})
#else /* !__GNUC__ */
# define __must_be_array(a) 0
# define __attribute__(_arg_)
# define ignore_result(x) ((void) (x))
#endif /* !__GNUC__ */
/*
* Function attributes
*/
#ifndef __ul_alloc_size
# if __GNUC_PREREQ (4, 3)
# define __ul_alloc_size(s) __attribute__((alloc_size(s)))
# else
# define __ul_alloc_size(s)
# endif
#endif
#ifndef __ul_calloc_size
# if __GNUC_PREREQ (4, 3)
# define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s)))
# else
# define __ul_calloc_size(n, s)
# endif
#endif
/* Force a compilation error if condition is true, but also produce a
* result (of value 0 and type size_t), so the expression can be used
* e.g. in a structure initializer (or where-ever else comma expressions
* aren't permitted).
*/
#define UL_BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
#endif
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef min
# define min(x, y) ({ \
__typeof__(x) _min1 = (x); \
__typeof__(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
#endif
#ifndef max
# define max(x, y) ({ \
__typeof__(x) _max1 = (x); \
__typeof__(y) _max2 = (y); \
(void) (&_max1 == &_max2); \
_max1 > _max2 ? _max1 : _max2; })
#endif
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
# ifdef HAVE___PROGNAME
extern char *__progname;
# define program_invocation_short_name __progname
# else
# ifdef HAVE_GETEXECNAME
# define program_invocation_short_name \
prog_inv_sh_nm_from_file(getexecname(), 0)
# else
# define program_invocation_short_name \
prog_inv_sh_nm_from_file(__FILE__, 1)
# endif
static char prog_inv_sh_nm_buf[256];
static inline char *
prog_inv_sh_nm_from_file(char *f, char stripext)
{
char *t;
if ((t = strrchr(f, '/')) != NULL)
t++;
else
t = f;
strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
*t = '\0';
return prog_inv_sh_nm_buf;
}
# endif
#endif
#ifndef HAVE_ERR_H
static inline void
errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
{
fprintf(stderr, "%s: ", program_invocation_short_name);
if (fmt != NULL) {
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
if (adderr)
fprintf(stderr, ": ");
}
if (adderr)
fprintf(stderr, "%m");
fprintf(stderr, "\n");
if (doexit)
exit(excode);
}
#ifndef HAVE_ERR
# define err(E, FMT...) errmsg(1, E, 1, FMT)
#endif
#ifndef HAVE_ERRX
# define errx(E, FMT...) errmsg(1, E, 0, FMT)
#endif
#ifndef HAVE_WARN
# define warn(FMT...) errmsg(0, 0, 1, FMT)
#endif
#ifndef HAVE_WARNX
# define warnx(FMT...) errmsg(0, 0, 0, FMT)
#endif
#endif /* !HAVE_ERR_H */
static inline __attribute__((const)) int is_power_of_2(unsigned long num)
{
return (num != 0 && ((num & (num - 1)) == 0));
}
#ifndef HAVE_LOFF_T
typedef int64_t loff_t;
#endif
#if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD)
#include <sys/types.h>
#include <dirent.h>
static inline int dirfd(DIR *d)
{
return d->dd_fd;
}
#endif
/*
* Fallback defines for old versions of glibc
*/
#include <fcntl.h>
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0x0020
#endif
#ifndef IUTF8
#define IUTF8 0040000
#endif
/*
* MAXHOSTNAMELEN replacement
*/
static inline size_t get_hostname_max(void)
{
long len = sysconf(_SC_HOST_NAME_MAX);
if (0 < len)
return len;
#ifdef MAXHOSTNAMELEN
return MAXHOSTNAMELEN;
#elif HOST_NAME_MAX
return HOST_NAME_MAX;
#endif
return 64;
}
/*
* Constant strings for usage() functions. For more info see
* Documentation/howto-usage-function.txt and sys-utils/arch.c
*/
#define USAGE_HEADER _("\nUsage:\n")
#define USAGE_OPTIONS _("\nOptions:\n")
#define USAGE_SEPARATOR _("\n")
#define USAGE_HELP _(" -h, --help display this help and exit\n")
#define USAGE_VERSION _(" -V, --version output version information and exit\n")
#define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man
#define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
/*
* scanf modifiers for "strings allocation"
*/
#ifdef HAVE_SCANF_MS_MODIFIER
#define UL_SCNsA "%ms"
#elif defined(HAVE_SCANF_AS_MODIFIER)
#define UL_SCNsA "%as"
#endif
/*
* seek stuff
*/
#ifndef SEEK_DATA
# define SEEK_DATA 3
#endif
#ifndef SEEK_HOLE
# define SEEK_HOLE 4
#endif
#endif /* UTIL_LINUX_C_H */
+275
View File
@@ -0,0 +1,275 @@
/*
* 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%
*/
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include "blkidP.h"
#include "env.h"
int blkid_debug_mask = 0;
/**
* SECTION:cache
* @title: Cache
* @short_description: basic routines to work with libblkid cache
*
* Block device information is normally kept in a cache file blkid.tab and is
* verified to still be valid before being returned to the user (if the user has
* read permission on the raw block device, otherwise not). The cache file also
* allows unprivileged users (normally anyone other than root, or those not in the
* "disk" group) to locate devices by label/id. The standard location of the
* cache file can be overridden by the environment variable BLKID_FILE.
*
* In situations where one is getting information about a single known device, it
* does not impact performance whether the cache is used or not (unless you are
* not able to read the block device directly). If you are dealing with multiple
* devices, use of the cache is highly recommended (even if empty) as devices will
* be scanned at most one time and the on-disk cache will be updated if possible.
* There is rarely a reason not to use the cache.
*
* In some cases (modular kernels), block devices are not even visible until after
* they are accessed the first time, so it is critical that there is some way to
* locate these devices without enumerating only visible devices, so the use of
* the cache file is required in this situation.
*/
#if 0 /* ifdef CONFIG_BLKID_DEBUG */
static blkid_debug_dump_cache(int mask, blkid_cache cache)
{
struct list_head *p;
if (!cache) {
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);
blkid_debug_dump_dev(dev);
}
}
#endif
#ifdef CONFIG_BLKID_DEBUG
void blkid_init_debug(int mask)
{
if (blkid_debug_mask & DEBUG_INIT)
return;
if (!mask)
{
char *dstr = getenv("LIBBLKID_DEBUG");
if (!dstr)
dstr = getenv("BLKID_DEBUG"); /* for backward compatibility */
if (dstr)
blkid_debug_mask = strtoul(dstr, 0, 0);
} else
blkid_debug_mask = mask;
if (blkid_debug_mask)
printf("libblkid: debug mask set to 0x%04x.\n", blkid_debug_mask);
blkid_debug_mask |= DEBUG_INIT;
}
#endif
static const char *get_default_cache_filename(void)
{
struct stat st;
if (stat(BLKID_RUNTIME_TOPDIR, &st) == 0 && S_ISDIR(st.st_mode))
return BLKID_CACHE_FILE; /* cache in /run */
return BLKID_CACHE_FILE_OLD; /* cache in /etc */
}
/* returns allocated path to cache */
char *blkid_get_cache_filename(struct blkid_config *conf)
{
char *filename;
filename = safe_getenv("BLKID_FILE");
if (filename)
filename = strdup(filename);
else if (conf)
filename = conf->cachefile ? strdup(conf->cachefile) : NULL;
else {
struct blkid_config *c = blkid_read_config(NULL);
if (!c)
filename = strdup(get_default_cache_filename());
else {
filename = c->cachefile; /* already allocated */
c->cachefile = NULL;
blkid_free_config(c);
}
}
return filename;
}
/**
* blkid_get_cache:
* @cache: pointer to return cache handler
* @filename: path to the cache file or NULL for the default path
*
* Allocates and initialize librray cache handler.
*
* Returns: 0 on success or number less than zero in case of error.
*/
int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
{
blkid_cache cache;
if (!ret_cache)
return -BLKID_ERR_PARAM;
blkid_init_debug(0);
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 && !*filename)
filename = NULL;
if (filename)
cache->bic_filename = strdup(filename);
else
cache->bic_filename = blkid_get_cache_filename(NULL);
blkid_read_cache(cache);
*ret_cache = cache;
return 0;
}
/**
* blkid_put_cache:
* @cache: cache handler
*
* Saves changes to cache file.
*/
void blkid_put_cache(blkid_cache cache)
{
if (!cache)
return;
(void) blkid_flush_cache(cache);
DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
/* DBG(DEBUG_CACHE, blkid_debug_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);
}
blkid_free_probe(cache->probe);
free(cache->bic_filename);
free(cache);
}
/**
* blkid_gc_cache:
* @cache: cache handler
*
* Removes garbage (non-existing devices) from the cache.
*/
void blkid_gc_cache(blkid_cache cache)
{
struct list_head *p, *pnext;
struct stat st;
if (!cache)
return;
list_for_each_safe(p, pnext, &cache->bic_devs) {
blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
if (stat(dev->bid_name, &st) < 0) {
DBG(DEBUG_CACHE,
printf("freeing %s\n", dev->bid_name));
blkid_free_dev(dev);
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
} else {
DBG(DEBUG_CACHE,
printf("Device %s exists\n", dev->bid_name));
}
}
}
#ifdef TEST_PROGRAM
int main(int argc, char** argv)
{
blkid_cache cache = NULL;
int ret;
blkid_init_debug(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_get_cache_filename(NULL));
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
+247
View File
@@ -0,0 +1,247 @@
/*
* canonicalize.c -- canonicalize pathname by removing symlinks
* Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library Public License for more details.
*
*/
/*
* This routine is part of libc. We include it nevertheless,
* since the libc version has some security flaws.
*
* TODO: use canonicalize_file_name() when exist in glibc
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include "canonicalize.h"
#ifndef MAXSYMLINKS
# define MAXSYMLINKS 256
#endif
static char *
myrealpath(const char *path, char *resolved_path, int maxreslth) {
int readlinks = 0;
char *npath;
char link_path[PATH_MAX+1];
int n;
char *buf = NULL;
npath = resolved_path;
/* If it's a relative pathname use getcwd for starters. */
if (*path != '/') {
if (!getcwd(npath, maxreslth-2))
return NULL;
npath += strlen(npath);
if (npath[-1] != '/')
*npath++ = '/';
} else {
*npath++ = '/';
path++;
}
/* Expand each slash-separated pathname component. */
while (*path != '\0') {
/* Ignore stray "/" */
if (*path == '/') {
path++;
continue;
}
if (*path == '.' && (path[1] == '\0' || path[1] == '/')) {
/* Ignore "." */
path++;
continue;
}
if (*path == '.' && path[1] == '.' &&
(path[2] == '\0' || path[2] == '/')) {
/* Backup for ".." */
path += 2;
while (npath > resolved_path+1 &&
(--npath)[-1] != '/')
;
continue;
}
/* Safely copy the next pathname component. */
while (*path != '\0' && *path != '/') {
if (npath-resolved_path > maxreslth-2) {
errno = ENAMETOOLONG;
goto err;
}
*npath++ = *path++;
}
/* Protect against infinite loops. */
if (readlinks++ > MAXSYMLINKS) {
errno = ELOOP;
goto err;
}
/* See if last pathname component is a symlink. */
*npath = '\0';
n = readlink(resolved_path, link_path, PATH_MAX);
if (n < 0) {
/* EINVAL means the file exists but isn't a symlink. */
if (errno != EINVAL)
goto err;
} else {
int m;
char *newbuf;
/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
if (*link_path == '/')
/* Start over for an absolute symlink. */
npath = resolved_path;
else
/* Otherwise back up over this component. */
while (*(--npath) != '/')
;
/* Insert symlink contents into path. */
m = strlen(path);
newbuf = malloc(m + n + 1);
if (!newbuf)
goto err;
memcpy(newbuf, link_path, n);
memcpy(newbuf + n, path, m + 1);
free(buf);
path = buf = newbuf;
}
*npath++ = '/';
}
/* Delete trailing slash but don't whomp a lone slash. */
if (npath != resolved_path+1 && npath[-1] == '/')
npath--;
/* Make sure it's null terminated. */
*npath = '\0';
free(buf);
return resolved_path;
err:
free(buf);
return NULL;
}
/*
* Converts private "dm-N" names to "/dev/mapper/<name>"
*
* Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
* provides the real DM device names in /sys/block/<ptname>/dm/name
*/
char *
canonicalize_dm_name(const char *ptname)
{
FILE *f;
size_t sz;
char path[256], name[256], *res = NULL;
snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
if (!(f = fopen(path, "r")))
return NULL;
/* read "<name>\n" from sysfs */
if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
name[sz - 1] = '\0';
snprintf(path, sizeof(path), "/dev/mapper/%s", name);
res = strdup(path);
}
fclose(f);
return res;
}
char *
canonicalize_path(const char *path)
{
char canonical[PATH_MAX+2];
char *p;
if (path == NULL)
return NULL;
if (!myrealpath(path, canonical, PATH_MAX+1))
return strdup(path);
p = strrchr(canonical, '/');
if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
p = canonicalize_dm_name(p+1);
if (p)
return p;
}
return strdup(canonical);
}
char *
canonicalize_path_restricted(const char *path)
{
char canonical[PATH_MAX+2];
char *p = NULL;
int errsv;
uid_t euid;
gid_t egid;
if (path == NULL)
return NULL;
euid = geteuid();
egid = getegid();
/* drop permissions */
if (setegid(getgid()) < 0 || seteuid(getuid()) < 0)
return NULL;
errsv = errno = 0;
if (myrealpath(path, canonical, PATH_MAX+1)) {
p = strrchr(canonical, '/');
if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4)))
p = canonicalize_dm_name(p+1);
else
p = NULL;
if (!p)
p = strdup(canonical);
} else
errsv = errno;
/* restore */
if (setegid(egid) < 0 || seteuid(euid) < 0) {
free(p);
return NULL;
}
errno = errsv;
return p;
}
#ifdef TEST_PROGRAM_CANONICALIZE
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "usage: %s <device>\n", argv[0]);
exit(EXIT_FAILURE);
}
fprintf(stdout, "orig: %s\n", argv[1]);
fprintf(stdout, "real: %s\n", canonicalize_path(argv[1]));
exit(EXIT_SUCCESS);
}
#endif
+21
View File
@@ -0,0 +1,21 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library Public License for more details.
*/
#ifndef CANONICALIZE_H
#define CANONICALIZE_H
#include "c.h" /* for PATH_MAX */
extern char *canonicalize_path(const char *path);
extern char *canonicalize_path_restricted(const char *path);
extern char *canonicalize_dm_name(const char *ptname);
#endif /* CANONICALIZE_H */
+29
View File
@@ -0,0 +1,29 @@
#ifndef _CAREFUULPUTC_H
#define _CAREFUULPUTC_H
/* putc() for use in write and wall (that sometimes are sgid tty) */
/* Avoid control characters in our locale, and also ASCII control characters.
Note that the locale of the recipient is unknown. */
#include <stdio.h>
#include <ctype.h>
#define iso8859x_iscntrl(c) \
(((c) & 0x7f) < 0x20 || (c) == 0x7f)
static inline int carefulputc(int c, FILE *fp) {
int ret;
if (c == '\007' || c == '\t' || c == '\r' || c == '\n' ||
(!iso8859x_iscntrl(c) && (isprint(c) || isspace(c))))
ret = putc(c, fp);
else if ((c & 0x80) || !isprint(c^0x40))
ret = fprintf(fp, "\\%3o", (unsigned char) c);
else {
ret = putc('^', fp);
if (ret != EOF)
ret = putc(c^0x40, fp);
}
return (ret < 0) ? EOF : 0;
}
#endif /* _CAREFUULPUTC_H */
+51
View File
@@ -0,0 +1,51 @@
#ifndef UTIL_LINUX_CLOSESTREAM_H
#define UTIL_LINUX_CLOSESTREAM_H
#include <stdio.h>
#ifdef HAVE_STDIO_EXT_H
#include <stdio_ext.h>
#endif
#include <unistd.h>
#include "c.h"
#include "nls.h"
#ifndef HAVE___FPENDING
static inline int
__fpending(FILE *stream __attribute__((__unused__)))
{
return 0;
}
#endif
static inline int
close_stream(FILE * stream)
{
const int some_pending = (__fpending(stream) != 0);
const int prev_fail = (ferror(stream) != 0);
const int fclose_fail = (fclose(stream) != 0);
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
if (!fclose_fail)
errno = 0;
return EOF;
}
return 0;
}
/* Meant to be used atexit(close_stdout); */
static inline void
close_stdout(void)
{
if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
if (errno)
warn(_("write error"));
else
warnx(_("write error"));
_exit(EXIT_FAILURE);
}
if (close_stream(stderr) != 0)
_exit(EXIT_FAILURE);
}
#endif /* UTIL_LINUX_CLOSESTREAM_H */
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Ondrej Oprala <ooprala@redhat.com>
*
* This file may be distributed under the terms of the
* GNU Lesser General Public License.
*/
#include "colors.h"
static int ul_color_term_ok;
int colors_init(void)
{
ul_color_term_ok = isatty(STDOUT_FILENO);
return ul_color_term_ok;
}
void color_enable(const char *color_scheme)
{
if (ul_color_term_ok)
fputs(color_scheme, stdout);
}
void color_disable(void)
{
if (ul_color_term_ok)
fputs(UL_COLOR_RESET, stdout);
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2012 Ondrej Oprala <ooprala@redhat.com>
*
* This file may be distributed under the terms of the
* GNU Lesser General Public License.
*/
#ifndef UTIL_LINUX_COLORS_H
#define UTIL_LINUX_COLORS_H
#include <stdio.h>
#include <unistd.h>
#define UL_COLOR_RESET "\033[0m"
#define UL_COLOR_BOLD "\033[1m"
#define UL_COLOR_HALFBRIGHT "\033[2m"
#define UL_COLOR_UNDERSCORE "\033[4m"
#define UL_COLOR_BLINK "\033[5m"
#define UL_COLOR_REVERSE "\033[7m"
/* Standard colors */
#define UL_COLOR_BLACK "\033[30m"
#define UL_COLOR_RED "\033[31m"
#define UL_COLOR_GREEN "\033[32m"
#define UL_COLOR_YELLOW "\033[33m"
#define UL_COLOR_BLUE "\033[34m"
#define UL_COLOR_MAGENTA "\033[35m"
#define UL_COLOR_CYAN "\033[36m"
#define UL_COLOR_GRAY "\033[37m"
/* Bold variants */
#define UL_COLOR_DARK_GRAY "\033[1;30m"
#define UL_COLOR_BOLD_RED "\033[1;31m"
#define UL_COLOR_BOLD_GREEN "\033[1;32m"
#define UL_COLOR_BOLD_YELLOW "\033[1;33m"
#define UL_COLOR_BOLD_BLUE "\033[1;34m"
#define UL_COLOR_BOLD_MAGENTA "\033[1;35m"
#define UL_COLOR_BOLD_CYAN "\033[1;36m"
#define UL_COLOR_WHITE "\033[1;37m"
/* Initialize the global variable OUT_IS_TERM */
extern int colors_init(void);
/* Set the color to CLR_SCHEME */
extern void color_enable(const char *clr_scheme);
/* Reset colors to default */
extern void color_disable(void);
#endif /* UTIL_LINUX_COLORS_H */
+201
View File
@@ -0,0 +1,201 @@
/*
* config.c - blkid.conf routines
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <stdint.h>
#include <stdarg.h>
#include "blkidP.h"
#include "env.h"
static int parse_evaluate(struct blkid_config *conf, char *s)
{
while(s && *s) {
char *sep;
if (conf->nevals >= __BLKID_EVAL_LAST)
goto err;
sep = strchr(s, ',');
if (sep)
*sep = '\0';
if (strcmp(s, "udev") == 0)
conf->eval[conf->nevals] = BLKID_EVAL_UDEV;
else if (strcmp(s, "scan") == 0)
conf->eval[conf->nevals] = BLKID_EVAL_SCAN;
else
goto err;
conf->nevals++;
if (sep)
s = sep + 1;
else
break;
}
return 0;
err:
DBG(DEBUG_CONFIG, printf(
"config file: unknown evaluation method '%s'.\n", s));
return -1;
}
static int parse_next(FILE *fd, struct blkid_config *conf)
{
char buf[BUFSIZ];
char *s;
/* read the next non-blank non-comment line */
do {
if (fgets (buf, sizeof(buf), fd) == NULL)
return feof(fd) ? 0 : -1;
s = strchr (buf, '\n');
if (!s) {
/* Missing final newline? Otherwise extremely */
/* long line - assume file was corrupted */
if (feof(fd))
s = strchr (buf, '\0');
else {
DBG(DEBUG_CONFIG, fprintf(stderr,
"libblkid: config file: missing newline at line '%s'.\n",
buf));
return -1;
}
}
*s = '\0';
if (--s >= buf && *s == '\r')
*s = '\0';
s = buf;
while (*s == ' ' || *s == '\t') /* skip space */
s++;
} while (*s == '\0' || *s == '#');
if (!strncmp(s, "SEND_UEVENT=", 12)) {
s += 13;
if (*s && !strcasecmp(s, "yes"))
conf->uevent = TRUE;
else if (*s)
conf->uevent = FALSE;
} else if (!strncmp(s, "CACHE_FILE=", 11)) {
s += 11;
if (*s)
conf->cachefile = strdup(s);
} else if (!strncmp(s, "EVALUATE=", 9)) {
s += 9;
if (*s && parse_evaluate(conf, s) == -1)
return -1;
} else {
DBG(DEBUG_CONFIG, printf(
"config file: unknown option '%s'.\n", s));
return -1;
}
return 0;
}
/* return real config data or built-in default */
struct blkid_config *blkid_read_config(const char *filename)
{
struct blkid_config *conf;
FILE *f;
if (!filename)
filename = safe_getenv("BLKID_CONF");
if (!filename)
filename = BLKID_CONFIG_FILE;
conf = (struct blkid_config *) calloc(1, sizeof(*conf));
if (!conf)
return NULL;
conf->uevent = -1;
DBG(DEBUG_CONFIG, fprintf(stderr,
"reading config file: %s.\n", filename));
f = fopen(filename, "r");
if (!f) {
DBG(DEBUG_CONFIG, fprintf(stderr,
"%s: does not exist, using built-in default\n", filename));
goto dflt;
}
while (!feof(f)) {
if (parse_next(f, conf)) {
DBG(DEBUG_CONFIG, fprintf(stderr,
"%s: parse error\n", filename));
goto err;
}
}
dflt:
if (!conf->nevals) {
conf->eval[0] = BLKID_EVAL_UDEV;
conf->eval[1] = BLKID_EVAL_SCAN;
conf->nevals = 2;
}
if (!conf->cachefile)
conf->cachefile = strdup(BLKID_CACHE_FILE);
if (conf->uevent == -1)
conf->uevent = TRUE;
if (f)
fclose(f);
return conf;
err:
free(conf);
fclose(f);
return NULL;
}
void blkid_free_config(struct blkid_config *conf)
{
if (!conf)
return;
free(conf->cachefile);
free(conf);
}
#ifdef TEST_PROGRAM
/*
* usage: tst_config [<filename>]
*/
int main(int argc, char *argv[])
{
int i;
struct blkid_config *conf;
char *filename = NULL;
blkid_init_debug(DEBUG_ALL);
if (argc == 2)
filename = argv[1];
conf = blkid_read_config(filename);
if (!conf)
return EXIT_FAILURE;
printf("EVALUATE: ");
for (i = 0; i < conf->nevals; i++)
printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan");
printf("\n");
printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE");
printf("CACHE_FILE: %s\n", conf->cachefile);
blkid_free_config(conf);
return EXIT_SUCCESS;
}
#endif
+654
View File
@@ -0,0 +1,654 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Should chfn and chsh require the user to enter the password? */
#define CHFN_CHSH_PASSWORD 1
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#define ENABLE_NLS 1
/* search path for fs helpers */
#define FS_SEARCH_PATH "/sbin:/sbin/fs.d:/sbin/fs"
/* Define to 1 if you have the <asm/io.h> header file. */
/* #undef HAVE_ASM_IO_H */
/* Define to 1 if you have the <byteswap.h> header file. */
#define HAVE_BYTESWAP_H 1
/* Define to 1 if the system has the type `cpu_set_t'. */
#define HAVE_CPU_SET_T 1
/* Define to 1 if you have the <crypt.h> header file. */
#define HAVE_CRYPT_H 1
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
#define HAVE_DCGETTEXT 1
/* Define to 1 if you have the declaration of `ADDR_COMPAT_LAYOUT', and to 0
if you don't. */
#define HAVE_DECL_ADDR_COMPAT_LAYOUT 1
/* Define to 1 if you have the declaration of `ADDR_LIMIT_32BIT', and to 0 if
you don't. */
#define HAVE_DECL_ADDR_LIMIT_32BIT 1
/* Define to 1 if you have the declaration of `ADDR_LIMIT_3GB', and to 0 if
you don't. */
#define HAVE_DECL_ADDR_LIMIT_3GB 1
/* Define to 1 if you have the declaration of `ADDR_NO_RANDOMIZE', and to 0 if
you don't. */
#define HAVE_DECL_ADDR_NO_RANDOMIZE 1
/* Define to 1 if you have the declaration of `CPU_ALLOC', and to 0 if you
don't. */
#define HAVE_DECL_CPU_ALLOC 1
/* Define to 1 if you have the declaration of `dirfd', and to 0 if you don't.
*/
/* #undef HAVE_DECL_DIRFD */
/* Define to 1 if you have the declaration of `FDPIC_FUNCPTRS', and to 0 if
you don't. */
#define HAVE_DECL_FDPIC_FUNCPTRS 1
/* Define to 1 if you have the declaration of `MMAP_PAGE_ZERO', and to 0 if
you don't. */
#define HAVE_DECL_MMAP_PAGE_ZERO 1
/* Define to 1 if you have the declaration of `READ_IMPLIES_EXEC', and to 0 if
you don't. */
#define HAVE_DECL_READ_IMPLIES_EXEC 1
/* Define to 1 if you have the declaration of `STICKY_TIMEOUTS', and to 0 if
you don't. */
#define HAVE_DECL_STICKY_TIMEOUTS 1
/* Define to 1 if you have the declaration of `UNAME26', and to 0 if you
don't. */
#define HAVE_DECL_UNAME26 1
/* Define to 1 if you have the declaration of `WHOLE_SECONDS', and to 0 if you
don't. */
#define HAVE_DECL_WHOLE_SECONDS 1
/* Define to 1 if you have the declaration of `_NL_TIME_WEEK_1STDAY', and to 0
if you don't. */
#define HAVE_DECL__NL_TIME_WEEK_1STDAY 1
/* Define to 1 if you have the `dirfd' function. */
#define HAVE_DIRFD 1
/* Define to 1 if `dd_fd' is a member of `DIR'. */
/* #undef HAVE_DIR_DD_FD */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <endian.h> header file. */
#define HAVE_ENDIAN_H 1
/* Define to 1 if have **environ prototype */
#define HAVE_ENVIRON_DECL 1
/* Define to 1 if you have the `err' function. */
#define HAVE_ERR 1
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the `errx' function. */
#define HAVE_ERRX 1
/* Define to 1 if you have the <err.h> header file. */
#define HAVE_ERR_H 1
/* Have valid fallocate() function */
#define HAVE_FALLOCATE 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1
/* Define to 1 if you have the `fstatat' function. */
#define HAVE_FSTATAT 1
/* Define to 1 if you have the `fsync' function. */
#define HAVE_FSYNC 1
/* Define to 1 if you have the `futimens' function. */
#define HAVE_FUTIMENS 1
/* Define to 1 if you have the `getdomainname' function. */
#define HAVE_GETDOMAINNAME 1
/* Define to 1 if you have the `getdtablesize' function. */
#define HAVE_GETDTABLESIZE 1
/* Define to 1 if you have the `getexecname' function. */
/* #undef HAVE_GETEXECNAME */
/* Define to 1 if you have the `getmntinfo' function. */
/* #undef HAVE_GETMNTINFO */
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getrlimit' function. */
#define HAVE_GETRLIMIT 1
/* Define if the GNU gettext() function is already present or preinstalled. */
#define HAVE_GETTEXT 1
/* Define if you have the iconv() function. */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the `inotify_init' function. */
#define HAVE_INOTIFY_INIT 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `ioperm' function. */
#define HAVE_IOPERM 1
/* Define to 1 if you have the `iopl' function. */
#define HAVE_IOPL 1
/* Define to 1 if you have the `jrand48' function. */
#define HAVE_JRAND48 1
/* Define to 1 if you have the <langinfo.h> header file. */
#define HAVE_LANGINFO_H 1
/* Define to 1 if you have the `lchown' function. */
#define HAVE_LCHOWN 1
/* Define to 1 if you have the `audit' library (-laudit). */
/* #undef HAVE_LIBAUDIT */
/* Define to 1 if you have the -lblkid. */
#define HAVE_LIBBLKID 1
/* Define to 1 if you have the `cap-ng' library (-lcap-ng). */
/* #undef HAVE_LIBCAP_NG */
/* Do we need -lcrypt? */
#define HAVE_LIBCRYPT 1
/* Define to 1 if you have the `ncurses' library (-lncurses). */
#define HAVE_LIBNCURSES 1
/* Define to 1 if you have the `ncursesw' library (-lncursesw). */
/* #undef HAVE_LIBNCURSESW */
/* Define if SELinux is available */
/* #undef HAVE_LIBSELINUX */
/* Define to 1 if you have the `termcap' library (-ltermcap). */
#define HAVE_LIBTERMCAP 1
/* Define to 1 if you have the `udev' library (-ludev). */
/* #undef HAVE_LIBUDEV */
/* Define to 1 if you have the `user' library (-luser). */
/* #undef HAVE_LIBUSER */
/* Define to 1 if you have the `utempter' library (-lutempter). */
/* #undef HAVE_LIBUTEMPTER */
/* Define to 1 if you have the `util' library (-lutil). */
#define HAVE_LIBUTIL 1
/* Define to 1 if you have the -luuid. */
#define HAVE_LIBUUID 1
/* Define to 1 if you have the <linux/blkpg.h> header file. */
#define HAVE_LINUX_BLKPG_H 1
/* Define to 1 if you have the <linux/cdrom.h> header file. */
#define HAVE_LINUX_CDROM_H 1
/* Define to 1 if you have the <linux/compiler.h> header file. */
/* #undef HAVE_LINUX_COMPILER_H */
/* Define to 1 if you have the <linux/falloc.h> header file. */
#define HAVE_LINUX_FALLOC_H 1
/* Define to 1 if you have the <linux/fd.h> header file. */
#define HAVE_LINUX_FD_H 1
/* Define to 1 if you have the <linux/major.h> header file. */
#define HAVE_LINUX_MAJOR_H 1
/* Define to 1 if you have the <linux/raw.h> header file. */
#define HAVE_LINUX_RAW_H 1
/* Define to 1 if you have the <linux/tiocl.h> header file. */
#define HAVE_LINUX_TIOCL_H 1
/* Define to 1 if you have the <linux/version.h> header file. */
#define HAVE_LINUX_VERSION_H 1
/* Define to 1 if you have the <linux/watchdog.h> header file. */
#define HAVE_LINUX_WATCHDOG_H 1
/* Define to 1 if you have the `llseek' function. */
#define HAVE_LLSEEK 1
/* Define to 1 if have llseek prototype */
/* #undef HAVE_LLSEEK_PROTOTYPE */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if the system has the type `loff_t'. */
#define HAVE_LOFF_T 1
/* Define to 1 if you have the `lseek64' function. */
#define HAVE_LSEEK64 1
/* Define to 1 if have lseek64 prototype */
#define HAVE_LSEEK64_PROTOTYPE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mempcpy' function. */
#define HAVE_MEMPCPY 0
/* Define to 1 if you have the <mntent.h> header file. */
#define HAVE_MNTENT_H 1
/* Define to 1 if you have the `nanosleep' function. */
#define HAVE_NANOSLEEP 1
/* Define to 1 if you have the <ncursesw/ncurses.h> header file. */
/* #undef HAVE_NCURSESW_NCURSES_H */
/* Define to 1 if you have the <ncurses.h> header file. */
#define HAVE_NCURSES_H 1
/* Define to 1 if you have the <ncurses/ncurses.h> header file. */
/* #undef HAVE_NCURSES_NCURSES_H */
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <net/if_dl.h> header file. */
/* #undef HAVE_NET_IF_DL_H */
/* Define to 1 if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
/* Define to 1 if you have the `openat' function. */
#define HAVE_OPENAT 1
/* Define to 1 if you have the <paths.h> header file. */
#define HAVE_PATHS_H 1
/* Define to 1 if you have the `personality' function. */
#define HAVE_PERSONALITY 1
/* Define to 1 if you have the `posix_fadvise' function. */
#define HAVE_POSIX_FADVISE 1
/* Define to 1 if you have the `prctl' function. */
#define HAVE_PRCTL 1
/* Define to 1 if you have the `prlimit' function. */
#define HAVE_PRLIMIT 1
/* Define if program_invocation_short_name is defined */
#define HAVE_PROGRAM_INVOCATION_SHORT_NAME 1
/* Define to 1 if you have the <pty.h> header file. */
#define HAVE_PTY_H 1
/* Define to 1 if you have the `rpmatch' function. */
#define HAVE_RPMATCH 1
/* Define if struct sockaddr contains sa_len */
/* #undef HAVE_SA_LEN */
/* Define to 1 if you have the `scandirat' function. */
#define HAVE_SCANDIRAT 1
/* scanf %as modifier */
/* #undef HAVE_SCANF_AS_MODIFIER */
/* scanf %ms modifier */
#define HAVE_SCANF_MS_MODIFIER 1
/* Define to 1 if you have the `secure_getenv' function. */
/* #undef HAVE_SECURE_GETENV */
/* Define to 1 if you have the <security/pam_misc.h> header file. */
#define HAVE_SECURITY_PAM_MISC_H 1
/* Define to 1 if you have the `setns' function. */
#define HAVE_SETNS 1
/* Define to 1 if you have the `setresgid' function. */
#define HAVE_SETRESGID 1
/* Define to 1 if you have the `setresuid' function. */
#define HAVE_SETRESUID 1
/* Define to 1 if you have the `sigqueue' function. */
#define HAVE_SIGQUEUE 1
/* Define to 1 if you have the <slang.h> header file. */
/* #undef HAVE_SLANG_H */
/* Define to 1 if you have the <slang/slang.h> header file. */
/* #undef HAVE_SLANG_SLANG_H */
/* Define to 1 if you have the <slang/slcurses.h> header file. */
/* #undef HAVE_SLANG_SLCURSES_H */
/* Define to 1 if you have the <slcurses.h> header file. */
/* #undef HAVE_SLCURSES_H */
/* Define to 1 if you have the `srandom' function. */
#define HAVE_SRANDOM 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio_ext.h> header file. */
#define HAVE_STDIO_EXT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strnchr' function. */
/* #undef HAVE_STRNCHR */
/* Define to 1 if you have the `strndup' function. */
#define HAVE_STRNDUP 1
/* Define to 1 if you have the `strnlen' function. */
#define HAVE_STRNLEN 1
/* Define to 1 if have strsignal function prototype */
#define HAVE_STRSIGNAL_DECL 1
/* Define to 1 if you have the `strtoull' function. */
#define HAVE_STRTOULL 1
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
/* Define to 1 if `c_line' is a member of `struct termios'. */
#define HAVE_STRUCT_TERMIOS_C_LINE 1
/* Define to 1 if you have the `sysconf' function. */
#define HAVE_SYSCONF 1
/* Define to 1 if you have the <sys/disklabel.h> header file. */
/* #undef HAVE_SYS_DISKLABEL_H */
/* Define to 1 if you have the <sys/disk.h> header file. */
/* #undef HAVE_SYS_DISK_H */
/* Define to 1 if you have the <sys/endian.h> header file. */
/* #undef HAVE_SYS_ENDIAN_H */
/* Define to 1 if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
/* Define to 1 if you have the <sys/ioccom.h> header file. */
/* #undef HAVE_SYS_IOCCOM_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/io.h> header file. */
#define HAVE_SYS_IO_H 1
/* Define to 1 if you have the <sys/mkdev.h> header file. */
/* #undef HAVE_SYS_MKDEV_H */
/* Define to 1 if you have the <sys/prctl.h> header file. */
#define HAVE_SYS_PRCTL_H 1
/* Define to 1 if you have the <sys/queue.h> header file. */
#define HAVE_SYS_QUEUE_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/sockio.h> header file. */
/* #undef HAVE_SYS_SOCKIO_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/swap.h> header file. */
#define HAVE_SYS_SWAP_H 1
/* Define to 1 if you have the <sys/syscall.h> header file. */
#define HAVE_SYS_SYSCALL_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/un.h> header file. */
#define HAVE_SYS_UN_H 1
/* Define to 1 if the target supports thread-local storage. */
#define HAVE_TLS 1
/* Does struct tm have a field tm_gmtoff? */
#define HAVE_TM_GMTOFF 1
/* Define to 1 if the system has the type `union semun'. */
/* #undef HAVE_UNION_SEMUN */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `unlinkat' function. */
#define HAVE_UNLINKAT 1
/* Define to 1 if you have the `unshare' function. */
#define HAVE_UNSHARE 1
/* Define to 1 if you have the `updwtmp' function. */
#define HAVE_UPDWTMP 1
/* Define to 1 if you have the `usleep' function. */
#define HAVE_USLEEP 1
/* Define to 1 if you want to use uuid daemon. */
#define HAVE_UUIDD 1
/* Define to 1 if you have the `warn' function. */
#define HAVE_WARN 1
/* Define to 1 if you have the `warnx' function. */
#define HAVE_WARNX 1
/* Do we have wide character support? */
#define HAVE_WIDECHAR 1
/* Define to 1 if you have the `__fpending' function. */
#define HAVE___FPENDING 1
/* Define if __progname is defined */
#define HAVE___PROGNAME 1
/* Define to 1 if you have the `__secure_getenv' function. */
#define HAVE___SECURE_GETENV 1
/* libblkid date string */
#define LIBBLKID_DATE "04-Sep-2012"
/* libblkid version string */
#define LIBBLKID_VERSION "2.22.0"
/* libmount version string */
#define LIBMOUNT_VERSION "2.22.0"
/* Should login chown /dev/vcsN? */
/* #undef LOGIN_CHOWN_VCS */
/* Should login stat() the mailbox? */
/* #undef LOGIN_STAT_MAIL */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Should chsh allow only shells in /etc/shells? */
#define ONLY_LISTED_SHELLS 1
/* Name of package */
#define PACKAGE "util-linux"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "kzak@redhat.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "util-linux"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "util-linux 2.22.552-d48f6"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "util-linux"
/* Define to the home page for this package. */
#define PACKAGE_URL "http://www.kernel.org/pub/linux/utils/util-linux/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.22.552-d48f6"
/* Should pg ring the bell on invalid keys? */
#define PG_BELL 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Is swapon() declared with two parameters? */
#define SWAPON_HAS_TWO_ARGS 1
/* Fallback syscall number for fallocate */
/* #undef SYS_fallocate */
/* Fallback syscall number for ioprio_get */
/* #undef SYS_ioprio_get */
/* Fallback syscall number for ioprio_set */
/* #undef SYS_ioprio_set */
/* Fallback syscall number for pivot_root */
/* #undef SYS_pivot_root */
/* Fallback syscall number for prlimit64 */
/* #undef SYS_prlimit64 */
/* Fallback syscall number for sched_getaffinity */
/* #undef SYS_sched_getaffinity */
/* Fallback syscall number for setns */
/* #undef SYS_setns */
/* Fallback syscall number for unshare */
/* #undef SYS_unshare */
/* Should uuidd support socket activation? */
/* #undef USE_SOCKET_ACTIVATION */
/* Should sulogin use a emergency mount of /dev and /proc? */
/* #undef USE_SULOGIN_EMERGENCY_MOUNT */
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Should wall and write be installed setgid tty? */
#define USE_TTY_GROUP 1
/* Version number of package */
#define VERSION "2.22.552-d48f6"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */
+402
View File
@@ -0,0 +1,402 @@
/*
* Terminology:
*
* cpuset - (libc) cpu_set_t data structure represents set of CPUs
* cpumask - string with hex mask (e.g. "0x00000001")
* cpulist - string with CPU ranges (e.g. "0-3,5,7,8")
*
* Based on code from taskset.c and Linux kernel.
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <sys/syscall.h>
#include "cpuset.h"
#include "c.h"
static inline int val_to_char(int v)
{
if (v >= 0 && v < 10)
return '0' + v;
else if (v >= 10 && v < 16)
return ('a' - 10) + v;
else
return -1;
}
static inline int char_to_val(int c)
{
int cl;
cl = tolower(c);
if (c >= '0' && c <= '9')
return c - '0';
else if (cl >= 'a' && cl <= 'f')
return cl + (10 - 'a');
else
return -1;
}
static const char *nexttoken(const char *q, int sep)
{
if (q)
q = strchr(q, sep);
if (q)
q++;
return q;
}
/*
* Number of bits in a CPU bitmask on current system
*/
int get_max_number_of_cpus(void)
{
#ifdef SYS_sched_getaffinity
int n, cpus = 2048;
size_t setsize;
cpu_set_t *set = cpuset_alloc(cpus, &setsize, NULL);
if (!set)
return -1; /* error */
for (;;) {
CPU_ZERO_S(setsize, set);
/* the library version does not return size of cpumask_t */
n = syscall(SYS_sched_getaffinity, 0, setsize, set);
if (n < 0 && errno == EINVAL && cpus < 1024 * 1024) {
cpuset_free(set);
cpus *= 2;
set = cpuset_alloc(cpus, &setsize, NULL);
if (!set)
return -1; /* error */
continue;
}
cpuset_free(set);
return n * 8;
}
#endif
return -1;
}
/*
* Allocates a new set for ncpus and returns size in bytes and size in bits
*/
cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits)
{
cpu_set_t *set = CPU_ALLOC(ncpus);
if (!set)
return NULL;
if (setsize)
*setsize = CPU_ALLOC_SIZE(ncpus);
if (nbits)
*nbits = cpuset_nbits(CPU_ALLOC_SIZE(ncpus));
return set;
}
void cpuset_free(cpu_set_t *set)
{
CPU_FREE(set);
}
#if !HAVE_DECL_CPU_ALLOC
/* Please, use CPU_COUNT_S() macro. This is fallback */
int __cpuset_count_s(size_t setsize, const cpu_set_t *set)
{
int s = 0;
const __cpu_mask *p = set->__bits;
const __cpu_mask *end = &set->__bits[setsize / sizeof (__cpu_mask)];
while (p < end) {
__cpu_mask l = *p++;
if (l == 0)
continue;
# if LONG_BIT > 32
l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul);
l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul);
l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful);
l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful);
l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful);
l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful);
# else
l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul);
l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul);
l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful);
l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful);
l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful);
# endif
s += l;
}
return s;
}
#endif
/*
* Returns human readable representation of the cpuset. The output format is
* a list of CPUs with ranges (for example, "0,1,3-9").
*/
char *cpulist_create(char *str, size_t len,
cpu_set_t *set, size_t setsize)
{
size_t i;
char *ptr = str;
int entry_made = 0;
size_t max = cpuset_nbits(setsize);
for (i = 0; i < max; i++) {
if (CPU_ISSET_S(i, setsize, set)) {
int rlen;
size_t j, run = 0;
entry_made = 1;
for (j = i + 1; j < max; j++) {
if (CPU_ISSET_S(j, setsize, set))
run++;
else
break;
}
if (!run)
rlen = snprintf(ptr, len, "%zd,", i);
else if (run == 1) {
rlen = snprintf(ptr, len, "%zd,%zd,", i, i + 1);
i++;
} else {
rlen = snprintf(ptr, len, "%zd-%zd,", i, i + run);
i += run;
}
if (rlen < 0 || (size_t) rlen + 1 > len)
return NULL;
ptr += rlen;
if (rlen > 0 && len > (size_t) rlen)
len -= rlen;
else
len = 0;
}
}
ptr -= entry_made;
*ptr = '\0';
return str;
}
/*
* Returns string with CPU mask.
*/
char *cpumask_create(char *str, size_t len,
cpu_set_t *set, size_t setsize)
{
char *ptr = str;
char *ret = NULL;
int cpu;
for (cpu = cpuset_nbits(setsize) - 4; cpu >= 0; cpu -= 4) {
char val = 0;
if (len == (size_t) (ptr - str))
break;
if (CPU_ISSET_S(cpu, setsize, set))
val |= 1;
if (CPU_ISSET_S(cpu + 1, setsize, set))
val |= 2;
if (CPU_ISSET_S(cpu + 2, setsize, set))
val |= 4;
if (CPU_ISSET_S(cpu + 3, setsize, set))
val |= 8;
if (!ret && val)
ret = ptr;
*ptr++ = val_to_char(val);
}
*ptr = '\0';
return ret ? ret : ptr - 1;
}
/*
* Parses string with CPUs mask.
*/
int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize)
{
int len = strlen(str);
const char *ptr = str + len - 1;
int cpu = 0;
/* skip 0x, it's all hex anyway */
if (len > 1 && !memcmp(str, "0x", 2L))
str += 2;
CPU_ZERO_S(setsize, set);
while (ptr >= str) {
char val;
/* cpu masks in /sys uses comma as a separator */
if (*ptr == ',')
ptr--;
val = char_to_val(*ptr);
if (val == (char) -1)
return -1;
if (val & 1)
CPU_SET_S(cpu, setsize, set);
if (val & 2)
CPU_SET_S(cpu + 1, setsize, set);
if (val & 4)
CPU_SET_S(cpu + 2, setsize, set);
if (val & 8)
CPU_SET_S(cpu + 3, setsize, set);
len--;
ptr--;
cpu += 4;
}
return 0;
}
/*
* Parses string with list of CPU ranges.
* Returns 0 on success.
* Returns 1 on error.
* Returns 2 if fail is set and a cpu number passed in the list doesn't fit
* into the cpu_set. If fail is not set cpu numbers that do not fit are
* ignored and 0 is returned instead.
*/
int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
{
size_t max = cpuset_nbits(setsize);
const char *p, *q;
int r = 0;
q = str;
CPU_ZERO_S(setsize, set);
while (p = q, q = nexttoken(q, ','), p) {
unsigned int a; /* beginning of range */
unsigned int b; /* end of range */
unsigned int s; /* stride */
const char *c1, *c2;
char c;
if ((r = sscanf(p, "%u%c", &a, &c)) < 1)
return 1;
b = a;
s = 1;
c1 = nexttoken(p, '-');
c2 = nexttoken(p, ',');
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
if ((r = sscanf(c1, "%u%c", &b, &c)) < 1)
return 1;
c1 = nexttoken(c1, ':');
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
if ((r = sscanf(c1, "%u%c", &s, &c)) < 1)
return 1;
if (s == 0)
return 1;
}
}
if (!(a <= b))
return 1;
while (a <= b) {
if (fail && (a >= max))
return 2;
CPU_SET_S(a, setsize, set);
a += s;
}
}
if (r == 2)
return 1;
return 0;
}
#ifdef TEST_PROGRAM
#include <getopt.h>
int main(int argc, char *argv[])
{
cpu_set_t *set;
size_t setsize, buflen, nbits;
char *buf, *mask = NULL, *range = NULL;
int ncpus = 2048, rc, c;
static const struct option longopts[] = {
{ "ncpus", 1, 0, 'n' },
{ "mask", 1, 0, 'm' },
{ "range", 1, 0, 'r' },
{ NULL, 0, 0, 0 }
};
while ((c = getopt_long(argc, argv, "n:m:r:", longopts, NULL)) != -1) {
switch(c) {
case 'n':
ncpus = atoi(optarg);
break;
case 'm':
mask = strdup(optarg);
break;
case 'r':
range = strdup(optarg);
break;
default:
goto usage_err;
}
}
if (!mask && !range)
goto usage_err;
set = cpuset_alloc(ncpus, &setsize, &nbits);
if (!set)
err(EXIT_FAILURE, "failed to allocate cpu set");
/*
fprintf(stderr, "ncpus: %d, cpuset bits: %zd, cpuset bytes: %zd\n",
ncpus, nbits, setsize);
*/
buflen = 7 * nbits;
buf = malloc(buflen);
if (!buf)
err(EXIT_FAILURE, "failed to allocate cpu set buffer");
if (mask)
rc = cpumask_parse(mask, set, setsize);
else
rc = cpulist_parse(range, set, setsize, 0);
if (rc)
errx(EXIT_FAILURE, "failed to parse string: %s", mask ? : range);
printf("%-15s = %15s ", mask ? : range,
cpumask_create(buf, buflen, set, setsize));
printf("[%s]\n", cpulist_create(buf, buflen, set, setsize));
free(buf);
free(range);
cpuset_free(set);
return EXIT_SUCCESS;
usage_err:
fprintf(stderr,
"usage: %s [--ncpus <num>] --mask <mask> | --range <list>",
program_invocation_short_name);
exit(EXIT_FAILURE);
}
#endif
+99
View File
@@ -0,0 +1,99 @@
/*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#ifndef UTIL_LINUX_CPUSET_H
#define UTIL_LINUX_CPUSET_H
#include <sched.h>
/*
* Fallback for old or obscure libcs without dynamically allocated cpusets
*
* The following macros are based on code from glibc.
*
* The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*/
#if !HAVE_DECL_CPU_ALLOC
# define CPU_ZERO_S(setsize, cpusetp) \
do { \
size_t __i; \
size_t __imax = (setsize) / sizeof (__cpu_mask); \
__cpu_mask *__bits = (cpusetp)->__bits; \
for (__i = 0; __i < __imax; ++__i) \
__bits[__i] = 0; \
} while (0)
# define CPU_SET_S(cpu, setsize, cpusetp) \
({ size_t __cpu = (cpu); \
__cpu < 8 * (setsize) \
? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
|= __CPUMASK (__cpu)) \
: 0; })
# define CPU_ISSET_S(cpu, setsize, cpusetp) \
({ size_t __cpu = (cpu); \
__cpu < 8 * (setsize) \
? ((((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
& __CPUMASK (__cpu))) != 0 \
: 0; })
# define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
({ __cpu_mask *__arr1 = (cpusetp1)->__bits; \
__cpu_mask *__arr2 = (cpusetp2)->__bits; \
size_t __imax = (setsize) / sizeof (__cpu_mask); \
size_t __i; \
for (__i = 0; __i < __imax; ++__i) \
if (__arr1[__i] != __arr2[__i]) \
break; \
__i == __imax; })
extern int __cpuset_count_s(size_t setsize, const cpu_set_t *set);
# define CPU_COUNT_S(setsize, cpusetp) __cpuset_count_s(setsize, cpusetp)
# define CPU_ALLOC_SIZE(count) \
((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask))
# define CPU_ALLOC(count) (malloc(CPU_ALLOC_SIZE(count)))
# define CPU_FREE(cpuset) (free(cpuset))
#endif /* !HAVE_DECL_CPU_ALLOC */
#define cpuset_nbits(setsize) (8 * (setsize))
/*
* The @idx parametr returns an index of the first mask from @ary array where
* the @cpu is set.
*
* Returns: 0 if found, otherwise 1.
*/
static inline int cpuset_ary_isset(size_t cpu, cpu_set_t **ary, size_t nmemb,
size_t setsize, size_t *idx)
{
size_t i;
for (i = 0; i < nmemb; i++) {
if (CPU_ISSET_S(cpu, setsize, ary[i])) {
*idx = i;
return 0;
}
}
return 1;
}
extern int get_max_number_of_cpus(void);
extern cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits);
extern void cpuset_free(cpu_set_t *set);
extern char *cpulist_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail);
extern char *cpumask_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
extern int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize);
#endif /* UTIL_LINUX_CPUSET_H */
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (C) 1999 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2001 by Andreas Dilger
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct cramfs_super
{
uint8_t magic[4];
uint32_t size;
uint32_t flags;
uint32_t future;
uint8_t signature[16];
struct cramfs_info
{
uint32_t crc;
uint32_t edition;
uint32_t blocks;
uint32_t files;
} __attribute__((packed)) info;
uint8_t name[16];
} __attribute__((packed));
static int probe_cramfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct cramfs_super *cs;
cs = blkid_probe_get_sb(pr, mag, struct cramfs_super);
if (!cs)
return -1;
blkid_probe_set_label(pr, cs->name, sizeof(cs->name));
return 0;
}
const struct blkid_idinfo cramfs_idinfo =
{
.name = "cramfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_cramfs,
.magics =
{
{ "\x45\x3d\xcd\x28", 4, 0, 0 },
{ "\x28\xcd\x3d\x45", 4, 0, 0 },
{ NULL }
}
};
+116
View File
@@ -0,0 +1,116 @@
/*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1.
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way,
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly.
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera-
* tions for all combinations of data and CRC register values.
*
* The values must be right-shifted by eight bits by the "updcrc"
* logic; the shift must be unsigned (bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions.
* polynomial $edb88320
*
*/
#include <stdio.h>
#include "crc32.h"
static const uint32_t crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/*
* This a generic crc32() function, it takes seed as an argument,
* and does __not__ xor at the end. Then individual users can do
* whatever they need.
*/
uint32_t crc32(uint32_t seed, const unsigned char *buf, size_t len)
{
uint32_t crc = seed;
const unsigned char *p = buf;
while(len-- > 0)
crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef UL_NG_CRC32_H
#define UL_NG_CRC32_H
#include <stdint.h>
extern uint32_t crc32(uint32_t seed, const unsigned char *buf, size_t len);
#endif
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
/* http://www.snia.org/standards/home */
#define DDF_GUID_LENGTH 24
#define DDF_REV_LENGTH 8
#define DDF_MAGIC 0xDE11DE11
struct ddf_header {
uint32_t signature;
uint32_t crc;
uint8_t guid[DDF_GUID_LENGTH];
char ddf_rev[8]; /* 01.02.00 */
uint32_t seq; /* starts at '1' */
uint32_t timestamp;
uint8_t openflag;
uint8_t foreignflag;
uint8_t enforcegroups;
uint8_t pad0; /* 0xff */
uint8_t pad1[12]; /* 12 * 0xff */
/* 64 bytes so far */
uint8_t header_ext[32]; /* reserved: fill with 0xff */
uint64_t primary_lba;
uint64_t secondary_lba;
uint8_t type;
uint8_t pad2[3]; /* 0xff */
uint32_t workspace_len; /* sectors for vendor space -
* at least 32768(sectors) */
uint64_t workspace_lba;
uint16_t max_pd_entries; /* one of 15, 63, 255, 1023, 4095 */
uint16_t max_vd_entries; /* 2^(4,6,8,10,12)-1 : i.e. as above */
uint16_t max_partitions; /* i.e. max num of configuration
record entries per disk */
uint16_t config_record_len; /* 1 +ROUNDUP(max_primary_element_entries
*12/512) */
uint16_t max_primary_element_entries; /* 16, 64, 256, 1024, or 4096 */
uint8_t pad3[54]; /* 0xff */
/* 192 bytes so far */
uint32_t controller_section_offset;
uint32_t controller_section_length;
uint32_t phys_section_offset;
uint32_t phys_section_length;
uint32_t virt_section_offset;
uint32_t virt_section_length;
uint32_t config_section_offset;
uint32_t config_section_length;
uint32_t data_section_offset;
uint32_t data_section_length;
uint32_t bbm_section_offset;
uint32_t bbm_section_length;
uint32_t diag_space_offset;
uint32_t diag_space_length;
uint32_t vendor_offset;
uint32_t vendor_length;
/* 256 bytes so far */
uint8_t pad4[256]; /* 0xff */
} __attribute__((packed));
static int probe_ddf(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
int hdrs[] = { 1, 257 };
size_t i;
struct ddf_header *ddf = NULL;
char version[DDF_REV_LENGTH + 1];
uint64_t off, lba;
if (pr->size < 0x30000)
return -1;
for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
ddf = (struct ddf_header *) blkid_probe_get_buffer(pr,
off,
sizeof(struct ddf_header));
if (!ddf)
return -1;
if (ddf->signature == cpu_to_be32(DDF_MAGIC) ||
ddf->signature == cpu_to_le32(DDF_MAGIC))
break;
ddf = NULL;
}
if (!ddf)
return -1;
lba = ddf->signature == cpu_to_be32(DDF_MAGIC) ?
be64_to_cpu(ddf->primary_lba) :
le64_to_cpu(ddf->primary_lba);
if (lba > 0) {
/* check primary header */
unsigned char *buf;
buf = blkid_probe_get_buffer(pr,
lba << 9, sizeof(ddf->signature));
if (!buf || memcmp(buf, &ddf->signature, 4))
return -1;
}
blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
*(version + sizeof(ddf->ddf_rev)) = '\0';
if (blkid_probe_set_version(pr, version) != 0)
return -1;
if (blkid_probe_set_magic(pr, off,
sizeof(ddf->signature),
(unsigned char *) &ddf->signature))
return -1;
return 0;
}
const struct blkid_idinfo ddfraid_idinfo = {
.name = "ddf_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_ddf,
.magics = BLKID_NONE_MAGIC
};
+272
View File
@@ -0,0 +1,272 @@
/*
* 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"
/*
* NOTE: reference manual is not structured as code. The following section is a generic
* section for all high-level cache search+iterate routines.
*/
/**
* SECTION:search
* @title: Search and iterate
* @short_description: search devices and iterate over devices in the cache.
*
* Note that high-level probing API provides information about superblocks
* (filesystems/raids) only. For partitions and topology is necessary to use
* the low-level API.
*/
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 ?
dev->bid_type : "(null)"));
DBG(DEBUG_DEV, blkid_debug_dump_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);
}
free(dev->bid_name);
free(dev);
}
/*
* Given a blkid device, return its name
*/
extern const char *blkid_dev_devname(blkid_dev dev)
{
return dev ? dev->bid_name : NULL;
}
#ifdef CONFIG_BLKID_DEBUG
void blkid_debug_dump_dev(blkid_dev dev)
{
struct list_head *p;
if (!dev) {
printf(" dev: NULL\n");
return;
}
printf(" dev: name = %s\n", dev->bid_name);
printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
printf(" dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
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);
if (tag)
printf(" tag: %s=\"%s\"\n", tag->bit_name,
tag->bit_val);
else
printf(" tag: NULL\n");
}
printf("\n");
}
#endif
/*
* 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;
char *search_type;
char *search_value;
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;
iter->search_type = 0;
iter->search_value = 0;
}
return iter;
}
extern int blkid_dev_set_search(blkid_dev_iterate iter,
char *search_type, char *search_value)
{
char *new_type, *new_value;
if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
!search_value)
return -1;
new_type = malloc(strlen(search_type)+1);
new_value = malloc(strlen(search_value)+1);
if (!new_type || !new_value) {
free(new_type);
free(new_value);
return -1;
}
strcpy(new_type, search_type);
strcpy(new_value, search_value);
free(iter->search_type);
free(iter->search_value);
iter->search_type = new_type;
iter->search_value = new_value;
return 0;
}
/*
* Return 0 on success, -1 on error
*/
extern int blkid_dev_next(blkid_dev_iterate iter,
blkid_dev *ret_dev)
{
blkid_dev dev;
if (!ret_dev || !iter || iter->magic != DEV_ITERATE_MAGIC)
return -1;
*ret_dev = 0;
while (iter->p != &iter->cache->bic_devs) {
dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
iter->p = iter->p->next;
if (iter->search_type &&
!blkid_dev_has_tag(dev, iter->search_type,
iter->search_value))
continue;
*ret_dev = dev;
return 0;
}
return -1;
}
extern void blkid_dev_iterate_end(blkid_dev_iterate iter)
{
if (!iter || iter->magic != DEV_ITERATE_MAGIC)
return;
iter->magic = 0;
free(iter->search_type);
free(iter->search_value);
free(iter);
}
#ifdef TEST_PROGRAM
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern char *optarg;
extern int optind;
#endif
void __attribute__((__noreturn__)) usage(char *prog)
{
fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
fprintf(stderr, "\tList all devices and exit\n");
exit(1);
}
int main(int argc, char **argv)
{
blkid_dev_iterate iter;
blkid_cache cache = NULL;
blkid_dev dev;
int c, ret;
char *tmp;
char *file = NULL;
char *search_type = NULL;
char *search_value = NULL;
while ((c = getopt (argc, argv, "m:f:")) != EOF)
switch (c) {
case 'f':
file = optarg;
break;
case 'm':
{
int mask = strtoul (optarg, &tmp, 0);
if (*tmp) {
fprintf(stderr, "Invalid debug mask: %s\n",
optarg);
exit(1);
}
blkid_init_debug(mask);
break;
}
case '?':
usage(argv[0]);
}
if (argc >= optind+2) {
search_type = argv[optind];
search_value = argv[optind+1];
optind += 2;
}
if (argc != optind)
usage(argv[0]);
if ((ret = blkid_get_cache(&cache, file)) != 0) {
fprintf(stderr, "%s: error creating cache (%d)\n",
argv[0], ret);
exit(1);
}
iter = blkid_dev_iterate_begin(cache);
if (search_type)
blkid_dev_set_search(iter, search_type, search_value);
while (blkid_dev_next(iter, &dev) == 0) {
printf("Device: %s\n", blkid_dev_devname(dev));
}
blkid_dev_iterate_end(iter);
blkid_put_cache(cache);
return (0);
}
#endif
+678
View File
@@ -0,0 +1,678 @@
/*
* 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%
*/
#define _GNU_SOURCE 1
#include <stdio.h>
#include <string.h>
#include <limits.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <dirent.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <time.h>
#include "blkidP.h"
#include "canonicalize.h" /* $(top_srcdir)/include */
#include "pathnames.h"
#include "sysfs.h"
#include "at.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, *pnext;
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)) {
if (access(devname, F_OK) < 0)
return NULL;
dev = blkid_new_dev();
if (!dev)
return NULL;
dev->bid_time = INT_MIN;
dev->bid_name = 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);
if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED))
return dev;
/*
* If the device is verified, then search the blkid
* cache for any entries that match on the type, uuid,
* and label, and verify them; if a cache entry can
* not be verified, then it's stale and so we remove
* it.
*/
list_for_each_safe(p, pnext, &cache->bic_devs) {
blkid_dev dev2 = list_entry(p, struct blkid_struct_dev, bid_devs);
if (dev2->bid_flags & BLKID_BID_FL_VERIFIED)
continue;
if (!dev->bid_type || !dev2->bid_type ||
strcmp(dev->bid_type, dev2->bid_type))
continue;
if (dev->bid_label && dev2->bid_label &&
strcmp(dev->bid_label, dev2->bid_label))
continue;
if (dev->bid_uuid && dev2->bid_uuid &&
strcmp(dev->bid_uuid, dev2->bid_uuid))
continue;
if ((dev->bid_label && !dev2->bid_label) ||
(!dev->bid_label && dev2->bid_label) ||
(dev->bid_uuid && !dev2->bid_uuid) ||
(!dev->bid_uuid && dev2->bid_uuid))
continue;
dev2 = blkid_verify(cache, dev2);
if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED))
blkid_free_dev(dev2);
}
}
return dev;
}
/* Directories where we will try to search for device names */
static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL };
static int is_dm_leaf(const char *devname)
{
struct dirent *de, *d_de;
DIR *dir, *d_dir;
char path[256];
int ret = 1;
if ((dir = opendir("/sys/block")) == NULL)
return 0;
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
!strcmp(de->d_name, devname) ||
strncmp(de->d_name, "dm-", 3) ||
strlen(de->d_name) > sizeof(path)-32)
continue;
sprintf(path, "/sys/block/%s/slaves", de->d_name);
if ((d_dir = opendir(path)) == NULL)
continue;
while ((d_de = readdir(d_dir)) != NULL) {
if (!strcmp(d_de->d_name, devname)) {
ret = 0;
break;
}
}
closedir(d_dir);
if (!ret)
break;
}
closedir(dir);
return ret;
}
/*
* 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, int only_if_new, int removable)
{
blkid_dev dev = NULL;
struct list_head *p, *pnext;
const char **dir;
char *devname = NULL;
/* See if we already have this device number in the cache. */
list_for_each_safe(p, pnext, &cache->bic_devs) {
blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
bid_devs);
if (tmp->bid_devno == devno) {
if (only_if_new && !access(tmp->bid_name, F_OK))
return;
dev = blkid_verify(cache, tmp);
if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
break;
dev = 0;
}
}
if (dev && dev->bid_devno == devno)
goto set_pri;
/* Try to translate private device-mapper dm-<N> names
* to standard /dev/mapper/<name>.
*/
if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) {
devname = canonicalize_dm_name(ptname);
if (!devname)
blkid__scan_dir("/dev/mapper", devno, 0, &devname);
if (devname)
goto get_dev;
}
/*
* 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 = dirlist; *dir; dir++) {
struct stat st;
char device[256];
snprintf(device, sizeof(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) ||
(S_ISCHR(st.st_mode) && !strncmp(ptname, "ubi", 3))) &&
st.st_rdev == devno) {
devname = strdup(device);
goto get_dev;
}
}
/* Do a short-cut scan of /dev/mapper first */
if (!devname)
blkid__scan_dir("/dev/mapper", devno, 0, &devname);
if (!devname) {
devname = blkid_devno_to_devname(devno);
if (!devname)
return;
}
get_dev:
dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
free(devname);
set_pri:
if (dev) {
if (pri)
dev->bid_pri = pri;
else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) {
dev->bid_pri = BLKID_PRI_DM;
if (is_dm_leaf(ptname))
dev->bid_pri += 5;
} else if (!strncmp(ptname, "md", 2))
dev->bid_pri = BLKID_PRI_MD;
if (removable)
dev->bid_flags |= BLKID_BID_FL_REMOVABLE;
}
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
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) %m\n", lvm_device, 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, int only_if_new)
{
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,
only_if_new, 0);
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, int only_if_new)
{
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,
only_if_new, 0);
num++;
}
fclose(procpt);
return num;
}
static void
ubi_probe_all(blkid_cache cache, int only_if_new)
{
const char **dirname;
for (dirname = dirlist; *dirname; dirname++) {
DBG(DEBUG_DEVNAME, printf("probing UBI volumes under %s\n",
*dirname));
DIR *dir;
struct dirent *iter;
dir = opendir(*dirname);
if (dir == NULL)
continue ;
while ((iter = readdir(dir)) != NULL) {
char *name;
struct stat st;
dev_t dev;
name = iter->d_name;
#ifdef _DIRENT_HAVE_D_TYPE
if (iter->d_type != DT_UNKNOWN &&
iter->d_type != DT_CHR && iter->d_type != DT_LNK)
continue;
#endif
if (!strcmp(name, ".") || !strcmp(name, "..") ||
!strstr(name, "ubi"))
continue;
if (!strcmp(name, "ubi_ctrl"))
continue;
if (fstat_at(dirfd(dir), *dirname, name, &st, 0))
continue;
dev = st.st_rdev;
if (!S_ISCHR(st.st_mode) || !minor(dev))
continue;
DBG(DEBUG_DEVNAME, printf("UBI vol %s/%s: devno 0x%04X\n",
*dirname, name, (int) dev));
probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new, 0);
}
closedir(dir);
}
}
/*
* Read the device data for all available block devices in the system.
*/
static int probe_all(blkid_cache cache, int only_if_new)
{
FILE *proc;
char line[1024];
char ptname0[128 + 1], ptname1[128 + 1], *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;
struct list_head *p, *pnext;
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, only_if_new);
#ifdef VG_DIR
lvm_probe_all(cache, only_if_new);
#endif
ubi_probe_all(cache, only_if_new);
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 base name of device has changed, also
* check previous dev to see if it didn't have a partn.
* heuristic: partition name ends in a digit, & partition
* names contain whole device name as substring.
*
* Skip extended partitions.
* heuristic: size is 1
*
* FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
*/
lens[which] = strlen(ptname);
/* ends in a digit, clearly a partition, so check */
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,
only_if_new, 0);
lens[which] = 0; /* mark as checked */
}
/*
* If last was a whole disk and we just found a partition
* on it, remove the whole-disk dev from the cache if
* it exists.
*/
if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) {
list_for_each_safe(p, pnext, &cache->bic_devs) {
blkid_dev tmp;
/* find blkid dev for the whole-disk devno */
tmp = list_entry(p, struct blkid_struct_dev,
bid_devs);
if (tmp->bid_devno == devs[last]) {
DBG(DEBUG_DEVNAME,
printf("freeing %s\n",
tmp->bid_name));
blkid_free_dev(tmp);
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
break;
}
}
lens[last] = 0;
}
/*
* If last was not checked because it looked like a whole-disk
* dev, and the device's base name has changed,
* check last as well.
*/
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,
only_if_new, 0);
lens[last] = 0;
}
}
/* Handle the last device if it wasn't partitioned */
if (lens[which])
probe_one(cache, ptname, devs[which], 0, only_if_new, 0);
fclose(proc);
blkid_flush_cache(cache);
return 0;
}
/* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...)
*/
static int probe_all_removable(blkid_cache cache)
{
DIR *dir;
struct dirent *d;
if (!cache)
return -BLKID_ERR_PARAM;
dir = opendir(_PATH_SYS_BLOCK);
if (!dir)
return -BLKID_ERR_PROC;
while((d = readdir(dir))) {
struct sysfs_cxt sysfs = UL_SYSFSCXT_EMPTY;
int removable = 0;
dev_t devno;
#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK)
continue;
#endif
if (d->d_name[0] == '.' &&
((d->d_name[1] == 0) ||
((d->d_name[1] == '.') && (d->d_name[2] == 0))))
continue;
devno = sysfs_devname_to_devno(d->d_name, NULL);
if (!devno)
continue;
if (sysfs_init(&sysfs, devno, NULL) == 0) {
sysfs_read_int(&sysfs, "removable", &removable);
sysfs_deinit(&sysfs);
}
if (removable)
probe_one(cache, d->d_name, devno, 0, 0, 1);
}
closedir(dir);
return 0;
}
/**
* blkid_probe_all:
* @cache: cache handler
*
* Probes all block devices.
*
* Returns: 0 on success, or number less than zero in case of error.
*/
int blkid_probe_all(blkid_cache cache)
{
int ret;
DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n"));
ret = probe_all(cache, 0);
if (ret == 0) {
cache->bic_time = time(0);
cache->bic_flags |= BLKID_BIC_FL_PROBED;
}
DBG(DEBUG_PROBE, printf("End blkid_probe_all() [rc=%d]\n", ret));
return ret;
}
/**
* blkid_probe_all_new:
* @cache: cache handler
*
* Probes all new block devices.
*
* Returns: 0 on success, or number less than zero in case of error.
*/
int blkid_probe_all_new(blkid_cache cache)
{
int ret;
DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n"));
ret = probe_all(cache, 1);
DBG(DEBUG_PROBE, printf("End blkid_probe_all_new() [rc=%d]\n", ret));
return ret;
}
/**
* blkid_probe_all_removable:
* @cache: cache handler
*
* The libblkid probing is based on devices from /proc/partitions by default.
* This file usually does not contain removable devices (e.g. CDROMs) and this kind
* of devices are invisible for libblkid.
*
* This function adds removable block devices to @cache (probing is based on
* information from the /sys directory). Don't forget that removable devices
* (floppies, CDROMs, ...) could be pretty slow. It's very bad idea to call
* this function by default.
*
* Note that devices which were detected by this function won't be written to
* blkid.tab cache file.
*
* Returns: 0 on success, or number less than zero in case of error.
*/
int blkid_probe_all_removable(blkid_cache cache)
{
int ret;
DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_removable()\n"));
ret = probe_all_removable(cache);
DBG(DEBUG_PROBE, printf("End blkid_probe_all_removable() [rc=%d]\n", ret));
return ret;
}
#ifdef TEST_PROGRAM
int main(int argc, char **argv)
{
blkid_cache cache = NULL;
int ret;
blkid_init_debug(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]);
if (blkid_probe_all_removable(cache) < 0)
printf("%s: error probing removable devices\n", argv[0]);
blkid_put_cache(cache);
return (0);
}
#endif
+379
View File
@@ -0,0 +1,379 @@
/*
* 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>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <dirent.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_MKDEV_H
#include <sys/mkdev.h>
#endif
#include <fcntl.h>
#include <inttypes.h>
#include "blkidP.h"
#include "pathnames.h"
#include "at.h"
#include "sysfs.h"
static char *blkid_strconcat(const char *a, const char *b, const char *c)
{
char *res, *p;
size_t len, al, bl, cl;
al = a ? strlen(a) : 0;
bl = b ? strlen(b) : 0;
cl = c ? strlen(c) : 0;
len = al + bl + cl;
if (!len)
return NULL;
p = res = malloc(len + 1);
if (!res)
return NULL;
if (al) {
memcpy(p, a, al);
p += al;
}
if (bl) {
memcpy(p, b, bl);
p += bl;
}
if (cl) {
memcpy(p, c, cl);
p += cl;
}
*p = '\0';
return res;
}
/*
* This function adds an entry to the directory list
*/
static void add_to_dirlist(const char *dir, const char *subdir,
struct dir_list **list)
{
struct dir_list *dp;
dp = malloc(sizeof(struct dir_list));
if (!dp)
return;
dp->name = subdir ? blkid_strconcat(dir, "/", subdir) :
dir ? strdup(dir) : NULL;
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;
}
void blkid__scan_dir(char *dirname, dev_t devno, struct dir_list **list,
char **devname)
{
DIR *dir;
struct dirent *dp;
struct stat st;
if ((dir = opendir(dirname)) == NULL)
return;
while ((dp = readdir(dir)) != NULL) {
#ifdef _DIRENT_HAVE_D_TYPE
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_BLK &&
dp->d_type != DT_LNK && dp->d_type != DT_DIR)
continue;
#endif
if (dp->d_name[0] == '.' &&
((dp->d_name[1] == 0) ||
((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
continue;
if (fstat_at(dirfd(dir), dirname, dp->d_name, &st, 0))
continue;
if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
*devname = blkid_strconcat(dirname, "/", dp->d_name);
DBG(DEBUG_DEVNO,
printf("found 0x%llx at %s\n", (long long)devno,
*devname));
break;
}
if (!list || !S_ISDIR(st.st_mode))
continue;
/* add subdirectory (but not symlink) to the list */
#ifdef _DIRENT_HAVE_D_TYPE
if (dp->d_type == DT_LNK)
continue;
if (dp->d_type == DT_UNKNOWN)
#endif
{
if (fstat_at(dirfd(dir), dirname, dp->d_name, &st, 1) ||
!S_ISDIR(st.st_mode))
continue; /* symlink or lstat() failed */
}
if (*dp->d_name == '.' || (
#ifdef _DIRENT_HAVE_D_TYPE
dp->d_type == DT_DIR &&
#endif
strcmp(dp->d_name, "shm") == 0))
/* ignore /dev/.{udev,mount,mdadm} and /dev/shm */
continue;
add_to_dirlist(dirname, dp->d_name, list);
}
closedir(dir);
return;
}
/* Directories where we will try to search for device numbers */
static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL };
/**
* SECTION: misc
* @title: Miscellaneous utils
* @short_description: mix of various utils for low-level and high-level API
*/
static char *scandev_devno_to_devpath(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 = devdirs; *dir; dir++)
add_to_dirlist(*dir, NULL, &list);
while (list) {
struct dir_list *current = list;
list = list->next;
DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
blkid__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);
return devname;
}
/**
* blkid_devno_to_devname:
* @devno: device number
*
* This function finds the pathname to a block device with a given
* device number.
*
* Returns: a pointer to allocated memory to the pathname on success,
* and NULL on failure.
*/
char *blkid_devno_to_devname(dev_t devno)
{
char *path = NULL;
char buf[PATH_MAX];
path = sysfs_devno_to_devpath(devno, buf, sizeof(buf));
if (path)
path = strdup(path);
if (!path)
path = scandev_devno_to_devpath(devno);
if (!path) {
DBG(DEBUG_DEVNO,
printf("blkid: couldn't find devno 0x%04lx\n",
(unsigned long) devno));
} else {
DBG(DEBUG_DEVNO,
printf("found devno 0x%04llx as %s\n", (long long)devno, path));
}
return path;
}
/**
* blkid_devno_to_wholedisk:
* @dev: device number
* @diskname: buffer to return diskname (or NULL)
* @len: diskname buffer size (or 0)
* @diskdevno: pointer to returns devno of entire disk (or NULL)
*
* This function uses sysfs to convert the @devno device number to the *name*
* of the whole disk. The function DOES NOT return full device name. The @dev
* argument could be partition or whole disk -- both is converted.
*
* For example: sda1, 0x0801 --> sda, 0x0800
*
* For conversion to the full disk *path* use blkid_devno_to_devname(), for
* example:
*
* <informalexample>
* <programlisting>
*
* dev_t dev = 0x0801, disk; // sda1 = 8:1
* char *diskpath, diskname[32];
*
* blkid_devno_to_wholedisk(dev, diskname, sizeof(diskname), &disk);
* diskpath = blkid_devno_to_devname(disk);
*
* // print "0x0801: sda, /dev/sda, 8:0
* printf("0x%x: %s, %s, %d:%d\n",
* dev, diskname, diskpath, major(disk), minor(disk));
*
* free(diskpath);
*
* </programlisting>
* </informalexample>
*
* Returns: 0 on success or -1 in case of error.
*/
int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
size_t len, dev_t *diskdevno)
{
return sysfs_devno_to_wholedisk( dev, diskname, len, diskdevno);
}
/*
* Returns 1 if the @major number is associated with @drvname.
*/
int blkid_driver_has_major(const char *drvname, int major)
{
FILE *f;
char buf[128];
int match = 0;
f = fopen(_PATH_PROC_DEVICES, "r");
if (!f)
return 0;
while (fgets(buf, sizeof(buf), f)) { /* skip to block dev section */
if (strncmp("Block devices:\n", buf, sizeof(buf)) == 0)
break;
}
while (fgets(buf, sizeof(buf), f)) {
int maj;
char name[64 + 1];
if (sscanf(buf, "%d %64[^\n ]", &maj, name) != 2)
continue;
if (maj == major && strcmp(name, drvname) == 0) {
match = 1;
break;
}
}
fclose(f);
DBG(DEBUG_DEVNO, printf("major %d %s associated with '%s' driver\n",
major, match ? "is" : "is NOT", drvname));
return match;
}
#ifdef TEST_PROGRAM
int main(int argc, char** argv)
{
char *devname, *tmp;
char diskname[PATH_MAX];
int major, minor;
dev_t devno, disk_devno;
const char *errmsg = "Couldn't parse %s: %s\n";
blkid_init_debug(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%04llx\n", (long long)devno);
devname = blkid_devno_to_devname(devno);
free(devname);
printf("Looking for whole-device for 0x%04llx\n", (long long)devno);
if (blkid_devno_to_wholedisk(devno, diskname,
sizeof(diskname), &disk_devno) == 0)
printf("found devno 0x%04llx as /dev/%s\n", (long long) disk_devno, diskname);
return 0;
}
#endif
+138
View File
@@ -0,0 +1,138 @@
/*
* device-mapper (dm) topology
* -- this is fallback for old systems where the topology information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "topology.h"
static int is_dm_device(dev_t devno)
{
return blkid_driver_has_major("device-mapper", major(devno));
}
static int probe_dm_tp(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
const char *paths[] = {
"/usr/local/sbin/dmsetup",
"/usr/sbin/dmsetup",
"/sbin/dmsetup"
};
int dmpipe[] = { -1, -1 }, stripes, stripesize;
char *cmd = NULL;
FILE *stream = NULL;
long long offset, size;
size_t i;
dev_t devno = blkid_probe_get_devno(pr);
if (!devno)
goto nothing; /* probably not a block device */
if (!is_dm_device(devno))
goto nothing;
for (i = 0; i < ARRAY_SIZE(paths); i++) {
struct stat sb;
if (stat(paths[i], &sb) == 0) {
cmd = (char *) paths[i];
break;
}
}
if (!cmd)
goto nothing;
if (pipe(dmpipe) < 0) {
DBG(DEBUG_LOWPROBE,
printf("Failed to open pipe: errno=%d", errno));
goto nothing;
}
switch (fork()) {
case 0:
{
char *dmargv[7], maj[16], min[16];
/* Plumbing */
close(dmpipe[0]);
if (dmpipe[1] != STDOUT_FILENO)
dup2(dmpipe[1], STDOUT_FILENO);
/* The libblkid library could linked with setuid programs */
if (setgid(getgid()) < 0)
exit(1);
if (setuid(getuid()) < 0)
exit(1);
snprintf(maj, sizeof(maj), "%d", major(devno));
snprintf(min, sizeof(min), "%d", minor(devno));
dmargv[0] = cmd;
dmargv[1] = "table";
dmargv[2] = "-j";
dmargv[3] = maj;
dmargv[4] = "-m";
dmargv[5] = min;
dmargv[6] = NULL;
execv(dmargv[0], dmargv);
DBG(DEBUG_LOWPROBE,
printf("Failed to execute %s: errno=%d", cmd, errno));
exit(1);
}
case -1:
DBG(DEBUG_LOWPROBE,
printf("Failed to forking: errno=%d", errno));
goto nothing;
default:
break;
}
stream = fdopen(dmpipe[0], "r");
if (!stream)
goto nothing;
if (fscanf(stream, "%lld %lld striped %d %d ",
&offset, &size, &stripes, &stripesize) != 0)
goto nothing;
blkid_topology_set_minimum_io_size(pr, stripesize << 9);
blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 9);
fclose(stream);
close(dmpipe[1]);
return 0;
nothing:
if (stream)
fclose(stream);
else if (dmpipe[0] != -1)
close(dmpipe[0]);
if (dmpipe[1] != -1)
close(dmpipe[1]);
return 1;
}
const struct blkid_idinfo dm_tp_idinfo =
{
.name = "dm",
.probefunc = probe_dm_tp,
.magics = BLKID_NONE_MAGIC
};
+297
View File
@@ -0,0 +1,297 @@
/*
* MS-DOS partition parsing code
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* Inspired by fdisk, partx, Linux kernel and libparted.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "partitions.h"
#include "dos.h"
#include "aix.h"
/* see superblocks/vfat.c */
extern int blkid_probe_is_vfat(blkid_probe pr);
static const struct dos_subtypes {
unsigned char type;
const struct blkid_idinfo *id;
} dos_nested[] = {
{ BLKID_FREEBSD_PARTITION, &bsd_pt_idinfo },
{ BLKID_NETBSD_PARTITION, &bsd_pt_idinfo },
{ BLKID_OPENBSD_PARTITION, &bsd_pt_idinfo },
{ BLKID_UNIXWARE_PARTITION, &unixware_pt_idinfo },
{ BLKID_SOLARIS_X86_PARTITION, &solaris_x86_pt_idinfo },
{ BLKID_MINIX_PARTITION, &minix_pt_idinfo }
};
static inline int is_extended(struct dos_partition *p)
{
return (p->sys_type == BLKID_DOS_EXTENDED_PARTITION ||
p->sys_type == BLKID_W95_EXTENDED_PARTITION ||
p->sys_type == BLKID_LINUX_EXTENDED_PARTITION);
}
static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
uint32_t ex_start, uint32_t ex_size, int ssf)
{
blkid_partlist ls = blkid_probe_get_partlist(pr);
uint32_t cur_start = ex_start, cur_size = ex_size;
unsigned char *data;
int ct_nodata = 0; /* count ext.partitions without data partitions */
int i;
while (1) {
struct dos_partition *p, *p0;
uint32_t start, size;
if (++ct_nodata > 100)
return 0;
data = blkid_probe_get_sector(pr, cur_start);
if (!data)
goto leave; /* malformed partition? */
if (!is_valid_mbr_signature(data))
goto leave;
p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
/* Usually, the first entry is the real data partition,
* the 2nd entry is the next extended partition, or empty,
* and the 3rd and 4th entries are unused.
* However, DRDOS sometimes has the extended partition as
* the first entry (when the data partition is empty),
* and OS/2 seems to use all four entries.
* -- Linux kernel fs/partitions/dos.c
*
* See also http://en.wikipedia.org/wiki/Extended_boot_record
*/
/* Parse data partition */
for (p = p0, i = 0; i < 4; i++, p++) {
uint32_t abs_start;
blkid_partition par;
/* the start is relative to the parental ext.partition */
start = dos_partition_start(p) * ssf;
size = dos_partition_size(p) * ssf;
abs_start = cur_start + start; /* absolute start */
if (!size || is_extended(p))
continue;
if (i >= 2) {
/* extra checks to detect real data on
* 3rd and 4th entries */
if (start + size > cur_size)
continue;
if (abs_start < ex_start)
continue;
if (abs_start + size > ex_start + ex_size)
continue;
}
par = blkid_partlist_add_partition(ls, tab, abs_start, size);
if (!par)
goto err;
blkid_partition_set_type(par, p->sys_type);
blkid_partition_set_flags(par, p->boot_ind);
ct_nodata = 0;
}
/* The first nested ext.partition should be a link to the next
* logical partition. Everything other (recursive ext.partitions)
* is junk.
*/
for (p = p0, i = 0; i < 4; i++, p++) {
start = dos_partition_start(p) * ssf;
size = dos_partition_size(p) * ssf;
if (size && is_extended(p))
break;
}
if (i == 4)
goto leave;
cur_start = ex_start + start;
cur_size = size;
}
leave:
return 0;
err:
return -1;
}
static int probe_dos_pt(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
int i;
int ssf;
blkid_parttable tab = NULL;
blkid_partlist ls;
struct dos_partition *p0, *p;
unsigned char *data;
uint32_t start, size, id;
data = blkid_probe_get_sector(pr, 0);
if (!data)
goto nothing;
/* ignore disks with AIX magic number -- for more details see aix.c */
if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0)
goto nothing;
/*
* Now that the 55aa signature is present, this is probably
* either the boot sector of a FAT filesystem or a DOS-type
* partition table.
*/
if (blkid_probe_is_vfat(pr)) {
DBG(DEBUG_LOWPROBE, printf("probably FAT -- ignore\n"));
goto nothing;
}
p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
/*
* Reject PT where boot indicator is not 0 or 0x80.
*/
for (p = p0, i = 0; i < 4; i++, p++)
if (p->boot_ind != 0 && p->boot_ind != 0x80) {
DBG(DEBUG_LOWPROBE, printf("missing boot indicator -- ignore\n"));
goto nothing;
}
/*
* GPT uses valid MBR
*/
for (p = p0, i = 0; i < 4; i++, p++) {
if (p->sys_type == BLKID_GPT_PARTITION) {
DBG(DEBUG_LOWPROBE, printf("probably GPT -- ignore\n"));
goto nothing;
}
}
blkid_probe_use_wiper(pr, BLKID_MSDOS_PT_OFFSET,
512 - BLKID_MSDOS_PT_OFFSET);
/*
* Well, all checks pass, it's MS-DOS partiton table
*/
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
ls = blkid_probe_get_partlist(pr);
/* sector size factor (the start and size are in the real sectors, but
* we need to convert all sizes to 512 logical sectors
*/
ssf = blkid_probe_get_sectorsize(pr) / 512;
/* allocate a new partition table */
tab = blkid_partlist_new_parttable(ls, "dos", BLKID_MSDOS_PT_OFFSET);
if (!tab)
goto err;
id = dos_parttable_id(data);
if (id) {
char buf[37];
snprintf(buf, sizeof(buf), "0x%08x", id);
blkid_parttable_set_id(tab, (unsigned char *) buf);
}
/* Parse primary partitions */
for (p = p0, i = 0; i < 4; i++, p++) {
blkid_partition par;
start = dos_partition_start(p) * ssf;
size = dos_partition_size(p) * ssf;
if (!size) {
/* Linux kernel ignores empty partitions, but partno for
* the empty primary partitions is not reused */
blkid_partlist_increment_partno(ls);
continue;
}
par = blkid_partlist_add_partition(ls, tab, start, size);
if (!par)
goto err;
blkid_partition_set_type(par, p->sys_type);
blkid_partition_set_flags(par, p->boot_ind);
}
/* Linux uses partition numbers greater than 4
* for all logical partition and all nested partition tables (bsd, ..)
*/
blkid_partlist_set_partno(ls, 5);
/* Parse logical partitions */
for (p = p0, i = 0; i < 4; i++, p++) {
start = dos_partition_start(p) * ssf;
size = dos_partition_size(p) * ssf;
if (!size)
continue;
if (is_extended(p) &&
parse_dos_extended(pr, tab, start, size, ssf) == -1)
goto err;
}
/* Parse subtypes (nested partitions) on large disks */
if (!blkid_probe_is_tiny(pr)) {
for (p = p0, i = 0; i < 4; i++, p++) {
size_t n;
if (!dos_partition_size(p) || is_extended(p))
continue;
for (n = 0; n < ARRAY_SIZE(dos_nested); n++) {
if (dos_nested[n].type != p->sys_type)
continue;
if (blkid_partitions_do_subprobe(pr,
blkid_partlist_get_partition(ls, i),
dos_nested[n].id) == -1)
goto err;
break;
}
}
}
return 0;
nothing:
return 1;
err:
return -1;
}
const struct blkid_idinfo dos_pt_idinfo =
{
.name = "dos",
.probefunc = probe_dos_pt,
.magics =
{
/* DOS master boot sector:
*
* 0 | Code Area
* 440 | Optional Disk signature
* 446 | Partition table
* 510 | 0x55
* 511 | 0xAA
*/
{ .magic = "\x55\xAA", .len = 2, .sboff = 510 },
{ NULL }
}
};
+41
View File
@@ -0,0 +1,41 @@
#ifndef BLKID_PARTITIONS_DOS_H
#define BLKID_PARTITIONS_DOS_H
struct dos_partition {
unsigned char boot_ind; /* 0x80 - active */
unsigned char bh, bs, bc; /* begin CHS */
unsigned char sys_type;
unsigned char eh, es, ec; /* end CHS */
unsigned char start_sect[4];
unsigned char nr_sects[4];
} __attribute__((packed));
#define BLKID_MSDOS_PT_OFFSET 0x1be
/* assemble badly aligned little endian integer */
static inline unsigned int assemble4le(const unsigned char *p)
{
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static inline unsigned int dos_partition_start(struct dos_partition *p)
{
return assemble4le(&(p->start_sect[0]));
}
static inline unsigned int dos_partition_size(struct dos_partition *p)
{
return assemble4le(&(p->nr_sects[0]));
}
static inline int is_valid_mbr_signature(const unsigned char *mbr)
{
return mbr[510] == 0x55 && mbr[511] == 0xaa ? 1 : 0;
}
static inline unsigned int dos_parttable_id(const unsigned char *mbr)
{
return assemble4le(&mbr[440]);
}
#endif /* BLKID_PARTITIONS_DOS_H */
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright (C) 2009 by Bastian Friedrich <bastian.friedrich@collax.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* defines, structs taken from drbd source; file names represent drbd source
* files.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
#include <stddef.h>
#include "superblocks.h"
/*
* drbd/linux/drbd.h
*/
#define DRBD_MAGIC 0x83740267
/*
* user/drbdmeta.c
* We only support v08 for now
*/
#define DRBD_MD_MAGIC_08 (DRBD_MAGIC+4)
#define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5)
/*
* drbd/linux/drbd.h
*/
enum drbd_uuid_index {
UI_CURRENT,
UI_BITMAP,
UI_HISTORY_START,
UI_HISTORY_END,
UI_SIZE, /* nl-packet: number of dirty bits */
UI_FLAGS, /* nl-packet: flags */
UI_EXTENDED_SIZE /* Everything. */
};
/*
* user/drbdmeta.c
* Minor modifications wrt. types
*/
struct md_on_disk_08 {
uint64_t la_sect; /* last agreed size. */
uint64_t uuid[UI_SIZE]; /* UUIDs */
uint64_t device_uuid;
uint64_t reserved_u64_1;
uint32_t flags;
uint32_t magic;
uint32_t md_size_sect;
int32_t al_offset; /* signed sector offset to this block */
uint32_t al_nr_extents; /* important for restoring the AL */
int32_t bm_offset; /* signed sector offset to the bitmap, from here */
uint32_t bm_bytes_per_bit;
uint32_t reserved_u32[4];
char reserved[8 * 512 - (8*(UI_SIZE+3)+4*11)];
};
static int probe_drbd(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct md_on_disk_08 *md;
off_t off;
off = pr->size - sizeof(*md);
/* Small devices cannot be drbd (?) */
if (pr->size < 0x10000)
return -1;
md = (struct md_on_disk_08 *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct md_on_disk_08));
if (!md)
return -1;
if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08 &&
be32_to_cpu(md->magic) != DRBD_MD_MAGIC_84_UNCLEAN)
return -1;
/*
* DRBD does not have "real" uuids; the following resembles DRBD's
* notion of uuids (64 bit, see struct above)
*/
blkid_probe_sprintf_uuid(pr,
(unsigned char *) &md->device_uuid, sizeof(md->device_uuid),
"%" PRIx64, be64_to_cpu(md->device_uuid));
blkid_probe_set_version(pr, "v08");
if (blkid_probe_set_magic(pr,
off + offsetof(struct md_on_disk_08, magic),
sizeof(md->magic),
(unsigned char *) &md->magic))
return -1;
return 0;
}
const struct blkid_idinfo drbd_idinfo =
{
.name = "drbd",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_drbd,
.magics = BLKID_NONE_MAGIC
};
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2011 by Philipp Marek <philipp.marek@linbit.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
#include <stddef.h>
#include "superblocks.h"
struct log_header_t {
uint64_t magic;
uint64_t version;
unsigned char uuid[16];
uint64_t flags;
} __attribute__((packed));
static int probe_drbdproxy_datalog(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct log_header_t *lh;
lh = (struct log_header_t *) blkid_probe_get_buffer(pr, 0, sizeof(*lh));
if (!lh)
return -1;
blkid_probe_set_uuid(pr, lh->uuid);
blkid_probe_sprintf_version(pr, "v%jd", le64_to_cpu(lh->version));
return 0;
}
const struct blkid_idinfo drbdproxy_datalog_idinfo =
{
.name = "drbdproxy_datalog",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_drbdproxy_datalog,
.minsz = 16*1024,
.magics =
{
{ .magic = "DRBDdlh*", .len = 8, .sboff = 0, .kboff = 0 },
{ NULL }
}
};
+340
View File
@@ -0,0 +1,340 @@
/*
* encode.c - string conversion routines (mostly for compatibility with
* udev/volume_id)
*
* Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include "blkidP.h"
#define UDEV_ALLOWED_CHARS_INPUT "/ $%?,"
/**
* SECTION: encode
* @title: Encoding utils
* @short_description: encode strings to safe udev-compatible formats
*
*/
/* count of characters used to encode one unicode char */
static int utf8_encoded_expected_len(const char *str)
{
unsigned char c = (unsigned char)str[0];
if (c < 0x80)
return 1;
if ((c & 0xe0) == 0xc0)
return 2;
if ((c & 0xf0) == 0xe0)
return 3;
if ((c & 0xf8) == 0xf0)
return 4;
if ((c & 0xfc) == 0xf8)
return 5;
if ((c & 0xfe) == 0xfc)
return 6;
return 0;
}
/* decode one unicode char */
static int utf8_encoded_to_unichar(const char *str)
{
int unichar;
int len;
int i;
len = utf8_encoded_expected_len(str);
switch (len) {
case 1:
return (int)str[0];
case 2:
unichar = str[0] & 0x1f;
break;
case 3:
unichar = (int)str[0] & 0x0f;
break;
case 4:
unichar = (int)str[0] & 0x07;
break;
case 5:
unichar = (int)str[0] & 0x03;
break;
case 6:
unichar = (int)str[0] & 0x01;
break;
default:
return -1;
}
for (i = 1; i < len; i++) {
if (((int)str[i] & 0xc0) != 0x80)
return -1;
unichar <<= 6;
unichar |= (int)str[i] & 0x3f;
}
return unichar;
}
/* expected size used to encode one unicode char */
static int utf8_unichar_to_encoded_len(int unichar)
{
if (unichar < 0x80)
return 1;
if (unichar < 0x800)
return 2;
if (unichar < 0x10000)
return 3;
if (unichar < 0x200000)
return 4;
if (unichar < 0x4000000)
return 5;
return 6;
}
/* check if unicode char has a valid numeric range */
static int utf8_unichar_valid_range(int unichar)
{
if (unichar > 0x10ffff)
return 0;
if ((unichar & 0xfffff800) == 0xd800)
return 0;
if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
return 0;
if ((unichar & 0xffff) == 0xffff)
return 0;
return 1;
}
/* validate one encoded unicode char and return its length */
static int utf8_encoded_valid_unichar(const char *str)
{
int len;
int unichar;
int i;
len = utf8_encoded_expected_len(str);
if (len == 0)
return -1;
/* ascii is valid */
if (len == 1)
return 1;
/* check if expected encoded chars are available */
for (i = 0; i < len; i++)
if ((str[i] & 0x80) != 0x80)
return -1;
unichar = utf8_encoded_to_unichar(str);
/* check if encoded length matches encoded value */
if (utf8_unichar_to_encoded_len(unichar) != len)
return -1;
/* check if value has valid range */
if (!utf8_unichar_valid_range(unichar))
return -1;
return len;
}
static int replace_whitespace(const char *str, char *to, size_t len)
{
size_t i, j;
/* strip trailing whitespace */
len = strnlen(str, len);
while (len && isspace(str[len-1]))
len--;
/* strip leading whitespace */
i = 0;
while (isspace(str[i]) && (i < len))
i++;
j = 0;
while (i < len) {
/* substitute multiple whitespace with a single '_' */
if (isspace(str[i])) {
while (isspace(str[i]))
i++;
to[j++] = '_';
}
to[j++] = str[i++];
}
to[j] = '\0';
return 0;
}
static int is_whitelisted(char c, const char *white)
{
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
strchr("#+-.:=@_", c) != NULL ||
(white != NULL && strchr(white, c) != NULL))
return 1;
return 0;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
static int replace_chars(char *str, const char *white)
{
size_t i = 0;
int replaced = 0;
while (str[i] != '\0') {
int len;
if (is_whitelisted(str[i], white)) {
i++;
continue;
}
/* accept hex encoding */
if (str[i] == '\\' && str[i+1] == 'x') {
i += 2;
continue;
}
/* accept valid utf8 */
len = utf8_encoded_valid_unichar(&str[i]);
if (len > 1) {
i += len;
continue;
}
/* if space is allowed, replace whitespace with ordinary space */
if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) {
str[i] = ' ';
i++;
replaced++;
continue;
}
/* everything else is replaced with '_' */
str[i] = '_';
i++;
replaced++;
}
return replaced;
}
size_t blkid_encode_to_utf8(int enc, unsigned char *dest, size_t len,
const unsigned char *src, size_t count)
{
size_t i, j;
uint16_t c;
for (j = i = 0; i + 2 <= count; i += 2) {
if (enc == BLKID_ENC_UTF16LE)
c = (src[i+1] << 8) | src[i];
else /* BLKID_ENC_UTF16BE */
c = (src[i] << 8) | src[i+1];
if (c == 0) {
dest[j] = '\0';
break;
} else if (c < 0x80) {
if (j+1 >= len)
break;
dest[j++] = (uint8_t) c;
} else if (c < 0x800) {
if (j+2 >= len)
break;
dest[j++] = (uint8_t) (0xc0 | (c >> 6));
dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
} else {
if (j+3 >= len)
break;
dest[j++] = (uint8_t) (0xe0 | (c >> 12));
dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
}
}
dest[j] = '\0';
return j;
}
/**
* blkid_encode_string:
* @str: input string to be encoded
* @str_enc: output string to store the encoded input string
* @len: maximum size of the output string, which may be
* four times as long as the input string
*
* Encode all potentially unsafe characters of a string to the
* corresponding hex value prefixed by '\x'.
*
* Returns: 0 if the entire string was copied, non-zero otherwise.
**/
int blkid_encode_string(const char *str, char *str_enc, size_t len)
{
size_t i, j;
if (!str || !str_enc || !len)
return -1;
for (i = 0, j = 0; str[i] != '\0'; i++) {
int seqlen;
seqlen = utf8_encoded_valid_unichar(&str[i]);
if (seqlen > 1) {
if (len-j < (size_t)seqlen)
goto err;
memcpy(&str_enc[j], &str[i], seqlen);
j += seqlen;
i += (seqlen-1);
} else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) {
if (len-j < 4)
goto err;
sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
j += 4;
} else {
if (len-j < 1)
goto err;
str_enc[j] = str[i];
j++;
}
if (j+3 >= len)
goto err;
}
if (len-j < 1)
goto err;
str_enc[j] = '\0';
return 0;
err:
return -1;
}
/**
* blkid_safe_string:
* @str: input string
* @str_safe: output string
* @len: size of output string
*
* Allows plain ascii, hex-escaping and valid utf8. Replaces all whitespaces
* with '_'.
*
* Returns: 0 on success or -1 in case of error.
*/
int blkid_safe_string(const char *str, char *str_safe, size_t len)
{
if (!str || !str_safe || !len)
return -1;
replace_whitespace(str, str_safe, len);
replace_chars(str_safe, UDEV_ALLOWED_CHARS_INPUT);
return 0;
}
+110
View File
@@ -0,0 +1,110 @@
/*
* Security checks of environment
* Added from shadow-utils package
* by Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#else
#define PR_GET_DUMPABLE 3
#endif
#if (!defined(HAVE_PRCTL) && defined(linux))
#include <sys/syscall.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include "env.h"
#ifndef HAVE_ENVIRON_DECL
extern char **environ;
#endif
static char * const forbid[] = {
"_RLD_=",
"BASH_ENV=", /* GNU creeping featurism strikes again... */
"ENV=",
"HOME=",
"IFS=",
"KRB_CONF=",
"LD_", /* anything with the LD_ prefix */
"LIBPATH=",
"MAIL=",
"NLSPATH=",
"PATH=",
"SHELL=",
"SHLIB_PATH=",
(char *) 0
};
/* these are allowed, but with no slashes inside
(to work around security problems in GNU gettext) */
static char * const noslash[] = {
"LANG=",
"LANGUAGE=",
"LC_", /* anything with the LC_ prefix */
(char *) 0
};
void
sanitize_env(void)
{
char **envp = environ;
char * const *bad;
char **cur;
char **move;
for (cur = envp; *cur; cur++) {
for (bad = forbid; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}
for (cur = envp; *cur; cur++) {
for (bad = noslash; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) != 0)
continue;
if (!strchr(*cur, '/'))
continue; /* OK */
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}
char *safe_getenv(const char *arg)
{
uid_t ruid = getuid();
if (ruid != 0 || (ruid != geteuid()) || (getgid() != getegid()))
return NULL;
#ifdef HAVE_PRCTL
if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
return NULL;
#else
#if (defined(linux) && defined(SYS_prctl))
if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
return NULL;
#endif
#endif
#ifdef HAVE_SECURE_GETENV
return secure_getenv(arg);
#elif HAVE___SECURE_GETENV
return __secure_getenv(arg);
#else
return getenv(arg);
#endif
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef UTIL_LINUX_ENV_H
#define UTIL_LINUX_ENV_H
#include "c.h"
extern void sanitize_env(void);
extern char *safe_getenv(const char *arg);
static inline void xsetenv(char const *name, char const *val, int overwrite)
{
if (setenv(name, val, overwrite) != 0)
err(EXIT_FAILURE, "failed to set the %s environment variable", name);
}
#endif /* UTIL_LINUX_ENV_H */
+328
View File
@@ -0,0 +1,328 @@
/*
* evaluate.c - very high-level API to evaluate LABELs or UUIDs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <stdint.h>
#include <stdarg.h>
#include "pathnames.h"
#include "canonicalize.h"
#include "blkidP.h"
/**
* SECTION:evaluate
* @title: Tags and Spec evaluation
* @short_description: top-level API for LABEL and UUID evaluation.
*
* This API provides very simple and portable way how evaluate LABEL and UUID
* tags. The blkid_evaluate_tag() and blkid_evaluate_spec() work on 2.4 and
* 2.6 systems and on systems with or without udev. Currently, the libblkid
* library supports "udev" and "scan" methods. The "udev" method uses udev
* /dev/disk/by-* symlinks and the "scan" method scans all block devices from
* the /proc/partitions file. The evaluation could be controlled by the
* /etc/blkid.conf config file. The default is to try "udev" and then "scan"
* method.
*
* The blkid_evaluate_tag() also automatically informs udevd when an obsolete
* /dev/disk/by-* symlink is detected.
*
* If you are not sure how translate LABEL or UUID to the device name use this
* API.
*/
#ifdef CONFIG_BLKID_VERIFY_UDEV
/* returns zero when the device has NAME=value (LABEL/UUID) */
static int verify_tag(const char *devname, const char *name, const char *value)
{
blkid_probe pr;
int fd = -1, rc = -1;
size_t len;
const char *data;
int errsv = 0;
pr = blkid_new_probe();
if (!pr)
return -1;
blkid_probe_enable_superblocks(pr, TRUE);
blkid_probe_set_superblocks_flags(pr,
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID);
blkid_probe_enable_partitions(pr, TRUE);
blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
fd = open(devname, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
errsv = errno;
goto done;
}
if (blkid_probe_set_device(pr, fd, 0, 0))
goto done;
rc = blkid_do_safeprobe(pr);
if (rc)
goto done;
rc = blkid_probe_lookup_value(pr, name, &data, &len);
if (!rc)
rc = memcmp(value, data, len);
done:
DBG(DEBUG_EVALUATE, printf("%s: %s verification %s\n",
devname, name, rc == 0 ? "PASS" : "FAILED"));
if (fd >= 0)
close(fd);
blkid_free_probe(pr);
/* for non-root users we use unverified udev links */
return errsv == EACCES ? 0 : rc;
}
#endif /* CONFIG_BLKID_VERIFY_UDEV*/
/**
* blkid_send_uevent:
* @devname: absolute path to the device
* @action: event string
*
* Returns: -1 in case of failure, or 0 on success.
*/
int blkid_send_uevent(const char *devname, const char *action)
{
char uevent[PATH_MAX];
struct stat st;
FILE *f;
int rc = -1;
DBG(DEBUG_EVALUATE, printf("%s: uevent '%s' requested\n", devname, action));
if (!devname || !action)
return -1;
if (stat(devname, &st) || !S_ISBLK(st.st_mode))
return -1;
snprintf(uevent, sizeof(uevent), "/sys/dev/block/%d:%d/uevent",
major(st.st_rdev), minor(st.st_rdev));
f = fopen(uevent, "w");
if (f) {
rc = 0;
if (fputs(action, f) >= 0)
rc = 0;
fclose(f);
}
DBG(DEBUG_EVALUATE, printf("%s: send uevent %s\n",
uevent, rc == 0 ? "SUCCES" : "FAILED"));
return rc;
}
static char *evaluate_by_udev(const char *token, const char *value, int uevent)
{
char dev[PATH_MAX];
char *path = NULL;
size_t len;
struct stat st;
DBG(DEBUG_EVALUATE,
printf("evaluating by udev %s=%s\n", token, value));
if (!strcmp(token, "UUID"))
strcpy(dev, _PATH_DEV_BYUUID "/");
else if (!strcmp(token, "LABEL"))
strcpy(dev, _PATH_DEV_BYLABEL "/");
else if (!strcmp(token, "PARTLABEL"))
strcpy(dev, _PATH_DEV_BYPARTLABEL "/");
else if (!strcmp(token, "PARTUUID"))
strcpy(dev, _PATH_DEV_BYPARTUUID "/");
else {
DBG(DEBUG_EVALUATE,
printf("unsupported token %s\n", token));
return NULL; /* unsupported tag */
}
len = strlen(dev);
if (blkid_encode_string(value, &dev[len], sizeof(dev) - len) != 0)
return NULL;
DBG(DEBUG_EVALUATE,
printf("expected udev link: %s\n", dev));
if (stat(dev, &st))
goto failed; /* link or device does not exist */
if (!S_ISBLK(st.st_mode))
return NULL;
path = canonicalize_path(dev);
if (!path)
return NULL;
#ifdef CONFIG_BLKID_VERIFY_UDEV
if (verify_tag(path, token, value))
goto failed;
#endif
return path;
failed:
DBG(DEBUG_EVALUATE, printf("failed to evaluate by udev\n"));
if (uevent && path)
blkid_send_uevent(path, "change");
free(path);
return NULL;
}
static char *evaluate_by_scan(const char *token, const char *value,
blkid_cache *cache, struct blkid_config *conf)
{
blkid_cache c = cache ? *cache : NULL;
char *res;
DBG(DEBUG_EVALUATE,
printf("evaluating by blkid scan %s=%s\n", token, value));
if (!c) {
char *cachefile = blkid_get_cache_filename(conf);
blkid_get_cache(&c, cachefile);
free(cachefile);
}
if (!c)
return NULL;
res = blkid_get_devname(c, token, value);
if (cache)
*cache = c;
else
blkid_put_cache(c);
return res;
}
/**
* blkid_evaluate_tag:
* @token: token name (e.g "LABEL" or "UUID") or unparsed tag (e.g. "LABEL=foo")
* @value: token data (e.g. "foo")
* @cache: pointer to cache (or NULL when you don't want to re-use the cache)
*
* Returns: allocated string with a device name.
*/
char *blkid_evaluate_tag(const char *token, const char *value, blkid_cache *cache)
{
struct blkid_config *conf = NULL;
char *t = NULL, *v = NULL;
char *ret = NULL;
int i;
if (!token)
return NULL;
if (!cache || !*cache)
blkid_init_debug(0);
DBG(DEBUG_EVALUATE,
printf("evaluating %s%s%s\n", token, value ? "=" : "",
value ? value : ""));
if (!value) {
if (!strchr(token, '=')) {
ret = strdup(token);
goto out;
}
blkid_parse_tag_string(token, &t, &v);
if (!t || !v)
goto out;
token = t;
value = v;
}
conf = blkid_read_config(NULL);
if (!conf)
goto out;
for (i = 0; i < conf->nevals; i++) {
if (conf->eval[i] == BLKID_EVAL_UDEV)
ret = evaluate_by_udev(token, value, conf->uevent);
else if (conf->eval[i] == BLKID_EVAL_SCAN)
ret = evaluate_by_scan(token, value, cache, conf);
if (ret)
break;
}
DBG(DEBUG_EVALUATE,
printf("%s=%s evaluated as %s\n", token, value, ret));
out:
blkid_free_config(conf);
free(t);
free(v);
return ret;
}
/**
* blkid_evaluate_spec:
* @spec: unparsed tag (e.g. "LABEL=foo") or path (e.g. /dev/dm-0)
* @cache: pointer to cache (or NULL when you don't want to re-use the cache)
*
* All returned paths are canonicalized, device-mapper paths are converted
* to the /dev/mapper/name format.
*
* Returns: allocated string with a device name.
*/
char *blkid_evaluate_spec(const char *spec, blkid_cache *cache)
{
char *t = NULL, *v = NULL, *res;
if (!spec)
return NULL;
if (strchr(spec, '=') &&
blkid_parse_tag_string(spec, &t, &v) != 0) /* parse error */
return NULL;
if (v)
res = blkid_evaluate_tag(t, v, cache);
else
res = canonicalize_path(spec);
free(t);
free(v);
return res;
}
#ifdef TEST_PROGRAM
int main(int argc, char *argv[])
{
blkid_cache cache = NULL;
char *res;
if (argc < 2) {
fprintf(stderr, "usage: %s <tag> | <spec>\n", argv[0]);
return EXIT_FAILURE;
}
blkid_init_debug(0);
res = blkid_evaluate_spec(argv[1], &cache);
if (res)
printf("%s\n", res);
if (cache)
blkid_put_cache(cache);
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
#endif
+77
View File
@@ -0,0 +1,77 @@
/*
* Evms topology
* -- this is fallback for old systems where the toplogy information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "topology.h"
#define EVMS_MAJOR 117
#ifndef _IOT__IOTBASE_u_int32_t
#define _IOT__IOTBASE_u_int32_t IOT_SIMPLE(uint32_t)
#endif
#define _IOT_evms_stripe_info _IOT (_IOTS(uint32_t), 2, 0, 0, 0, 0)
#define EVMS_GET_STRIPE_INFO _IOR(EVMS_MAJOR, 0xF0, struct evms_stripe_info)
struct evms_stripe_info {
uint32_t size; /* stripe unit 512-byte blocks */
uint32_t width; /* the number of stripe members or RAID data disks */
} evms_stripe_info;
static int is_evms_device(dev_t devno)
{
if (major(devno) == EVMS_MAJOR)
return 1;
return blkid_driver_has_major("evms", major(devno));
}
static int probe_evms_tp(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct evms_stripe_info evms;
dev_t devno = blkid_probe_get_devno(pr);
if (!devno)
goto nothing; /* probably not a block device */
if (!is_evms_device(devno))
goto nothing;
memset(&evms, 0, sizeof(evms));
if (ioctl(pr->fd, EVMS_GET_STRIPE_INFO, &evms))
goto nothing;
blkid_topology_set_minimum_io_size(pr, evms.size << 9);
blkid_topology_set_optimal_io_size(pr, (evms.size * evms.width) << 9);
return 0;
nothing:
return 1;
}
const struct blkid_idinfo evms_tp_idinfo =
{
.name = "evms",
.probefunc = probe_evms_tp,
.magics = BLKID_NONE_MAGIC
};
+27
View File
@@ -0,0 +1,27 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "nls.h"
#include "c.h"
#include "xalloc.h"
#include "exec_shell.h"
#define DEFAULT_SHELL "/bin/sh"
void __attribute__((__noreturn__)) exec_shell(void) {
const char *shell = getenv("SHELL"), *shell_basename;
char *arg0;
if (!shell)
shell = DEFAULT_SHELL;
shell_basename = basename(shell);
arg0 = xmalloc(strlen(shell_basename) + 2);
arg0[0] = '-';
strcpy(arg0 + 1, shell_basename);
execl(shell, arg0, NULL);
err(EXIT_FAILURE, _("failed to execute %s"), shell);
}
+1
View File
@@ -0,0 +1 @@
extern void __attribute__((__noreturn__)) exec_shell(void);
+146
View File
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2010 Andrew Nayenko <resver@gmail.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include "superblocks.h"
struct exfat_super_block {
uint8_t jump[3];
uint8_t oem_name[8];
uint8_t __unused1[53];
uint64_t block_start;
uint64_t block_count;
uint32_t fat_block_start;
uint32_t fat_block_count;
uint32_t cluster_block_start;
uint32_t cluster_count;
uint32_t rootdir_cluster;
uint8_t volume_serial[4];
struct {
uint8_t minor;
uint8_t major;
} version;
uint16_t volume_state;
uint8_t block_bits;
uint8_t bpc_bits;
uint8_t fat_count;
uint8_t drive_no;
uint8_t allocated_percent;
} __attribute__((__packed__));
struct exfat_entry_label {
uint8_t type;
uint8_t length;
uint8_t name[30];
} __attribute__((__packed__));
#define BLOCK_SIZE(sb) (1 << (sb)->block_bits)
#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
#define EXFAT_FIRST_DATA_CLUSTER 2
#define EXFAT_LAST_DATA_CLUSTER 0xffffff6
#define EXFAT_ENTRY_SIZE 32
#define EXFAT_ENTRY_EOD 0x00
#define EXFAT_ENTRY_LABEL 0x83
static blkid_loff_t block_to_offset(const struct exfat_super_block *sb,
blkid_loff_t block)
{
return (blkid_loff_t) block << sb->block_bits;
}
static blkid_loff_t cluster_to_block(const struct exfat_super_block *sb,
uint32_t cluster)
{
return le32_to_cpu(sb->cluster_block_start) +
((blkid_loff_t) (cluster - EXFAT_FIRST_DATA_CLUSTER)
<< sb->bpc_bits);
}
static blkid_loff_t cluster_to_offset(const struct exfat_super_block *sb,
uint32_t cluster)
{
return block_to_offset(sb, cluster_to_block(sb, cluster));
}
static uint32_t next_cluster(blkid_probe pr,
const struct exfat_super_block *sb, uint32_t cluster)
{
uint32_t *next;
blkid_loff_t fat_offset;
fat_offset = block_to_offset(sb, le32_to_cpu(sb->fat_block_start))
+ (blkid_loff_t) cluster * sizeof(cluster);
next = (uint32_t *) blkid_probe_get_buffer(pr, fat_offset,
sizeof(uint32_t));
if (!next)
return 0;
return le32_to_cpu(*next);
}
static struct exfat_entry_label *find_label(blkid_probe pr,
const struct exfat_super_block *sb)
{
uint32_t cluster = le32_to_cpu(sb->rootdir_cluster);
blkid_loff_t offset = cluster_to_offset(sb, cluster);
uint8_t *entry;
for (;;) {
entry = (uint8_t *) blkid_probe_get_buffer(pr, offset,
EXFAT_ENTRY_SIZE);
if (!entry)
return NULL;
if (entry[0] == EXFAT_ENTRY_EOD)
return NULL;
if (entry[0] == EXFAT_ENTRY_LABEL)
return (struct exfat_entry_label *) entry;
offset += EXFAT_ENTRY_SIZE;
if (offset % CLUSTER_SIZE(sb) == 0) {
cluster = next_cluster(pr, sb, cluster);
if (cluster < EXFAT_FIRST_DATA_CLUSTER)
return NULL;
if (cluster > EXFAT_LAST_DATA_CLUSTER)
return NULL;
offset = cluster_to_offset(sb, cluster);
}
}
}
static int probe_exfat(blkid_probe pr, const struct blkid_idmag *mag)
{
struct exfat_super_block *sb;
struct exfat_entry_label *label;
sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block);
if (!sb)
return -1;
label = find_label(pr, sb);
if (label)
blkid_probe_set_utf8label(pr, label->name,
min(label->length * 2, 30), BLKID_ENC_UTF16LE);
blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4,
"%02hhX%02hhX-%02hhX%02hhX",
sb->volume_serial[3], sb->volume_serial[2],
sb->volume_serial[1], sb->volume_serial[0]);
blkid_probe_sprintf_version(pr, "%u.%u",
sb->version.major, sb->version.minor);
return 0;
}
const struct blkid_idinfo exfat_idinfo =
{
.name = "exfat",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_exfat,
.magics =
{
{ .magic = "EXFAT ", .len = 8, .sboff = 3 },
{ NULL }
}
};
+35
View File
@@ -0,0 +1,35 @@
#ifndef UTIL_LINUX_EXITCODES_H
#define UTIL_LINUX_EXITCODES_H
/*
* BE CAREFUL
*
* These exit codes are part of the official interface for mount,
* fsck, mkfs, etc. wrappers.
*/
/* Exit codes used by mkfs-type programs */
#define MKFS_EX_OK 0 /* No errors */
#define MKFS_EX_ERROR 8 /* Operational error */
#define MKFS_EX_USAGE 16 /* Usage or syntax error */
/* Exit codes used by fsck-type programs */
#define FSCK_EX_OK 0 /* No errors */
#define FSCK_EX_NONDESTRUCT 1 /* File system errors corrected */
#define FSCK_EX_REBOOT 2 /* System should be rebooted */
#define FSCK_EX_DESTRUCT FSCK_EX_REBOOT /* Alias */
#define FSCK_EX_UNCORRECTED 4 /* File system errors left uncorrected */
#define FSCK_EX_ERROR 8 /* Operational error */
#define FSCK_EX_USAGE 16 /* Usage or syntax error */
#define FSCK_EX_LIBRARY 128 /* Shared library error */
/* Exit codes used by mount-line programs */
#define MOUNT_EX_SUCCESS 0 /* No errors */
#define MOUNT_EX_USAGE 1 /* incorrect invocation or permission */
#define MOUNT_EX_SYSERR 2 /* out of memory, cannot fork, ... */
#define MOUNT_EX_SOFTWARE 4 /* internal mount bug or wrong version */
#define MOUNT_EX_USER 8 /* user interrupt */
#define MOUNT_EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */
#define MOUNT_EX_FAIL 32 /* mount failure */
#define MOUNT_EX_SOMEOK 64 /* some mount succeeded */
#endif /* UTIL_LINUX_EXITCODES_H */
+540
View File
@@ -0,0 +1,540 @@
/*
* Copyright (C) 1999, 2001 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
#ifdef __linux__
#include <sys/utsname.h>
#endif
#include <time.h>
#include "linux_version.h"
#include "superblocks.h"
struct ext2_super_block {
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_r_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
uint32_t s_dummy3[7];
unsigned char s_magic[2];
uint16_t s_state;
uint16_t s_errors;
uint16_t s_minor_rev_level;
uint32_t s_lastcheck;
uint32_t s_checkinterval;
uint32_t s_creator_os;
uint32_t s_rev_level;
uint16_t s_def_resuid;
uint16_t s_def_resgid;
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_block_group_nr;
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
unsigned char s_uuid[16];
char s_volume_name[16];
char s_last_mounted[64];
uint32_t s_algorithm_usage_bitmap;
uint8_t s_prealloc_blocks;
uint8_t s_prealloc_dir_blocks;
uint16_t s_reserved_gdt_blocks;
uint8_t s_journal_uuid[16];
uint32_t s_journal_inum;
uint32_t s_journal_dev;
uint32_t s_last_orphan;
uint32_t s_hash_seed[4];
uint8_t s_def_hash_version;
uint8_t s_jnl_backup_type;
uint16_t s_reserved_word_pad;
uint32_t s_default_mount_opts;
uint32_t s_first_meta_bg;
uint32_t s_mkfs_time;
uint32_t s_jnl_blocks[17];
uint32_t s_blocks_count_hi;
uint32_t s_r_blocks_count_hi;
uint32_t s_free_blocks_hi;
uint16_t s_min_extra_isize;
uint16_t s_want_extra_isize;
uint32_t s_flags;
uint16_t s_raid_stride;
uint16_t s_mmp_interval;
uint64_t s_mmp_block;
uint32_t s_raid_stripe_width;
uint32_t s_reserved[163];
} __attribute__((packed));
/* magic string */
#define EXT_SB_MAGIC "\123\357"
/* supper block offset */
#define EXT_SB_OFF 0x400
/* supper block offset in kB */
#define EXT_SB_KBOFF (EXT_SB_OFF >> 10)
/* magic string offset within super block */
#define EXT_MAG_OFF 0x38
/* for s_flags */
#define EXT2_FLAGS_TEST_FILESYS 0x0004
/* for s_feature_compat */
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
/* for s_feature_ro_compat */
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
/* for s_feature_incompat */
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
EXT2_FEATURE_INCOMPAT_META_BG)
#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
EXT3_FEATURE_INCOMPAT_RECOVER| \
EXT2_FEATURE_INCOMPAT_META_BG)
#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP
#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP
/*
* Check to see if a filesystem is in /proc/filesystems.
* Returns 1 if found, 0 if not
*/
static int fs_proc_check(const char *fs_name)
{
FILE *f;
char buf[80], *cp, *t;
f = fopen("/proc/filesystems", "r");
if (!f)
return 0;
while (!feof(f)) {
if (!fgets(buf, sizeof(buf), f))
break;
cp = buf;
if (!isspace(*cp)) {
while (*cp && !isspace(*cp))
cp++;
}
while (*cp && isspace(*cp))
cp++;
if ((t = strchr(cp, '\n')) != NULL)
*t = 0;
if ((t = strchr(cp, '\t')) != NULL)
*t = 0;
if ((t = strchr(cp, ' ')) != NULL)
*t = 0;
if (!strcmp(fs_name, cp)) {
fclose(f);
return 1;
}
}
fclose(f);
return (0);
}
/*
* Check to see if a filesystem is available as a module
* Returns 1 if found, 0 if not
*/
static int check_for_modules(const char *fs_name)
{
#ifdef __linux__
struct utsname uts;
FILE *f;
char buf[1024], *cp;
int namesz;
if (uname(&uts))
return 0;
snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
f = fopen(buf, "r");
if (!f)
return 0;
namesz = strlen(fs_name);
while (!feof(f)) {
if (!fgets(buf, sizeof(buf), f))
break;
if ((cp = strchr(buf, ':')) != NULL)
*cp = 0;
else
continue;
if ((cp = strrchr(buf, '/')) == NULL)
continue;
cp++;
if (!strncmp(cp, fs_name, namesz) &&
(!strcmp(cp + namesz, ".ko") ||
!strcmp(cp + namesz, ".ko.gz"))) {
fclose(f);
return 1;
}
}
fclose(f);
#endif /* __linux__ */
return 0;
}
/*
* Starting in 2.6.29, ext4 can be used to support filesystems
* without a journal.
*/
#define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29)
static int system_supports_ext2(void)
{
static time_t last_check = 0;
static int ret = -1;
time_t now = time(0);
if (ret != -1 || (now - last_check) < 5)
return ret;
last_check = now;
ret = (fs_proc_check("ext2") || check_for_modules("ext2"));
return ret;
}
static int system_supports_ext4(void)
{
static time_t last_check = 0;
static int ret = -1;
time_t now = time(0);
if (ret != -1 || (now - last_check) < 5)
return ret;
last_check = now;
ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
return ret;
}
static int system_supports_ext4dev(void)
{
static time_t last_check = 0;
static int ret = -1;
time_t now = time(0);
if (ret != -1 || (now - last_check) < 5)
return ret;
last_check = now;
ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
return ret;
}
static int system_supports_ext4_ext2(void)
{
#ifdef __linux__
return get_linux_version() >= EXT4_SUPPORTS_EXT2;
#else
return 0;
#endif
}
/*
* reads superblock and returns:
* fc = feature_compat
* fi = feature_incompat
* frc = feature_ro_compat
*/
static struct ext2_super_block *ext_get_super(
blkid_probe pr, uint32_t *fc, uint32_t *fi, uint32_t *frc)
{
struct ext2_super_block *es;
es = (struct ext2_super_block *)
blkid_probe_get_buffer(pr, EXT_SB_OFF, 0x200);
if (!es)
return NULL;
if (fc)
*fc = le32_to_cpu(es->s_feature_compat);
if (fi)
*fi = le32_to_cpu(es->s_feature_incompat);
if (frc)
*frc = le32_to_cpu(es->s_feature_ro_compat);
return es;
}
static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es)
{
struct blkid_chain *chn = blkid_probe_get_chain(pr);
DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
le32_to_cpu(es->s_feature_compat),
le32_to_cpu(es->s_feature_incompat),
le32_to_cpu(es->s_feature_ro_compat)));
if (strlen(es->s_volume_name))
blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name,
sizeof(es->s_volume_name));
blkid_probe_set_uuid(pr, es->s_uuid);
if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL");
if (ver != 2 && (chn->flags & BLKID_SUBLKS_SECTYPE) &&
((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
blkid_probe_set_value(pr, "SEC_TYPE",
(unsigned char *) "ext2",
sizeof("ext2"));
blkid_probe_sprintf_version(pr, "%u.%u",
le32_to_cpu(es->s_rev_level),
le16_to_cpu(es->s_minor_rev_level));
}
static int probe_jbd(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct ext2_super_block *es;
uint32_t fi;
es = ext_get_super(pr, NULL, &fi, NULL);
if (!es)
return -BLKID_ERR_PARAM;
if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
return -BLKID_ERR_PARAM;
ext_get_info(pr, 2, es);
return 0;
}
static int probe_ext2(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct ext2_super_block *es;
uint32_t fc, frc, fi;
es = ext_get_super(pr, &fc, &fi, &frc);
if (!es)
return -BLKID_ERR_PARAM;
/* Distinguish between ext3 and ext2 */
if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
return -BLKID_ERR_PARAM;
/* Any features which ext2 doesn't understand */
if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
(fi & EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
return -BLKID_ERR_PARAM;
/*
* If ext2 is not present, but ext4 or ext4dev are, then
* disclaim we are ext2
*/
if (!system_supports_ext2() &&
(system_supports_ext4() || system_supports_ext4dev()) &&
system_supports_ext4_ext2())
return -BLKID_ERR_PARAM;
ext_get_info(pr, 2, es);
return 0;
}
static int probe_ext3(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct ext2_super_block *es;
uint32_t fc, frc, fi;
es = ext_get_super(pr, &fc, &fi, &frc);
if (!es)
return -BLKID_ERR_PARAM;
/* ext3 requires journal */
if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
return -BLKID_ERR_PARAM;
/* Any features which ext3 doesn't understand */
if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
return -BLKID_ERR_PARAM;
ext_get_info(pr, 3, es);
return 0;
}
static int probe_ext4dev(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct ext2_super_block *es;
uint32_t fc, frc, fi;
es = ext_get_super(pr, &fc, &fi, &frc);
if (!es)
return -BLKID_ERR_PARAM;
/* Distinguish from jbd */
if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
return -BLKID_ERR_PARAM;
/*
* If the filesystem does not have a journal and ext2 and ext4
* is not present, then force this to be detected as an
* ext4dev filesystem.
*/
if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
!system_supports_ext2() && !system_supports_ext4() &&
system_supports_ext4dev() &&
system_supports_ext4_ext2())
goto force_ext4dev;
/*
* If the filesystem is marked as OK for use by in-development
* filesystem code, but ext4dev is not supported, and ext4 is,
* then don't call ourselves ext4dev, since we should be
* detected as ext4 in that case.
*
* If the filesystem is marked as in use by production
* filesystem, then it can only be used by ext4 and NOT by
* ext4dev, so always disclaim we are ext4dev in that case.
*/
if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
if (!system_supports_ext4dev() && system_supports_ext4())
return -BLKID_ERR_PARAM;
} else
return -BLKID_ERR_PARAM;
force_ext4dev:
ext_get_info(pr, 4, es);
return 0;
}
static int probe_ext4(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct ext2_super_block *es;
uint32_t fc, frc, fi;
es = ext_get_super(pr, &fc, &fi, &frc);
if (!es)
return -1;
/* Distinguish from jbd */
if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
return -BLKID_ERR_PARAM;
/*
* If the filesystem does not have a journal and ext2 is not
* present, then force this to be detected as an ext2
* filesystem.
*/
if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
!system_supports_ext2() && system_supports_ext4() &&
system_supports_ext4_ext2())
goto force_ext4;
/* Ext4 has at least one feature which ext3 doesn't understand */
if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
!(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
return -BLKID_ERR_PARAM;
force_ext4:
/*
* If the filesystem is a OK for use by in-development
* filesystem code, and ext4dev is supported or ext4 is not
* supported, then don't call ourselves ext4, so we can redo
* the detection and mark the filesystem as ext4dev.
*
* If the filesystem is marked as in use by production
* filesystem, then it can only be used by ext4 and NOT by
* ext4dev.
*/
if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
if (system_supports_ext4dev() || !system_supports_ext4())
return -BLKID_ERR_PARAM;
}
ext_get_info(pr, 4, es);
return 0;
}
#define BLKID_EXT_MAGICS \
{ \
{ \
.magic = EXT_SB_MAGIC, \
.len = sizeof(EXT_SB_MAGIC) - 1, \
.kboff = EXT_SB_KBOFF, \
.sboff = EXT_MAG_OFF \
}, \
{ NULL } \
}
const struct blkid_idinfo jbd_idinfo =
{
.name = "jbd",
.usage = BLKID_USAGE_OTHER,
.probefunc = probe_jbd,
.magics = BLKID_EXT_MAGICS
};
const struct blkid_idinfo ext2_idinfo =
{
.name = "ext2",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ext2,
.magics = BLKID_EXT_MAGICS
};
const struct blkid_idinfo ext3_idinfo =
{
.name = "ext3",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ext3,
.magics = BLKID_EXT_MAGICS
};
const struct blkid_idinfo ext4_idinfo =
{
.name = "ext4",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ext4,
.magics = BLKID_EXT_MAGICS
};
const struct blkid_idinfo ext4dev_idinfo =
{
.name = "ext4dev",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ext4dev,
.magics = BLKID_EXT_MAGICS
};
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2013 Alejandro Martinez Ruiz <alex@nowcomputing.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License
*/
#include <stddef.h>
#include <string.h>
#include "superblocks.h"
#define F2FS_MAGIC "\x10\x20\xF5\xF2"
#define F2FS_MAGIC_OFF 0
#define F2FS_UUID_SIZE 16
#define F2FS_LABEL_SIZE 512
#define F2FS_SB1_OFF 0x400
#define F2FS_SB1_KBOFF (F2FS_SB1_OFF >> 10)
#define F2FS_SB2_OFF 0x1400
#define F2FS_SB2_KBOFF (F2FS_SB2_OFF >> 10)
struct f2fs_super_block { /* According to version 1.1 */
/* 0x00 */ uint32_t magic; /* Magic Number */
/* 0x04 */ uint16_t major_ver; /* Major Version */
/* 0x06 */ uint16_t minor_ver; /* Minor Version */
/* 0x08 */ uint32_t log_sectorsize; /* log2 sector size in bytes */
/* 0x0C */ uint32_t log_sectors_per_block; /* log2 # of sectors per block */
/* 0x10 */ uint32_t log_blocksize; /* log2 block size in bytes */
/* 0x14 */ uint32_t log_blocks_per_seg; /* log2 # of blocks per segment */
/* 0x18 */ uint32_t segs_per_sec; /* # of segments per section */
/* 0x1C */ uint32_t secs_per_zone; /* # of sections per zone */
/* 0x20 */ uint32_t checksum_offset; /* checksum offset inside super block */
/* 0x24 */ uint64_t block_count; /* total # of user blocks */
/* 0x2C */ uint32_t section_count; /* total # of sections */
/* 0x30 */ uint32_t segment_count; /* total # of segments */
/* 0x34 */ uint32_t segment_count_ckpt; /* # of segments for checkpoint */
/* 0x38 */ uint32_t segment_count_sit; /* # of segments for SIT */
/* 0x3C */ uint32_t segment_count_nat; /* # of segments for NAT */
/* 0x40 */ uint32_t segment_count_ssa; /* # of segments for SSA */
/* 0x44 */ uint32_t segment_count_main; /* # of segments for main area */
/* 0x48 */ uint32_t segment0_blkaddr; /* start block address of segment 0 */
/* 0x4C */ uint32_t cp_blkaddr; /* start block address of checkpoint */
/* 0x50 */ uint32_t sit_blkaddr; /* start block address of SIT */
/* 0x54 */ uint32_t nat_blkaddr; /* start block address of NAT */
/* 0x58 */ uint32_t ssa_blkaddr; /* start block address of SSA */
/* 0x5C */ uint32_t main_blkaddr; /* start block address of main area */
/* 0x60 */ uint32_t root_ino; /* root inode number */
/* 0x64 */ uint32_t node_ino; /* node inode number */
/* 0x68 */ uint32_t meta_ino; /* meta inode number */
/* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; /* 128-bit uuid for volume */
/* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; /* volume name */
#if 0
/* 0x47C */ uint32_t extension_count; /* # of extensions below */
/* 0x480 */ uint8_t extension_list[64][8]; /* extension array */
#endif
} __attribute__((packed));
static int probe_f2fs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct f2fs_super_block *sb;
uint16_t major, minor;
sb = blkid_probe_get_sb(pr, mag, struct f2fs_super_block);
if (!sb)
return -1;
major = le16_to_cpu(sb->major_ver);
minor = le16_to_cpu(sb->minor_ver);
/* For version 1.0 we cannot know the correct sb structure */
if (major == 1 && minor == 0)
return 0;
if (*((unsigned char *) sb->volume_name))
blkid_probe_set_utf8label(pr, (unsigned char *) sb->volume_name,
sizeof(sb->volume_name),
BLKID_ENC_UTF16LE);
blkid_probe_set_uuid(pr, sb->uuid);
blkid_probe_sprintf_version(pr, "%u.%u", major, minor);
return 0;
}
const struct blkid_idinfo f2fs_idinfo =
{
.name = "f2fs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_f2fs,
.magics =
{
{
.magic = F2FS_MAGIC,
.len = 4,
.kboff = F2FS_SB1_KBOFF,
.sboff = F2FS_MAGIC_OFF
},
{ NULL }
}
};
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi>
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "c.h"
#include "fileutils.h"
#include "pathnames.h"
#include "xalloc.h"
#define _PATH_TMP "/tmp"
/* Create open temporary file in safe way. Please notice that the
* file permissions are -rw------- by default. */
int xmkstemp(char **tmpname, char *dir)
{
char *localtmp;
char *tmpenv;
mode_t old_mode;
int fd;
/* Some use cases must be capable of being moved atomically
* with rename(2), which is the reason why dir is here. */
if (dir != NULL)
tmpenv = dir;
else
tmpenv = getenv("TMPDIR");
if (tmpenv)
xasprintf(&localtmp, "%s/%s.XXXXXX", tmpenv,
program_invocation_short_name);
else
xasprintf(&localtmp, "%s/%s.XXXXXX", _PATH_TMP,
program_invocation_short_name);
old_mode = umask(077);
fd = mkstemp(localtmp);
umask(old_mode);
if (fd == -1) {
free(localtmp);
localtmp = NULL;
}
*tmpname = localtmp;
return fd;
}
/*
* portable getdtablesize()
*/
int get_fd_tabsize(void)
{
int m;
#if defined(HAVE_GETDTABLESIZE)
m = getdtablesize();
#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rl;
getrlimit(RLIMIT_NOFILE, &rl);
m = rl.rlim_cur;
#elif defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
m = sysconf(_SC_OPEN_MAX);
#else
m = OPEN_MAX;
#endif
return m;
}
#ifdef TEST_PROGRAM
int main(void)
{
FILE *f;
char *tmpname;
f = xfmkstemp(&tmpname, NULL);
unlink(tmpname);
free(tmpname);
fclose(f);
return EXIT_FAILURE;
}
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef UTIL_LINUX_FILEUTILS
#define UTIL_LINUX_FILEUTILS
extern int xmkstemp(char **tmpname, char *dir);
static inline FILE *xfmkstemp(char **tmpname, char *dir)
{
int fd;
FILE *ret;
fd = xmkstemp(tmpname, dir);
if (fd == -1) {
return NULL;
}
if (!(ret = fdopen(fd, "w+"))) {
close(fd);
return NULL;
}
return ret;
}
extern int get_fd_tabsize(void);
#endif /* UTIL_LINUX_FILEUTILS */
+34
View File
@@ -0,0 +1,34 @@
/*
* getsize.c --- get the size of a partition.
*
* Copyright (C) 1995, 1995 Theodore Ts'o.
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
* %End-Header%
*/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "blkidP.h"
/**
* blkid_get_dev_size:
* @fd: file descriptor
*
* Returns: size (in bytes) of the block device or size of the regular file or 0.
*/
blkid_loff_t blkid_get_dev_size(int fd)
{
unsigned long long bytes;
if (blkdev_get_size(fd, &bytes))
return 0;
return bytes;
}
+131
View File
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
/* Common gfs/gfs2 constants: */
#define GFS_LOCKNAME_LEN 64
/* gfs1 constants: */
#define GFS_FORMAT_FS 1309
#define GFS_FORMAT_MULTI 1401
/* gfs2 constants: */
#define GFS2_FORMAT_FS 1801
#define GFS2_FORMAT_MULTI 1900
struct gfs2_meta_header {
uint32_t mh_magic;
uint32_t mh_type;
uint64_t __pad0; /* Was generation number in gfs1 */
uint32_t mh_format;
uint32_t __pad1; /* Was incarnation number in gfs1 */
};
struct gfs2_inum {
uint64_t no_formal_ino;
uint64_t no_addr;
};
struct gfs2_sb {
struct gfs2_meta_header sb_header;
uint32_t sb_fs_format;
uint32_t sb_multihost_format;
uint32_t __pad0; /* Was superblock flags in gfs1 */
uint32_t sb_bsize;
uint32_t sb_bsize_shift;
uint32_t __pad1; /* Was journal segment size in gfs1 */
struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */
struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */
struct gfs2_inum sb_root_dir;
char sb_lockproto[GFS_LOCKNAME_LEN];
char sb_locktable[GFS_LOCKNAME_LEN];
struct gfs2_inum __pad3; /* Was quota inode in gfs1 */
struct gfs2_inum __pad4; /* Was licence inode in gfs1 */
uint8_t sb_uuid[16]; /* The UUID maybe 0 for backwards compat */
} __attribute__((packed));
static int probe_gfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct gfs2_sb *sbd;
sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
if (!sbd)
return -1;
if (be32_to_cpu(sbd->sb_fs_format) == GFS_FORMAT_FS &&
be32_to_cpu(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
{
if (*sbd->sb_locktable)
blkid_probe_set_label(pr,
(unsigned char *) sbd->sb_locktable,
sizeof(sbd->sb_locktable));
blkid_probe_set_uuid(pr, sbd->sb_uuid);
return 0;
}
return -1;
}
static int probe_gfs2(blkid_probe pr, const struct blkid_idmag *mag)
{
struct gfs2_sb *sbd;
sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
if (!sbd)
return -1;
if (be32_to_cpu(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
be32_to_cpu(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
{
if (*sbd->sb_locktable)
blkid_probe_set_label(pr,
(unsigned char *) sbd->sb_locktable,
sizeof(sbd->sb_locktable));
blkid_probe_set_uuid(pr, sbd->sb_uuid);
blkid_probe_set_version(pr, "1");
return 0;
}
return -1;
}
const struct blkid_idinfo gfs_idinfo =
{
.name = "gfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_gfs,
.minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */
.magics =
{
{ .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
{ NULL }
}
};
const struct blkid_idinfo gfs2_idinfo =
{
.name = "gfs2",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_gfs2,
.minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */
.magics =
{
{ .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
{ NULL }
}
};
+412
View File
@@ -0,0 +1,412 @@
/*
* EFI GPT partition parsing code
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* This code is not copy & past from any other implementation.
*
* For more information about GPT start your study at:
* http://en.wikipedia.org/wiki/GUID_Partition_Table
* http://technet.microsoft.com/en-us/library/cc739412(WS.10).aspx
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include "partitions.h"
#include "crc32.h"
#include "dos.h"
#define GPT_PRIMARY_LBA 1
/* Signature - “EFI PART” */
#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
#define GPT_HEADER_SIGNATURE_STR "EFI PART"
/* basic types */
typedef uint16_t efi_char16_t;
/* UUID */
typedef struct {
uint32_t time_low;
uint16_t time_mid;
uint16_t time_hi_and_version;
uint8_t clock_seq_hi;
uint8_t clock_seq_low;
uint8_t node[6];
} efi_guid_t;
#define GPT_UNUSED_ENTRY_GUID \
((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
struct gpt_header {
uint64_t signature; /* "EFI PART" */
uint32_t revision;
uint32_t header_size; /* usually 92 bytes */
uint32_t header_crc32; /* checksum of header with this
* field zeroed during calculation */
uint32_t reserved1;
uint64_t my_lba; /* location of this header copy */
uint64_t alternate_lba; /* location of the other header copy */
uint64_t first_usable_lba; /* lirst usable LBA for partitions */
uint64_t last_usable_lba; /* last usable LBA for partitions */
efi_guid_t disk_guid; /* disk UUID */
uint64_t partition_entries_lba; /* always 2 in primary header copy */
uint32_t num_partition_entries;
uint32_t sizeof_partition_entry;
uint32_t partition_entry_array_crc32;
/*
* The rest of the block is reserved by UEFI and must be zero. EFI
* standard handles this by:
*
* uint8_t reserved2[ BLKSSZGET - 92 ];
*
* This definition is useless in practice. It is necessary to read
* whole block from the device rather than sizeof(struct gpt_header)
* only.
*/
} __attribute__ ((packed));
/*** not used
struct gpt_entry_attributes {
uint64_t required_to_function:1;
uint64_t reserved:47;
uint64_t type_guid_specific:16;
} __attribute__ ((packed));
***/
struct gpt_entry {
efi_guid_t partition_type_guid; /* type UUID */
efi_guid_t unique_partition_guid; /* partition UUID */
uint64_t starting_lba;
uint64_t ending_lba;
/*struct gpt_entry_attributes attributes;*/
uint64_t attributes;
efi_char16_t partition_name[72 / sizeof(efi_char16_t)]; /* UTF-16LE string*/
} __attribute__ ((packed));
/*
* EFI uses crc32 with ~0 seed and xor's with ~0 at the end.
*/
static inline uint32_t count_crc32(const unsigned char *buf, size_t len)
{
return (crc32(~0L, buf, len) ^ ~0L);
}
static inline unsigned char *get_lba_buffer(blkid_probe pr,
uint64_t lba, size_t bytes)
{
return blkid_probe_get_buffer(pr,
blkid_probe_get_sectorsize(pr) * lba, bytes);
}
static inline int guidcmp(efi_guid_t left, efi_guid_t right)
{
return memcmp(&left, &right, sizeof (efi_guid_t));
}
/*
* UUID is traditionally 16 byte big-endian array, except Intel EFI
* specification where the UUID is a structure of little-endian fields.
*/
static void swap_efi_guid(efi_guid_t *uid)
{
uid->time_low = swab32(uid->time_low);
uid->time_mid = swab16(uid->time_mid);
uid->time_hi_and_version = swab16(uid->time_hi_and_version);
}
static int last_lba(blkid_probe pr, uint64_t *lba)
{
blkid_loff_t sz = blkid_probe_get_size(pr);
unsigned int ssz = blkid_probe_get_sectorsize(pr);
if (sz < ssz)
return -1;
*lba = (sz / ssz) - 1ULL;
return 0;
}
/*
* Protective (legacy) MBR.
*
* This MBR contains standard DOS partition table with a single partition, type
* of 0xEE. The partition usually encompassing the entire GPT drive - or 2TiB
* for large disks.
*
* Note that Apple uses GPT/MBR hybrid disks, where the DOS partition table is
* synchronized with GPT. This synchronization has many restriction of course
* (due DOS PT limitations).
*
* Note that the PMBR detection is optional (enabled by default) and could be
* disabled by BLKID_PARTS_FOPCE_GPT flag (see also blkid_paertitions_set_flags()).
*/
static int is_pmbr_valid(blkid_probe pr)
{
int flags = blkid_partitions_get_flags(pr);
unsigned char *data;
struct dos_partition *p;
int i;
if (flags & BLKID_PARTS_FORCE_GPT)
goto ok; /* skip PMBR check */
data = blkid_probe_get_sector(pr, 0);
if (!data)
goto failed;
if (!is_valid_mbr_signature(data))
goto failed;
p = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
for (i = 0; i < 4; i++, p++) {
if (p->sys_type == BLKID_GPT_PARTITION)
goto ok;
}
failed:
return 0;
ok:
return 1;
}
/*
* Reads GPT header to @hdr and returns a pointer to @hdr or NULL in case of
* error. The function also returns GPT entries in @ents.
*
* Note, this function does not allocate any memory. The GPT header has fixed
* size so we use stack, and @ents returns memory from libblkid buffer (so the
* next blkid_probe_get_buffer() will overwrite this buffer).
*
* This function checks validity of header and entries array. A corrupted
* header is not returned.
*/
static struct gpt_header *get_gpt_header(
blkid_probe pr, struct gpt_header *hdr,
struct gpt_entry **ents, uint64_t lba,
uint64_t lastlba)
{
struct gpt_header *h;
uint32_t crc, orgcrc;
uint64_t lu, fu;
size_t esz;
uint32_t hsz, ssz;
ssz = blkid_probe_get_sectorsize(pr);
/* whole sector is allocated for GPT header */
h = (struct gpt_header *) get_lba_buffer(pr, lba, ssz);
if (!h)
return NULL;
if (le64_to_cpu(h->signature) != GPT_HEADER_SIGNATURE)
return NULL;
hsz = le32_to_cpu(h->header_size);
/* EFI: The HeaderSize must be greater than 92 and must be less
* than or equal to the logical block size.
*/
if (hsz > ssz || hsz < sizeof(*h))
return NULL;
/* Header has to be verified when header_crc32 is zero */
orgcrc = h->header_crc32;
h->header_crc32 = 0;
crc = count_crc32((unsigned char *) h, hsz);
h->header_crc32 = orgcrc;
if (crc != le32_to_cpu(orgcrc)) {
DBG(DEBUG_LOWPROBE, printf("GPT header corrupted\n"));
return NULL;
}
/* Valid header has to be at MyLBA */
if (le64_to_cpu(h->my_lba) != lba) {
DBG(DEBUG_LOWPROBE, printf(
"GPT->MyLBA mismatch with real position\n"));
return NULL;
}
fu = le64_to_cpu(h->first_usable_lba);
lu = le64_to_cpu(h->last_usable_lba);
/* Check if First and Last usable LBA makes sense */
if (lu < fu || fu > lastlba || lu > lastlba) {
DBG(DEBUG_LOWPROBE, printf(
"GPT->{First,Last}UsableLBA out of range\n"));
return NULL;
}
/* The header has to be outside usable range */
if (fu < lba && lba < lu) {
DBG(DEBUG_LOWPROBE, printf("GPT header is inside usable area\n"));
return NULL;
}
/* Size of blocks with GPT entries */
esz = le32_to_cpu(h->num_partition_entries) *
le32_to_cpu(h->sizeof_partition_entry);
if (!esz) {
DBG(DEBUG_LOWPROBE, printf("GPT entries undefined\n"));
return NULL;
}
/* The header seems valid, save it
* (we don't care about zeros in hdr->reserved2 area) */
memcpy(hdr, h, sizeof(*h));
h = hdr;
/* Read GPT entries */
*ents = (struct gpt_entry *) get_lba_buffer(pr,
le64_to_cpu(h->partition_entries_lba), esz);
if (!*ents) {
DBG(DEBUG_LOWPROBE, printf("GPT entries unreadable\n"));
return NULL;
}
/* Validate entries */
crc = count_crc32((unsigned char *) *ents, esz);
if (crc != le32_to_cpu(h->partition_entry_array_crc32)) {
DBG(DEBUG_LOWPROBE, printf("GPT entries corrupted\n"));
return NULL;
}
return h;
}
static int probe_gpt_pt(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
uint64_t lastlba = 0, lba;
struct gpt_header hdr, *h;
struct gpt_entry *e;
blkid_parttable tab = NULL;
blkid_partlist ls;
uint64_t fu, lu;
uint32_t ssf, i;
efi_guid_t guid;
if (last_lba(pr, &lastlba))
goto nothing;
if (!is_pmbr_valid(pr))
goto nothing;
h = get_gpt_header(pr, &hdr, &e, (lba = GPT_PRIMARY_LBA), lastlba);
if (!h)
h = get_gpt_header(pr, &hdr, &e, (lba = lastlba), lastlba);
if (!h)
goto nothing;
blkid_probe_use_wiper(pr, lba * blkid_probe_get_size(pr), 8);
if (blkid_probe_set_magic(pr, lba << 9,
sizeof(GPT_HEADER_SIGNATURE_STR) - 1,
(unsigned char *) GPT_HEADER_SIGNATURE_STR))
goto err;
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
ls = blkid_probe_get_partlist(pr);
if (!ls)
goto err;
tab = blkid_partlist_new_parttable(ls, "gpt", lba << 9);
if (!tab)
goto err;
guid = h->disk_guid;
swap_efi_guid(&guid);
blkid_parttable_set_id(tab, (const unsigned char *) &guid);
ssf = blkid_probe_get_sectorsize(pr) / 512;
fu = le64_to_cpu(h->first_usable_lba);
lu = le64_to_cpu(h->last_usable_lba);
for (i = 0; i < le32_to_cpu(h->num_partition_entries); i++, e++) {
blkid_partition par;
uint64_t start = le64_to_cpu(e->starting_lba);
uint64_t size = le64_to_cpu(e->ending_lba) -
le64_to_cpu(e->starting_lba) + 1ULL;
/* 00000000-0000-0000-0000-000000000000 entry */
if (!guidcmp(e->partition_type_guid, GPT_UNUSED_ENTRY_GUID)) {
blkid_partlist_increment_partno(ls);
continue;
}
/* the partition has to inside usable range */
if (start < fu || start + size - 1 > lu) {
DBG(DEBUG_LOWPROBE, printf(
"GPT entry[%d] overflows usable area - ignore\n",
i));
blkid_partlist_increment_partno(ls);
continue;
}
par = blkid_partlist_add_partition(ls, tab,
start * ssf, size * ssf);
if (!par)
goto err;
blkid_partition_set_utf8name(par,
(unsigned char *) e->partition_name,
sizeof(e->partition_name), BLKID_ENC_UTF16LE);
guid = e->unique_partition_guid;
swap_efi_guid(&guid);
blkid_partition_set_uuid(par, (const unsigned char *) &guid);
guid = e->partition_type_guid;
swap_efi_guid(&guid);
blkid_partition_set_type_uuid(par, (const unsigned char *) &guid);
blkid_partition_set_flags(par, e->attributes);
}
return 0;
nothing:
return 1;
err:
return -1;
}
const struct blkid_idinfo gpt_pt_idinfo =
{
.name = "gpt",
.probefunc = probe_gpt_pt,
.minsz = 1024 * 1440 + 1, /* ignore floppies */
/*
* It would be possible to check for DOS signature (0xAA55), but
* unfortunately almost all EFI GPT implemenations allow to optionaly
* skip the legacy MBR. We follows this behavior and MBR is optional.
* See is_valid_pmbr().
*
* It means we have to always call probe_gpt_pt().
*/
.magics = BLKID_NONE_MAGIC
};
+321
View File
@@ -0,0 +1,321 @@
/*
* Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include "superblocks.h"
#include "md5.h"
/* HFS / HFS+ */
struct hfs_finder_info {
uint32_t boot_folder;
uint32_t start_app;
uint32_t open_folder;
uint32_t os9_folder;
uint32_t reserved;
uint32_t osx_folder;
uint8_t id[8];
} __attribute__((packed));
struct hfs_mdb {
uint8_t signature[2];
uint32_t cr_date;
uint32_t ls_Mod;
uint16_t atrb;
uint16_t nm_fls;
uint16_t vbm_st;
uint16_t alloc_ptr;
uint16_t nm_al_blks;
uint32_t al_blk_size;
uint32_t clp_size;
uint16_t al_bl_st;
uint32_t nxt_cnid;
uint16_t free_bks;
uint8_t label_len;
uint8_t label[27];
uint32_t vol_bkup;
uint16_t vol_seq_num;
uint32_t wr_cnt;
uint32_t xt_clump_size;
uint32_t ct_clump_size;
uint16_t num_root_dirs;
uint32_t file_count;
uint32_t dir_count;
struct hfs_finder_info finder_info;
uint8_t embed_sig[2];
uint16_t embed_startblock;
uint16_t embed_blockcount;
} __attribute__((packed));
#define HFS_NODE_LEAF 0xff
#define HFSPLUS_POR_CNID 1
struct hfsplus_bnode_descriptor {
uint32_t next;
uint32_t prev;
uint8_t type;
uint8_t height;
uint16_t num_recs;
uint16_t reserved;
} __attribute__((packed));
struct hfsplus_bheader_record {
uint16_t depth;
uint32_t root;
uint32_t leaf_count;
uint32_t leaf_head;
uint32_t leaf_tail;
uint16_t node_size;
} __attribute__((packed));
struct hfsplus_catalog_key {
uint16_t key_len;
uint32_t parent_id;
uint16_t unicode_len;
uint8_t unicode[255 * 2];
} __attribute__((packed));
struct hfsplus_extent {
uint32_t start_block;
uint32_t block_count;
} __attribute__((packed));
#define HFSPLUS_EXTENT_COUNT 8
struct hfsplus_fork {
uint64_t total_size;
uint32_t clump_size;
uint32_t total_blocks;
struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
} __attribute__((packed));
struct hfsplus_vol_header {
uint8_t signature[2];
uint16_t version;
uint32_t attributes;
uint32_t last_mount_vers;
uint32_t reserved;
uint32_t create_date;
uint32_t modify_date;
uint32_t backup_date;
uint32_t checked_date;
uint32_t file_count;
uint32_t folder_count;
uint32_t blocksize;
uint32_t total_blocks;
uint32_t free_blocks;
uint32_t next_alloc;
uint32_t rsrc_clump_sz;
uint32_t data_clump_sz;
uint32_t next_cnid;
uint32_t write_count;
uint64_t encodings_bmp;
struct hfs_finder_info finder_info;
struct hfsplus_fork alloc_file;
struct hfsplus_fork ext_file;
struct hfsplus_fork cat_file;
struct hfsplus_fork attr_file;
struct hfsplus_fork start_file;
} __attribute__((packed));
#define HFSPLUS_SECTOR_SIZE 512
static int hfs_set_uuid(blkid_probe pr, unsigned char const *hfs_info, size_t len)
{
static unsigned char const hash_init[MD5LENGTH] = {
0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6,
0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
};
unsigned char uuid[MD5LENGTH];
struct MD5Context md5c;
if (memcmp(hfs_info, "\0\0\0\0\0\0\0\0", len) == 0)
return -1;
MD5Init(&md5c);
MD5Update(&md5c, hash_init, MD5LENGTH);
MD5Update(&md5c, hfs_info, len);
MD5Final(uuid, &md5c);
uuid[6] = 0x30 | (uuid[6] & 0x0f);
uuid[8] = 0x80 | (uuid[8] & 0x3f);
return blkid_probe_set_uuid(pr, uuid);
}
static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct hfs_mdb *hfs;
hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
if (!hfs)
return -1;
if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
(memcmp(hfs->embed_sig, "HX", 2) == 0))
return 1; /* Not hfs, but an embedded HFS+ */
hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id));
blkid_probe_set_label(pr, hfs->label, hfs->label_len);
return 0;
}
static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag)
{
struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
struct hfsplus_bnode_descriptor *descr;
struct hfsplus_bheader_record *bnode;
struct hfsplus_catalog_key *key;
struct hfsplus_vol_header *hfsplus;
struct hfs_mdb *sbd;
unsigned int alloc_block_size;
unsigned int alloc_first_block;
unsigned int embed_first_block;
unsigned int off = 0;
unsigned int blocksize;
unsigned int cat_block;
unsigned int ext_block_start;
unsigned int ext_block_count;
unsigned int record_count;
unsigned int leaf_node_head;
unsigned int leaf_node_count;
unsigned int leaf_node_size;
unsigned int leaf_block;
int ext;
uint64_t leaf_off;
unsigned char *buf;
sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
if (!sbd)
return -1;
/* Check for a HFS+ volume embedded in a HFS volume */
if (memcmp(sbd->signature, "BD", 2) == 0) {
if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
(memcmp(sbd->embed_sig, "HX", 2) != 0))
/* This must be an HFS volume, so fail */
return 1;
alloc_block_size = be32_to_cpu(sbd->al_blk_size);
alloc_first_block = be16_to_cpu(sbd->al_bl_st);
embed_first_block = be16_to_cpu(sbd->embed_startblock);
off = (alloc_first_block * 512) +
(embed_first_block * alloc_block_size);
buf = blkid_probe_get_buffer(pr,
off + (mag->kboff * 1024),
sizeof(struct hfsplus_vol_header));
hfsplus = (struct hfsplus_vol_header *) buf;
} else
hfsplus = blkid_probe_get_sb(pr, mag,
struct hfsplus_vol_header);
if (!hfsplus)
return -1;
if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
(memcmp(hfsplus->signature, "HX", 2) != 0))
return 1;
hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id));
blocksize = be32_to_cpu(hfsplus->blocksize);
if (blocksize < HFSPLUS_SECTOR_SIZE)
return -1;
memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
cat_block = be32_to_cpu(extents[0].start_block);
buf = blkid_probe_get_buffer(pr,
off + ((blkid_loff_t) cat_block * blocksize), 0x2000);
if (!buf)
return 0;
bnode = (struct hfsplus_bheader_record *)
&buf[sizeof(struct hfsplus_bnode_descriptor)];
leaf_node_head = be32_to_cpu(bnode->leaf_head);
leaf_node_size = be16_to_cpu(bnode->node_size);
leaf_node_count = be32_to_cpu(bnode->leaf_count);
if (leaf_node_count == 0)
return 0;
leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
/* get physical location */
for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
ext_block_start = be32_to_cpu(extents[ext].start_block);
ext_block_count = be32_to_cpu(extents[ext].block_count);
if (ext_block_count == 0)
return 0;
/* this is our extent */
if (leaf_block < ext_block_count)
break;
leaf_block -= ext_block_count;
}
if (ext == HFSPLUS_EXTENT_COUNT)
return 0;
leaf_off = (ext_block_start + leaf_block) * blocksize;
buf = blkid_probe_get_buffer(pr,
(blkid_loff_t) off + leaf_off,
leaf_node_size);
if (!buf)
return 0;
descr = (struct hfsplus_bnode_descriptor *) buf;
record_count = be16_to_cpu(descr->num_recs);
if (record_count == 0)
return 0;
if (descr->type != HFS_NODE_LEAF)
return 0;
key = (struct hfsplus_catalog_key *)
&buf[sizeof(struct hfsplus_bnode_descriptor)];
if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
return 0;
blkid_probe_set_utf8label(pr, key->unicode,
be16_to_cpu(key->unicode_len) * 2,
BLKID_ENC_UTF16BE);
return 0;
}
const struct blkid_idinfo hfs_idinfo =
{
.name = "hfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_hfs,
.flags = BLKID_IDINFO_TOLERANT,
.magics =
{
{ .magic = "BD", .len = 2, .kboff = 1 },
{ NULL }
}
};
const struct blkid_idinfo hfsplus_idinfo =
{
.name = "hfsplus",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_hfsplus,
.magics =
{
{ .magic = "BD", .len = 2, .kboff = 1 },
{ .magic = "H+", .len = 2, .kboff = 1 },
{ .magic = "HX", .len = 2, .kboff = 1 },
{ NULL }
}
};
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct hpt45x_metadata {
uint32_t magic;
};
#define HPT45X_MAGIC_OK 0x5a7816f3
#define HPT45X_MAGIC_BAD 0x5a7816fd
static int probe_highpoint45x(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct hpt45x_metadata *hpt;
uint64_t off;
uint32_t magic;
if (pr->size < 0x10000)
return -1;
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
off = ((pr->size / 0x200) - 11) * 0x200;
hpt = (struct hpt45x_metadata *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct hpt45x_metadata));
if (!hpt)
return -1;
magic = le32_to_cpu(hpt->magic);
if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(hpt->magic),
(unsigned char *) &hpt->magic))
return -1;
return 0;
}
static int probe_highpoint37x(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
return 0;
}
const struct blkid_idinfo highpoint45x_idinfo = {
.name = "hpt45x_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_highpoint45x,
.magics = BLKID_NONE_MAGIC
};
const struct blkid_idinfo highpoint37x_idinfo = {
.name = "hpt37x_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_highpoint37x,
.magics = {
/*
* Superblok offset: 4608 bytes (9 sectors)
* Magic string offset within superblock: 32 bytes
*
* kboff = (4608 + 32) / 1024
* sboff = (4608 + 32) % kboff
*/
{ .magic = "\xf0\x16\x78\x5a", .len = 4, .kboff = 4, .sboff = 544 },
{ .magic = "\xfd\x16\x78\x5a", .len = 4, .kboff = 4, .sboff = 544 },
{ NULL }
}
};
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct hpfs_boot_block
{
uint8_t jmp[3];
uint8_t oem_id[8];
uint8_t bytes_per_sector[2];
uint8_t sectors_per_cluster;
uint8_t n_reserved_sectors[2];
uint8_t n_fats;
uint8_t n_rootdir_entries[2];
uint8_t n_sectors_s[2];
uint8_t media_byte;
uint16_t sectors_per_fat;
uint16_t sectors_per_track;
uint16_t heads_per_cyl;
uint32_t n_hidden_sectors;
uint32_t n_sectors_l;
uint8_t drive_number;
uint8_t mbz;
uint8_t sig_28h;
uint8_t vol_serno[4];
uint8_t vol_label[11];
uint8_t sig_hpfs[8];
uint8_t pad[448];
uint8_t magic[2];
} __attribute__((packed));
struct hpfs_super_block
{
uint8_t magic[4];
uint8_t magic1[4];
uint8_t version;
} __attribute__((packed));
struct hpfs_spare_super
{
uint8_t magic[4];
uint8_t magic1[4];
} __attribute__((packed));
#define HPFS_SB_OFFSET 0x2000
#define HPFS_SBSPARE_OFFSET 0x2200
static int probe_hpfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct hpfs_super_block *hs;
struct hpfs_spare_super *hss;
struct hpfs_boot_block *hbb;
uint8_t version;
/* super block */
hs = blkid_probe_get_sb(pr, mag, struct hpfs_super_block);
if (!hs)
return -1;
version = hs->version;
/* spare super block */
hss = (struct hpfs_spare_super *)
blkid_probe_get_buffer(pr,
HPFS_SBSPARE_OFFSET,
sizeof(struct hpfs_spare_super));
if (!hss)
return -1;
if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0)
return -1;
/* boot block (with UUID and LABEL) */
hbb = (struct hpfs_boot_block *)
blkid_probe_get_buffer(pr,
0,
sizeof(struct hpfs_boot_block));
if (!hbb)
return -1;
if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 &&
memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 &&
hbb->sig_28h == 0x28) {
blkid_probe_set_label(pr, hbb->vol_label, sizeof(hbb->vol_label));
blkid_probe_sprintf_uuid(pr,
hbb->vol_serno, sizeof(hbb->vol_serno),
"%02X%02X-%02X%02X",
hbb->vol_serno[3], hbb->vol_serno[2],
hbb->vol_serno[1], hbb->vol_serno[0]);
}
blkid_probe_sprintf_version(pr, "%u", version);
return 0;
}
const struct blkid_idinfo hpfs_idinfo =
{
.name = "hpfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_hpfs,
.magics =
{
{
.magic = "\x49\xe8\x95\xf9",
.len = 4,
.kboff = (HPFS_SB_OFFSET >> 10)
},
{ NULL }
}
};
+74
View File
@@ -0,0 +1,74 @@
/*
* ioctl based topology -- gathers topology information
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include "topology.h"
/*
* ioctl topology values
*/
static struct topology_val {
long ioc;
/* functions to set probing result */
int (*set_ulong)(blkid_probe, unsigned long);
int (*set_int)(blkid_probe, int);
} topology_vals[] = {
{ BLKALIGNOFF, NULL, blkid_topology_set_alignment_offset },
{ BLKIOMIN, blkid_topology_set_minimum_io_size },
{ BLKIOOPT, blkid_topology_set_optimal_io_size },
{ BLKPBSZGET, blkid_topology_set_physical_sector_size }
/* we read BLKSSZGET in topology.c */
};
static int probe_ioctl_tp(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
size_t i;
for (i = 0; i < ARRAY_SIZE(topology_vals); i++) {
struct topology_val *val = &topology_vals[i];
int rc = 1;
unsigned int data;
if (ioctl(pr->fd, val->ioc, &data) == -1)
goto nothing;
if (val->set_int)
rc = val->set_int(pr, (int) data);
else
rc = val->set_ulong(pr, (unsigned long) data);
if (rc)
goto err;
}
return 0;
nothing:
return 1;
err:
return -1;
}
const struct blkid_idinfo ioctl_tp_idinfo =
{
.name = "ioctl",
.probefunc = probe_ioctl_tp,
.magics = BLKID_NONE_MAGIC
};
+387
View File
@@ -0,0 +1,387 @@
/*
* ismounted.c --- Check to see if the filesystem was mounted
*
* Copyright (C) 1995,1996,1997,1998,1999,2000,2008 Theodore Ts'o.
*
* This file may be redistributed under the terms of the GNU Public
* License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/param.h>
#ifdef __APPLE__
#include <sys/ucred.h>
#include <sys/mount.h>
#endif
#include "pathnames.h"
#include "ismounted.h"
#include "c.h"
#ifdef __linux__
# include "loopdev.h"
#endif
#ifdef HAVE_MNTENT_H
/*
* Helper function which checks a file in /etc/mtab format to see if a
* filesystem is mounted. Returns an error if the file doesn't exist
* or can't be opened.
*/
static int check_mntent_file(const char *mtab_file, const char *file,
int *mount_flags, char *mtpt, int mtlen)
{
struct mntent *mnt;
struct stat st_buf;
int retval = 0;
dev_t file_dev=0, file_rdev=0;
ino_t file_ino=0;
FILE *f;
int fd;
*mount_flags = 0;
if ((f = setmntent (mtab_file, "r")) == NULL)
return errno;
if (stat(file, &st_buf) == 0) {
if (S_ISBLK(st_buf.st_mode)) {
#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
file_rdev = st_buf.st_rdev;
#endif /* __GNU__ */
} else {
file_dev = st_buf.st_dev;
file_ino = st_buf.st_ino;
}
}
while ((mnt = getmntent (f)) != NULL) {
if (mnt->mnt_fsname[0] != '/')
continue;
if (strcmp(file, mnt->mnt_fsname) == 0)
break;
if (stat(mnt->mnt_fsname, &st_buf) != 0)
continue;
if (S_ISBLK(st_buf.st_mode)) {
#ifndef __GNU__
if (file_rdev && file_rdev == st_buf.st_rdev)
break;
#ifdef __linux__
/* maybe the file is loopdev backing file */
if (file_dev
&& major(st_buf.st_rdev) == LOOPDEV_MAJOR
&& loopdev_is_used(mnt->mnt_fsname, file, 0, 0))
break;
#endif /* __linux__ */
#endif /* __GNU__ */
} else {
if (file_dev && ((file_dev == st_buf.st_dev) &&
(file_ino == st_buf.st_ino)))
break;
}
}
if (mnt == NULL) {
#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
/*
* Do an extra check to see if this is the root device. We
* can't trust /etc/mtab, and /proc/mounts will only list
* /dev/root for the root filesystem. Argh. Instead we
* check if the given device has the same major/minor number
* as the device that the root directory is on.
*/
if (file_rdev && stat("/", &st_buf) == 0 &&
st_buf.st_dev == file_rdev) {
*mount_flags = MF_MOUNTED;
if (mtpt)
strncpy(mtpt, "/", mtlen);
goto is_root;
}
#endif /* __GNU__ */
goto errout;
}
#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
/* Validate the entry in case /etc/mtab is out of date */
/*
* We need to be paranoid, because some broken distributions
* (read: Slackware) don't initialize /etc/mtab before checking
* all of the non-root filesystems on the disk.
*/
if (stat(mnt->mnt_dir, &st_buf) < 0) {
retval = errno;
if (retval == ENOENT) {
#ifdef DEBUG
printf("Bogus entry in %s! (%s does not exist)\n",
mtab_file, mnt->mnt_dir);
#endif /* DEBUG */
retval = 0;
}
goto errout;
}
if (file_rdev && (st_buf.st_dev != file_rdev)) {
#ifdef DEBUG
printf("Bogus entry in %s! (%s not mounted on %s)\n",
mtab_file, file, mnt->mnt_dir);
#endif /* DEBUG */
goto errout;
}
#endif /* __GNU__ */
*mount_flags = MF_MOUNTED;
#ifdef MNTOPT_RO
/* Check to see if the ro option is set */
if (hasmntopt(mnt, MNTOPT_RO))
*mount_flags |= MF_READONLY;
#endif
if (mtpt)
strncpy(mtpt, mnt->mnt_dir, mtlen);
/*
* Check to see if we're referring to the root filesystem.
* If so, do a manual check to see if we can open /etc/mtab
* read/write, since if the root is mounted read/only, the
* contents of /etc/mtab may not be accurate.
*/
if (!strcmp(mnt->mnt_dir, "/")) {
is_root:
#define TEST_FILE "/.ismount-test-file"
*mount_flags |= MF_ISROOT;
fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600);
if (fd < 0) {
if (errno == EROFS)
*mount_flags |= MF_READONLY;
} else
close(fd);
(void) unlink(TEST_FILE);
}
retval = 0;
errout:
endmntent (f);
return retval;
}
static int check_mntent(const char *file, int *mount_flags,
char *mtpt, int mtlen)
{
int retval;
#ifdef DEBUG
retval = check_mntent_file("/tmp/mtab", file, mount_flags,
mtpt, mtlen);
if (retval == 0)
return 0;
#endif /* DEBUG */
#ifdef __linux__
retval = check_mntent_file("/proc/mounts", file, mount_flags,
mtpt, mtlen);
if (retval == 0 && (*mount_flags != 0))
return 0;
if (access("/proc/mounts", R_OK) == 0) {
*mount_flags = 0;
return retval;
}
#endif /* __linux__ */
#if defined(MOUNTED) || defined(_PATH_MOUNTED)
#ifndef MOUNTED
#define MOUNTED _PATH_MOUNTED
#endif /* MOUNTED */
retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
return retval;
#else
*mount_flags = 0;
return 0;
#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
}
#else
#if defined(HAVE_GETMNTINFO)
static int check_getmntinfo(const char *file, int *mount_flags,
char *mtpt, int mtlen)
{
struct statfs *mp;
int len, n;
const char *s1;
char *s2;
n = getmntinfo(&mp, MNT_NOWAIT);
if (n == 0)
return errno;
len = sizeof(_PATH_DEV) - 1;
s1 = file;
if (strncmp(_PATH_DEV, s1, len) == 0)
s1 += len;
*mount_flags = 0;
while (--n >= 0) {
s2 = mp->f_mntfromname;
if (strncmp(_PATH_DEV, s2, len) == 0) {
s2 += len - 1;
*s2 = 'r';
}
if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
*mount_flags = MF_MOUNTED;
break;
}
++mp;
}
if (mtpt)
strncpy(mtpt, mp->f_mntonname, mtlen);
return 0;
}
#endif /* HAVE_GETMNTINFO */
#endif /* HAVE_MNTENT_H */
/*
* Check to see if we're dealing with the swap device.
*/
static int is_swap_device(const char *file)
{
FILE *f;
char buf[1024], *cp;
dev_t file_dev;
struct stat st_buf;
int ret = 0;
file_dev = 0;
#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
if ((stat(file, &st_buf) == 0) &&
S_ISBLK(st_buf.st_mode))
file_dev = st_buf.st_rdev;
#endif /* __GNU__ */
if (!(f = fopen("/proc/swaps", "r")))
return 0;
/* Skip the first line */
if (!fgets(buf, sizeof(buf), f))
goto leave;
if (*buf && strncmp(buf, "Filename\t", 9))
/* Linux <=2.6.19 contained a bug in the /proc/swaps
* code where the header would not be displayed
*/
goto valid_first_line;
while (fgets(buf, sizeof(buf), f)) {
valid_first_line:
if ((cp = strchr(buf, ' ')) != NULL)
*cp = 0;
if ((cp = strchr(buf, '\t')) != NULL)
*cp = 0;
if (strcmp(buf, file) == 0) {
ret++;
break;
}
#ifndef __GNU__
if (file_dev && (stat(buf, &st_buf) == 0) &&
S_ISBLK(st_buf.st_mode) &&
file_dev == st_buf.st_rdev) {
ret++;
break;
}
#endif /* __GNU__ */
}
leave:
fclose(f);
return ret;
}
/*
* check_mount_point() fills determines if the device is mounted or otherwise
* busy, and fills in mount_flags with one or more of the following flags:
* MF_MOUNTED, MF_ISROOT, MF_READONLY, MF_SWAP, and MF_BUSY. If mtpt is
* non-NULL, the directory where the device is mounted is copied to where mtpt
* is pointing, up to mtlen characters.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
int check_mount_point(const char *device, int *mount_flags,
char *mtpt, int mtlen)
{
struct stat st_buf;
int retval = 0;
int fd;
if (is_swap_device(device)) {
*mount_flags = MF_MOUNTED | MF_SWAP;
strncpy(mtpt, "<swap>", mtlen);
} else {
#ifdef HAVE_MNTENT_H
retval = check_mntent(device, mount_flags, mtpt, mtlen);
#else
#ifdef HAVE_GETMNTINFO
retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
#else
#ifdef __GNUC__
#warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
#endif
*mount_flags = 0;
#endif /* HAVE_GETMNTINFO */
#endif /* HAVE_MNTENT_H */
}
if (retval)
return retval;
#ifdef __linux__ /* This only works on Linux 2.6+ systems */
if ((stat(device, &st_buf) != 0) ||
!S_ISBLK(st_buf.st_mode))
return 0;
fd = open(device, O_RDONLY | O_EXCL);
if (fd < 0) {
if (errno == EBUSY)
*mount_flags |= MF_BUSY;
} else
close(fd);
#endif
return 0;
}
int is_mounted(const char *file)
{
int retval;
int mount_flags = 0;
retval = check_mount_point(file, &mount_flags, NULL, 0);
if (retval)
return 0;
return mount_flags & MF_MOUNTED;
}
#ifdef TEST_PROGRAM
int main(int argc, char **argv)
{
int flags = 0;
char devname[PATH_MAX];
if (argc < 2) {
fprintf(stderr, "Usage: %s device\n", argv[0]);
return EXIT_FAILURE;
}
if (check_mount_point(argv[1], &flags, devname, sizeof(devname)) == 0 &&
(flags & MF_MOUNTED)) {
if (flags & MF_SWAP)
printf("used swap device\n");
else
printf("mounted on %s\n", devname);
return EXIT_SUCCESS;
}
printf("not mounted\n");
return EXIT_FAILURE;
}
#endif /* DEBUG */
+14
View File
@@ -0,0 +1,14 @@
#ifndef IS_MOUNTED_H
#define IS_MOUNTED_H
#define MF_MOUNTED 1
#define MF_ISROOT 2
#define MF_READONLY 4
#define MF_SWAP 8
#define MF_BUSY 16
extern int is_mounted(const char *file);
extern int check_mount_point(const char *device, int *mount_flags,
char *mtpt, int mtlen);
#endif /* IS_MOUNTED_H */
+273
View File
@@ -0,0 +1,273 @@
/*
* Copyright (C) 1999 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2001 by Andreas Dilger
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired also by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include "superblocks.h"
struct iso9660_date {
unsigned char year[4];
unsigned char month[2];
unsigned char day[2];
unsigned char hour[2];
unsigned char minute[2];
unsigned char second[2];
unsigned char hundredth[2];
unsigned char offset;
} __attribute__ ((packed));
/* PVD - Primary volume descriptor */
struct iso_volume_descriptor {
unsigned char vd_type;
unsigned char vd_id[5];
unsigned char vd_version;
unsigned char flags;
unsigned char system_id[32];
unsigned char volume_id[32];
unsigned char unused[8];
unsigned char space_size[8];
unsigned char escape_sequences[8];
unsigned char unused1[222];
unsigned char publisher_id[128];
unsigned char unused2[128];
unsigned char application_id[128];
unsigned char unused3[111];
struct iso9660_date created;
struct iso9660_date modified;
} __attribute__((packed));
/* Boot Record */
struct boot_record {
unsigned char vd_type;
unsigned char vd_id[5];
unsigned char vd_version;
unsigned char boot_system_id[32];
unsigned char boot_id[32];
unsigned char unused[1];
} __attribute__((packed));
#define ISO_SUPERBLOCK_OFFSET 0x8000
#define ISO_SECTOR_SIZE 0x800
#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
#define ISO_VD_BOOT_RECORD 0x0
#define ISO_VD_SUPPLEMENTARY 0x2
#define ISO_VD_END 0xff
#define ISO_VD_MAX 16
struct high_sierra_volume_descriptor {
unsigned char foo[8];
unsigned char type;
unsigned char id[5];
unsigned char version;
unsigned char unused1;
unsigned char system_id[32];
unsigned char volume_id[32];
} __attribute__((packed));
/* returns 1 if the begin of @ascii is equal to @utf16 string.
*/
static int ascii_eq_utf16be(unsigned char *ascii,
unsigned char *utf16, size_t len)
{
size_t a, u;
for (a = 0, u = 0; u < len; a++, u += 2) {
if (utf16[u] != 0x0 || ascii[a] != utf16[u + 1])
return 0;
}
return 1;
}
/* old High Sierra format */
static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct high_sierra_volume_descriptor *iso;
iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor);
if (!iso)
return -1;
blkid_probe_set_version(pr, "High Sierra");
blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id));
return 0;
}
static int probe_iso9660_set_uuid (blkid_probe pr, const struct iso9660_date *date)
{
unsigned char buffer[16];
unsigned int i, zeros = 0;
buffer[0] = date->year[0];
buffer[1] = date->year[1];
buffer[2] = date->year[2];
buffer[3] = date->year[3];
buffer[4] = date->month[0];
buffer[5] = date->month[1];
buffer[6] = date->day[0];
buffer[7] = date->day[1];
buffer[8] = date->hour[0];
buffer[9] = date->hour[1];
buffer[10] = date->minute[0];
buffer[11] = date->minute[1];
buffer[12] = date->second[0];
buffer[13] = date->second[1];
buffer[14] = date->hundredth[0];
buffer[15] = date->hundredth[1];
/* count the number of zeros ('0') in the date buffer */
for (i = 0, zeros = 0; i < sizeof(buffer); i++)
if (buffer[i] == '0')
zeros++;
/* due to the iso9660 standard if all date fields are '0' and offset is 0, the date is unset */
if (zeros == sizeof(buffer) && date->offset == 0)
return 0;
/* generate an UUID using this date and return success */
blkid_probe_sprintf_uuid (pr, buffer, sizeof(buffer),
"%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c",
buffer[0], buffer[1], buffer[2], buffer[3],
buffer[4], buffer[5],
buffer[6], buffer[7],
buffer[8], buffer[9],
buffer[10], buffer[11],
buffer[12], buffer[13],
buffer[14], buffer[15]);
return 1;
}
static int is_str_empty(const unsigned char *str, size_t len)
{
size_t i;
if (!str || !*str)
return 1;
for (i = 0; i < len; i++)
if (!isspace(str[i]))
return 0;
return 1;
}
/* iso9660 [+ Microsoft Joliet Extension] */
int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
{
struct iso_volume_descriptor *iso;
unsigned char label[32];
int i;
int off;
if (strcmp(mag->magic, "CDROM") == 0)
return probe_iso9660_hsfs(pr, mag);
iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor);
if (!iso)
return -1;
memcpy(label, iso->volume_id, sizeof(label));
if (!is_str_empty(iso->system_id, sizeof(iso->system_id)))
blkid_probe_set_id_label(pr, "SYSTEM_ID",
iso->system_id, sizeof(iso->system_id));
if (!is_str_empty(iso->publisher_id, sizeof(iso->publisher_id)))
blkid_probe_set_id_label(pr, "PUBLISHER_ID",
iso->publisher_id, sizeof(iso->publisher_id));
if (!is_str_empty(iso->application_id, sizeof(iso->application_id)))
blkid_probe_set_id_label(pr, "APPLICATION_ID",
iso->application_id, sizeof(iso->application_id));
/* create an UUID using the modified/created date */
if (! probe_iso9660_set_uuid(pr, &iso->modified))
probe_iso9660_set_uuid(pr, &iso->created);
/* Joliet Extension and Boot Record */
off = ISO_VD_OFFSET;
for (i = 0; i < ISO_VD_MAX; i++) {
struct boot_record *boot= (struct boot_record *)
blkid_probe_get_buffer(pr,
off,
max(sizeof(struct boot_record),
sizeof(struct iso_volume_descriptor)));
if (boot == NULL || boot->vd_type == ISO_VD_END)
break;
if (boot->vd_type == ISO_VD_BOOT_RECORD) {
if (!is_str_empty(boot->boot_system_id,
sizeof(boot->boot_system_id)))
blkid_probe_set_id_label(pr, "BOOT_SYSTEM_ID",
boot->boot_system_id,
sizeof(boot->boot_system_id));
off += ISO_SECTOR_SIZE;
continue;
}
/* Not a Boot record, lets see if its supplemntary volume descriptor */
iso = (struct iso_volume_descriptor *) boot;
if (iso->vd_type != ISO_VD_SUPPLEMENTARY) {
off += ISO_SECTOR_SIZE;
continue;
}
if (memcmp(iso->escape_sequences, "%/@", 3) == 0 ||
memcmp(iso->escape_sequences, "%/C", 3) == 0 ||
memcmp(iso->escape_sequences, "%/E", 3) == 0) {
blkid_probe_set_version(pr, "Joliet Extension");
/* Is the Joliet (UTF16BE) label equal to the label in
* the PVD? If yes, use PVD label. The Jolied version
* of the label could be trimed (because UTF16..).
*/
if (ascii_eq_utf16be(label, iso->volume_id, 32))
break;
blkid_probe_set_utf8label(pr,
iso->volume_id,
sizeof(iso->volume_id),
BLKID_ENC_UTF16BE);
goto has_label;
}
off += ISO_SECTOR_SIZE;
}
/* Joliet not found, let use standard iso label */
blkid_probe_set_label(pr, label, sizeof(label));
has_label:
return 0;
}
const struct blkid_idinfo iso9660_idinfo =
{
.name = "iso9660",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_iso9660,
.flags = BLKID_IDINFO_TOLERANT,
.magics =
{
{ .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
{ .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9 },
{ NULL }
}
};
+14
View File
@@ -0,0 +1,14 @@
/*
* Copyright (C) 2013 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#ifndef _BLKID_ISO9660_H
#define _BLKID_ISO9660_H
#include "blkidP.h"
extern int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag);
#endif /* _BLKID_ISO9660_H */
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct isw_metadata {
uint8_t sig[32];
uint32_t check_sum;
uint32_t mpb_size;
uint32_t family_num;
uint32_t generation_num;
};
#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. "
static int probe_iswraid(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
uint64_t off;
struct isw_metadata *isw;
if (pr->size < 0x10000)
return -1;
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
off = ((pr->size / 0x200) - 2) * 0x200;
isw = (struct isw_metadata *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct isw_metadata));
if (!isw)
return -1;
if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
return -1;
if (blkid_probe_sprintf_version(pr, "%6s",
&isw->sig[sizeof(ISW_SIGNATURE)-1]) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(isw->sig),
(unsigned char *) isw->sig))
return -1;
return 0;
}
const struct blkid_idinfo iswraid_idinfo = {
.name = "isw_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_iswraid,
.magics = BLKID_NONE_MAGIC
};
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (C) 1999 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2001 by Andreas Dilger
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
#include "superblocks.h"
struct jfs_super_block {
unsigned char js_magic[4];
uint32_t js_version;
uint64_t js_size;
uint32_t js_bsize; /* 4: aggregate block size in bytes */
uint16_t js_l2bsize; /* 2: log2 of s_bsize */
uint16_t js_l2bfactor; /* 2: log2(s_bsize/hardware block size) */
uint32_t js_pbsize; /* 4: hardware/LVM block size in bytes */
uint16_t js_l2pbsize; /* 2: log2 of s_pbsize */
uint16_t js_pad; /* 2: padding necessary for alignment */
uint32_t js_dummy2[26];
unsigned char js_uuid[16];
unsigned char js_label[16];
unsigned char js_loguuid[16];
};
static int probe_jfs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct jfs_super_block *js;
js = blkid_probe_get_sb(pr, mag, struct jfs_super_block);
if (!js)
return -1;
if (le32_to_cpu(js->js_bsize) != (1U << le16_to_cpu(js->js_l2bsize)))
return 1;
if (le32_to_cpu(js->js_pbsize) != (1U << le16_to_cpu(js->js_l2pbsize)))
return 1;
if ((le16_to_cpu(js->js_l2bsize) - le16_to_cpu(js->js_l2pbsize)) !=
le16_to_cpu(js->js_l2bfactor))
return 1;
if (strlen((char *) js->js_label))
blkid_probe_set_label(pr, js->js_label, sizeof(js->js_label));
blkid_probe_set_uuid(pr, js->js_uuid);
return 0;
}
const struct blkid_idinfo jfs_idinfo =
{
.name = "jfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_jfs,
.minsz = 16 * 1024 * 1024,
.magics =
{
{ .magic = "JFS1", .len = 4, .kboff = 32 },
{ NULL }
}
};
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct jm_metadata {
int8_t signature[2];
uint8_t minor_version;
uint8_t major_version;
uint16_t checksum;
};
#define JM_SIGNATURE "JM"
static int probe_jmraid(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
uint64_t off;
struct jm_metadata *jm;
if (pr->size < 0x10000)
return -1;
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
off = ((pr->size / 0x200) - 1) * 0x200;
jm = (struct jm_metadata *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct jm_metadata));
if (!jm)
return -1;
if (memcmp(jm->signature, JM_SIGNATURE, sizeof(JM_SIGNATURE) - 1) != 0)
return -1;
if (blkid_probe_sprintf_version(pr, "%u.%u",
jm->major_version, jm->minor_version) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(jm->signature),
(unsigned char *) jm->signature))
return -1;
return 0;
}
const struct blkid_idinfo jmraid_idinfo = {
.name = "jmicron_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_jmraid,
.magics = BLKID_NONE_MAGIC
};
+121
View File
@@ -0,0 +1,121 @@
/*
* This is callback solution for systems without nl_langinfo(), this function
* returns hardcoded and on locale setting independed value.
*
* See langinfo.h man page for more details.
*
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*/
#include "nls.h"
char *langinfo_fallback(nl_item item)
{
switch (item) {
case CODESET:
return "ISO-8859-1";
case THOUSEP:
return ",";
case D_T_FMT:
case ERA_D_T_FMT:
return "%a %b %e %H:%M:%S %Y";
case D_FMT:
case ERA_D_FMT:
return "%m/%d/%y";
case T_FMT:
case ERA_T_FMT:
return "%H:%M:%S";
case T_FMT_AMPM:
return "%I:%M:%S %p";
case AM_STR:
return "AM";
case PM_STR:
return "PM";
case DAY_1:
return "Sunday";
case DAY_2:
return "Monday";
case DAY_3:
return "Tuesday";
case DAY_4:
return "Wednesday";
case DAY_5:
return "Thursday";
case DAY_6:
return "Friday";
case DAY_7:
return "Saturday";
case ABDAY_1:
return "Sun";
case ABDAY_2:
return "Mon";
case ABDAY_3:
return "Tue";
case ABDAY_4:
return "Wed";
case ABDAY_5:
return "Thu";
case ABDAY_6:
return "Fri";
case ABDAY_7:
return "Sat";
case MON_1:
return "January";
case MON_2:
return "February";
case MON_3:
return "March";
case MON_4:
return "April";
case MON_5:
return "May";
case MON_6:
return "June";
case MON_7:
return "July";
case MON_8:
return "August";
case MON_9:
return "September";
case MON_10:
return "October";
case MON_11:
return "November";
case MON_12:
return "December";
case ABMON_1:
return "Jan";
case ABMON_2:
return "Feb";
case ABMON_3:
return "Mar";
case ABMON_4:
return "Apr";
case ABMON_5:
return "May";
case ABMON_6:
return "Jun";
case ABMON_7:
return "Jul";
case ABMON_8:
return "Aug";
case ABMON_9:
return "Sep";
case ABMON_10:
return "Oct";
case ABMON_11:
return "Nov";
case ABMON_12:
return "Dec";
case ALT_DIGITS:
return "\0\0\0\0\0\0\0\0\0\0";
case CRNCYSTR:
return "-";
case YESEXPR:
return "^[yY]";
case NOEXPR:
return "^[nN]";
default:
return "";
}
}
+258
View File
@@ -0,0 +1,258 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct mdp0_super_block {
uint32_t md_magic;
uint32_t major_version;
uint32_t minor_version;
uint32_t patch_version;
uint32_t gvalid_words;
uint32_t set_uuid0;
uint32_t ctime;
uint32_t level;
uint32_t size;
uint32_t nr_disks;
uint32_t raid_disks;
uint32_t md_minor;
uint32_t not_persistent;
uint32_t set_uuid1;
uint32_t set_uuid2;
uint32_t set_uuid3;
};
/*
* Version-1, little-endian.
*/
struct mdp1_super_block {
/* constant array information - 128 bytes */
uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */
uint32_t major_version; /* 1 */
uint32_t feature_map; /* 0 for now */
uint32_t pad0; /* always set to 0 when writing */
uint8_t set_uuid[16]; /* user-space generated. */
unsigned char set_name[32]; /* set and interpreted by user-space */
uint64_t ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/
uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5 */
uint32_t layout; /* only for raid5 currently */
uint64_t size; /* used size of component devices, in 512byte sectors */
uint32_t chunksize; /* in 512byte sectors */
uint32_t raid_disks;
uint32_t bitmap_offset; /* sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
/* These are only valid with feature bit '4' */
uint32_t new_level; /* new level we are reshaping to */
uint64_t reshape_position; /* next address in array-space for reshape */
uint32_t delta_disks; /* change in number of raid_disks */
uint32_t new_layout; /* new layout */
uint32_t new_chunk; /* new chunk size (bytes) */
uint8_t pad1[128-124]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
uint64_t data_offset; /* sector start of data, often 0 */
uint64_t data_size; /* sectors in this device that can be used for data */
uint64_t super_offset; /* sector start of this superblock */
uint64_t recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
uint32_t dev_number; /* permanent identifier of this device - not role in raid */
uint32_t cnt_corrected_read; /* number of read errors that were corrected by re-writing */
uint8_t device_uuid[16]; /* user-space setable, ignored by kernel */
uint8_t devflags; /* per-device flags. Only one defined...*/
uint8_t pad2[64-57]; /* set to 0 when writing */
/* array state information - 64 bytes */
uint64_t utime; /* 40 bits second, 24 btes microseconds */
uint64_t events; /* incremented when superblock updated */
uint64_t resync_offset; /* data before this offset (from data_offset) known to be in sync */
uint32_t sb_csum; /* checksum up to dev_roles[max_dev] */
uint32_t max_dev; /* size of dev_roles[] array to consider */
uint8_t pad3[64-32]; /* set to 0 when writing */
/* device state information. Indexed by dev_number.
* 2 bytes per device
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
uint16_t dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
};
#define MD_RESERVED_BYTES 0x10000
#define MD_SB_MAGIC 0xa92b4efc
static int probe_raid0(blkid_probe pr, blkid_loff_t off)
{
struct mdp0_super_block *mdp0;
union {
uint32_t ints[4];
uint8_t bytes[16];
} uuid;
uint32_t ma, mi, pa;
uint64_t size;
if (pr->size < MD_RESERVED_BYTES)
return -1;
mdp0 = (struct mdp0_super_block *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct mdp0_super_block));
if (!mdp0)
return -1;
memset(uuid.ints, 0, sizeof(uuid.ints));
if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
uuid.ints[0] = swab32(mdp0->set_uuid0);
if (le32_to_cpu(mdp0->minor_version) >= 90) {
uuid.ints[1] = swab32(mdp0->set_uuid1);
uuid.ints[2] = swab32(mdp0->set_uuid2);
uuid.ints[3] = swab32(mdp0->set_uuid3);
}
ma = le32_to_cpu(mdp0->major_version);
mi = le32_to_cpu(mdp0->minor_version);
pa = le32_to_cpu(mdp0->patch_version);
size = le32_to_cpu(mdp0->size);
} else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
uuid.ints[0] = mdp0->set_uuid0;
if (be32_to_cpu(mdp0->minor_version) >= 90) {
uuid.ints[1] = mdp0->set_uuid1;
uuid.ints[2] = mdp0->set_uuid2;
uuid.ints[3] = mdp0->set_uuid3;
}
ma = be32_to_cpu(mdp0->major_version);
mi = be32_to_cpu(mdp0->minor_version);
pa = be32_to_cpu(mdp0->patch_version);
size = be32_to_cpu(mdp0->size);
} else
return 1;
size <<= 10; /* convert KiB to bytes */
if (pr->size < 0 || (uint64_t) pr->size < size + MD_RESERVED_BYTES)
/* device is too small */
return 1;
if (off < 0 || (uint64_t) off < size)
/* no space before superblock */
return 1;
/*
* Check for collisions between RAID and partition table
*
* For example the superblock is at the end of the last partition, it's
* the same position as at the end of the disk...
*/
if ((S_ISREG(pr->mode) || blkid_probe_is_wholedisk(pr)) &&
blkid_probe_is_covered_by_pt(pr,
off - size, /* min. start */
size + MD_RESERVED_BYTES)) { /* min. length */
/* ignore this superblock, it's within any partition and
* we are working with whole-disk now */
return 1;
}
if (blkid_probe_sprintf_version(pr, "%u.%u.%u", ma, mi, pa) != 0)
return -1;
if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(mdp0->md_magic),
(unsigned char *) &mdp0->md_magic))
return -1;
return 0;
}
static int probe_raid1(blkid_probe pr, off_t off)
{
struct mdp1_super_block *mdp1;
mdp1 = (struct mdp1_super_block *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct mdp1_super_block));
if (!mdp1)
return -1;
if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
return -1;
if (le32_to_cpu(mdp1->major_version) != 1U)
return -1;
if (le64_to_cpu(mdp1->super_offset) != (uint64_t) off >> 9)
return -1;
if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0)
return -1;
if (blkid_probe_set_uuid_as(pr,
(unsigned char *) mdp1->device_uuid, "UUID_SUB") != 0)
return -1;
if (blkid_probe_set_label(pr, mdp1->set_name,
sizeof(mdp1->set_name)) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(mdp1->magic),
(unsigned char *) &mdp1->magic))
return -1;
return 0;
}
int probe_raid(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
const char *ver = NULL;
if (pr->size > MD_RESERVED_BYTES) {
/* version 0 at the end of the device */
uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1))
- MD_RESERVED_BYTES;
if (probe_raid0(pr, sboff) == 0)
return 0;
/* version 1.0 at the end of the device */
sboff = (pr->size & ~(0x1000 - 1)) - 0x2000;
if (probe_raid1(pr, sboff) == 0)
ver = "1.0";
}
if (!ver) {
/* version 1.1 at the start of the device */
if (probe_raid1(pr, 0) == 0)
ver = "1.1";
/* version 1.2 at 4k offset from the start */
else if (probe_raid1(pr, 0x1000) == 0)
ver = "1.2";
}
if (ver) {
blkid_probe_set_version(pr, ver);
return 0;
}
return -1;
}
const struct blkid_idinfo linuxraid_idinfo = {
.name = "linux_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_raid,
.magics = BLKID_NONE_MAGIC
};
+72
View File
@@ -0,0 +1,72 @@
#ifndef _LINUX_REBOOT_H
#define _LINUX_REBOOT_H
/*
* Magic values required to use _reboot() system call.
*/
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#define LINUX_REBOOT_MAGIC2 672274793
#define LINUX_REBOOT_MAGIC2A 85072278
#define LINUX_REBOOT_MAGIC2B 369367448
/*
* Commands accepted by the _reboot() system call.
*
* RESTART Restart system using default command and mode.
* HALT Stop OS and give system control to ROM monitor, if any.
* CAD_ON Ctrl-Alt-Del sequence causes RESTART command.
* CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task.
* POWER_OFF Stop OS and remove all power from system, if possible.
* RESTART2 Restart system using given command string.
*/
#define LINUX_REBOOT_CMD_RESTART 0x01234567
#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
/* Including <unistd.h> makes sure that on a glibc system
<features.h> is included, which again defines __GLIBC__ */
#include <unistd.h>
#include "linux_reboot.h"
#define USE_LIBC
#ifdef USE_LIBC
/* libc version */
#if defined __GLIBC__ && __GLIBC__ >= 2
# include <sys/reboot.h>
# define REBOOT(cmd) reboot(cmd)
#else
extern int reboot(int, int, int);
# define REBOOT(cmd) reboot(LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,(cmd))
#endif
static inline int my_reboot(int cmd) {
return REBOOT(cmd);
}
#else /* no USE_LIBC */
/* direct syscall version */
#include <linux/unistd.h>
#ifdef _syscall3
_syscall3(int, reboot, int, magic, int, magic_too, int, cmd);
#else
/* Let us hope we have a 3-argument reboot here */
extern int reboot(int, int, int);
#endif
static inline int my_reboot(int cmd) {
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd);
}
#endif
#endif /* _LINUX_REBOOT_H */
+25
View File
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <sys/utsname.h>
#include "linux_version.h"
int get_linux_version (void)
{
static int kver = -1;
struct utsname uts;
int major = 0;
int minor = 0;
int teeny = 0;
int n;
if (kver != -1)
return kver;
if (uname (&uts))
return kver = 0;
n = sscanf(uts.release, "%d.%d.%d", &major, &minor, &teeny);
if (n < 1 || n > 3)
return kver = 0;
return kver = KERNEL_VERSION(major, minor, teeny);
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef LINUX_VERSION_H
#define LINUX_VERSION_H
#ifdef HAVE_LINUX_VERSION_H
# include <linux/version.h>
#endif
#ifndef KERNEL_VERSION
# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#endif
int get_linux_version(void);
#endif /* LINUX_VERSION_H */
+340
View File
@@ -0,0 +1,340 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
* Copyright (C) 1999-2008 by Theodore Ts'o
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
* (based on list.h from e2fsprogs)
* Merge sort based on kernel's implementation.
*/
#ifndef UTIL_LINUX_LIST_H
#define UTIL_LINUX_LIST_H
/* TODO: use AC_C_INLINE */
#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_entry_is_last - tests whether is entry last in the list
* @entry: the entry to test.
* @head: the list to test.
*/
_INLINE_ int list_entry_is_last(struct list_head *entry, struct list_head *head)
{
return head->prev == entry;
}
/**
* 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) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define list_first_entry(head, type, member) \
((head) && (head)->next != (head) ? list_entry((head)->next, type, member) : NULL)
#define list_last_entry(head, type, member) \
((head) && (head)->prev != (head) ? list_entry((head)->prev, type, member) : NULL)
/**
* 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_backwardly - iterate over elements in a list in reverse
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each_backwardly(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* 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)
#define MAX_LIST_LENGTH_BITS 20
/*
* Returns a list organized in an intermediate format suited
* to chaining of merge() calls: null-terminated, no reserved or
* sentinel head node, "prev" links not maintained.
*/
_INLINE_ struct list_head *merge(int (*cmp)(struct list_head *a,
struct list_head *b),
struct list_head *a, struct list_head *b)
{
struct list_head head, *tail = &head;
while (a && b) {
/* if equal, take 'a' -- important for sort stability */
if ((*cmp)(a, b) <= 0) {
tail->next = a;
a = a->next;
} else {
tail->next = b;
b = b->next;
}
tail = tail->next;
}
tail->next = a ? a : b;
return head.next;
}
/*
* Combine final list merge with restoration of standard doubly-linked
* list structure. This approach duplicates code from merge(), but
* runs faster than the tidier alternatives of either a separate final
* prev-link restoration pass, or maintaining the prev links
* throughout.
*/
_INLINE_ void merge_and_restore_back_links(int (*cmp)(struct list_head *a,
struct list_head *b),
struct list_head *head,
struct list_head *a, struct list_head *b)
{
struct list_head *tail = head;
while (a && b) {
/* if equal, take 'a' -- important for sort stability */
if ((*cmp)(a, b) <= 0) {
tail->next = a;
a->prev = tail;
a = a->next;
} else {
tail->next = b;
b->prev = tail;
b = b->next;
}
tail = tail->next;
}
tail->next = a ? a : b;
do {
/*
* In worst cases this loop may run many iterations.
* Continue callbacks to the client even though no
* element comparison is needed, so the client's cmp()
* routine can invoke cond_resched() periodically.
*/
(*cmp)(tail->next, tail->next);
tail->next->prev = tail;
tail = tail->next;
} while (tail->next);
tail->next = head;
head->prev = tail;
}
/**
* list_sort - sort a list
* @head: the list to sort
* @cmp: the elements comparison function
*
* This function implements "merge sort", which has O(nlog(n))
* complexity.
*
* The comparison function @cmp must return a negative value if @a
* should sort before @b, and a positive value if @a should sort after
* @b. If @a and @b are equivalent, and their original relative
* ordering is to be preserved, @cmp must return 0.
*/
_INLINE_ void list_sort(struct list_head *head,
int (*cmp)(struct list_head *a,
struct list_head *b))
{
struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
-- last slot is a sentinel */
size_t lev; /* index into part[] */
size_t max_lev = 0;
struct list_head *list;
if (list_empty(head))
return;
memset(part, 0, sizeof(part));
head->prev->next = NULL;
list = head->next;
while (list) {
struct list_head *cur = list;
list = list->next;
cur->next = NULL;
for (lev = 0; part[lev]; lev++) {
cur = merge(cmp, part[lev], cur);
part[lev] = NULL;
}
if (lev > max_lev) {
/* list passed to list_sort() too long for efficiency */
if (lev >= ARRAY_SIZE(part) - 1)
lev--;
max_lev = lev;
}
part[lev] = cur;
}
for (lev = 0; lev < max_lev; lev++)
if (part[lev])
list = merge(cmp, part[lev], list);
merge_and_restore_back_links(cmp, head, part[max_lev], list);
}
#undef _INLINE_
#endif /* UTIL_LINUX_LIST_H */
+91
View File
@@ -0,0 +1,91 @@
/*
* 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%
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef __MSDOS__
#include <io.h>
#endif
#include "blkidP.h"
#ifdef __linux__
#define my_llseek lseek64
#include <linux/unistd.h>
#ifndef __NR__llseek
#define __NR__llseek 140
#endif
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;
}
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 */
+73
View File
@@ -0,0 +1,73 @@
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=cm_sunfire
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76L
============================================
No private recovery resources for TARGET_DEVICE sunfire
make: Entering directory `/builds/cm9'
build/core/tasks/kernel.mk:40: ***************************************************************
build/core/tasks/kernel.mk:41: * Using prebuilt kernel binary instead of source *
build/core/tasks/kernel.mk:42: * THIS IS DEPRECATED, AND WILL BE DISCONTINUED *
build/core/tasks/kernel.mk:43: * Please configure your device to download the kernel *
build/core/tasks/kernel.mk:44: * source repository to kernel/moto/sunfire
build/core/tasks/kernel.mk:45: * See http://wiki.cyanogenmod.com/wiki/Integrated_kernel_building
build/core/tasks/kernel.mk:46: * for more information *
build/core/tasks/kernel.mk:47: ***************************************************************
target thumb C: libblkid <= bootable/recovery/libblkid/sysfs1.c
bootable/recovery/libblkid/sysfs1.c: In function 'sysfs_is_partition_dirent':
bootable/recovery/libblkid/sysfs1.c:322: warning: implicit declaration of function 'faccessat'
target thumb C: libblkid <= bootable/recovery/libblkid/sysfs2.c
In file included from bootable/recovery/libblkid/blkidP.h:30,
from bootable/recovery/libblkid/topology.h:4,
from bootable/recovery/libblkid/sysfs2.c:21:
bootable/recovery/libblkid/bitops.h:59:1: warning: "htobe16" redefined
In file included from bionic/libc/arch-arm/include/endian.h:87,
from bionic/libc/include/sys/stat.h:36,
from bootable/recovery/libblkid/sysfs2.c:16:
bionic/libc/include/sys/endian.h:190:1: warning: this is the location of the previous definition
In file included from bootable/recovery/libblkid/blkidP.h:30,
from bootable/recovery/libblkid/topology.h:4,
from bootable/recovery/libblkid/sysfs2.c:21:
bootable/recovery/libblkid/bitops.h:63:1: warning: "htobe32" redefined
In file included from bionic/libc/arch-arm/include/endian.h:87,
from bionic/libc/include/sys/stat.h:36,
from bootable/recovery/libblkid/sysfs2.c:16:
bionic/libc/include/sys/endian.h:191:1: warning: this is the location of the previous definition
In file included from bootable/recovery/libblkid/blkidP.h:30,
from bootable/recovery/libblkid/topology.h:4,
from bootable/recovery/libblkid/sysfs2.c:21:
bootable/recovery/libblkid/bitops.h:67:1: warning: "htobe64" redefined
In file included from bionic/libc/arch-arm/include/endian.h:87,
from bionic/libc/include/sys/stat.h:36,
from bootable/recovery/libblkid/sysfs2.c:16:
bionic/libc/include/sys/endian.h:192:1: warning: this is the location of the previous definition
bootable/recovery/libblkid/sysfs2.c:37: warning: missing initializer
bootable/recovery/libblkid/sysfs2.c:37: warning: (near initialization for 'topology_vals[1].set_int')
bootable/recovery/libblkid/sysfs2.c:38: warning: missing initializer
bootable/recovery/libblkid/sysfs2.c:38: warning: (near initialization for 'topology_vals[2].set_int')
bootable/recovery/libblkid/sysfs2.c:39: warning: missing initializer
bootable/recovery/libblkid/sysfs2.c:39: warning: (near initialization for 'topology_vals[3].set_int')
bootable/recovery/libblkid/sysfs2.c:117: warning: missing initializer
bootable/recovery/libblkid/sysfs2.c:117: warning: (near initialization for 'sysfs_tp_idinfo.magics[0].len')
target SharedLib: libblkid (out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/LINKED/libblkid.so)
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/dos.o: in function dos_nested:dos.c(.data.rel.ro.dos_nested+0x2c): error: undefined reference to 'minix_pt_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/mbsalign.o: in function mbsalign:bootable/recovery/libblkid/mbsalign.c:280: error: undefined reference to 'mempcpy'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/partitions.o: in function idinfos:partitions.c(.data.rel.idinfos+0x28): error: undefined reference to 'minix_pt_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/superblocks.o: in function idinfos:superblocks.c(.data.rel.idinfos+0x28): error: undefined reference to 'adraid_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/superblocks.o: in function idinfos:superblocks.c(.data.rel.idinfos+0x38): error: undefined reference to 'lvm2_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/superblocks.o: in function idinfos:superblocks.c(.data.rel.idinfos+0x3c): error: undefined reference to 'lvm1_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/superblocks.o: in function idinfos:superblocks.c(.data.rel.idinfos+0x40): error: undefined reference to 'snapcow_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/superblocks.o: in function idinfos:superblocks.c(.data.rel.idinfos+0x44): error: undefined reference to 'verity_hash_idinfo'
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/sysfs1.o: in function sysfs_is_partition_dirent:bootable/recovery/libblkid/sysfs1.c:322: error: undefined reference to 'faccessat'
collect2: ld returned 1 exit status
make: *** [out/target/product/sunfire/obj/SHARED_LIBRARIES/libblkid_intermediates/LINKED/libblkid.so] Error 1
make: Leaving directory `/builds/cm9'
+1559
View File
File diff suppressed because it is too large Load Diff
+192
View File
@@ -0,0 +1,192 @@
#ifndef UTIL_LINUX_LOOPDEV_H
#define UTIL_LINUX_LOOPDEV_H
#include "sysfs.h"
/*
* loop_info.lo_encrypt_type
*/
#define LO_CRYPT_NONE 0
#define LO_CRYPT_XOR 1
#define LO_CRYPT_DES 2
#define LO_CRYPT_CRYPTOAPI 18
#define LOOP_SET_FD 0x4C00
#define LOOP_CLR_FD 0x4C01
/*
* Obsolete (kernel < 2.6)
*
* #define LOOP_SET_STATUS 0x4C02
* #define LOOP_GET_STATUS 0x4C03
*/
#define LOOP_SET_STATUS64 0x4C04
#define LOOP_GET_STATUS64 0x4C05
/* #define LOOP_CHANGE_FD 0x4C06 */
#define LOOP_SET_CAPACITY 0x4C07
/* /dev/loop-control interface */
#ifndef LOOP_CTL_ADD
# define LOOP_CTL_ADD 0x4C80
# define LOOP_CTL_REMOVE 0x4C81
# define LOOP_CTL_GET_FREE 0x4C82
#endif
/*
* loop_info.lo_flags
*/
enum {
LO_FLAGS_READ_ONLY = 1,
LO_FLAGS_USE_AOPS = 2,
LO_FLAGS_AUTOCLEAR = 4, /* kernel >= 2.6.25 */
LO_FLAGS_PARTSCAN = 8, /* kernel >= 3.2 */
};
#define LO_NAME_SIZE 64
#define LO_KEY_SIZE 32
/*
* Linux LOOP_{SET,GET}_STATUS64 ioclt struct
*/
struct loop_info64 {
uint64_t lo_device;
uint64_t lo_inode;
uint64_t lo_rdevice;
uint64_t lo_offset;
uint64_t lo_sizelimit; /* bytes, 0 == max available */
uint32_t lo_number;
uint32_t lo_encrypt_type;
uint32_t lo_encrypt_key_size;
uint32_t lo_flags;
uint8_t lo_file_name[LO_NAME_SIZE];
uint8_t lo_crypt_name[LO_NAME_SIZE];
uint8_t lo_encrypt_key[LO_KEY_SIZE];
uint64_t lo_init[2];
};
#define LOOPDEV_MAJOR 7 /* loop major number */
#define LOOPDEV_DEFAULT_NNODES 8 /* default number of loop devices */
struct loopdev_iter {
FILE *proc; /* /proc/partitions */
DIR *sysblock; /* /sys/block */
int ncur; /* current position */
int *minors; /* ary of minor numbers (when scan whole /dev) */
int nminors; /* number of items in *minors */
int ct_perm; /* count permission problems */
int ct_succ; /* count number of detected devices */
unsigned int done:1; /* scanning done */
unsigned int default_check:1;/* check first LOOPDEV_NLOOPS */
int flags; /* LOOPITER_FL_* flags */
};
enum {
LOOPITER_FL_FREE = (1 << 0),
LOOPITER_FL_USED = (1 << 1)
};
/*
* handler for work with loop devices
*/
struct loopdev_cxt {
char device[128]; /* device path (e.g. /dev/loop<N>) */
char *filename; /* backing file for loopcxt_set_... */
int fd; /* open(/dev/looo<N>) */
int mode; /* fd mode O_{RDONLY,RDWR} */
int flags; /* LOOPDEV_FL_* flags */
unsigned int has_info:1; /* .info contains data */
unsigned int extra_check:1; /* unusual stuff for iterator */
unsigned int debug:1; /* debug mode ON/OFF */
unsigned int info_failed:1; /* LOOP_GET_STATUS ioctl failed */
struct sysfs_cxt sysfs; /* pointer to /sys/dev/block/<maj:min>/ */
struct loop_info64 info; /* for GET/SET ioctl */
struct loopdev_iter iter; /* scans /sys or /dev for used/free devices */
};
#define UL_LOOPDEVCXT_EMPTY { .fd = -1, .sysfs = UL_SYSFSCXT_EMPTY }
/*
* loopdev_cxt.flags
*/
enum {
LOOPDEV_FL_RDONLY = (1 << 0), /* open(/dev/loop) mode; default */
LOOPDEV_FL_RDWR = (1 << 1), /* necessary for loop setup only */
LOOPDEV_FL_OFFSET = (1 << 4),
LOOPDEV_FL_NOSYSFS = (1 << 5),
LOOPDEV_FL_NOIOCTL = (1 << 6),
LOOPDEV_FL_DEVSUBDIR = (1 << 7),
LOOPDEV_FL_CONTROL = (1 << 8), /* system with /dev/loop-control */
LOOPDEV_FL_SIZELIMIT = (1 << 9)
};
/*
* High-level
*/
extern int loopmod_supports_partscan(void);
extern int is_loopdev(const char *device);
extern int loopdev_is_autoclear(const char *device);
extern char *loopdev_get_backing_file(const char *device);
extern int loopdev_is_used(const char *device, const char *filename,
uint64_t offset, int flags);
extern char *loopdev_find_by_backing_file(const char *filename,
uint64_t offset, int flags);
extern int loopcxt_find_unused(struct loopdev_cxt *lc);
extern int loopdev_delete(const char *device);
extern int loopdev_count_by_backing_file(const char *filename, char **loopdev);
/*
* Low-level
*/
extern int loopcxt_init(struct loopdev_cxt *lc, int flags)
__attribute__ ((warn_unused_result));
extern void loopcxt_deinit(struct loopdev_cxt *lc);
extern void loopcxt_enable_debug(struct loopdev_cxt *lc, int enable);
extern int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
__attribute__ ((warn_unused_result));
extern int loopcxt_has_device(struct loopdev_cxt *lc);
extern char *loopcxt_strdup_device(struct loopdev_cxt *lc);
extern const char *loopcxt_get_device(struct loopdev_cxt *lc);
extern struct sysfs_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc);
extern struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc);
extern int loopcxt_get_fd(struct loopdev_cxt *lc);
extern int loopcxt_set_fd(struct loopdev_cxt *lc, int fd, int mode);
extern int loopcxt_init_iterator(struct loopdev_cxt *lc, int flags);
extern int loopcxt_deinit_iterator(struct loopdev_cxt *lc);
extern int loopcxt_next(struct loopdev_cxt *lc);
extern int loopcxt_setup_device(struct loopdev_cxt *lc);
extern int loopcxt_delete_device(struct loopdev_cxt *lc);
int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset);
int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit);
int loopcxt_set_flags(struct loopdev_cxt *lc, uint32_t flags);
int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename);
extern char *loopcxt_get_backing_file(struct loopdev_cxt *lc);
extern int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno);
extern int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino);
extern int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset);
extern int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size);
extern int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type);
extern const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc);
extern int loopcxt_is_autoclear(struct loopdev_cxt *lc);
extern int loopcxt_is_readonly(struct loopdev_cxt *lc);
extern int loopcxt_is_partscan(struct loopdev_cxt *lc);
extern int loopcxt_find_by_backing_file(struct loopdev_cxt *lc,
const char *filename,
uint64_t offset, int flags);
extern int loopcxt_is_used(struct loopdev_cxt *lc,
struct stat *st,
const char *backing_file,
uint64_t offset,
int flags);
#endif /* UTIL_LINUX_LOOPDEV_H */
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct lsi_metadata {
uint8_t sig[6];
};
#define LSI_SIGNATURE "$XIDE$"
static int probe_lsiraid(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
uint64_t off;
struct lsi_metadata *lsi;
if (pr->size < 0x10000)
return -1;
if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
return -1;
off = ((pr->size / 0x200) - 1) * 0x200;
lsi = (struct lsi_metadata *)
blkid_probe_get_buffer(pr,
off,
sizeof(struct lsi_metadata));
if (!lsi)
return -1;
if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
return -1;
if (blkid_probe_set_magic(pr, off, sizeof(lsi->sig),
(unsigned char *) lsi->sig))
return -1;
return 0;
}
const struct blkid_idinfo lsiraid_idinfo = {
.name = "lsi_mega_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_lsiraid,
.magics = BLKID_NONE_MAGIC
};
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
#include "superblocks.h"
#define LUKS_CIPHERNAME_L 32
#define LUKS_CIPHERMODE_L 32
#define LUKS_HASHSPEC_L 32
#define LUKS_DIGESTSIZE 20
#define LUKS_SALTSIZE 32
#define LUKS_MAGIC_L 6
#define UUID_STRING_L 40
struct luks_phdr {
uint8_t magic[LUKS_MAGIC_L];
uint16_t version;
uint8_t cipherName[LUKS_CIPHERNAME_L];
uint8_t cipherMode[LUKS_CIPHERMODE_L];
uint8_t hashSpec[LUKS_HASHSPEC_L];
uint32_t payloadOffset;
uint32_t keyBytes;
uint8_t mkDigest[LUKS_DIGESTSIZE];
uint8_t mkDigestSalt[LUKS_SALTSIZE];
uint32_t mkDigestIterations;
uint8_t uuid[UUID_STRING_L];
} __attribute__((packed));
static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag)
{
struct luks_phdr *header;
header = blkid_probe_get_sb(pr, mag, struct luks_phdr);
if (header == NULL)
return -1;
blkid_probe_strncpy_uuid(pr, (unsigned char *) header->uuid,
sizeof(header->uuid));
blkid_probe_sprintf_version(pr, "%u", be16_to_cpu(header->version));
return 0;
}
const struct blkid_idinfo luks_idinfo =
{
.name = "crypto_LUKS",
.usage = BLKID_USAGE_CRYPTO,
.probefunc = probe_luks,
.magics =
{
{ .magic = "LUKS\xba\xbe", .len = 6 },
{ NULL }
}
};
+150
View File
@@ -0,0 +1,150 @@
/*
* lvm topology
* -- this is fallback for old systems where the topology information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "topology.h"
#ifndef LVM_BLK_MAJOR
# define LVM_BLK_MAJOR 58
#endif
static int is_lvm_device(dev_t devno)
{
if (major(devno) == LVM_BLK_MAJOR)
return 1;
return blkid_driver_has_major("lvm", major(devno));
}
static int probe_lvm_tp(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
const char *paths[] = {
"/usr/local/sbin/lvdisplay",
"/usr/sbin/lvdisplay",
"/sbin/lvdisplay"
};
int lvpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
FILE *stream = NULL;
char *cmd = NULL, *devname = NULL, buf[1024];
size_t i;
dev_t devno = blkid_probe_get_devno(pr);
if (!devno)
goto nothing; /* probably not a block device */
if (!is_lvm_device(devno))
goto nothing;
for (i = 0; i < ARRAY_SIZE(paths); i++) {
struct stat sb;
if (stat(paths[i], &sb) == 0) {
cmd = (char *) paths[i];
break;
}
}
if (!cmd)
goto nothing;
devname = blkid_devno_to_devname(devno);
if (!devname)
goto nothing;
if (pipe(lvpipe) < 0) {
DBG(DEBUG_LOWPROBE,
printf("Failed to open pipe: errno=%d", errno));
goto nothing;
}
switch (fork()) {
case 0:
{
char *lvargv[3];
/* Plumbing */
close(lvpipe[0]);
if (lvpipe[1] != STDOUT_FILENO)
dup2(lvpipe[1], STDOUT_FILENO);
/* The libblkid library could linked with setuid programs */
if (setgid(getgid()) < 0)
exit(1);
if (setuid(getuid()) < 0)
exit(1);
lvargv[0] = cmd;
lvargv[1] = devname;
lvargv[2] = NULL;
execv(lvargv[0], lvargv);
DBG(DEBUG_LOWPROBE,
printf("Failed to execute %s: errno=%d", cmd, errno));
exit(1);
}
case -1:
DBG(DEBUG_LOWPROBE,
printf("Failed to forking: errno=%d", errno));
goto nothing;
default:
break;
}
stream = fdopen(lvpipe[0], "r");
if (!stream)
goto nothing;
while (fgets(buf, sizeof(buf), stream) != NULL) {
if (!strncmp(buf, "Stripes", 7))
sscanf(buf, "Stripes %d", &stripes);
if (!strncmp(buf, "Stripe size", 11))
sscanf(buf, "Stripe size (KByte) %d", &stripesize);
}
if (!stripes)
goto nothing;
blkid_topology_set_minimum_io_size(pr, stripesize << 10);
blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
free(devname);
fclose(stream);
close(lvpipe[1]);
return 0;
nothing:
free(devname);
if (stream)
fclose(stream);
else if (lvpipe[0] != -1)
close(lvpipe[0]);
if (lvpipe[1] != -1)
close(lvpipe[1]);
return 1;
}
const struct blkid_idinfo lvm_tp_idinfo =
{
.name = "lvm",
.probefunc = probe_lvm_tp,
.magics = BLKID_NONE_MAGIC
};
+228
View File
@@ -0,0 +1,228 @@
/*
* Copyright (C) 1999 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2001 by Andreas Dilger
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
* Copyright (C) 2012 Milan Broz <mbroz@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
#define LVM1_ID_LEN 128
#define LVM2_ID_LEN 32
struct lvm2_pv_label_header {
/* label_header */
uint8_t id[8]; /* LABELONE */
uint64_t sector_xl; /* Sector number of this label */
uint32_t crc_xl; /* From next field to end of sector */
uint32_t offset_xl; /* Offset from start of struct to contents */
uint8_t type[8]; /* LVM2 001 */
/* pv_header */
uint8_t pv_uuid[LVM2_ID_LEN];
} __attribute__ ((packed));
struct lvm1_pv_label_header {
uint8_t id[2]; /* HM */
uint16_t version; /* version 1 or 2 */
uint32_t _notused[10]; /* lvm1 internals */
uint8_t pv_uuid[LVM1_ID_LEN];
} __attribute__ ((packed));
#define LVM2_LABEL_SIZE 512
static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
{
static const unsigned int crctab[] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned int i, crc = 0xf597a6cf;
const uint8_t *data = (const uint8_t *) buf;
for (i = 0; i < size; i++) {
crc ^= *data++;
crc = (crc >> 4) ^ crctab[crc & 0xf];
crc = (crc >> 4) ^ crctab[crc & 0xf];
}
return crc;
}
/* Length of real UUID is always LVM2_ID_LEN */
static void format_lvm_uuid(char *dst_uuid, char *src_uuid)
{
unsigned int i, b;
for (i = 0, b = 1; i < LVM2_ID_LEN; i++, b <<= 1) {
if (b & 0x4444440)
*dst_uuid++ = '-';
*dst_uuid++ = *src_uuid++;
}
*dst_uuid = '\0';
}
static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
{
int sector = mag->kboff << 1;
struct lvm2_pv_label_header *label;
char uuid[LVM2_ID_LEN + 7];
unsigned char *buf;
buf = blkid_probe_get_buffer(pr,
mag->kboff << 10,
512 + sizeof(struct lvm2_pv_label_header));
if (!buf)
return -1;
/* buf is at 0k or 1k offset; find label inside */
if (memcmp(buf, "LABELONE", 8) == 0) {
label = (struct lvm2_pv_label_header *) buf;
} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
label = (struct lvm2_pv_label_header *)(buf + 512);
sector++;
} else {
return 1;
}
if (le64_to_cpu(label->sector_xl) != (unsigned) sector)
return 1;
if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
((char *) &label->offset_xl - (char *) label)) !=
le32_to_cpu(label->crc_xl)) {
DBG(DEBUG_PROBE,
printf("LVM2: label checksum incorrect at sector %d\n",
sector));
return 1;
}
format_lvm_uuid(uuid, (char *) label->pv_uuid);
blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
"%s", uuid);
/* the mag->magic is the same string as label->type,
* but zero terminated */
blkid_probe_set_version(pr, mag->magic);
/* LVM (pvcreate) wipes begin of the device -- let's remember this
* to resolve conflicts bettween LVM and partition tables, ...
*/
blkid_probe_set_wiper(pr, 0, 8 * 1024);
return 0;
}
static int probe_lvm1(blkid_probe pr, const struct blkid_idmag *mag)
{
struct lvm1_pv_label_header *label;
char uuid[LVM2_ID_LEN + 7];
unsigned int version;
label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header);
if (!label)
return -1;
version = le16_to_cpu(label->version);
if (version != 1 && version != 2)
return 1;
format_lvm_uuid(uuid, (char *) label->pv_uuid);
blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
"%s", uuid);
return 0;
}
struct verity_sb {
uint8_t signature[8]; /* "verity\0\0" */
uint32_t version; /* superblock version */
uint32_t hash_type; /* 0 - Chrome OS, 1 - normal */
uint8_t uuid[16]; /* UUID of hash device */
uint8_t algorithm[32];/* hash algorithm name */
uint32_t data_block_size; /* data block in bytes */
uint32_t hash_block_size; /* hash block in bytes */
uint64_t data_blocks; /* number of data blocks */
uint16_t salt_size; /* salt size */
uint8_t _pad1[6];
uint8_t salt[256]; /* salt */
uint8_t _pad2[168];
} __attribute__((packed));
static int probe_verity(blkid_probe pr, const struct blkid_idmag *mag)
{
struct verity_sb *sb;
unsigned int version;
sb = blkid_probe_get_sb(pr, mag, struct verity_sb);
if (sb == NULL)
return -1;
version = le32_to_cpu(sb->version);
if (version != 1)
return 1;
blkid_probe_set_uuid(pr, sb->uuid);
blkid_probe_sprintf_version(pr, "%u", version);
return 0;
}
/* NOTE: the original libblkid uses "lvm2pv" as a name */
const struct blkid_idinfo lvm2_idinfo =
{
.name = "LVM2_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_lvm2,
.magics =
{
{ .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
{ .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
{ NULL }
}
};
const struct blkid_idinfo lvm1_idinfo =
{
.name = "LVM1_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_lvm1,
.magics =
{
{ .magic = "HM", .len = 2 },
{ NULL }
}
};
const struct blkid_idinfo snapcow_idinfo =
{
.name = "DM_snapshot_cow",
.usage = BLKID_USAGE_OTHER,
.magics =
{
{ .magic = "SnAp", .len = 4 },
{ NULL }
}
};
const struct blkid_idinfo verity_hash_idinfo =
{
.name = "DM_verity_hash",
.usage = BLKID_USAGE_CRYPTO,
.probefunc = probe_verity,
.magics =
{
{ .magic = "verity\0\0", .len = 8 },
{ NULL }
}
};
+183
View File
@@ -0,0 +1,183 @@
/*
* mac partitions parsing code
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "partitions.h"
#define MAC_PARTITION_MAGIC 0x504d
#define MAC_PARTITION_MAGIC_OLD 0x5453
/*
* Mac partition entry
* http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-126.html
*/
struct mac_partition {
uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
uint16_t reserved; /* reserved */
uint32_t map_count; /* # blocks in partition map */
uint32_t start_block; /* absolute starting block # of partition */
uint32_t block_count; /* number of blocks in partition */
char name[32]; /* partition name */
char type[32]; /* string type description */
uint32_t data_start; /* rel block # of first data block */
uint32_t data_count; /* number of data blocks */
uint32_t status; /* partition status bits */
uint32_t boot_start; /* first logical block of boot code */
uint32_t boot_size; /* size of boot code, in bytes */
uint32_t boot_load; /* boot code load address */
uint32_t boot_load2; /* reserved */
uint32_t boot_entry; /* boot code entry point */
uint32_t boot_entry2; /* reserved */
uint32_t boot_cksum; /* boot code checksum */
char processor[16]; /* identifies ISA of boot */
/* there is more stuff after this that we don't need */
} __attribute__((packed));
/*
* Driver descriptor structure, in block 0
* http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-121.html
*/
struct mac_driver_desc {
uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
uint16_t block_size; /* block size of the device */
uint32_t block_count; /* number of blocks on the device */
/* there is more stuff after this that we don't need */
} __attribute__((packed));
static inline unsigned char *get_mac_block(
blkid_probe pr,
uint16_t block_size,
uint32_t num)
{
return blkid_probe_get_buffer(pr,
(blkid_loff_t) num * block_size, block_size);
}
static inline int has_part_signature(struct mac_partition *p)
{
return be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC ||
be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC_OLD;
}
static int probe_mac_pt(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct mac_driver_desc *md;
struct mac_partition *p;
blkid_parttable tab = NULL;
blkid_partlist ls;
uint16_t block_size;
uint16_t ssf; /* sector size fragment */
uint32_t nblks, i;
/* The driver descriptor record is always located at physical block 0,
* the first block on the disk.
*/
md = (struct mac_driver_desc *) blkid_probe_get_sector(pr, 0);
if (!md)
goto nothing;
block_size = be16_to_cpu(md->block_size);
/* The partition map always begins at physical block 1,
* the second block on the disk.
*/
p = (struct mac_partition *) get_mac_block(pr, block_size, 1);
if (!p)
goto nothing;
/* check the first partition signature */
if (!has_part_signature(p))
goto nothing;
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
ls = blkid_probe_get_partlist(pr);
if (!ls)
goto err;
tab = blkid_partlist_new_parttable(ls, "mac", 0);
if (!tab)
goto err;
ssf = block_size / 512;
nblks = be32_to_cpu(p->map_count);
for (i = 1; i <= nblks; ++i) {
blkid_partition par;
uint32_t start;
uint32_t size;
p = (struct mac_partition *) get_mac_block(pr, block_size, i);
if (!p)
goto nothing;
if (!has_part_signature(p))
goto nothing;
if (be32_to_cpu(p->map_count) != nblks) {
DBG(DEBUG_LOWPROBE, printf(
"mac: inconsisten map_count in partition map, "
"entry[0]: %d, entry[%d]: %d\n",
nblks, i - 1,
be32_to_cpu(p->map_count)));
}
/*
* note that libparted ignores some mac partitions according to
* the partition name (e.g. "Apple_Free" or "Apple_Void"). We
* follows Linux kernel and all partitions are visible
*/
start = be32_to_cpu(p->start_block) * ssf;
size = be32_to_cpu(p->block_count) * ssf;
par = blkid_partlist_add_partition(ls, tab, start, size);
if (!par)
goto err;
blkid_partition_set_name(par, (unsigned char *) p->name,
sizeof(p->name));
blkid_partition_set_type_string(par, (unsigned char *) p->type,
sizeof(p->type));
}
return 0;
nothing:
return 1;
err:
return -1;
}
/*
* Mac disk always begin with "Driver Descriptor Record"
* (struct mac_driver_desc) and magic 0x4552.
*/
const struct blkid_idinfo mac_pt_idinfo =
{
.name = "mac",
.probefunc = probe_mac_pt,
.magics =
{
/* big-endian magic string */
{ .magic = "\x45\x52", .len = 2 },
{ NULL }
}
};
+166
View File
@@ -0,0 +1,166 @@
/*
* Functions for \oct encoding used in mtab/fstab/swaps/etc.
*
* Based on code from mount(8).
*
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "mangle.h"
#include "c.h"
#define isoctal(a) (((a) & ~7) == '0')
#define from_hex(c) (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10)
#define is_unwanted_char(x) (strchr(" \t\n\\", (unsigned int) x) != NULL)
char *mangle(const char *s)
{
char *ss, *sp;
if (!s)
return NULL;
ss = sp = malloc(4 * strlen(s) + 1);
if (!sp)
return NULL;
while(1) {
if (!*s) {
*sp = '\0';
break;
}
if (is_unwanted_char(*s)) {
*sp++ = '\\';
*sp++ = '0' + ((*s & 0300) >> 6);
*sp++ = '0' + ((*s & 070) >> 3);
*sp++ = '0' + (*s & 07);
} else
*sp++ = *s;
s++;
}
return ss;
}
void unmangle_to_buffer(const char *s, char *buf, size_t len)
{
size_t sz = 0;
if (!s)
return;
while(*s && sz < len - 1) {
if (*s == '\\' && sz + 3 < len - 1 && isoctal(s[1]) &&
isoctal(s[2]) && isoctal(s[3])) {
*buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
s += 4;
sz += 4;
} else {
*buf++ = *s++;
sz++;
}
}
*buf = '\0';
}
void unhexmangle_to_buffer(const char *s, char *buf, size_t len)
{
size_t sz = 0;
if (!s)
return;
while(*s && sz < len - 1) {
if (*s == '\\' && sz + 3 < len - 1 && s[1] == 'x' &&
isxdigit(s[2]) && isxdigit(s[3])) {
*buf++ = from_hex(s[2]) << 4 | from_hex(s[3]);
s += 4;
sz += 4;
} else {
*buf++ = *s++;
sz++;
}
}
*buf = '\0';
}
static inline char *skip_nonspaces(const char *s)
{
while (*s && !(*s == ' ' || *s == '\t'))
s++;
return (char *) s;
}
/*
* Returns mallocated buffer or NULL in case of error.
*/
char *unmangle(const char *s, char **end)
{
char *buf;
char *e;
size_t sz;
if (!s)
return NULL;
e = skip_nonspaces(s);
sz = e - s + 1;
if (end)
*end = e;
if (e == s)
return NULL; /* empty string */
buf = malloc(sz);
if (!buf)
return NULL;
unmangle_to_buffer(s, buf, sz);
return buf;
}
#ifdef TEST_PROGRAM
#include <errno.h>
int main(int argc, char *argv[])
{
char *p = NULL;
if (argc < 3) {
fprintf(stderr, "usage: %s --mangle|unmangle <string>\n",
program_invocation_short_name);
return EXIT_FAILURE;
}
if (!strcmp(argv[1], "--mangle")) {
p = mangle(argv[2]);
printf("mangled: '%s'\n", p);
free(p);
}
else if (!strcmp(argv[1], "--unmangle")) {
char *x = unmangle(argv[2], NULL);
if (x) {
printf("unmangled: '%s'\n", x);
free(x);
}
x = strdup(argv[2]);
unmangle_to_buffer(x, x, strlen(x) + 1);
if (x) {
printf("self-unmangled: '%s'\n", x);
free(x);
}
}
return EXIT_SUCCESS;
}
#endif /* TEST_PROGRAM */
+26
View File
@@ -0,0 +1,26 @@
#ifndef UTIL_LINUX_MANGLE_H
#define UTIL_LINUX_MANGLE_H
/*
* Functions for \oct encoding used in mtab/fstab/swaps/etc.
*/
extern char *mangle(const char *s);
extern void unmangle_to_buffer(const char *s, char *buf, size_t len);
void unhexmangle_to_buffer(const char *s, char *buf, size_t len);
extern char *unmangle(const char *s, char **end);
static inline void unmangle_string(char *s)
{
unmangle_to_buffer(s, s, strlen(s) + 1);
}
static inline void unhexmangle_string(char *s)
{
unhexmangle_to_buffer(s, s, strlen(s) + 1);
}
#endif /* UTIL_LINUX_MANGLE_H */
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2011 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <string.h>
#include "match.h"
/*
* match_fstype:
* @type: filesystem type
* @pattern: filesystem name or comma delimited list of names
*
* The @pattern list of filesystem can be prefixed with a global
* "no" prefix to invert matching of the whole list. The "no" could
* also be used for individual items in the @pattern list. So,
* "nofoo,bar" has the same meaning as "nofoo,nobar".
*/
int match_fstype(const char *type, const char *pattern)
{
int no = 0; /* negated types list */
int len;
const char *p;
if (!pattern && !type)
return 1;
if (!pattern)
return 0;
if (!strncmp(pattern, "no", 2)) {
no = 1;
pattern += 2;
}
/* Does type occur in types, separated by commas? */
len = strlen(type);
p = pattern;
while(1) {
if (!strncmp(p, "no", 2) && !strncmp(p+2, type, len) &&
(p[len+2] == 0 || p[len+2] == ','))
return 0;
if (strncmp(p, type, len) == 0 && (p[len] == 0 || p[len] == ','))
return !no;
p = strchr(p,',');
if (!p)
break;
p++;
}
return no;
}
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright (C) 2011 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#ifndef UTIL_LINUX_MATCH_H
#define UTIL_LINUX_MATCH_H
extern int match_fstype(const char *type, const char *pattern);
#endif /* UTIL_LINUX_MATCH_H */
+291
View File
@@ -0,0 +1,291 @@
/* Align/Truncate a string in a given screen width
Copyright (C) 2009-2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Pádraig Brady. */
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
#include "c.h"
#include "mbsalign.h"
#include "widechar.h"
#ifdef HAVE_WIDECHAR
/* Replace non printable chars.
Note \t and \n etc. are non printable.
Return 1 if replacement made, 0 otherwise. */
static bool
wc_ensure_printable (wchar_t *wchars)
{
bool replaced = false;
wchar_t *wc = wchars;
while (*wc)
{
if (!iswprint ((wint_t) *wc))
{
*wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
replaced = true;
}
wc++;
}
return replaced;
}
/* Truncate wchar string to width cells.
* Returns number of cells used. */
static size_t
wc_truncate (wchar_t *wc, size_t width)
{
size_t cells = 0;
int next_cells = 0;
while (*wc)
{
next_cells = wcwidth (*wc);
if (next_cells == -1) /* non printable */
{
*wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
next_cells = 1;
}
if (cells + next_cells > width)
break;
cells += next_cells;
wc++;
}
*wc = L'\0';
return cells;
}
/* FIXME: move this function to gnulib as it's missing on:
OpenBSD 3.8, IRIX 5.3, Solaris 2.5.1, mingw, BeOS */
static int
rpl_wcswidth (const wchar_t *s, size_t n)
{
int ret = 0;
while (n-- > 0 && *s != L'\0')
{
int nwidth = wcwidth (*s++);
if (nwidth == -1) /* non printable */
return -1;
if (ret > (INT_MAX - nwidth)) /* overflow */
return -1;
ret += nwidth;
}
return ret;
}
#endif
/* Truncate multi-byte string to @width and returns number of
* bytes of the new string @str, and in @width returns number
* of cells.
*/
size_t
mbs_truncate(char *str, size_t *width)
{
ssize_t bytes = strlen(str);
#ifdef HAVE_WIDECHAR
ssize_t sz = mbstowcs(NULL, str, 0);
wchar_t *wcs = NULL;
if (sz == (ssize_t) -1)
goto done;
wcs = malloc((sz + 1) * sizeof(wchar_t));
if (!wcs)
goto done;
if (!mbstowcs(wcs, str, sz))
goto done;
*width = wc_truncate(wcs, *width);
bytes = wcstombs(str, wcs, bytes);
done:
free(wcs);
#else
if (*width < bytes)
bytes = *width;
#endif
if (bytes >= 0)
str[bytes] = '\0';
return bytes;
}
/* Write N_SPACES space characters to DEST while ensuring
nothing is written beyond DEST_END. A terminating NUL
is always added to DEST.
A pointer to the terminating NUL is returned. */
static char*
mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
{
/* FIXME: Should we pad with "figure space" (\u2007)
if non ascii data present? */
while (n_spaces-- && (dest < dest_end))
*dest++ = ' ';
*dest = '\0';
return dest;
}
/* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte
characters; write the result into the DEST_SIZE-byte buffer, DEST.
ALIGNMENT specifies whether to left- or right-justify or to center.
If SRC requires more than *WIDTH columns, truncate it to fit.
When centering, the number of trailing spaces may be one less than the
number of leading spaces. The FLAGS parameter is unused at present.
Return the length in bytes required for the final result, not counting
the trailing NUL. A return value of DEST_SIZE or larger means there
wasn't enough space. DEST will be NUL terminated in any case.
Return (size_t) -1 upon error (invalid multi-byte sequence in SRC,
or malloc failure), unless MBA_UNIBYTE_FALLBACK is specified.
Update *WIDTH to indicate how many columns were used before padding. */
size_t
mbsalign (const char *src, char *dest, size_t dest_size,
size_t *width, mbs_align_t align, int flags)
{
size_t ret = -1;
size_t src_size = strlen (src) + 1;
char *newstr = NULL;
wchar_t *str_wc = NULL;
const char *str_to_print = src;
size_t n_cols = src_size - 1;
size_t n_used_bytes = n_cols; /* Not including NUL */
size_t n_spaces = 0;
bool conversion = false;
bool wc_enabled = false;
#ifdef HAVE_WIDECHAR
/* In multi-byte locales convert to wide characters
to allow easy truncation. Also determine number
of screen columns used. */
if (MB_CUR_MAX > 1)
{
size_t src_chars = mbstowcs (NULL, src, 0);
if (src_chars == (size_t) -1)
{
if (flags & MBA_UNIBYTE_FALLBACK)
goto mbsalign_unibyte;
else
goto mbsalign_cleanup;
}
src_chars += 1; /* make space for NUL */
str_wc = malloc (src_chars * sizeof (wchar_t));
if (str_wc == NULL)
{
if (flags & MBA_UNIBYTE_FALLBACK)
goto mbsalign_unibyte;
else
goto mbsalign_cleanup;
}
if (mbstowcs (str_wc, src, src_chars) != 0)
{
str_wc[src_chars - 1] = L'\0';
wc_enabled = true;
conversion = wc_ensure_printable (str_wc);
n_cols = rpl_wcswidth (str_wc, src_chars);
}
}
/* If we transformed or need to truncate the source string
then create a modified copy of it. */
if (wc_enabled && (conversion || (n_cols > *width)))
{
if (conversion)
{
/* May have increased the size by converting
\t to \uFFFD for example. */
src_size = wcstombs(NULL, str_wc, 0) + 1;
}
newstr = malloc (src_size);
if (newstr == NULL)
{
if (flags & MBA_UNIBYTE_FALLBACK)
goto mbsalign_unibyte;
else
goto mbsalign_cleanup;
}
str_to_print = newstr;
n_cols = wc_truncate (str_wc, *width);
n_used_bytes = wcstombs (newstr, str_wc, src_size);
}
#endif
mbsalign_unibyte:
if (n_cols > *width) /* Unibyte truncation required. */
{
n_cols = *width;
n_used_bytes = n_cols;
}
if (*width > n_cols) /* Padding required. */
n_spaces = *width - n_cols;
/* indicate to caller how many cells needed (not including padding). */
*width = n_cols;
/* indicate to caller how many bytes needed (not including NUL). */
ret = n_used_bytes + (n_spaces * 1);
/* Write as much NUL terminated output to DEST as possible. */
if (dest_size != 0)
{
char *dest_end = dest + dest_size - 1;
size_t start_spaces = n_spaces / 2 + n_spaces % 2;
size_t end_spaces = n_spaces / 2;
switch (align)
{
case MBS_ALIGN_CENTER:
start_spaces = n_spaces / 2 + n_spaces % 2;
end_spaces = n_spaces / 2;
break;
case MBS_ALIGN_LEFT:
start_spaces = 0;
end_spaces = n_spaces;
break;
case MBS_ALIGN_RIGHT:
start_spaces = n_spaces;
end_spaces = 0;
break;
default:
abort();
}
dest = mbs_align_pad (dest, dest_end, start_spaces);
size_t space_left = dest_end - dest;
//dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left));
memcpy (dest, str_to_print, min (n_used_bytes, space_left));
mbs_align_pad (dest, dest_end, end_spaces);
}
mbsalign_cleanup:
free (str_wc);
free (newstr);
return ret;
}
+45
View File
@@ -0,0 +1,45 @@
/* Align/Truncate a string in a given screen width
Copyright (C) 2009-2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <stddef.h>
typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t;
enum {
/* Use unibyte mode for invalid multibyte strings or
or when heap memory is exhausted. */
MBA_UNIBYTE_FALLBACK = 0x0001,
#if 0 /* Other possible options. */
/* Skip invalid multibyte chars rather than failing */
MBA_IGNORE_INVALID = 0x0002,
/* Align multibyte strings using "figure space" (\u2007) */
MBA_USE_FIGURE_SPACE = 0x0004,
/* Don't add any padding */
MBA_TRUNCATE_ONLY = 0x0008,
/* Don't truncate */
MBA_PAD_ONLY = 0x0010,
#endif
};
extern size_t mbs_truncate(char *str, size_t *width);
extern size_t mbsalign (const char *src, char *dest,
size_t dest_size, size_t *width,
mbs_align_t align, int flags);
+154
View File
@@ -0,0 +1,154 @@
/*
* Linux Software RAID (md) topology
* -- this is fallback for old systems where the topology information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "topology.h"
#ifndef MD_MAJOR
#define MD_MAJOR 9
#endif
#ifndef _IOT__IOTBASE_uint32_t
#define _IOT__IOTBASE_uint32_t IOT_SIMPLE(uint32_t)
#endif
#define _IOT_md_array_info _IOT (_IOTS(uint32_t), 18, 0, 0, 0, 0)
#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, struct md_array_info)
struct md_array_info {
/*
* Generic constant information
*/
uint32_t major_version;
uint32_t minor_version;
uint32_t patch_version;
uint32_t ctime;
uint32_t level;
uint32_t size;
uint32_t nr_disks;
uint32_t raid_disks;
uint32_t md_minor;
uint32_t not_persistent;
/*
* Generic state information
*/
uint32_t utime; /* 0 Superblock update time */
uint32_t state; /* 1 State bits (clean, ...) */
uint32_t active_disks; /* 2 Number of currently active disks */
uint32_t working_disks; /* 3 Number of working disks */
uint32_t failed_disks; /* 4 Number of failed disks */
uint32_t spare_disks; /* 5 Number of spare disks */
/*
* Personality information
*/
uint32_t layout; /* 0 the array's physical layout */
uint32_t chunk_size; /* 1 chunk size in bytes */
};
static int is_md_device(dev_t devno)
{
if (major(devno) == MD_MAJOR)
return 1;
return blkid_driver_has_major("md", major(devno));
}
static int probe_md_tp(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
int fd = -1;
dev_t disk = 0;
dev_t devno = blkid_probe_get_devno(pr);
struct md_array_info md;
if (!devno)
goto nothing; /* probably not a block device */
if (!is_md_device(devno))
goto nothing;
if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk))
goto nothing;
if (disk == devno)
fd = pr->fd;
else {
char *diskpath = blkid_devno_to_devname(disk);
if (!diskpath)
goto nothing;
fd = open(diskpath, O_RDONLY|O_CLOEXEC);
free(diskpath);
if (fd == -1)
goto nothing;
}
memset(&md, 0, sizeof(md));
if (ioctl(fd, GET_ARRAY_INFO, &md))
goto nothing;
if (fd >= 0 && fd != pr->fd) {
close(fd);
fd = -1;
}
/*
* Ignore levels we don't want aligned (e.g. linear)
* and deduct disk(s) from stripe width on RAID4/5/6
*/
switch (md.level) {
case 6:
md.raid_disks--;
/* fallthrough */
case 5:
case 4:
md.raid_disks--;
/* fallthrough */
case 1:
case 0:
case 10:
break;
default:
goto nothing;
}
blkid_topology_set_minimum_io_size(pr, md.chunk_size);
blkid_topology_set_optimal_io_size(pr, md.chunk_size * md.raid_disks);
return 0;
nothing:
if (fd >= 0 && fd != pr->fd)
close(fd);
return 1;
}
const struct blkid_idinfo md_tp_idinfo =
{
.name = "md",
.probefunc = probe_md_tp,
.magics = BLKID_NONE_MAGIC
};
+257
View File
@@ -0,0 +1,257 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#include <string.h> /* for memcpy() */
#include "md5.h"
#if !defined(WORDS_BIGENDIAN)
#define byteReverse(buf, len) /* Nothing */
#else
void byteReverse(unsigned char *buf, unsigned longs);
#ifndef ASM_MD5
/*
* Note: this code is harmless on little-endian machines.
*/
void byteReverse(unsigned char *buf, unsigned longs)
{
uint32_t t;
do {
t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32_t *) buf = t;
buf += 4;
} while (--longs);
}
#endif
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32_t t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[MD5LENGTH], struct MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform.
* Use memcpy to avoid aliasing problems. On most systems,
* this will be optimized away to the same code.
*/
memcpy(&ctx->in[14 * sizeof(uint32_t)], &ctx->bits[0], 4);
memcpy(&ctx->in[15 * sizeof(uint32_t)], &ctx->bits[1], 4);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, MD5LENGTH);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(uint32_t buf[4], uint32_t const in[16])
{
register uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#endif
+29
View File
@@ -0,0 +1,29 @@
#ifndef MD5_H
#define MD5_H
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
typedef unsigned int uint32_t;
#endif
#define MD5LENGTH 16
struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len);
void MD5Final(unsigned char digest[MD5LENGTH], struct MD5Context *context);
void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
*/
typedef struct MD5Context MD5_CTX;
#endif /* !MD5_H */
+82
View File
@@ -0,0 +1,82 @@
#ifndef UTIL_LINUX_MINIX_H
#define UTIL_LINUX_MINIX_H
#include <stdint.h>
struct minix_inode {
uint16_t i_mode;
uint16_t i_uid;
uint32_t i_size;
uint32_t i_time;
uint8_t i_gid;
uint8_t i_nlinks;
uint16_t i_zone[9];
};
struct minix2_inode {
uint16_t i_mode;
uint16_t i_nlinks;
uint16_t i_uid;
uint16_t i_gid;
uint32_t i_size;
uint32_t i_atime;
uint32_t i_mtime;
uint32_t i_ctime;
uint32_t i_zone[10];
};
struct minix_super_block {
uint16_t s_ninodes;
uint16_t s_nzones;
uint16_t s_imap_blocks;
uint16_t s_zmap_blocks;
uint16_t s_firstdatazone;
uint16_t s_log_zone_size;
uint32_t s_max_size;
uint16_t s_magic;
uint16_t s_state;
uint32_t s_zones;
};
/* V3 minix super-block data on disk */
struct minix3_super_block {
uint32_t s_ninodes;
uint16_t s_pad0;
uint16_t s_imap_blocks;
uint16_t s_zmap_blocks;
uint16_t s_firstdatazone;
uint16_t s_log_zone_size;
uint16_t s_pad1;
uint32_t s_max_size;
uint32_t s_zones;
uint16_t s_magic;
uint16_t s_pad2;
uint16_t s_blocksize;
uint8_t s_disk_version;
};
/*
* Minix subpartitions are always within primary dos partition.
*/
#define MINIX_MAXPARTITIONS 4
#define MINIX_BLOCK_SIZE_BITS 10
#define MINIX_BLOCK_SIZE (1 << MINIX_BLOCK_SIZE_BITS)
#define MINIX_NAME_MAX 255 /* # chars in a file name */
#define MINIX_MAX_INODES 65535
#define MINIX_INODES_PER_BLOCK ((MINIX_BLOCK_SIZE)/(sizeof (struct minix_inode)))
#define MINIX2_INODES_PER_BLOCK ((MINIX_BLOCK_SIZE)/(sizeof (struct minix2_inode)))
/* minix_super_block.s_state */
#define MINIX_VALID_FS 0x0001 /* Clean fs. */
#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
#define MINIX3_SUPER_MAGIC 0x4d5a /* minix V3 fs (60 char names) */
#endif /* UTIL_LINUX_MINIX_H */
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright (C) 1999 by Andries Brouwer
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
* Copyright (C) 2001 by Andreas Dilger
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <string.h>
#include "superblocks.h"
#include "minix.h"
static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
{
unsigned char *ext;
int version;
/* for more details see magic strings below */
switch(mag->magic[1]) {
case '\023':
version = 1;
break;
case '\044':
version = 2;
break;
case '\115':
version = 3;
break;
default:
return -1;
break;
}
if (version <= 2) {
struct minix_super_block *sb;
uint32_t zones;
sb = blkid_probe_get_sb(pr, mag, struct minix_super_block);
if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
return -1;
zones = version == 2 ? sb->s_zones : sb->s_nzones;
/* sanity checks to be sure that the FS is really minix */
if (sb->s_imap_blocks * MINIX_BLOCK_SIZE * 8 < sb->s_ninodes + 1)
return -1;
if (sb->s_zmap_blocks * MINIX_BLOCK_SIZE * 8 < zones - sb->s_firstdatazone + 1)
return -1;
} else if (version == 3) {
struct minix3_super_block *sb;
sb = blkid_probe_get_sb(pr, mag, struct minix3_super_block);
if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
return -1;
}
/* unfortunately, some parts of ext3 is sometimes possible to
* interpreted as minix superblock. So check for extN magic
* string. (For extN magic string and offsets see ext.c.)
*/
ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
if (ext && memcmp(ext, "\123\357", 2) == 0)
return -1;
blkid_probe_sprintf_version(pr, "%d", version);
return 0;
}
const struct blkid_idinfo minix_idinfo =
{
.name = "minix",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_minix,
.magics =
{
/* version 1 */
{ .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
{ .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
/* version 2 */
{ .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
{ .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
/* version 3 */
{ .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
{ NULL }
}
};
+100
View File
@@ -0,0 +1,100 @@
/*
* Minix partition parsing code
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "partitions.h"
#include "dos.h"
#include "minix.h"
static int probe_minix_pt(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
struct dos_partition *p;
blkid_parttable tab = NULL;
blkid_partition parent;
blkid_partlist ls;
unsigned char *data;
int i;
data = blkid_probe_get_sector(pr, 0);
if (!data)
goto nothing;
ls = blkid_probe_get_partlist(pr);
if (!ls)
goto err;
/* Parent is required, because Minix uses the same PT as DOS and
* difference is only in primary partition (parent) type.
*/
parent = blkid_partlist_get_parent(ls);
if (!parent)
goto nothing;
if (blkid_partition_get_type(parent) != BLKID_MINIX_PARTITION)
goto nothing;
if (blkid_partitions_need_typeonly(pr))
/* caller does not ask for details about partitions */
return 0;
p = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
tab = blkid_partlist_new_parttable(ls, "minix", BLKID_MSDOS_PT_OFFSET);
if (!tab)
goto err;
for (i = 0; i < MINIX_MAXPARTITIONS; i++, p++) {
uint32_t start, size;
blkid_partition par;
if (p->sys_type != BLKID_MINIX_PARTITION)
continue;
start = dos_partition_start(p);
size = dos_partition_size(p);
if (parent && !blkid_is_nested_dimension(parent, start, size)) {
DBG(DEBUG_LOWPROBE, printf(
"WARNING: minix partition (%d) overflow "
"detected, ignore\n", i));
continue;
}
par = blkid_partlist_add_partition(ls, tab, start, size);
if (!par)
goto err;
blkid_partition_set_type(par, p->sys_type);
blkid_partition_set_flags(par, p->boot_ind);
}
return 0;
nothing:
return 1;
err:
return -1;
}
/* same as DOS */
const struct blkid_idinfo minix_pt_idinfo =
{
.name = "minix",
.probefunc = probe_minix_pt,
.magics =
{
{ .magic = "\x55\xAA", .len = 2, .sboff = 510 },
{ NULL }
}
};
+42
View File
@@ -0,0 +1,42 @@
/* Compat code so unshare and setns can be used with older libcs */
#ifndef UTIL_LINUX_NAMESPACE_H
# define UTIL_LINUX_NAMESPACE_H
# include <sched.h>
# ifndef CLONE_NEWSNS
# define CLONE_NEWNS 0x00020000
# endif
# ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
# endif
# ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
# endif
# ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
# endif
# ifndef CLONE_NEWUSER
# define CLONE_NEWUSER 0x10000000
# endif
# ifndef CLONE_NEWPID
# define CLONE_NEWPID 0x20000000
# endif
# ifndef HAVE_UNSHARE
# include <sys/syscall.h>
static inline int unshare(int flags)
{
return syscall(SYS_unshare, flags);
}
# endif
# ifndef HAVE_SETNS
# include <sys/syscall.h>
static inline int setns(int fd, int nstype)
{
return syscall(SYS_setns, fd, nstype);
}
# endif
#endif /* UTIL_LINUX_NAMESPACE_H */
+97
View File
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include "superblocks.h"
struct netware_super_block {
uint8_t SBH_Signature[4];
uint16_t SBH_VersionMajor;
uint16_t SBH_VersionMinor;
uint16_t SBH_VersionMediaMajor;
uint16_t SBH_VersionMediaMinor;
uint32_t SBH_ItemsMoved;
uint8_t SBH_InternalID[16];
uint32_t SBH_PackedSize;
uint32_t SBH_Checksum;
uint32_t supersyncid;
int64_t superlocation[4];
uint32_t physSizeUsed;
uint32_t sizeUsed;
uint32_t superTimeStamp;
uint32_t reserved0[1];
int64_t SBH_LoggedPoolDataBlk;
int64_t SBH_PoolDataBlk;
uint8_t SBH_OldInternalID[16];
uint32_t SBH_PoolToLVStartUTC;
uint32_t SBH_PoolToLVEndUTC;
uint16_t SBH_VersionMediaMajorCreate;
uint16_t SBH_VersionMediaMinorCreate;
uint32_t SBH_BlocksMoved;
uint32_t SBH_TempBTSpBlk;
uint32_t SBH_TempFTSpBlk;
uint32_t SBH_TempFTSpBlk1;
uint32_t SBH_TempFTSpBlk2;
uint32_t nssMagicNumber;
uint32_t poolClassID;
uint32_t poolID;
uint32_t createTime;
int64_t SBH_LoggedVolumeDataBlk;
int64_t SBH_VolumeDataBlk;
int64_t SBH_SystemBeastBlkNum;
uint64_t totalblocks;
uint16_t SBH_Name[64];
uint8_t SBH_VolumeID[16];
uint8_t SBH_PoolID[16];
uint8_t SBH_PoolInternalID[16];
uint64_t SBH_Lsn;
uint32_t SBH_SS_Enabled;
uint32_t SBH_SS_CreateTime;
uint8_t SBH_SS_OriginalPoolID[16];
uint8_t SBH_SS_OriginalVolumeID[16];
uint8_t SBH_SS_Guid[16];
uint16_t SBH_SS_OriginalName[64];
uint32_t reserved2[64-(2+46)];
} __attribute__((__packed__));
static int probe_netware(blkid_probe pr, const struct blkid_idmag *mag)
{
struct netware_super_block *nw;
nw = blkid_probe_get_sb(pr, mag, struct netware_super_block);
if (!nw)
return -1;
blkid_probe_set_uuid(pr, nw->SBH_PoolID);
blkid_probe_sprintf_version(pr, "%u.%02u",
le16_to_cpu(nw->SBH_VersionMediaMajor),
le16_to_cpu(nw->SBH_VersionMediaMinor));
return 0;
}
const struct blkid_idinfo netware_idinfo =
{
.name = "nss",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_netware,
.magics =
{
{ .magic = "SPB5", .len = 4, .kboff = 4 },
{ NULL }
}
};
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright (C) 2010 by Jiro SEKIBA <jir@unicus.jp>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License
*/
#include <stddef.h>
#include <string.h>
#include "superblocks.h"
#include "crc32.h"
struct nilfs_super_block {
uint32_t s_rev_level;
uint16_t s_minor_rev_level;
uint16_t s_magic;
uint16_t s_bytes;
uint16_t s_flags;
uint32_t s_crc_seed;
uint32_t s_sum;
uint32_t s_log_block_size;
uint64_t s_nsegments;
uint64_t s_dev_size;
uint64_t s_first_data_block;
uint32_t s_blocks_per_segment;
uint32_t s_r_segments_percentage;
uint64_t s_last_cno;
uint64_t s_last_pseg;
uint64_t s_last_seq;
uint64_t s_free_blocks_count;
uint64_t s_ctime;
uint64_t s_mtime;
uint64_t s_wtime;
uint16_t s_mnt_count;
uint16_t s_max_mnt_count;
uint16_t s_state;
uint16_t s_errors;
uint64_t s_lastcheck;
uint32_t s_checkinterval;
uint32_t s_creator_os;
uint16_t s_def_resuid;
uint16_t s_def_resgid;
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_dat_entry_size;
uint16_t s_checkpoint_size;
uint16_t s_segment_usage_size;
uint8_t s_uuid[16];
char s_volume_name[80];
uint32_t s_c_interval;
uint32_t s_c_block_max;
uint32_t s_reserved[192];
};
/* nilfs2 magic string */
#define NILFS_SB_MAGIC "\x34\x34"
/* nilfs2 super block offset */
#define NILFS_SB_OFF 0x400
/* nilfs2 super block offset in kB */
#define NILFS_SB_KBOFF (NILFS_SB_OFF >> 10)
/* nilfs2 magic string offset within super block */
#define NILFS_MAG_OFF 6
static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
{
struct nilfs_super_block *sb;
static unsigned char sum[4];
const int sumoff = offsetof(struct nilfs_super_block, s_sum);
size_t bytes;
uint32_t crc;
sb = blkid_probe_get_sb(pr, mag, struct nilfs_super_block);
if (!sb)
return -1;
bytes = le16_to_cpu(sb->s_bytes);
crc = crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff);
crc = crc32(crc, sum, 4);
crc = crc32(crc, (unsigned char *)sb + sumoff + 4, bytes - sumoff - 4);
if (crc != le32_to_cpu(sb->s_sum))
return -1;
if (strlen(sb->s_volume_name))
blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name,
sizeof(sb->s_volume_name));
blkid_probe_set_uuid(pr, sb->s_uuid);
blkid_probe_sprintf_version(pr, "%u", le32_to_cpu(sb->s_rev_level));
return 0;
}
const struct blkid_idinfo nilfs2_idinfo =
{
.name = "nilfs2",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_nilfs2,
.magics =
{
{
.magic = NILFS_SB_MAGIC,
.len = 2,
.kboff = NILFS_SB_KBOFF,
.sboff = NILFS_MAG_OFF
},
{ NULL }
}
};
+115
View File
@@ -0,0 +1,115 @@
#ifndef UTIL_LINUX_NLS_H
#define UTIL_LINUX_NLS_H
int main(int argc, char *argv[]);
#ifndef LOCALEDIR
#define LOCALEDIR "/usr/share/locale"
#endif
#ifdef HAVE_LOCALE_H
# include <locale.h>
#else
# undef setlocale
# define setlocale(Category, Locale) /* empty */
struct lconv
{
char *decimal_point;
};
# undef localeconv
# define localeconv() NULL
#endif
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
# define P_(Singular, Plural, n) ngettext (Singular, Plural, n)
#else
# undef bindtextdomain
# define bindtextdomain(Domain, Directory) /* empty */
# undef textdomain
# define textdomain(Domain) /* empty */
# define _(Text) (Text)
# define N_(Text) (Text)
# define P_(Singular, Plural, n) ((n) == 1 ? (Singular) : (Plural))
#endif
#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#else
typedef int nl_item;
extern char *langinfo_fallback(nl_item item);
# define nl_langinfo langinfo_fallback
enum {
CODESET = 1,
RADIXCHAR,
THOUSEP,
D_T_FMT,
D_FMT,
T_FMT,
T_FMT_AMPM,
AM_STR,
PM_STR,
DAY_1,
DAY_2,
DAY_3,
DAY_4,
DAY_5,
DAY_6,
DAY_7,
ABDAY_1,
ABDAY_2,
ABDAY_3,
ABDAY_4,
ABDAY_5,
ABDAY_6,
ABDAY_7,
MON_1,
MON_2,
MON_3,
MON_4,
MON_5,
MON_6,
MON_7,
MON_8,
MON_9,
MON_10,
MON_11,
MON_12,
ABMON_1,
ABMON_2,
ABMON_3,
ABMON_4,
ABMON_5,
ABMON_6,
ABMON_7,
ABMON_8,
ABMON_9,
ABMON_10,
ABMON_11,
ABMON_12,
ERA_D_FMT,
ERA_D_T_FMT,
ERA_T_FMT,
ALT_DIGITS,
CRNCYSTR,
YESEXPR,
NOEXPR
};
#endif /* !HAVE_LANGINFO_H */
#endif /* UTIL_LINUX_NLS_H */

Some files were not shown because too many files have changed in this diff Show More