L4Re/departure

libext2fs/lib/libsupport/plausible.c

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