dosfstools  4.2
About: dosfstools are utilities to create, check and label (MS-DOS) FAT filesystems.
  Fossies Dox: dosfstools-4.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

file.c
Go to the documentation of this file.
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 ==
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 {
286 }
int dos_char_to_printable(char **p, unsigned char c, unsigned int out_size)
Definition: charconv.c:353
void die(const char *msg,...)
Definition: common.c:53
void * alloc(int size)
Definition: common.c:81
static void put_char(char **p, unsigned char c, unsigned int out_size)
Definition: file.c:41
void file_modify(FDSC **curr, char *fixed)
Definition: file.c:244
FDSC * fp_root
Definition: file.c:39
int file_cvt(unsigned char *name, unsigned char *fixed)
Definition: file.c:95
FDSC ** file_cd(FDSC **curr, char *fixed)
Definition: file.c:200
char * file_name(unsigned char *fixed)
Definition: file.c:63
static FDSC ** file_find(FDSC **dir, char *fixed)
Definition: file.c:212
static void report_unused(FDSC *this)
Definition: file.c:267
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:235
void file_add(char *path, FD_TYPE type)
Definition: file.c:156
void file_unused(void)
Definition: file.c:283
FD_TYPE
Definition: file.h:28
@ fdt_none
Definition: file.h:28
@ fdt_undelete
Definition: file.h:28
@ fdt_drop
Definition: file.h:28
#define DELETED_FLAG
Definition: msdos_fs.h:41
#define MSDOS_NAME
Definition: msdos_fs.h:44
Definition: file.h:30
FD_TYPE type
Definition: file.h:32
struct _fptr * first
Definition: file.h:33
char name[11]
Definition: file.h:31
struct _fptr * next
Definition: file.h:34