Merge git://git.denx.de/u-boot-dm
[oweals/u-boot.git] / fs / fat / file.c
1 /*
2  * file.c
3  *
4  * Mini "VFS" by Marcus Sundberg
5  *
6  * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
7  * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <common.h>
13 #include <config.h>
14 #include <malloc.h>
15 #include <fat.h>
16 #include <linux/stat.h>
17 #include <linux/time.h>
18
19 /* Supported filesystems */
20 static const struct filesystem filesystems[] = {
21         { file_fat_detectfs,  file_fat_ls,  file_fat_read,  "FAT" },
22 };
23 #define NUM_FILESYS     (sizeof(filesystems)/sizeof(struct filesystem))
24
25 /* The filesystem which was last detected */
26 static int current_filesystem = FSTYPE_NONE;
27
28 /* The current working directory */
29 #define CWD_LEN         511
30 char file_cwd[CWD_LEN+1] = "/";
31
32 const char *
33 file_getfsname(int idx)
34 {
35         if (idx < 0 || idx >= NUM_FILESYS)
36                 return NULL;
37
38         return filesystems[idx].name;
39 }
40
41 static void
42 pathcpy(char *dest, const char *src)
43 {
44         char *origdest = dest;
45
46         do {
47                 if (dest-file_cwd >= CWD_LEN) {
48                         *dest = '\0';
49                         return;
50                 }
51                 *(dest) = *(src);
52                 if (*src == '\0') {
53                         if (dest-- != origdest && ISDIRDELIM(*dest)) {
54                                 *dest = '\0';
55                         }
56                         return;
57                 }
58                 ++dest;
59
60                 if (ISDIRDELIM(*src))
61                         while (ISDIRDELIM(*src)) src++;
62                 else
63                         src++;
64         } while (1);
65 }
66
67 int
68 file_cd(const char *path)
69 {
70         if (ISDIRDELIM(*path)) {
71                 while (ISDIRDELIM(*path)) path++;
72                 strncpy(file_cwd+1, path, CWD_LEN-1);
73         } else {
74                 const char *origpath = path;
75                 char *tmpstr = file_cwd;
76                 int back = 0;
77
78                 while (*tmpstr != '\0') tmpstr++;
79                 do {
80                         tmpstr--;
81                 } while (ISDIRDELIM(*tmpstr));
82
83                 while (*path == '.') {
84                         path++;
85                         while (*path == '.') {
86                                 path++;
87                                 back++;
88                         }
89                         if (*path != '\0' && !ISDIRDELIM(*path)) {
90                                 path = origpath;
91                                 back = 0;
92                                 break;
93                         }
94                         while (ISDIRDELIM(*path)) path++;
95                         origpath = path;
96                 }
97
98                 while (back--) {
99                         /* Strip off path component */
100                         while (!ISDIRDELIM(*tmpstr)) {
101                                 tmpstr--;
102                         }
103                         if (tmpstr == file_cwd) {
104                                 /* Incremented again right after the loop. */
105                                 tmpstr--;
106                                 break;
107                         }
108                         /* Skip delimiters */
109                         while (ISDIRDELIM(*tmpstr)) tmpstr--;
110                 }
111                 tmpstr++;
112                 if (*path == '\0') {
113                         if (tmpstr == file_cwd) {
114                                 *tmpstr = '/';
115                                 tmpstr++;
116                         }
117                         *tmpstr = '\0';
118                         return 0;
119                 }
120                 *tmpstr = '/';
121                 pathcpy(tmpstr+1, path);
122         }
123
124         return 0;
125 }
126
127 int
128 file_detectfs(void)
129 {
130         int i;
131
132         current_filesystem = FSTYPE_NONE;
133
134         for (i = 0; i < NUM_FILESYS; i++) {
135                 if (filesystems[i].detect() == 0) {
136                         strcpy(file_cwd, "/");
137                         current_filesystem = i;
138                         break;
139                 }
140         }
141
142         return current_filesystem;
143 }
144
145 int
146 file_ls(const char *dir)
147 {
148         char fullpath[1024];
149         const char *arg;
150
151         if (current_filesystem == FSTYPE_NONE) {
152                 printf("Can't list files without a filesystem!\n");
153                 return -1;
154         }
155
156         if (ISDIRDELIM(*dir)) {
157                 arg = dir;
158         } else {
159                 sprintf(fullpath, "%s/%s", file_cwd, dir);
160                 arg = fullpath;
161         }
162         return filesystems[current_filesystem].ls(arg);
163 }
164
165 int file_read(const char *filename, void *buffer, int maxsize)
166 {
167         char fullpath[1024];
168         const char *arg;
169
170         if (current_filesystem == FSTYPE_NONE) {
171                 printf("Can't load file without a filesystem!\n");
172                 return -1;
173         }
174
175         if (ISDIRDELIM(*filename)) {
176                 arg = filename;
177         } else {
178                 sprintf(fullpath, "%s/%s", file_cwd, filename);
179                 arg = fullpath;
180         }
181
182         return filesystems[current_filesystem].read(arg, buffer, maxsize);
183 }