~daniel-mehrmann/e2fsprogs/master

« back to all changes in this revision

Viewing changes to .pc/0001-mke2fs-use-ext2fs_open_file-in-check_plausibility.patch/misc/util.c

  • Committer: Package Import Robot
  • Author(s): Michael Vogt
  • Date: 2014-10-27 09:44:27 UTC
  • mfrom: (8.4.29 sid)
  • Revision ID: package-import@ubuntu.com-20141027094427-g56dce6sg7pasdgm
Tags: 1.42.12-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - debian/rules:
      Block pkg-create-dbgsym from operating on this package.
      Build without dietlibc-dev, which is in universe 
      Use the autotools-dev dh addon to update config.guess/config.sub for new
      ports.
  - debian/control:
      Regenerate with ./debian/rules debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * util.c --- helper functions used by tune2fs and mke2fs
3
 
 *
4
 
 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
5
 
 *
6
 
 * %Begin-Header%
7
 
 * This file may be redistributed under the terms of the GNU Public
8
 
 * License.
9
 
 * %End-Header%
10
 
 */
11
 
 
12
 
#define _LARGEFILE_SOURCE
13
 
#define _LARGEFILE64_SOURCE
14
 
 
15
 
#include "config.h"
16
 
#include <fcntl.h>
17
 
#include <setjmp.h>
18
 
#include <signal.h>
19
 
#include <stdio.h>
20
 
#include <string.h>
21
 
#ifdef HAVE_ERRNO_H
22
 
#include <errno.h>
23
 
#endif
24
 
#ifdef HAVE_LINUX_MAJOR_H
25
 
#include <linux/major.h>
26
 
#endif
27
 
#include <sys/types.h>
28
 
#ifdef HAVE_SYS_STAT_H
29
 
#include <sys/stat.h>
30
 
#endif
31
 
#include <time.h>
32
 
 
33
 
#include "et/com_err.h"
34
 
#include "e2p/e2p.h"
35
 
#include "ext2fs/ext2_fs.h"
36
 
#include "ext2fs/ext2fs.h"
37
 
#include "nls-enable.h"
38
 
#include "blkid/blkid.h"
39
 
#include "util.h"
40
 
 
41
 
char *journal_location_string = NULL;
42
 
 
43
 
#ifndef HAVE_STRCASECMP
44
 
int strcasecmp (char *s1, char *s2)
45
 
{
46
 
        while (*s1 && *s2) {
47
 
                int ch1 = *s1++, ch2 = *s2++;
48
 
                if (isupper (ch1))
49
 
                        ch1 = tolower (ch1);
50
 
                if (isupper (ch2))
51
 
                        ch2 = tolower (ch2);
52
 
                if (ch1 != ch2)
53
 
                        return ch1 - ch2;
54
 
        }
55
 
        return *s1 ? 1 : *s2 ? -1 : 0;
56
 
}
57
 
#endif
58
 
 
59
 
/*
60
 
 * Given argv[0], return the program name.
61
 
 */
62
 
char *get_progname(char *argv_zero)
63
 
{
64
 
        char    *cp;
65
 
 
66
 
        cp = strrchr(argv_zero, '/');
67
 
        if (!cp )
68
 
                return argv_zero;
69
 
        else
70
 
                return cp+1;
71
 
}
72
 
 
73
 
static jmp_buf alarm_env;
74
 
 
75
 
static void alarm_signal(int signal)
76
 
{
77
 
        longjmp(alarm_env, 1);
78
 
}
79
 
 
80
 
void proceed_question(int delay)
81
 
