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
put_char(char ** p,unsigned char c)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 */
file_name(unsigned char * fixed)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
file_cvt(unsigned char * name,unsigned char * fixed)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
file_add(char * path,FD_TYPE type)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
file_cd(FDSC ** curr,char * fixed)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
file_find(FDSC ** dir,char * fixed)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. */
file_type(FDSC ** curr,char * fixed)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
file_modify(FDSC ** curr,char * fixed)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
report_unused(FDSC * this)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
file_unused(void)269 void file_unused(void)
270 {
271 report_unused(fp_root);
272 }
273