L4Re/departure

Annotated libext2fs/lib/libsupport/plausible.c

212:c0651b3b711f
2021-10-09 Paul Boddie Updated libext2fs to version 1.46.2, also introducing some notes about the process of adapting the library for L4Re, together with a tool to generate a configuration from an existing, external "host" build of the library.
paul@181 1
/*
paul@181 2
 * plausible.c --- Figure out if a pathname is ext* or something else.
paul@181 3
 *
paul@181 4
 * Copyright 2014, Oracle, Inc.
paul@181 5
 *
paul@181 6
 * Some parts are:
paul@181 7
 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
paul@181 8
 *
paul@181 9
 * %Begin-Header%
paul@181 10
 * This file may be redistributed under the terms of the GNU Public
paul@181 11
 * License.
paul@181 12
 * %End-Header%
paul@181 13
 */
paul@181 14
paul@181 15
#ifndef _LARGEFILE_SOURCE
paul@181 16
#define _LARGEFILE_SOURCE
paul@181 17
#endif
paul@181 18
#ifndef _LARGEFILE64_SOURCE
paul@181 19
#define _LARGEFILE64_SOURCE
paul@181 20
#endif
paul@181 21
paul@181 22
#include "config.h"
paul@181 23
#include <fcntl.h>
paul@181 24
#include <time.h>
paul@181 25
#include <sys/types.h>
paul@181 26
#ifdef HAVE_SYS_STAT_H
paul@181 27
#include <sys/stat.h>
paul@181 28
#endif
paul@181 29
#ifdef HAVE_UNISTD_H
paul@181 30
#include <unistd.h>
paul@181 31
#endif
paul@181 32
#ifdef HAVE_MAGIC_H
paul@181 33
#include <magic.h>
paul@181 34
#endif
paul@181 35
#include "plausible.h"
paul@181 36
#include "ext2fs/ext2fs.h"
paul@181 37
#include "nls-enable.h"
paul@181 38
#include "blkid/blkid.h"
paul@181 39
paul@181 40
#ifdef HAVE_MAGIC_H
paul@181 41
static magic_t (*dl_magic_open)(int);
paul@181 42
static const char *(*dl_magic_file)(magic_t, const char *);
paul@181 43
static int (*dl_magic_load)(magic_t, const char *);
paul@181 44
static void (*dl_magic_close)(magic_t);
paul@181 45
paul@181 46
/*
paul@181 47
 * NO_CHECK functionality was only added in file 4.20.
paul@181 48
 * Older systems like RHEL 5.x still have file 4.17
paul@181 49
 */
paul@181 50
#ifndef MAGIC_NO_CHECK_COMPRESS
paul@181 51
#define MAGIC_NO_CHECK_COMPRESS 0x0001000
paul@181 52
#endif
paul@181 53
#ifndef MAGIC_NO_CHECK_ELF
paul@181 54
#define MAGIC_NO_CHECK_ELF 0x0010000
paul@181 55
#endif
paul@181 56
paul@181 57
#ifdef HAVE_DLOPEN
paul@181 58
#include <dlfcn.h>
paul@181 59
paul@181 60
static void *magic_handle;
paul@181 61
paul@181 62
static int magic_library_available(void)
paul@181 63
{
paul@181 64
	if (!magic_handle) {
paul@181 65
		magic_handle = dlopen("libmagic.so.1", RTLD_NOW);
paul@181 66
		if (!magic_handle)
paul@181 67
			return 0;
paul@181 68
paul@181 69
		dl_magic_open = (magic_t (*)(int))
paul@181 70
			dlsym(magic_handle, "magic_open");
paul@181 71
		dl_magic_file = (const char *(*)(magic_t, const char *))
paul@181 72
			dlsym(magic_handle, "magic_file");
paul@181 73
		dl_magic_load = (int (*)(magic_t, const char *))
paul@181 74
			dlsym(magic_handle, "magic_load");
paul@181 75
		dl_magic_close = (void (*)(magic_t))
paul@181 76
			dlsym(magic_handle, "magic_close");
paul@181 77
	}
paul@181 78
paul@181 79
	if (!dl_magic_open || !dl_magic_file ||
paul@181 80
	    !dl_magic_load || !dl_magic_close)
paul@181 81
		return 0;
paul@181 82
	return 1;
paul@181 83
}
paul@181 84
#else
paul@181 85
static int magic_library_available(void)
paul@181 86
{
paul@181 87
	dl_magic_open = magic_open;
paul@181 88
	dl_magic_file = magic_file;
paul@181 89
	dl_magic_load = magic_load;
paul@181 90
	dl_magic_close = magic_close;
paul@181 91
paul@181 92
	return 1;
paul@181 93
}
paul@181 94
#endif
paul@181 95
#endif
paul@181 96
paul@181 97
static void print_ext2_info(const char *device)
paul@181 98
paul@181 99
{
paul@181 100
	struct ext2_super_block	*sb;
paul@181 101
	ext2_filsys		fs;
paul@181 102
	errcode_t		retval;
paul@181 103
	time_t			tm;
paul@181 104
paul@181 105
	retval = ext2fs_open2(device, 0, EXT2_FLAG_64BITS, 0, 0,
paul@181 106
			      unix_io_manager, &fs);
paul@181 107
	if (retval)
paul@181 108
		return;
paul@181 109
	sb = fs->super;
paul@181 110
paul@181 111
	if (sb->s_mtime) {
paul@181 112
		tm = sb->s_mtime;
paul@212 113
		if (sb->s_last_mounted[0])
paul@212 114
			printf(_("\tlast mounted on %.*s on %s"),
paul@212 115
			       EXT2_LEN_STR(sb->s_last_mounted), ctime(&tm));
paul@212 116
		else
paul@181 117
			printf(_("\tlast mounted on %s"), ctime(&tm));
paul@181 118
	} else if (sb->s_mkfs_time) {
paul@181 119
		tm = sb->s_mkfs_time;
paul@181 120
		printf(_("\tcreated on %s"), ctime(&tm));
paul@181 121
	} else if (sb->s_wtime) {
paul@181 122
		tm = sb->s_wtime;
paul@181 123
		printf(_("\tlast modified on %s"), ctime(&tm));
paul@181 124
	}
paul@181 125
	ext2fs_close_free(&fs);
paul@181 126
}
paul@181 127
paul@181 128
/*
paul@181 129
 * return 1 if there is no partition table, 0 if a partition table is
paul@181 130
 * detected, and -1 on an error.
paul@181 131
 */