{
82
 
        char buf[256];
83
 
        const char *short_yes = _("yY");
84
 
 
85
 
        fflush(stdout);
86
 
        fflush(stderr);
87
 
        if (delay > 0) {
88
 
                if (setjmp(alarm_env)) {
89
 
                        signal(SIGALRM, SIG_IGN);
90
 
                        printf(_("<proceeding>\n"));
91
 
                        return;
92
 
                }
93
 
                signal(SIGALRM, alarm_signal);
94
 
                printf(_("Proceed anyway (or wait %d seconds) ? (y,n) "),
95
 
                       delay);
96
 
                alarm(delay);
97
 
        } else
98
 
                fputs(_("Proceed anyway? (y,n) "), stdout);
99
 
        buf[0] = 0;
100
 
        if (!fgets(buf, sizeof(buf), stdin) ||
101
 
            strchr(short_yes, buf[0]) == 0) {
102
 
                putc('\n', stdout);
103
 
                exit(1);
104
 
        }
105
 
        signal(SIGALRM, SIG_IGN);
106
 
}
107
 
 
108
 
static void print_ext2_info(const char *device)
109
 
 
110
 
{
111
 
        struct ext2_super_block *sb;
112
 
        ext2_filsys             fs;
113
 
        errcode_t               retval;
114
 
        time_t                  tm;
115
 
        char                    buf[80];
116
 
 
117
 
        retval = ext2fs_open2(device, 0, EXT2_FLAG_64BITS, 0, 0,
118
 
                              unix_io_manager, &fs);
119
 
        if (retval)
120
 
                return;
121
 
        sb = fs->super;
122
 
 
123
 
        if (sb->s_mtime) {
124
 
                tm = sb->s_mtime;
125
 
                if (sb->s_last_mounted[0]) {
126
 
                        memset(buf, 0, sizeof(buf));
127
 
                        strncpy(buf, sb->s_last_mounted,
128
 
                                sizeof(sb->s_last_mounted));
129
 
                        printf(_("\tlast mounted on %s on %s"), buf,
130
 
                               ctime(&tm));
131
 
                } else
132
 
                        printf(_("\tlast mounted on %s"), ctime(&tm));
133
 
        } else if (sb->s_mkfs_time) {
134
 
                tm = sb->s_mkfs_time;
135
 
                printf(_("\tcreated on %s"), ctime(&tm));
136
 
        } else if (sb->s_wtime) {
137
 
                tm = sb->s_wtime;
138
 
                printf(_("\tlast modified on %s"), ctime(&tm));
139
 
        }
140
 
        ext2fs_close(fs);
141
 
}
142
 
 
143
 
/*
144
 
 * return 1 if there is no partition table, 0 if a partition table is
145
 
 * detected, and -1 on an error.
146
 
 */
147
 
static int check_partition_table(const char *device)
148
 
{
149
 
#ifdef HAVE_BLKID_PROBE_ENABLE_PARTITIONS
150
 
        blkid_probe pr;
151
 
        const char *value;
152
 
        int ret;
153
 
 
154
 
        pr = blkid_new_probe_from_filename(device);
155
 
        if (!pr)
156
 
                return -1;
157
 
 
158
 
        ret = blkid_probe_enable_partitions(pr, 1);
159
 
        if (ret < 0)
160
 
                goto errout;
161
 
 
162
 
        ret = blkid_probe_enable_superblocks(pr, 0);
163
 
        if (ret < 0)
164
 
                goto errout;
165
 
 
166
 
        ret = blkid_do_fullprobe(pr);
167
 
        if (ret < 0)
168
 
                goto errout;
169
 
 
170
 
        ret = blkid_probe_lookup_value(pr, "PTTYPE", &value, NULL);
171
 
        if (ret == 0)
172
 
                fprintf(stderr, _("Found a %s partition table in %s\n"),
173
 
                        value, device);
174
 
        else
175
 
                ret = 1;
176
 
 
177
 
errout:
178
 
        blkid_free_probe(pr);
179
 
        return ret;
180
 
#else
181
 
        return -1;
182
 
#endif
183
 
}
184
 
 
185
 
/*
186
 
 * return 1 if the device looks plausible, creating the file if necessary
187
 
 */
188
 
int check_plausibility(const char *device, int flags, int *ret_is_dev)
189
 
