From 014678f7a0cff81248a95a91d47086e7a50fe380 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 5 Jul 2007 18:01:51 +0200 Subject: [PATCH] svn_rev_406 let normalise path allocate the string instead of changing the original one --- fs/fs.c | 150 ++++++++++++++++++++++++++++++++++++--------------- include/fs.h | 5 +- 2 files changed, 111 insertions(+), 44 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 03ea96f9e..0dd2f0749 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -6,6 +6,7 @@ #include #include #include +#include char *mkmodestr(unsigned long mode, char *str) { @@ -37,34 +38,78 @@ char *mkmodestr(unsigned long mode, char *str) return str; } +static char *cwd; + +static int init_cwd(void) +{ + cwd = xzalloc(PATH_MAX); + *cwd = '/'; + return 0; +} + +core_initcall(init_cwd); + /* * - Remove all multiple slashes * - Remove trailing slashes (except path consists of only * a single slash) * - TODO: illegal characters? */ -void normalise_path(char *path) +char *normalise_path(const char *pathname) { - char *out = path, *in = path; + char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2); + char *in, *out, *slashes[32]; + int sl = 0; - while(*in) { +//printf("in: %s\n", pathname); + if (*pathname != '/') + strcpy(path, cwd); + strcat(path, "/"); + strcat(path, pathname); + + slashes[0] = in = out = path; + + while (*in) { if(*in == '/') { + slashes[sl++] = out; *out++ = *in++; while(*in == '/') in++; } else { + if (*in == '.' && (*(in + 1) == '/' || !*(in + 1))) { + sl--; + if (sl < 0) + sl = 0; + out = slashes[sl]; + in++; + continue; + } + if (*in == '.' && *(in + 1) == '.') { + sl -= 2; + if (sl < 0) + sl = 0; + out = slashes[sl]; + in += 2; + continue; + } *out++ = *in++; } } - /* - * Remove trailing slash, but only if - * we were given more than a single slash - */ - if (out > path + 1 && *(out - 1) == '/') - *(out - 1) = 0; + *out-- = 0; - *out = 0; + /* + * Remove trailing slash + */ + if (*out == '/') + *out = 0; + + if (!*path) { + *path = '/'; + *(path + 1) = 0; + } + + return path; } static struct mtab_entry *mtab; @@ -130,8 +175,6 @@ static struct device_d *get_device_by_path(char **path) struct device_d *dev; struct mtab_entry *e; - normalise_path(*path); - e = get_mtab_entry_by_path(*path); if (!e) return NULL; @@ -177,11 +220,18 @@ static int path_check_prereq(const char *path, unsigned int flags) struct stat s; unsigned int m; + errno = 0; + if (stat(path, &s)) { if (flags & S_UB_DOES_NOT_EXIST) return 0; errno = -ENOENT; - return errno; + goto out; + } + + if (flags & S_UB_DOES_NOT_EXIST) { + errno = -EEXIST; + goto out; } if (flags == S_UB_EXISTS) @@ -192,29 +242,50 @@ static int path_check_prereq(const char *path, unsigned int flags) if (S_ISDIR(m)) { if (flags & S_IFREG) { errno = -EISDIR; - return errno; + goto out; } if ((flags & S_UB_IS_EMPTY) && !dir_is_empty(path)) { errno = -ENOTEMPTY; - return errno; + goto out; } } if ((flags & S_IFDIR) && S_ISREG(m)) { errno = -ENOTDIR; - return errno; + goto out; } - return 0; +out: + return errno; +} + +const char *getcwd(void) +{ + return cwd; +} + +int chdir(const char *pathname) +{ + char *p = normalise_path(pathname); + errno = 0; + + if (path_check_prereq(p, S_IFDIR)) + goto out; + + strcpy(cwd, p); + + free(p); +out: + return errno; } int unlink(const char *pathname) { struct device_d *dev; struct fs_driver_d *fsdrv; - char *p = strdup(pathname); + char *p = normalise_path(pathname); char *freep = p; if (path_check_prereq(pathname, S_IFREG)) - return errno; + goto out; dev = get_device_by_path(&p); if (!dev) @@ -234,30 +305,27 @@ int open(const char *pathname, int flags) FILE *f; int exist; struct stat s; - char *path; - char *freep; + char *path = normalise_path(pathname); + char *freep = path; - exist = (stat(pathname, &s) == 0) ? 1 : 0; + exist = (stat(path, &s) == 0) ? 1 : 0; if (exist && (s.st_mode & S_IFDIR)) { errno = -EISDIR; - return errno; + goto out1; } if (!exist && !(flags & O_CREAT)) { errno = -ENOENT; - return errno; + goto out1; } f = get_file(); if (!f) { errno = -EMFILE; - return errno; + goto out1; } - path = strdup(pathname); - freep = path; - dev = get_device_by_path(&path); if (!dev) goto out; @@ -273,7 +341,7 @@ int open(const char *pathname, int flags) } if (!exist) { - errno = fsdrv->create(dev, pathname, S_IFREG); + errno = fsdrv->create(dev, path, S_IFREG); if (errno) goto out; } @@ -297,6 +365,7 @@ int open(const char *pathname, int flags) out: put_file(f); +out1: free(freep); return errno; } @@ -481,9 +550,7 @@ int umount(const char *pathname) { struct mtab_entry *entry = mtab; struct mtab_entry *last = mtab; - char *p = strdup(pathname); - - normalise_path(p); + char *p = normalise_path(pathname); while(entry && strcmp(p, entry->path)) { last = entry; @@ -505,7 +572,6 @@ int umount(const char *pathname) unregister_device(entry->dev); free(entry->dev->type_data); free(entry); - return 0; } @@ -514,7 +580,7 @@ struct dir *opendir(const char *pathname) struct dir *dir = NULL; struct device_d *dev; struct fs_driver_d *fsdrv; - char *p = strdup(pathname); + char *p = normalise_path(pathname); char *freep = p; if (path_check_prereq(pathname, S_IFDIR)) @@ -553,13 +619,11 @@ int stat(const char *filename, struct stat *s) struct device_d *dev; struct fs_driver_d *fsdrv; struct mtab_entry *e; - char *buf = strdup(filename); - char *f = buf; + char *f = normalise_path(filename); + char *freep = f; memset(s, 0, sizeof(struct stat)); - normalise_path(f); - e = get_mtab_entry_by_path(f); if (!e) { errno = -ENOENT; @@ -579,7 +643,7 @@ int stat(const char *filename, struct stat *s) errno = fsdrv->stat(dev, f, s); out: - free(buf); + free(freep); return errno; } @@ -587,11 +651,11 @@ int mkdir (const char *pathname) { struct fs_driver_d *fsdrv; struct device_d *dev; - char *p = strdup(pathname); + char *p = normalise_path(pathname); char *freep = p; if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST)) - return errno; + goto out; dev = get_device_by_path(&p); if (!dev) @@ -613,11 +677,11 @@ int rmdir (const char *pathname) { struct fs_driver_d *fsdrv; struct device_d *dev; - char *p = strdup(pathname); + char *p = normalise_path(pathname); char *freep = p; if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY)) - return errno; + goto out; dev = get_device_by_path(&p); if (!dev) diff --git a/include/fs.h b/include/fs.h index e7e66483e..d2bc1581c 100644 --- a/include/fs.h +++ b/include/fs.h @@ -95,6 +95,9 @@ int rmdir (const char *pathname); int mount (const char *device, const char *fsname, const char *path); int umount(const char *pathname); +const char *getcwd(void); +int chdir(const char *pathname); + struct dir *opendir(const char *pathname); struct dirent *readdir(struct dir *dir); int closedir(struct dir *dir); @@ -111,6 +114,6 @@ struct mtab_entry { struct device_d *parent_device; }; -void normalise_path(char *path); +char *normalise_path(const char *path); #endif /* __FS_H */