L4Re/departure

libext2fs/lib/libsupport/plausible.c

617:2733e5770ee9
9 months ago Paul Boddie Made the run command wait for completion, introducing the spawn command to run programs in the background. Introduced conveniences for waiting for the last job to be initiated and for piping from the last job, also subscribing to signals from pipe-supplying jobs so that they may be transparently removed from the job list upon completion. Augmented the job listing with the "+" notation familiar from Unix. Prevented new jobs from being started when no job slots are available.
     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