{
190
 
        int fd, ret, is_dev = 0;
191
 
        ext2fs_struct_stat s;
192
 
        int fl = O_RDONLY;
193
 
        blkid_cache cache = NULL;
194
 
        char *fs_type = NULL;
195
 
        char *fs_label = NULL;
196
 
 
197
 
        fd = open(device, fl, 0666);
198
 
        if ((fd < 0) && (errno == ENOENT) && (flags & CREATE_FILE)) {
199
 
                fl |= O_CREAT;
200
 
                fd = open(device, fl, 0666);
201
 
                if (fd >= 0 && (flags & VERBOSE_CREATE))
202
 
                        printf(_("Creating regular file %s\n"), device);
203
 
        }
204
 
        if (fd < 0) {
205
 
                fprintf(stderr, _("Could not open %s: %s\n"),
206
 
                        device, error_message(errno));
207
 
                if (errno == ENOENT)
208
 
                        fputs(_("\nThe device apparently does not exist; "
209
 
                                "did you specify it correctly?\n"), stderr);
210
 
                exit(1);
211
 
        }
212
 
 
213
 
        if (ext2fs_fstat(fd, &s) < 0) {
214
 
                perror("stat");
215
 
                exit(1);
216
 
        }
217
 
        close(fd);
218
 
 
219
 
        if (S_ISBLK(s.st_mode))
220
 
                is_dev = 1;
221
 
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
222
 
        /* On FreeBSD, all disk devices are character specials */
223
 
        if (S_ISCHR(s.st_mode))
224
 
                is_dev = 1;
225
 
#endif
226
 
        if (ret_is_dev)
227
 
                *ret_is_dev = is_dev;
228
 
 
229
 
        if ((flags & CHECK_BLOCK_DEV) && !is_dev) {
230
 
                printf(_("%s is not a block special device.\n"), device);
231
 
                return 0;
232
 
        }
233
 
 
234
 
        /*
235
 
         * Note: we use the older-style blkid API's here because we
236
 
         * want as much functionality to be available when using the
237
 
         * internal blkid library, when e2fsprogs is compiled for
238
 
         * non-Linux systems that will probably not have the libraries
239
 
         * from util-linux available.  We only use the newer
240
 
         * blkid-probe interfaces to access functionality not
241
 
         * available in the original blkid library.
242
 
         */
243
 
        if ((flags & CHECK_FS_EXIST) && blkid_get_cache(&cache, NULL) >= 0) {
244
 
                fs_type = blkid_get_tag_value(cache, "TYPE", device);
245
 
                if (fs_type)
246
 
                        fs_label = blkid_get_tag_value(cache, "LABEL", device);
247
 
                blkid_put_cache(cache);
248
 
        }
249
 
 
250
 
        if (fs_type) {
251
 
                if (fs_label)
252
 
                        printf(_("%s contains a %s file system "
253
 
                                 "labelled '%s'\n"), device, fs_type, fs_label);
254
 
                else
255
 
                        printf(_("%s contains a %s file system\n"), device,
256
 
                               fs_type);
257
 
                if (strncmp(fs_type, "ext", 3) == 0)
258
 
                        print_ext2_info(device);
259
 
                free(fs_type);
260
 
                free(fs_label);
261
 
                return 0;
262
 
        }
263
 
 
264
 
        ret = check_partition_table(device);
265
 
        if (ret >= 0)
266
 
                return ret;
267
 
 
268
 
#ifdef HAVE_LINUX_MAJOR_H
269
 
#ifndef MAJOR
270
 
#define MAJOR(dev)      ((dev)>>8)
271
 
#define MINOR(dev)      ((dev) & 0xff)
272
 
#endif
273
 
#ifndef SCSI_BLK_MAJOR
274
 
#ifdef SCSI_DISK0_MAJOR
275
 
#ifdef SCSI_DISK8_MAJOR
276
 
#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
277
 
  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
278
 
  ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
279
 
#else
280
 
#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
281
 
  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
282
 
#endif /* defined(SCSI_DISK8_MAJOR) */
283
 
#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
284
 
#else
285
 
#define SCSI_BLK_MAJOR(M)  ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
286
 
#endif /* defined(SCSI_DISK0_MAJOR) */
287
 
#endif /* defined(SCSI_BLK_MAJOR) */
288
 
        if (((MAJOR(s.st_rdev) == HD_MAJOR &&
289
 
              MINOR(s.st_rdev)%64 == 0) ||
290
 
             (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
291
 
              MINOR(s.st_rdev)%16 == 0))) {
292
 
                printf(_("%s is entire device, not just one partition!\n"),
293
 
                       device);
294
 
                return 0;
295
 
        }
296
 
#endif
297
 
        return 1;
298
 
}
299
 
 
300
 
