~ubuntu-branches/debian/sid/ntfs-3g/sid

« back to all changes in this revision

Viewing changes to .pc/0002-exit-values.patch/ntfsprogs/ntfslabel.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2014-10-05 09:34:12 UTC
  • mfrom: (1.2.6)
  • Revision ID: package-import@ubuntu.com-20141005093412-4ohtygxt9pm9v5u9
Tags: 1:2014.2.15AR.2-1
* New upstream release.
* Remove 0001-type-inconsistencies.patch and 0002-exit-values.patch , this
  release contains those.
* Update Standards-Version to 3.9.6 .

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * ntfslabel - Part of the Linux-NTFS project.
3
 
 *
4
 
 * Copyright (c) 2002 Matthew J. Fanto
5
 
 * Copyright (c) 2002-2005 Anton Altaparmakov
6
 
 * Copyright (c) 2002-2003 Richard Russon
7
 
 * Copyright (c) 2012-2014 Jean-Pierre Andre
8
 
 *
9
 
 * This utility will display/change the label on an NTFS partition.
10
 
 *
11
 
 * This program is free software; you can redistribute it and/or modify
12
 
 * it under the terms of the GNU General Public License as published by
13
 
 * the Free Software Foundation; either version 2 of the License, or
14
 
 * (at your option) any later version.
15
 
 *
16
 
 * This program is distributed in the hope that it will be useful,
17
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
 * GNU General Public License for more details.
20
 
 *
21
 
 * You should have received a copy of the GNU General Public License
22
 
 * along with this program (in the main directory of the Linux-NTFS
23
 
 * distribution in the file COPYING); if not, write to the Free Software
24
 
 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 
 */
26
 
 
27
 
#include "config.h"
28
 
 
29
 
#ifdef HAVE_STDLIB_H
30
 
#include <stdlib.h>
31
 
#endif
32
 
#ifdef HAVE_STDIO_H
33
 
#include <stdio.h>
34
 
#endif
35
 
#ifdef HAVE_STRING_H
36
 
#include <string.h>
37
 
#endif
38
 
#ifdef HAVE_ERRNO_H
39
 
#include <errno.h>
40
 
#endif
41
 
#ifdef HAVE_LOCALE_H
42
 
#include <locale.h>
43
 
#endif
44
 
#ifdef HAVE_GETOPT_H
45
 
#include <getopt.h>
46
 
#endif
47
 
#ifdef HAVE_UNISTD_H
48
 
#include <unistd.h>
49
 
#endif
50
 
 
51
 
#include "debug.h"
52
 
#include "mft.h"
53
 
#include "utils.h"
54
 
/* #include "version.h" */
55
 
#include "logging.h"
56
 
#include "misc.h"
57
 
 
58
 
static const char *EXEC_NAME = "ntfslabel";
59
 
 
60
 
static struct options {
61
 
        char    *device;        /* Device/File to work with */
62
 
        char    *label;         /* Set the label to this */
63
 
        int      quiet;         /* Less output */
64
 
        int      verbose;       /* Extra output */
65
 
        int      force;         /* Override common sense */
66
 
        int      new_serial;    /* Change the serial number */
67
 
        unsigned long long serial;      /* Forced serial number value */
68
 
        int      noaction;      /* Do not write to disk */
69
 
} opts;
70
 
 
71
 
/**
72
 
 * version - Print version information about the program
73
 
 *
74
 
 * Print a copyright statement and a brief description of the program.
75
 
 *
76
 
 * Return:  none
77
 
 */
78
 
static void version(void)
79
 
{
80
 
        ntfs_log_info("\n%s v%s (libntfs-3g) - Display, or set, the label for an "
81
 
                        "NTFS Volume.\n\n", EXEC_NAME, VERSION);
82
 
        ntfs_log_info("Copyright (c)\n");
83
 
        ntfs_log_info("    2002      Matthew J. Fanto\n");
84
 
        ntfs_log_info("    2002-2005 Anton Altaparmakov\n");
85
 
        ntfs_log_info("    2002-2003 Richard Russon\n");
86
 
        ntfs_log_info("    2012      Jean-Pierre Andre\n");
87
 
        ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
88
 
}
89
 
 
90
 
/**
91
 
 * usage - Print a list of the parameters to the program
92
 
 *
93
 
 * Print a list of the parameters and options for the program.
94
 
 *
95
 
 * Return:  none
96
 
 */
97
 
static void usage(void)
98
 