paul@181 132
#ifdef HAVE_BLKID_PROBE_ENABLE_PARTITIONS
paul@181 133
static int check_partition_table(const char *device)
paul@181 134
{
paul@181 135
	blkid_probe pr;
paul@181 136
	const char *value;
paul@181 137
	int ret;
paul@181 138
paul@181 139
	pr = blkid_new_probe_from_filename(device);
paul@181 140
	if (!pr)
paul@181 141
		return -1;
paul@181 142
paul@181 143
	ret = blkid_probe_enable_partitions(pr, 1);
paul@181 144
	if (ret < 0)
paul@181 145
		goto errout;
paul@181 146
paul@181 147
	ret = blkid_probe_enable_superblocks(pr, 0);
paul@181 148
	if (ret < 0)
paul@181 149
		goto errout;
paul@181 150
paul@181 151
	ret = blkid_do_fullprobe(pr);
paul@181 152
	if (ret < 0)
paul@181 153
		goto errout;
paul@181 154
paul@181 155
	ret = blkid_probe_lookup_value(pr, "PTTYPE", &value, NULL);
paul@181 156
	if (ret == 0)
paul@181 157
		fprintf(stderr, _("Found a %s partition table in %s\n"),
paul@181 158
			value, device);
paul@181 159
	else
paul@181 160
		ret = 1;
paul@181 161
paul@181 162
errout:
paul@181 163
	blkid_free_probe(pr);
paul@181 164
	return ret;
paul@181 165
}
paul@181 166
#else
paul@181 167
static int check_partition_table(const char *device EXT2FS_ATTR((unused)))
paul@181 168
{
paul@181 169
	return -1;
paul@181 170
}
paul@181 171
#endif
paul@181 172
paul@181 173
/*
paul@181 174
 * return 1 if the device looks plausible, creating the file if necessary
paul@181 175
 */
