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