use libblkid to get filesystem type
we can now use libblkid to detect exfat
This commit is contained in:
+3
-2
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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 */
|
||||
|
||||
@@ -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, §or_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, §ors) < 0)
|
||||
err(EXIT_FAILURE, "blkdev_get_sectors() failed");
|
||||
if (blkdev_get_sector_size(fd, §or_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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
extern void __attribute__((__noreturn__)) exec_shell(void);
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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 "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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: ***************************************************************
|
||||
[33mtarget thumb C:[0m 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'
|
||||
[33mtarget thumb C:[0m 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
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user