"Fossies" - the Fresh Open Source Software Archive

Member "dosfstools-4.2/src/file.c" (31 Jan 2021, 6770 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 "file.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 /* file.c - Additional file attributes
    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) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
    6    Copyright (C) 2020 Pali Rohár <pali.rohar@gmail.com>
    7 
    8    This program is free software: you can redistribute it and/or modify
    9    it under the terms of the GNU General Public License as published by
   10    the Free Software Foundation, either version 3 of the License, or
   11    (at your option) any later version.
   12 
   13    This program is distributed in the hope that it will be useful,
   14    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   16    GNU General Public License for more details.
   17 
   18    You should have received a copy of the GNU General Public License
   19    along with this program. If not, see <http://www.gnu.org/licenses/>.
   20 
   21    The complete text of the GNU General Public License
   22    can be found in /usr/share/common-licenses/GPL-3 file.
   23 */
   24 
   25 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
   26  * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
   27 
   28 #include <stdlib.h>
   29 #include <stdio.h>
   30 #include <string.h>
   31 #include <ctype.h>
   32 #include <unistd.h>
   33 
   34 #include "common.h"
   35 #include "file.h"
   36 #include "msdos_fs.h"
   37 #include "charconv.h"
   38 
   39 FDSC *fp_root = NULL;
   40 
   41 static void put_char(char **p, unsigned char c, unsigned int out_size)
   42 {
   43     if (dos_char_to_printable(p, c, out_size))
   44     return;
   45     if (out_size >= 1 && c >= ' ' && c < 0x7f)
   46     *(*p)++ = c;
   47     else if (out_size >= 4) {
   48     *(*p)++ = '\\';
   49     *(*p)++ = '0' + (c >> 6);
   50     *(*p)++ = '0' + ((c >> 3) & 7);
   51     *(*p)++ = '0' + (c & 7);
   52     }
   53 }
   54 
   55 /**
   56  * Construct the "pretty-printed" representation of the name in a short directory entry.
   57  *
   58  * @param[in]    fixed  Pointer to name[0] of a DIR_ENT
   59  *
   60  * @return  Pointer to static string containing pretty "8.3" equivalent of the
   61  *          name in the directory entry.
   62  */
   63 char *file_name(unsigned char *fixed)
   64 {
   65     static char path[256];
   66     char *p;
   67     int i, j;
   68 
   69     p = path;
   70     i = j = 0;
   71     if (fixed[0] == 0x05) {
   72         put_char(&p, 0xe5, path + sizeof(path) - 1 - p);
   73         ++i;
   74         ++j;
   75     }
   76     for (; i < 8; i++)
   77     if (fixed[i] != ' ') {
   78         while (j++ < i)
   79         *p++ = ' ';
   80         put_char(&p, fixed[i], path + sizeof(path) - 1 - p);
   81     }
   82     if (strncmp((const char *)(fixed + 8), "   ", 3)) {
   83     *p++ = '.';
   84     for (i = j = 0; i < 3; i++)
   85         if (fixed[i + 8] != ' ') {
   86         while (j++ < i)
   87             *p++ = ' ';
   88         put_char(&p, fixed[i + 8], path + sizeof(path) - 1 - p);
   89         }
   90     }
   91     *p = 0;
   92     return path;
   93 }
   94 
   95 int file_cvt(unsigned char *name, unsigned char *fixed)
   96 {
   97     unsigned char c;
   98     int size, ext, cnt;
   99 
  100     size = 8;
  101     ext = 0;
  102     while (*name) {
  103     c = *name;
  104     if (c < ' ' || c > 0x7e || strchr("*?<>|\"/", c)) {
  105         printf("Invalid character in name. Use \\ooo for special "
  106            "characters.\n");
  107         return 0;
  108     }
  109     if (c == '.') {
  110         if (ext) {
  111         printf("Duplicate dots in name.\n");
  112         return 0;
  113         }
  114         while (size--)
  115         *fixed++ = ' ';
  116         size = 3;
  117         ext = 1;
  118         name++;
  119         continue;
  120     }
  121     if (c == '\\') {
  122         c = 0;
  123         name++;
  124         for (cnt = 3; cnt; cnt--) {
  125         if (*name < '0' || *name > '7') {
  126             printf("Expected three octal digits.\n");
  127             return 0;
  128         }
  129         c = c * 8 + *name++ - '0';
  130         }
  131         name--;
  132     }
  133     if (islower(c))
  134         c = toupper(c);
  135     if (size) {
  136         if (size == 8 && c == 0xE5)
  137         *fixed++ = 0x05;
  138         else
  139         *fixed++ = c;
  140         size--;
  141     }
  142     name++;
  143     }
  144     if (*name || size == 8)
  145     return 0;
  146     if (!ext) {
  147     while (size--)
  148         *fixed++ = ' ';
  149     size = 3;
  150     }
  151     while (size--)
  152     *fixed++ = ' ';
  153     return 1;
  154 }
  155 
  156 void file_add(char *path, FD_TYPE type)
  157 {
  158     FDSC **current, *walk;
  159     char name[MSDOS_NAME];
  160     char *here;
  161 
  162     current = &fp_root;
  163     if (*path != '/')
  164     die("%s: Absolute path required.", path);
  165     path++;
  166     while (1) {
  167     if ((here = strchr(path, '/')))
  168         *here = 0;
  169     if (!file_cvt((unsigned char *)path, (unsigned char *)name))
  170         exit(2);
  171     for (walk = *current; walk; walk = walk->next)
  172         if (!here && (!strncmp(name, walk->name, MSDOS_NAME) || (type ==
  173                                      fdt_undelete
  174                                      &&
  175                                      !strncmp
  176                                      (name + 1,
  177                                       walk->name
  178                                       + 1,
  179                                       MSDOS_NAME
  180                                       - 1))))
  181         die("Ambiguous name: \"%s\"", path);
  182         else if (here && !strncmp(name, walk->name, MSDOS_NAME))
  183         break;
  184     if (!walk) {
  185         walk = alloc(sizeof(FDSC));
  186         strncpy(walk->name, name, MSDOS_NAME);
  187         walk->type = here ? fdt_none : type;
  188         walk->first = NULL;
  189         walk->next = *current;
  190         *current = walk;
  191     }
  192     current = &walk->first;
  193     if (!here)
  194         break;
  195     *here = '/';
  196     path = here + 1;
  197     }
  198 }
  199 
  200 FDSC **file_cd(FDSC ** curr, char *fixed)
  201 {
  202     FDSC **walk;
  203 
  204     if (!curr || !*curr)
  205     return NULL;
  206     for (walk = curr; *walk; walk = &(*walk)->next)
  207     if (!strncmp((*walk)->name, fixed, MSDOS_NAME) && (*walk)->first)
  208         return &(*walk)->first;
  209     return NULL;
  210 }
  211 
  212 static FDSC **file_find(FDSC ** dir, char *fixed)
  213 {
  214     if (!dir || !*dir)
  215     return NULL;
  216     if (*(unsigned char *)fixed == DELETED_FLAG) {
  217     while (*dir) {
  218         if (!strncmp((*dir)->name + 1, fixed + 1, MSDOS_NAME - 1)
  219         && !(*dir)->first)
  220         return dir;
  221         dir = &(*dir)->next;
  222     }
  223     return NULL;
  224     }
  225     while (*dir) {
  226     if (!strncmp((*dir)->name, fixed, MSDOS_NAME) && !(*dir)->first)
  227         return dir;
  228     dir = &(*dir)->next;
  229     }
  230     return NULL;
  231 }
  232 
  233 /* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
  234    such file exists or if CURR is NULL. */
  235 FD_TYPE file_type(FDSC ** curr, char *fixed)
  236 {
  237     FDSC **this;
  238 
  239     if ((this = file_find(curr, fixed)))
  240     return (*this)->type;
  241     return fdt_none;
  242 }
  243 
  244 void file_modify(FDSC ** curr, char *fixed)
  245 {
  246     FDSC **this, *next;
  247 
  248     if (!(this = file_find(curr, fixed)))
  249     die("Internal error: file_find failed");
  250     switch ((*this)->type) {
  251     case fdt_drop:
  252     printf("Dropping %s\n", file_name((unsigned char *)fixed));
  253     *(unsigned char *)fixed = DELETED_FLAG;
  254     break;
  255     case fdt_undelete:
  256     *fixed = *(*this)->name;
  257     printf("Undeleting %s\n", file_name((unsigned char *)fixed));
  258     break;
  259     default:
  260     die("Internal error: file_modify");
  261     }
  262     next = (*this)->next;
  263     free(*this);
  264     *this = next;
  265 }
  266 
  267 static void report_unused(FDSC * this)
  268 {
  269     FDSC *next;
  270 
  271     while (this) {
  272     next = this->next;
  273     if (this->first)
  274         report_unused(this->first);
  275     else if (this->type != fdt_none)
  276         printf("Warning: did not %s file %s\n", this->type == fdt_drop ?
  277            "drop" : "undelete", file_name((unsigned char *)this->name));
  278     free(this);
  279     this = next;
  280     }
  281 }
  282 
  283 void file_unused(void)
  284 {
  285     report_unused(fp_root);
  286 }