- Remove the remaining __USE_W32API, deprecated for ages.
[reactos.git] / reactos / lib / fslib / vfatlib / check / file.c
1 /* file.c - Additional file attributes */
2
3 /* Written 1993 by Werner Almesberger */
4
5 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
6 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
7
8 #include "vfatlib.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 FDSC *fp_root = NULL;
14
15
16 static void put_char(char **p,unsigned char c)
17 {
18 if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c;
19 else {
20 *(*p)++ = '\\';
21 *(*p)++ = '0'+(c >> 6);
22 *(*p)++ = '0'+((c >> 3) & 7);
23 *(*p)++ = '0'+(c & 7);
24 }
25 }
26
27
28 char *file_name(unsigned char *fixed)
29 {
30 static char path[MSDOS_NAME*4+2];
31 char *p;
32 int i,j;
33
34 p = path;
35 for (i = j = 0; i < 8; i++)
36 if (fixed[i] != ' ') {
37 while (j++ < i) *p++ = ' ';
38 put_char(&p,fixed[i]);
39 }
40 if (strncmp((char*)fixed+8," ",3)) {
41 *p++ = '.';
42 for (i = j = 0; i < 3; i++)
43 if (fixed[i+8] != ' ') {
44 while (j++ < i) *p++ = ' ';
45 put_char(&p,fixed[i+8]);
46 }
47 }
48 *p = 0;
49 return path;
50 }
51
52 int file_cvt(unsigned char *name,unsigned char *fixed)
53 {
54 unsigned char c;
55 int size,ext,cnt;
56
57 size = 8;
58 ext = 0;
59 while (*name) {
60 c = *name;
61 if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) {
62 VfatPrint("Invalid character in name. Use \\ooo for special "
63 "characters.\n");
64 return 0;
65 }
66 if (c == '.') {
67 if (ext) {
68 VfatPrint("Duplicate dots in name.\n");
69 return 0;
70 }
71 while (size--) *fixed++ = ' ';
72 size = 3;
73 ext = 1;
74 name++;
75 continue;
76 }
77 if (c == '\\') {
78 c = 0;
79 for (cnt = 3; cnt; cnt--) {
80 if (*name < '0' || *name > '7') {
81 VfatPrint("Invalid octal character.\n");
82 return 0;
83 }
84 c = c*8+*name++-'0';
85 }
86 if (cnt < 4) {
87 VfatPrint("Expected three octal digits.\n");
88 return 0;
89 }
90 name += 3;
91 }
92 if (islower(c)) c = toupper(c);
93 if (size) {
94 *fixed++ = c;
95 size--;
96 }
97 name++;
98 }
99 if (*name || size == 8) return 0;
100 if (!ext) {
101 while (size--) *fixed++ = ' ';
102 size = 3;
103 }
104 while (size--) *fixed++ = ' ';
105 return 1;
106 }
107
108
109 void file_add(char *path,FD_TYPE type)
110 {
111 FDSC **current,*walk;
112 char name[MSDOS_NAME];
113 char *here;
114
115 current = &fp_root;
116 if (*path != '/') die("%s: Absolute path required.",path);
117 path++;
118 while (1) {
119 if ((here = strchr(path,'/'))) *here = 0;
120 if (!file_cvt((unsigned char*)path,(unsigned char *)name)) {return; /*exit(2);*/}
121 for (walk = *current; walk; walk = walk->next)
122 if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type ==
123 fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1))))
124 die("Ambiguous name: \"%s\"",path);
125 else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break;
126 if (!walk) {
127 walk = vfalloc(sizeof(FDSC));
128 strncpy(walk->name,name,MSDOS_NAME);
129 walk->type = here ? fdt_none : type;
130 walk->first = NULL;
131 walk->next = *current;
132 *current = walk;
133 }
134 current = &walk->first;
135 if (!here) break;
136 *here = '/';
137 path = here+1;
138 }
139 }
140
141
142 FDSC **file_cd(FDSC **curr,char *fixed)
143 {
144 FDSC **walk;
145
146 if (!curr || !*curr) return NULL;
147 for (walk = curr; *walk; walk = &(*walk)->next)
148 if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first)
149 return &(*walk)->first;
150 return NULL;
151 }
152
153
154 static FDSC **file_find(FDSC **dir,char *fixed)
155 {
156 if (!dir || !*dir) return NULL;
157 if (*(unsigned char *) fixed == DELETED_FLAG) {
158 while (*dir) {
159 if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first)
160 return dir;
161 dir = &(*dir)->next;
162 }
163 return NULL;
164 }
165 while (*dir) {
166 if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first)
167 return dir;
168 dir = &(*dir)->next;
169 }
170 return NULL;
171 }
172
173
174 FD_TYPE file_type(FDSC **curr,char *fixed)
175 {
176 FDSC **this;
177
178 if ((this = file_find(curr,fixed))) return (*this)->type;
179 return fdt_none;
180 }
181
182
183 void file_modify(FDSC **curr,unsigned char *fixed)
184 {
185 FDSC **this,*next;
186
187 if (!(this = file_find(curr,(char *)fixed)))
188 die("Internal error: file_find failed");
189 switch ((*this)->type) {
190 case fdt_drop:
191 VfatPrint("Dropping %s\n",file_name(fixed));
192 *fixed = DELETED_FLAG;
193 break;
194 case fdt_undelete:
195 *fixed = *(*this)->name;
196 VfatPrint("Undeleting %s\n",file_name(fixed));
197 break;
198 default:
199 die("Internal error: file_modify");
200 }
201 next = (*this)->next;
202 vffree(*this);
203 *this = next;
204 }
205
206
207 static void report_unused(FDSC *this)
208 {
209 FDSC *next;
210
211 while (this) {
212 next = this->next;
213 if (this->first) report_unused(this->first);
214 else if (this->type != fdt_none)
215 VfatPrint("Warning: did not %s file %s\n",this->type == fdt_drop ?
216 "drop" : "undelete",file_name((unsigned char*)this->name));
217 vffree(this);
218 this = next;
219 }
220 }
221
222
223 void file_unused(void)
224 {
225 report_unused(fp_root);
226 }
227
228 /* Local Variables: */
229 /* tab-width: 8 */
230 /* End: */