and added files (forgot git commit -a again)
[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  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <common.h>
29 #include <config.h>
30 #include <malloc.h>
31 #include <fat.h>
32 #include <linux/stat.h>
33 #include <linux/time.h>
34
35 #if (CONFIG_COMMANDS & CFG_CMD_FAT)
36
37 /* Supported filesystems */
38 static const struct filesystem filesystems[] = {
39         { file_fat_detectfs,  file_fat_ls,  file_fat_read,  "FAT" },
40 };
41 #define NUM_FILESYS     (sizeof(filesystems)/sizeof(struct filesystem))
42
43 /* The filesystem which was last detected */
44 static int current_filesystem = FSTYPE_NONE;
45
46 /* The current working directory */
47 #define CWD_LEN         511
48 char file_cwd[CWD_LEN+1] = "/";
49
50 const char *
51 file_getfsname(int idx)
52 {
53         if (idx < 0 || idx >= NUM_FILESYS) return NULL;
54
55         return filesystems[idx].name;
56 }
57
58
59 static void
60 pathcpy(char *dest, const char *src)
61 {
62         char *origdest = dest;
63
64         do {
65                 if (dest-file_cwd >= CWD_LEN) {
66                         *dest = '\0';
67                         return;
68                 }
69                 *(dest) = *(src);
70                 if (*src == '\0') {
71                         if (dest-- != origdest && ISDIRDELIM(*dest)) {
72                                 *dest = '\0';
73                         }
74                         return;
75                 }
76                 ++dest;
77                 if (ISDIRDELIM(*src)) {
78                         while (ISDIRDELIM(*src)) src++;
79                 } else {
80                         src++;
81                 }
82         } while (1);
83 }
84
85
86 int
87 file_cd(const char *path)
88 {
89         if (ISDIRDELIM(*path)) {
90                 while (ISDIRDELIM(*path)) path++;
91                 strncpy(file_cwd+1, path, CWD_LEN-1);
92         } else {
93                 const char *origpath = path;
94                 char *tmpstr = file_cwd;
95                 int back = 0;
96
97                 while (*tmpstr != '\0') tmpstr++;
98                 do {
99                         tmpstr--;
100                 } while (ISDIRDELIM(*tmpstr));
101
102                 while (*path == '.') {
103                         path++;
104                         while (*path == '.') {
105                                 path++;
106                                 back++;
107                         }
108                         if (*path != '\0' && !ISDIRDELIM(*path)) {
109                                 path = origpath;
110                                 back = 0;
111                                 break;
112                         }
113                         while (ISDIRDELIM(*path)) path++;
114                         origpath = path;
115                 }
116
117                 while (back--) {
118                         /* Strip off path component */
119                         while (!ISDIRDELIM(*tmpstr)) {
120                                 tmpstr--;
121                         }
122                         if (tmpstr == file_cwd) {
123                                 /* Incremented again right after the loop. */
124                                 tmpstr--;
125                                 break;
126                         }
127                         /* Skip delimiters */
128                         while (ISDIRDELIM(*tmpstr)) tmpstr--;
129                 }
130                 tmpstr++;
131                 if (*path == '\0') {
132                         if (tmpstr == file_cwd) {
133                                 *tmpstr = '/';
134                                 tmpstr++;
135                         }
136                         *tmpstr = '\0';
137                         return 0;
138                 }
139                 *tmpstr = '/';
140                 pathcpy(tmpstr+1, path);
141         }
142
143         return 0;
144 }
145
146
147 int
148 file_detectfs(void)
149 {
150         int i;
151
152         current_filesystem = FSTYPE_NONE;
153
154         for (i = 0; i < NUM_FILESYS; i++) {
155                 if (filesystems[i].detect() == 0) {
156                         strcpy(file_cwd, "/");
157                         current_filesystem = i;
158                         break;
159                 }
160         }
161
162         return current_filesystem;
163 }
164
165
166 int
167 file_ls(const char *dir)
168 {
169         char fullpath[1024];
170         const char *arg;
171
172         if (current_filesystem == FSTYPE_NONE) {
173                 printf("Can't list files without a filesystem!\n");
174                 return -1;
175         }
176
177         if (ISDIRDELIM(*dir)) {
178                 arg = dir;
179         } else {
180                 sprintf(fullpath, "%s/%s", file_cwd, dir);
181                 arg = fullpath;
182         }
183         return filesystems[current_filesystem].ls(arg);
184 }
185
186
187 long
188 file_read(const char *filename, void *buffer, unsigned long maxsize)
189 {
190         char fullpath[1024];
191         const char *arg;
192
193         if (current_filesystem == FSTYPE_NONE) {
194                 printf("Can't load file without a filesystem!\n");
195                 return -1;
196         }
197
198         if (ISDIRDELIM(*filename)) {
199                 arg = filename;
200         } else {
201                 sprintf(fullpath, "%s/%s", file_cwd, filename);
202                 arg = fullpath;
203         }
204
205         return filesystems[current_filesystem].read(arg, buffer, maxsize);
206 }
207
208 #endif /* #if (CONFIG_COMMANDS & CFG_CMD_FAT) */