{
99
 
        ntfs_log_info("\nUsage: %s [options] device [label]\n"
100
 
               "    -n, --no-action    Do not write to disk\n"
101
 
               "    -f, --force        Use less caution\n"
102
 
               "        --new-serial   Set a new serial number\n"
103
 
               "        --new-half-serial Set a partial new serial number\n"
104
 
               "    -q, --quiet        Less output\n"
105
 
               "    -v, --verbose      More output\n"
106
 
               "    -V, --version      Display version information\n"
107
 
               "    -h, --help         Display this help\n\n",
108
 
               EXEC_NAME);
109
 
        ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
110
 
}
111
 
 
112
 
/**
113
 
 * parse_options - Read and validate the programs command line
114
 
 *
115
 
 * Read the command line, verify the syntax and parse the options.
116
 
 * This function is very long, but quite simple.
117
 
 *
118
 
 * Return:  1 Success
119
 
 *          0 Error, one or more problems
120
 
 */
121
 
static int parse_options(int argc, char *argv[])
122
 
{
123
 
        static const char *sopt = "-fh?IinqvV";
124
 
        static const struct option lopt[] = {
125
 
                { "force",       no_argument,           NULL, 'f' },
126
 
                { "help",        no_argument,           NULL, 'h' },
127
 
                { "new-serial",  optional_argument,     NULL, 'I' },
128
 
                { "new-half-serial", optional_argument, NULL, 'i' },
129
 
                { "no-action",   no_argument,           NULL, 'n' },
130
 
                { "quiet",       no_argument,           NULL, 'q' },
131
 
                { "verbose",     no_argument,           NULL, 'v' },
132
 
                { "version",     no_argument,           NULL, 'V' },
133
 
                { NULL, 0, NULL, 0 },
134
 
        };
135
 
 
136
 
        int c = -1;
137
 
        int err  = 0;
138
 
        int ver  = 0;
139
 
        int help = 0;
140
 
        int levels = 0;
141
 
        char *endserial;
142
 
 
143
 
        opterr = 0; /* We'll handle the errors, thank you. */
144
 
 
145
 
        while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
146
 
                switch (c) {
147
 
                case 1: /* A non-option argument */
148
 
                        if (!err && !opts.device)
149
 
                                opts.device = argv[optind-1];
150
 
                        else if (!err && !opts.label)
151
 
                                opts.label = argv[optind-1];
152
 
                        else
153
 
                                err++;
154
 
                        break;
155
 
                case 'f':
156
 
                        opts.force++;
157
 
                        break;
158
 
                case 'h':
159
 
                case '?':
160
 
                        if (strncmp (argv[optind-1], "--log-", 6) == 0) {
161
 
                                if (!ntfs_log_parse_option (argv[optind-1]))
162
 
                                        err++;
163
 
                                break;
164
 
                        }
165
 
                        help++;
166
 
                        break;
167
 
                case 'I' :      /* not proposed as a short option letter */
168
 
                        if (optarg) {
169
 
                                opts.serial = strtoull(optarg, &endserial, 16);
170
 
                                if (*endserial)
171
 
                                        ntfs_log_error("Bad hexadecimal serial number.\n");
172
 
                        }
173
 
                        opts.new_serial |= 2;
174
 
                        break;
175
 
                case 'i' :      /* not proposed as a short option letter */
176
 
                        if (optarg) {
177
 
                                opts.serial = strtoull(optarg, &endserial, 16)
178
 
                                                        << 32;
179
 
                                if (*endserial)
180
 
                                        ntfs_log_error("Bad hexadecimal serial number.\n");
181
 
                        }
182
 
                        opts.new_serial |= 1;
183
 
                        break;
184
 
                case 'n':
185
 
                        opts.noaction++;
186
 
                        break;
187
 
                case 'q':
188
 
                        opts.quiet++;
189
 
                        ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
190
 
                        break;
191
 
                case 'v':
192
 
                        opts.verbose++;
193
 
                        ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
194
 
                        break;
195
 
                case 'V':
196
 
                        ver++;
197
 
                        break;
198
 
                default:
199
 
                        ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
200
 
                        err++;
201
 
                        break;
202
 
                }
203
 
        }
204
 
 
205
 
        /* Make sure we're in sync with the log levels */
206
 
        levels = ntfs_log_get_levels();
207
 
        if (levels & NTFS_LOG_LEVEL_VERBOSE)
208
 
                opts.verbose++;
209
 
        if (!(levels & NTFS_LOG_LEVEL_QUIET))
210
 
                opts.quiet++;
211
 
 
212
 
        if (help || ver) {
213
 
                opts.quiet = 0;
214
 
        } else {
215
 
                if (opts.device == NULL) {
216
 
                        if (argc > 1)
217
 
                                ntfs_log_error("You must specify a device.\n");
218
 
                        err++;
219
 
                }
220
 
 
221
 
                if (opts.quiet && opts.verbose) {
222
 
                        ntfs_log_error("You may not use --quiet and --verbose at "
223
 
                                        "the same time.\n");
224
 
                        err++;
225
 
                }
226
 
        }