paul@181 176
int check_plausibility(const char *device, int flags, int *ret_is_dev)
paul@181 177
{
paul@181 178
	int fd, ret, is_dev = 0;
paul@181 179
	ext2fs_struct_stat s;
paul@181 180
	int fl = O_RDONLY;
paul@181 181
	blkid_cache cache = NULL;
paul@181 182
	char *fs_type = NULL;
paul@181 183
	char *fs_label = NULL;
paul@181 184
paul@181 185
	fd = ext2fs_open_file(device, fl, 0666);
paul@181 186
	if ((fd < 0) && (errno == ENOENT) && (flags & NO_SIZE)) {
paul@181 187
		fprintf(stderr, _("The file %s does not exist and no "
paul@181 188
				  "size was specified.\n"), device);
paul@181 189
		exit(1);
paul@181 190
	}
paul@181 191
	if ((fd < 0) && (errno == ENOENT) && (flags & CREATE_FILE)) {
paul@181 192
		fl |= O_CREAT;
paul@181 193
		fd = ext2fs_open_file(device, fl, 0666);
paul@181 194
		if (fd >= 0 && (flags & VERBOSE_CREATE))
paul@181 195
			printf(_("Creating regular file %s\n"), device);
paul@181 196
	}
paul@181 197
	if (fd < 0) {
paul@181 198
		fprintf(stderr, _("Could not open %s: %s\n"),
paul@181 199
			device, error_message(errno));
paul@181 200
		if (errno == ENOENT)
paul@181 201
			fputs(_("\nThe device apparently does not exist; "
paul@181 202
				"did you specify it correctly?\n"), stderr);
paul@181 203
		exit(1);
paul@181 204
	}
paul@181 205
paul@181 206
	if (ext2fs_fstat(fd, &s) < 0) {
paul@181 207
		perror("stat");
paul@181 208
		exit(1);
paul@181 209
	}
paul@181 210
	close(fd);
paul@181 211
paul@181 212
	if (S_ISBLK(s.st_mode))
paul@181 213
		is_dev = 1;
paul@181 214
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
paul@181 215
	/* On FreeBSD, all disk devices are character specials */
paul@181 216
	if (S_ISCHR(s.st_mode))
paul@181 217
		is_dev = 1;
paul@181 218
#endif
paul@181 219
	if (ret_is_dev)
paul@181 220
		*ret_is_dev = is_dev;
paul@181 221
paul@181 222
	if ((flags & CHECK_BLOCK_DEV) && !is_dev) {
paul@181 223
		printf(_("%s is not a block special device.\n"), device);
paul@181 224
		return 0;
paul@181 225
	}
paul@181 226
paul@181 227
	/*
paul@181 228
	 * Note: we use the older-style blkid API's here because we
paul@181 229
	 * want as much functionality to be available when using the
paul@181 230
	 * internal blkid library, when e2fsprogs is compiled for
paul@181 231
	 * non-Linux systems that will probably not have the libraries
paul@181 232
	 * from util-linux available.  We only use the newer
paul@181 233
	 * blkid-probe interfaces to access functionality not
paul@181 234
	 * available in the original blkid library.
paul@181 235
	 */
paul@181 236
	if ((flags & CHECK_FS_EXIST) && blkid_get_cache(&cache, NULL) >= 0) {
paul@181 237
		fs_type = blkid_get_tag_value(cache, "TYPE", device);
paul@181 238
		if (fs_type)
paul@181 239
			fs_label = blkid_get_tag_value(cache, "LABEL", device);
paul@181 240
		blkid_put_cache(cache);
paul@181 241
	}
paul@181 242
paul@181 243
	if (fs_type) {
paul@181 244
		if (fs_label)
paul@181 245
			printf(_("%s contains a %s file system labelled '%s'\n"),
paul@181 246
			       device, fs_type, fs_label);
paul@181 247
		else
paul@181 248
			printf(_("%s contains a %s file system\n"), device,
paul@181 249
			       fs_type);
paul@181 250
		if (strncmp(fs_type, "ext", 3) == 0)
paul@181 251
			print_ext2_info(device);
paul@181 252
		free(fs_type);
paul@181 253
		free(fs_label);
paul@181 254
		return 0;
paul@181 255
	}
paul@181 256
paul@181 257
#ifdef HAVE_MAGIC_H
paul@181 258
	if ((flags & CHECK_FS_EXIST) &&
paul@181 259
	    !getenv("E2FSPROGS_LIBMAGIC_SUPPRESS") &&
paul@181 260
	    magic_library_available()) {
paul@181 261
		const char *msg;
paul@181 262
		magic_t mag;
paul@181 263
		int has_magic = 0;
paul@181 264
paul@181 265
		mag = dl_magic_open(MAGIC_RAW | MAGIC_SYMLINK | MAGIC_DEVICES |
paul@181 266
				    MAGIC_ERROR | MAGIC_NO_CHECK_ELF |
paul@181 267
				    MAGIC_NO_CHECK_COMPRESS);
paul@181 268
		dl_magic_load(mag, NULL);
paul@181 269
paul@181 270
		msg = dl_magic_file(mag, device);
paul@181 271
		if (msg && strcmp(msg, "data") && strcmp(msg, "empty")) {
paul@181 272
			printf(_("%s contains `%s' data\n"), device, msg);
paul@181 273
			has_magic = 1;
paul@181 274
		}
paul@181 275
paul@181 276
		dl_magic_close(mag);
paul@181 277
		return !has_magic;
paul@181 278
	}
paul@181 279
#endif
paul@181 280
paul@181 281
	ret = check_partition_table(device);
paul@181 282
	if (ret >= 0)
paul@181 283
		return ret;
paul@181 284
paul@181 285
	return 1;
paul@181 286
}
paul@181 287