void check_mount(const char *device, int force, const char *type)
301
 
{
302
 
        errcode_t       retval;
303
 
        int             mount_flags;
304
 
 
305
 
        retval = ext2fs_check_if_mounted(device, &mount_flags);
306
 
        if (retval) {
307
 
                com_err("ext2fs_check_if_mount", retval,
308
 
                        _("while determining whether %s is mounted."),
309
 
                        device);
310
 
                return;
311
 
        }
312
 
        if (mount_flags & EXT2_MF_MOUNTED) {
313
 
                fprintf(stderr, _("%s is mounted; "), device);
314
 
                if (force >= 2) {
315
 
                        fputs(_("mke2fs forced anyway.  Hope /etc/mtab is "
316
 
                                "incorrect.\n"), stderr);
317
 
                        return;
318
 
                }
319
 
        abort_mke2fs:
320
 
                fprintf(stderr, _("will not make a %s here!\n"), type);
321
 
                exit(1);
322
 
        }
323
 
        if (mount_flags & EXT2_MF_BUSY) {
324
 
                fprintf(stderr, _("%s is apparently in use by the system; "),
325
 
                        device);
326
 
                if (force >= 2) {
327
 
                        fputs(_("mke2fs forced anyway.\n"), stderr);
328
 
                        return;
329
 
                }
330
 
                goto abort_mke2fs;
331
 
        }
332
 
}
333
 
 
334
 
void parse_journal_opts(const char *opts)
335
 
{
336
 
        char    *buf, *token, *next, *p, *arg;
337
 
        int     len;
338
 
        int     journal_usage = 0;
339
 
 
340
 
        len = strlen(opts);
341
 
        buf = malloc(len+1);
342
 
        if (!buf) {
343
 
                fputs(_("Couldn't allocate memory to parse journal "
344
 
                        "options!\n"), stderr);
345
 
                exit(1);
346
 
        }
347
 
        strcpy(buf, opts);
348
 
        for (token = buf; token && *token; token = next) {
349
 
                p = strchr(token, ',');
350
 
                next = 0;
351
 
                if (p) {
352
 
                        *p = 0;
353
 
                        next = p+1;
354
 
                }
355
 
                arg = strchr(token, '=');
356
 
                if (arg) {
357
 
                        *arg = 0;
358
 
                        arg++;
359
 
                }
360
 
#if 0
361
 
                printf("Journal option=%s, argument=%s\n", token,
362
 
                       arg ? arg : "NONE");
363
 
#endif
364
 
                if (strcmp(token, "device") == 0) {
365
 
                        journal_device = blkid_get_devname(NULL, arg, NULL);
366
 
                        if (!journal_device) {
367
 
                                if (arg)
368
 
                                        fprintf(stderr, _("\nCould not find "
369
 
                                                "journal device matching %s\n"),
370
 
                                                arg);
371
 
                                journal_usage++;
372
 
                                continue;
373
 
                        }
374
 
                } else if (strcmp(token, "size") == 0) {
375
 
                        if (!arg) {
376
 
                                journal_usage++;
377
 
                                continue;
378
 
                        }
379
 
                        journal_size = strtoul(arg, &p, 0);
380
 
                        if (*p)
381
 
                                journal_usage++;
382
 
                } else if (!strcmp(token, "location")) {
383
 
                        if (!arg) {
384
 
                                journal_usage++;
385
 
                                continue;
386
 
                        }
387
 
                        journal_location_string = strdup(arg);
388
 
                } else if (strcmp(token, "v1_superblock") == 0) {
389
 
                        journal_flags |= EXT2_MKJOURNAL_V1_SUPER;
390
 
                        continue;
391
 
                } else
392
 
                        journal_usage++;
393
 
        }
394
 
        if (journal_usage) {
395
 
                fputs(_("\nBad journal options specified.\n\n"
396
 
                        "Journal options are separated by commas, "
397
 
                        "and may take an argument which\n"
398
 
                        "\tis set off by an equals ('=') sign.\n\n"
399
 
                        "Valid journal options are:\n"
400
 
                        "\tsize=<journal size in megabytes>\n"
401
 
                        "\tdevice=<journal device>\n"
402
 
                        "\tlocation=<journal location>\n\n"
403
 
                        "The journal size must be between "
404
 
                        "1024 and 10240000 filesystem blocks.\n\n"), stderr);
405
 
                free(buf);
406
 
                exit(1);
407
 
        }
408
 
        free(buf);
409
 
}
410
 
 
411
 
