/* * file.c * * Mini "VFS" by Marcus Sundberg * * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 * 2003-03-10 - kharris@nexus-tech.net - ported to uboot * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include <common.h> #include <config.h> #include <malloc.h> #include <fat.h> #include <linux/stat.h> #include <linux/time.h> /* Supported filesystems */ static const struct filesystem filesystems[] = { { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" }, }; #define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem)) /* The filesystem which was last detected */ static int current_filesystem = FSTYPE_NONE; /* The current working directory */ #define CWD_LEN 511 char file_cwd[CWD_LEN+1] = "/"; const char * file_getfsname(int idx) { if (idx < 0 || idx >= NUM_FILESYS) return NULL; return filesystems[idx].name; } static void pathcpy(char *dest, const char *src) { char *origdest = dest; do { if (dest-file_cwd >= CWD_LEN) { *dest = '\0'; return; } *(dest) = *(src); if (*src == '\0') { if (dest-- != origdest && ISDIRDELIM(*dest)) { *dest = '\0'; } return; } ++dest; if (ISDIRDELIM(*src)) { while (ISDIRDELIM(*src)) src++; } else { src++; } } while (1); } int file_cd(const char *path) { if (ISDIRDELIM(*path)) { while (ISDIRDELIM(*path)) path++; strncpy(file_cwd+1, path, CWD_LEN-1); } else { const char *origpath = path; char *tmpstr = file_cwd; int back = 0; while (*tmpstr != '\0') tmpstr++; do { tmpstr--; } while (ISDIRDELIM(*tmpstr)); while (*path == '.') { path++; while (*path == '.') { path++; back++; } if (*path != '\0' && !ISDIRDELIM(*path)) { path = origpath; back = 0; break; } while (ISDIRDELIM(*path)) path++; origpath = path; } while (back--) { /* Strip off path component */ while (!ISDIRDELIM(*tmpstr)) { tmpstr--; } if (tmpstr == file_cwd) { /* Incremented again right after the loop. */ tmpstr--; break; } /* Skip delimiters */ while (ISDIRDELIM(*tmpstr)) tmpstr--; } tmpstr++; if (*path == '\0') { if (tmpstr == file_cwd) { *tmpstr = '/'; tmpstr++; } *tmpstr = '\0'; return 0; } *tmpstr = '/'; pathcpy(tmpstr+1, path); } return 0; } int file_detectfs(void) { int i; current_filesystem = FSTYPE_NONE; for (i = 0; i < NUM_FILESYS; i++) { if (filesystems[i].detect() == 0) { strcpy(file_cwd, "/"); current_filesystem = i; break; } } return current_filesystem; } int file_ls(const char *dir) { char fullpath[1024]; const char *arg; if (current_filesystem == FSTYPE_NONE) { printf("Can't list files without a filesystem!\n"); return -1; } if (ISDIRDELIM(*dir)) { arg = dir; } else { sprintf(fullpath, "%s/%s", file_cwd, dir); arg = fullpath; } return filesystems[current_filesystem].ls(arg); } long file_read(const char *filename, void *buffer, unsigned long maxsize) { char fullpath[1024]; const char *arg; if (current_filesystem == FSTYPE_NONE) { printf("Can't load file without a filesystem!\n"); return -1; } if (ISDIRDELIM(*filename)) { arg = filename; } else { sprintf(fullpath, "%s/%s", file_cwd, filename); arg = fullpath; } return filesystems[current_filesystem].read(arg, buffer, maxsize); }