"Fossies" - the Fresh Open Source Software Archive

Member "dosfstools-4.2/src/fatlabel.c" (31 Jan 2021, 7174 Bytes) of package /linux/misc/dosfstools-4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fatlabel.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1_vs_4.2.

    1 /* fatlabel.c - User interface
    2 
    3    Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
    4    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
    5    Copyright (C) 2007 Red Hat, Inc.
    6    Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
    7    Copyright (C) 2015-2017 Andreas Bombe <aeb@debian.org>
    8    Copyright (C) 2017-2018 Pali Rohár <pali.rohar@gmail.com>
    9 
   10    This program is free software: you can redistribute it and/or modify
   11    it under the terms of the GNU General Public License as published by
   12    the Free Software Foundation, either version 3 of the License, or
   13    (at your option) any later version.
   14 
   15    This program is distributed in the hope that it will be useful,
   16    but WITHOUT ANY WARRANTY; without even the implied warranty of
   17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   18    GNU General Public License for more details.
   19 
   20    You should have received a copy of the GNU General Public License
   21    along with this program. If not, see <http://www.gnu.org/licenses/>.
   22 
   23    The complete text of the GNU General Public License
   24    can be found in /usr/share/common-licenses/GPL-3 file.
   25 */
   26 
   27 #include "version.h"
   28 
   29 #include <stdbool.h>
   30 #include <errno.h>
   31 #include <stdio.h>
   32 #include <stdlib.h>
   33 #include <string.h>
   34 #include <stdlib.h>
   35 #include <limits.h>
   36 #include <unistd.h>
   37 #include <getopt.h>
   38 #include <ctype.h>
   39 
   40 #include "common.h"
   41 #include "fsck.fat.h"
   42 #include "io.h"
   43 #include "boot.h"
   44 #include "fat.h"
   45 #include "file.h"
   46 #include "check.h"
   47 #include "charconv.h"
   48 
   49 int rw = 0, list = 0, test = 0, verbose = 0, no_spaces_in_sfns = 0;
   50 long fat_table = 0;
   51 unsigned n_files = 0;
   52 void *mem_queue = NULL;
   53 
   54 
   55 static void handle_label(bool change, bool reset, const char *device, char *newlabel)
   56 {
   57     DOS_FS fs = { 0 };
   58     off_t offset;
   59     DIR_ENT de;
   60 
   61     char label[12] = { 0 };
   62     size_t len;
   63     int ret;
   64     int i;
   65 
   66     if (change) {
   67     len = mbstowcs(NULL, newlabel, 0);
   68     if (len != (size_t)-1 && len > 11) {
   69         fprintf(stderr,
   70             "fatlabel: labels can be no longer than 11 characters\n");
   71         exit(1);
   72     }
   73 
   74     if (!local_string_to_dos_string(label, newlabel, 12)) {
   75         fprintf(stderr,
   76             "fatlabel: error when processing label\n");
   77         exit(1);
   78     }
   79 
   80     for (i = strlen(label); i < 11; ++i)
   81         label[i] = ' ';
   82     label[11] = 0;
   83 
   84     ret = validate_volume_label(label);
   85     if (ret & 0x1) {
   86         fprintf(stderr,
   87             "fatlabel: warning - lowercase labels might not work properly on some systems\n");
   88     }
   89     if (ret & 0x2) {
   90         fprintf(stderr,
   91             "fatlabel: labels with characters below 0x20 are not allowed\n");
   92         exit(1);
   93     }
   94     if (ret & 0x4) {
   95         fprintf(stderr,
   96             "fatlabel: labels with characters *?.,;:/\\|+=<>[]\" are not allowed\n");
   97         exit(1);
   98     }
   99     if (ret & 0x08) {
  100         fprintf(stderr,
  101             "fatlabel: labels can't be empty or white space only\n");
  102         exit(1);
  103     }
  104     if (ret & 0x10) {
  105         fprintf(stderr,
  106             "fatlabel: labels can't start with a space character\n");
  107         exit(1);
  108     }
  109     }
  110 
  111     fs_open(device, rw);
  112     read_boot(&fs);
  113 
  114     if (!change && !reset) {
  115     if (fs.fat_bits == 32)
  116         read_fat(&fs, 0);
  117 
  118     offset = find_volume_de(&fs, &de);
  119     if (offset != 0) {
  120         if (de.name[0] == 0x05)
  121         de.name[0] = 0xe5;
  122         printf("%s\n", pretty_label((char *)de.name));
  123     }
  124 
  125     if (fs.fat_bits == 32)
  126         release_fat(&fs);
  127 
  128     exit(0);
  129     }
  130 
  131     if (fs.fat_bits == 32)
  132     read_fat(&fs, 1);
  133 
  134     if (!reset)
  135     write_label(&fs, label);
  136     else
  137     remove_label(&fs);
  138 
  139     if (fs.fat_bits == 32)
  140     release_fat(&fs);
  141 }
  142 
  143 
  144 static void handle_volid(bool change, bool reset, const char *device, const char *newserial)
  145 {
  146     DOS_FS fs = { 0 };
  147     char *tmp;
  148     long long conversion;
  149     uint32_t serial = 0;
  150 
  151     if (change) {
  152     errno = 0;
  153     conversion = strtoll(newserial, &tmp, 16);
  154 
  155     if (!*newserial || isspace(*newserial) || *tmp || conversion < 0) {
  156         fprintf(stderr, "fatlabel: volume ID must be a hexadecimal number\n");
  157         exit(1);
  158     }
  159     if (conversion > UINT32_MAX) {
  160         fprintf(stderr, "fatlabel: given volume ID does not fit in 32 bit\n");
  161         exit(1);
  162     }
  163     if (errno) {
  164         fprintf(stderr, "fatlabel: parsing volume ID failed (%s)\n", strerror(errno));
  165         exit(1);
  166     }
  167 
  168     serial = conversion;
  169     }
  170 
  171     if (reset)
  172     serial = generate_volume_id();
  173 
  174     fs_open(device, rw);
  175     read_boot(&fs);
  176     if (!change && !reset) {
  177     printf("%08x\n", fs.serial);
  178     exit(0);
  179     }
  180 
  181     write_serial(&fs, serial);
  182 }
  183 
  184 
  185 static void usage(int error, int usage_only)
  186 {
  187     FILE *f = error ? stderr : stdout;
  188     int status = error ? 1 : 0;
  189 
  190     fprintf(f, "Usage: fatlabel [OPTIONS] DEVICE [NEW]\n");
  191     if (usage_only)
  192     exit(status);
  193 
  194     fprintf(f, "Change the FAT filesystem label or serial on DEVICE to NEW or display the\n");
  195     fprintf(f, "existing label or serial if NEW is not given.\n");
  196     fprintf(f, "\n");
  197     fprintf(f, "Options:\n");
  198     fprintf(f, "  -i, --volume-id     Work on serial number instead of label\n");
  199     fprintf(f, "  -r, --reset         Remove label or generate new serial number\n");
  200     fprintf(f, "  -c N, --codepage=N  use DOS codepage N to encode/decode label (default: %d)\n", DEFAULT_DOS_CODEPAGE);
  201     fprintf(f, "  -V, --version       Show version number and terminate\n");
  202     fprintf(f, "  -h, --help          Print this message and terminate\n");
  203     exit(status);
  204 }
  205 
  206 
  207 int main(int argc, char *argv[])
  208 {
  209     const struct option long_options[] = {
  210     {"volume-id", no_argument, NULL, 'i'},
  211     {"reset",     no_argument, NULL, 'r'},
  212     {"codepage",  required_argument, NULL, 'c'},
  213     {"version",   no_argument, NULL, 'V'},
  214     {"help",      no_argument, NULL, 'h'},
  215     {0,}
  216     };
  217     bool change;
  218     bool reset = false;
  219     bool volid_mode = false;
  220     char *device = NULL;
  221     char *new = NULL;
  222     char *tmp;
  223     long codepage;
  224     int c;
  225 
  226     check_atari();
  227 
  228     while ((c = getopt_long(argc, argv, "irc:Vh", long_options, NULL)) != -1) {
  229     switch (c) {
  230         case 'i':
  231         volid_mode = 1;
  232         break;
  233 
  234         case 'r':
  235         reset = true;
  236         break;
  237 
  238         case 'c':
  239         errno = 0;
  240         codepage = strtol(optarg, &tmp, 10);
  241         if (!*optarg || isspace(*optarg) || *tmp || errno || codepage < 0 || codepage > INT_MAX) {
  242             fprintf(stderr, "Invalid codepage : %s\n", optarg);
  243             usage(1, 0);
  244         }
  245         if (!set_dos_codepage(codepage))
  246             usage(1, 0);
  247         break;
  248 
  249         case 'V':
  250         printf("fatlabel " VERSION " (" VERSION_DATE ")\n");
  251         exit(0);
  252         break;
  253 
  254         case 'h':
  255         usage(0, 0);
  256         break;
  257 
  258         case '?':
  259         usage(1, 0);
  260         exit(1);
  261 
  262         default:
  263         fprintf(stderr,
  264             "Internal error: getopt_long() returned unexpected value %d\n", c);
  265         exit(2);
  266     }
  267     }
  268 
  269     if (!set_dos_codepage(-1))  /* set default codepage if none was given in command line */
  270         exit(1);
  271 
  272     if (optind == argc - 2) {
  273     change = true;
  274     } else if (optind == argc - 1) {
  275     change = false;
  276     } else {
  277     usage(1, 1);
  278     }
  279 
  280     if (change || reset)
  281     rw = 1;
  282 
  283     if (change && reset) {
  284     fprintf(stderr, "fatlabel: giving new value with --reset not allowed\n");
  285     exit(1);
  286     }
  287 
  288     device = argv[optind++];
  289     if (change)
  290     new = argv[optind];
  291 
  292     if (!volid_mode)
  293     handle_label(change, reset, device, new);
  294     else
  295     handle_volid(change, reset, device, new);
  296 
  297     fs_close(rw);
  298     return 0;
  299 }