227
 
 
228
 
        if (ver)
229
 
                version();
230
 
        if (help || err)
231
 
                usage();
232
 
 
233
 
        return (!err && !help && !ver);
234
 
}
235
 
 
236
 
static int change_serial(ntfs_volume *vol, u64 sector, le64 serial_number,
237
 
                        NTFS_BOOT_SECTOR *bs, NTFS_BOOT_SECTOR *oldbs)
238
 
{
239
 
        int res;
240
 
        le64 mask;
241
 
        BOOL same;
242
 
 
243
 
        res = -1;
244
 
        if ((ntfs_pread(vol->dev, sector << vol->sector_size_bits,
245
 
                        vol->sector_size, bs) == vol->sector_size)) {
246
 
                same = TRUE;
247
 
                if (!sector)
248
 
                                /* save the real bootsector */
249
 
                        memcpy(oldbs, bs, vol->sector_size);
250
 
                else
251
 
                                /* backup bootsector must be similar */
252
 
                        same = !memcmp(oldbs, bs, vol->sector_size);
253
 
                if (same) {
254
 
                        if (opts.new_serial & 2)
255
 
                                bs->volume_serial_number = serial_number;
256
 
                        else {
257
 
                                mask = const_cpu_to_le64(~0x0ffffffffULL);
258
 
                                bs->volume_serial_number
259
 
                                    = (serial_number & mask)
260
 
                                        | (bs->volume_serial_number & ~mask);
261
 
                        }
262
 
                        if (opts.noaction
263
 
                            || (ntfs_pwrite(vol->dev,
264
 
                                sector << vol->sector_size_bits,
265
 
                                vol->sector_size, bs) == vol->sector_size)) {
266
 
                                res = 0;
267
 
                        }
268
 
                } else {
269
 
                        ntfs_log_info("* Warning : the backup boot sector"
270
 
                                " does not match (leaving unchanged)\n");
271
 
                        res = 0;
272
 
                }
273
 
        }
274
 
        return (res);
275
 
}
276
 
 
277
 
static int set_new_serial(ntfs_volume *vol)
278
 
{
279
 
        NTFS_BOOT_SECTOR *bs; /* full boot sectors */
280
 
        NTFS_BOOT_SECTOR *oldbs; /* full original boot sector */
281
 
        le64 serial_number;
282
 
        u64 number_of_sectors;
283
 
        u64 sn;
284
 
        int res;
285
 
 
286
 
        res = -1;
287
 
        bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
288
 
        oldbs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
289
 
        if (bs && oldbs) {
290
 
                if (opts.serial)
291
 
                        serial_number = cpu_to_le64(opts.serial);
292
 
                else {
293
 
                        /* different values for parallel processes */
294
 
                        srandom(time((time_t*)NULL) ^ (getpid() << 16));
295
 
                        sn = ((u64)random() << 32)
296
 
                                        | ((u64)random() & 0xffffffff);
297
 
                        serial_number = cpu_to_le64(sn);
298
 
                }
299
 
                if (!change_serial(vol, 0, serial_number, bs, oldbs)) {
300
 
                        number_of_sectors = le64_to_cpu(bs->number_of_sectors);
301
 
                        if (!change_serial(vol, number_of_sectors,
302
 
                                                serial_number, bs, oldbs)) {
303
 
                                ntfs_log_info("New serial number : %016llx\n",
304
 
                                        (long long)le64_to_cpu(
305
 
                                                bs->volume_serial_number));
306
 
                                res = 0;
307
 
                                }
308
 
                }
309
 
                free(bs);
310
 
                free(oldbs);
311
 
        }
312
 
        if (res)
313
 
                ntfs_log_info("Error setting a new serial number\n");
314
 
        return (res);
315
 
}
316
 
 
317
 
static int print_serial(ntfs_volume *vol)
318
 
{
319
 
        NTFS_BOOT_SECTOR *bs; /* full boot sectors */
320
 
        int res;
321
 
 
322
 
        res = -1;
323
 
        bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
324
 
        if (bs
325
 
            && (ntfs_pread(vol->dev, 0,
326
 
                        vol->sector_size, bs) == vol->sector_size)) {
327
 
                ntfs_log_info("Serial number : %016llx\n",
328
 
                        (long long)le64_to_cpu(bs->volume_serial_number));
329
 
                res = 0;
330
 
                free(bs);
331
 
        }
332
 
        if (res)
333
 
                ntfs_log_info("Error getting the serial number\n");
334
 
        return (res);
335
 
}
336
 
 
337
 
