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