| /* | 
 |  * 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); | 
 | } |