/**
338
 
 * print_label - display the current label of a mounted ntfs partition.
339
 
 * @dev:        device to read the label from
340
 
 * @mnt_flags:  mount flags of the device or 0 if not mounted
341
 
 * @mnt_point:  mount point of the device or NULL
342
 
 *
343
 
 * Print the label of the device @dev.
344
 
 */
345
 
static int print_label(ntfs_volume *vol, unsigned long mnt_flags)
346
 
{
347
 
        int result = 0;
348
 
        //XXX significant?
349
 
        if ((mnt_flags & (NTFS_MF_MOUNTED | NTFS_MF_READONLY)) ==
350
 
                        NTFS_MF_MOUNTED) {
351
 
                ntfs_log_error("%s is mounted read-write, results may be "
352
 
                        "unreliable.\n", opts.device);
353
 
                result = 1;
354
 
        }
355
 
 
356
 
        if (opts.verbose)
357
 
                ntfs_log_info("Volume label :  %s\n", vol->vol_name);
358
 
        else
359
 
                ntfs_log_info("%s\n", vol->vol_name);
360
 
        return result;
361
 
}
362
 
 
363
 
/**
364
 
 * change_label - change the current label on a device
365
 
 * @dev:        device to change the label on
366
 
 * @mnt_flags:  mount flags of the device or 0 if not mounted
367
 
 * @mnt_point:  mount point of the device or NULL
368
 
 * @label:      the new label
369
 
 *
370
 
 * Change the label on the device @dev to @label.
371
 
 */
372
 
static int change_label(ntfs_volume *vol, char *label)
373
 
{
374
 
        ntfschar *new_label = NULL;
375
 
        int label_len;
376
 
        int result = 0;
377
 
 
378
 
        label_len = ntfs_mbstoucs(label, &new_label);
379
 
        if (label_len == -1) {
380
 
                ntfs_log_perror("Unable to convert label string to Unicode");
381
 
                return 1;
382
 
        }
383
 
        else if (label_len*sizeof(ntfschar) > 0x100) {
384
 
                ntfs_log_warning("New label is too long. Maximum %u characters "
385
 
                                "allowed. Truncating %u excess characters.\n",
386
 
                                (unsigned)(0x100 / sizeof(ntfschar)),
387
 
                                (unsigned)(label_len -
388
 
                                (0x100 / sizeof(ntfschar))));
389
 
                label_len = 0x100 / sizeof(ntfschar);
390
 
                label[label_len] = const_cpu_to_le16(0);
391
 
        }
392
 
 
393
 
        if(!opts.noaction)
394
 
                result = ntfs_volume_rename(vol, new_label, label_len) ? 1 : 0;
395
 
 
396
 
        free(new_label);
397
 
        return result;
398
 
}
399
 
 
400
 
/**
401
 
 * main - Begin here
402
 
 *
403
 
 * Start from here.
404
 
 *
405
 
 * Return:  0  Success, the program worked
406
 
 *          1  Error, something went wrong
407
 
 */
408
 
int main(int argc, char **argv)
409
 
{
410
 
        unsigned long mnt_flags = 0;
411
 
        int result = 0;
412
 
        ntfs_volume *vol;
413
 
 
414
 
        ntfs_log_set_handler(ntfs_log_handler_outerr);
415
 
 
416
 
        if (!parse_options(argc, argv))
417
 
                return 1;
418
 
 
419
 
        utils_set_locale();
420
 
 
421
 
        if ((opts.label || opts.new_serial)
422
 
            && !opts.noaction
423
 
            && !opts.force
424
 
            && !ntfs_check_if_mounted(opts.device, &mnt_flags)
425
 
            && (mnt_flags & NTFS_MF_MOUNTED)) {
426
 
                ntfs_log_error("Cannot make changes to a mounted device\n");
427
 
                result = 1;
428
 
                goto abort;
429
 
        }
430
 
 
431
 
        if (!opts.label && !opts.new_serial)
432
 
                opts.noaction++;
433
 
 
434
 
        vol = utils_mount_volume(opts.device,
435
 
                        (opts.noaction ? NTFS_MNT_RDONLY : 0) |
436
 
                        (opts.force ? NTFS_MNT_RECOVER : 0));
437
 
        if (!vol)
438
 
                return 1;
439
 
 
440
 
        if (opts.new_serial) {
441
 
                result = set_new_serial(vol);
442
 
                if (result)
443
 
                        goto unmount;
444
 
        } else {
445
 
                if (opts.verbose)
446
 
                        result = print_serial(vol);
447
 
        }
448
 
        if (opts.label)
449
 
                result = change_label(vol, opts.label);
450
 
        else
451
 
                result = print_label(vol, mnt_flags);
452
 
 
453
 
unmount :
454
 
        ntfs_umount(vol, FALSE);
455
 
abort :
456
 
        return result;
457
 
}
458