/*
412
 
 * Determine the number of journal blocks to use, either via
413
 
 * user-specified # of megabytes, or via some intelligently selected
414
 
 * defaults.
415
 
 *
416
 
 * Find a reasonable journal file size (in blocks) given the number of blocks
417
 
 * in the filesystem.  For very small filesystems, it is not reasonable to
418
 
 * have a journal that fills more than half of the filesystem.
419
 
 */
420
 
unsigned int figure_journal_size(int size, ext2_filsys fs)
421
 
{
422
 
        int j_blocks;
423
 
 
424
 
        j_blocks = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
425
 
        if (j_blocks < 0) {
426
 
                fputs(_("\nFilesystem too small for a journal\n"), stderr);
427
 
                return 0;
428
 
        }
429
 
 
430
 
        if (size > 0) {
431
 
                j_blocks = size * 1024 / (fs->blocksize / 1024);
432
 
                if (j_blocks < 1024 || j_blocks > 10240000) {
433
 
                        fprintf(stderr, _("\nThe requested journal "
434
 
                                "size is %d blocks; it must be\n"
435
 
                                "between 1024 and 10240000 blocks.  "
436
 
                                "Aborting.\n"),
437
 
                                j_blocks);
438
 
                        exit(1);
439
 
                }
440
 
                if ((unsigned) j_blocks > ext2fs_free_blocks_count(fs->super) / 2) {
441
 
                        fputs(_("\nJournal size too big for filesystem.\n"),
442
 
                              stderr);
443
 
                        exit(1);
444
 
                }
445
 
        }
446
 
        return j_blocks;
447
 
}
448
 
 
449
 
void print_check_message(int mnt, unsigned int check)
450
 
{
451
 
        if (mnt < 0)
452
 
                mnt = 0;
453
 
        if (!mnt && !check)
454
 
                return;
455
 
        printf(_("This filesystem will be automatically "
456
 
                 "checked every %d mounts or\n"
457
 
                 "%g days, whichever comes first.  "
458
 
                 "Use tune2fs -c or -i to override.\n"),
459
 
               mnt, ((double) check) / (3600 * 24));
460
 
}
461
 
 
462
 
void dump_mmp_msg(struct mmp_struct *mmp, const char *msg)
463
 
{
464
 
 
465
 
        if (msg)
466
 
                printf("MMP check failed: %s\n", msg);
467
 
        if (mmp) {
468
 
                time_t t = mmp->mmp_time;
469
 
 
470
 
                printf("MMP error info: last update: %s node: %s device: %s\n",
471
 
                       ctime(&t), mmp->mmp_nodename, mmp->mmp_bdevname);
472
 
        }
473
 
}