Initial checkin
[pandora-x-loader.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 <part.h>
32 #include <fat.h>
33 #include <linux/stat.h>
34 #include <linux/time.h>
35
36 #if (CONFIG_COMMANDS & CFG_CMD_FAT)
37
38 /* Supported filesystems */
39 static const struct filesystem filesystems[] = {
40         { file_fat_detectfs,  file_fat_ls,  file_fat_read,  "FAT" },
41 };
42 #define NUM_FILESYS     (sizeof(filesystems)/sizeof(struct filesystem))
43
44 /* The filesystem which was last detected */
45 static int current_filesystem = FSTYPE_NONE;
46
47 /* The current working directory */
48 #define CWD_LEN         511
49 char file_cwd[CWD_LEN+1] = "/";
50
51 const char *
52 file_getfsname(int idx)
53 {
54         if (idx < 0 || idx >= NUM_FILESYS) return NULL;
55
56         return filesystems[idx].name;
57 }
58
59
60 static void
61 pathcpy(char *dest, const char *src)
62 {
63         char *origdest = dest;
64
65         do {
66                 if (dest-file_cwd >= CWD_LEN) {
67                         *dest = '\0';
68                         return;
69                 }
70                 *(dest) = *(src);
71                 if (*src == '\0') {
72                         if (dest-- != origdest && ISDIRDELIM(*dest)) {
73                                 *dest = '\0';
74                         }
75                         return;
76                 }
77                 ++dest;
78                 if (ISDIRDELIM(*src)) {
79                         while (ISDIRDELIM(*src)) src++;
80                 } else {
81                         src++;
82                 }
83         } while (1);
84 }
85
86
87 int
88 file_cd(const char *path)
89 {
90         if (ISDIRDELIM(*path)) {
91                 while (ISDIRDELIM(*path)) path++;
92                 strncpy(file_cwd+1, path, CWD_LEN-1);
93         } else {
94                 const char *origpath = path;
95                 char *tmpstr = file_cwd;
96                 int back = 0;
97
98                 while (*tmpstr != '\0') tmpstr++;
99                 do {
100                         tmpstr--;
101                 } while (ISDIRDELIM(*tmpstr));
102
103                 while (*path == '.') {
104                         path++;
105                         while (*path == '.') {
106                                 path++;
107                                 back++;
108                         }
109                         if (*path != '\0' && !ISDIRDELIM(*path)) {
110                                 path = origpath;
111                                 back = 0;
112                                 break;
113                         }
114                         while (ISDIRDELIM(*path)) path++;
115                         origpath = path;
116                 }
117
118                 while (back--) {
119                         /* Strip off path component */
120                         while (!ISDIRDELIM(*tmpstr)) {
121                                 tmpstr--;
122                         }
123                         if (tmpstr == file_cwd) {
124                                 /* Incremented again right after the loop. */
125                                 tmpstr--;
126                                 break;
127                         }
128                         /* Skip delimiters */
129                         while (ISDIRDELIM(*tmpstr)) tmpstr--;
130                 }
131                 tmpstr++;
132                 if (*path == '\0') {
133                         if (tmpstr == file_cwd) {
134                                 *tmpstr = '/';
135                                 tmpstr++;
136                         }
137                         *tmpstr = '\0';
138                         return 0;
139                 }
140                 *tmpstr = '/';
141                 pathcpy(tmpstr+1, path);
142         }
143
144         return 0;
145 }
146
147
148 int
149 file_detectfs(void)
150 {
151         int i;
152
153         current_filesystem = FSTYPE_NONE;
154
155         for (i = 0; i < NUM_FILESYS; i++) {
156                 if (filesystems[i].detect() == 0) {
157                         strcpy(file_cwd, "/");
158                         current_filesystem = i;
159                         break;
160                 }
161         }
162
163         return current_filesystem;
164 }
165
166
167 int
168 file_ls(const char *dir)
169 {
170         char fullpath[1024];
171         const char *arg;
172
173         if (current_filesystem == FSTYPE_NONE) {
174                 printf("Can't list files without a filesystem!\n");
175                 return -1;
176         }
177
178         if (ISDIRDELIM(*dir)) {
179                 arg = dir;
180         } else {
181                 sprintf(fullpath, "%s/%s", file_cwd, dir);
182                 arg = fullpath;
183         }
184         return filesystems[current_filesystem].ls(arg);
185 }
186
187
188 long
189 file_read(const char *filename, void *buffer, unsigned long maxsize)
190 {
191         char fullpath[1024];
192         const char *arg;
193
194         if (current_filesystem == FSTYPE_NONE) {
195                 printf("Can't load file without a filesystem!\n");
196                 return -1;
197         }
198
199         if (ISDIRDELIM(*filename)) {
200                 arg = filename;
201         } else {
202                 sprintf(fullpath, "%s/%s", file_cwd, filename);
203                 arg = fullpath;
204         }
205
206         return filesystems[current_filesystem].read(arg, buffer, maxsize);
207 }
208
209 #endif /* #if (CONFIG_COMMANDS & CFG_CMD_FAT) */