9
0
Fork 0

svn_rev_406

let normalise path allocate the string instead of changing the original one
This commit is contained in:
Sascha Hauer 2007-07-05 18:01:51 +02:00 committed by Sascha Hauer
parent e6a048eb57
commit 014678f7a0
2 changed files with 111 additions and 44 deletions

150
fs/fs.c
View File

@ -6,6 +6,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <xfuncs.h> #include <xfuncs.h>
#include <init.h>
char *mkmodestr(unsigned long mode, char *str) char *mkmodestr(unsigned long mode, char *str)
{ {
@ -37,34 +38,78 @@ char *mkmodestr(unsigned long mode, char *str)
return 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 all multiple slashes
* - Remove trailing slashes (except path consists of only * - Remove trailing slashes (except path consists of only
* a single slash) * a single slash)
* - TODO: illegal characters? * - 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 == '/') { if(*in == '/') {
slashes[sl++] = out;
*out++ = *in++; *out++ = *in++;
while(*in == '/') while(*in == '/')
in++; in++;
} else { } 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++; *out++ = *in++;
} }
} }
/* *out-- = 0;
* 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; /*
* Remove trailing slash
*/
if (*out == '/')
*out = 0;
if (!*path) {
*path = '/';
*(path + 1) = 0;
}
return path;
} }
static struct mtab_entry *mtab; static struct mtab_entry *mtab;
@ -130,8 +175,6 @@ static struct device_d *get_device_by_path(char **path)
struct device_d *dev; struct device_d *dev;
struct mtab_entry *e; struct mtab_entry *e;
normalise_path(*path);
e = get_mtab_entry_by_path(*path); e = get_mtab_entry_by_path(*path);
if (!e) if (!e)
return NULL; return NULL;
@ -177,11 +220,18 @@ static int path_check_prereq(const char *path, unsigned int flags)
struct stat s; struct stat s;
unsigned int m; unsigned int m;
errno = 0;
if (stat(path, &s)) { if (stat(path, &s)) {
if (flags & S_UB_DOES_NOT_EXIST) if (flags & S_UB_DOES_NOT_EXIST)
return 0; return 0;
errno = -ENOENT; errno = -ENOENT;
return errno; goto out;
}
if (flags & S_UB_DOES_NOT_EXIST) {
errno = -EEXIST;
goto out;
} }
if (flags == S_UB_EXISTS) 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 (S_ISDIR(m)) {
if (flags & S_IFREG) { if (flags & S_IFREG) {
errno = -EISDIR; errno = -EISDIR;
return errno; goto out;
} }
if ((flags & S_UB_IS_EMPTY) && !dir_is_empty(path)) { if ((flags & S_UB_IS_EMPTY) && !dir_is_empty(path)) {
errno = -ENOTEMPTY; errno = -ENOTEMPTY;
return errno; goto out;
} }
} }
if ((flags & S_IFDIR) && S_ISREG(m)) { if ((flags & S_IFDIR) && S_ISREG(m)) {
errno = -ENOTDIR; 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) int unlink(const char *pathname)
{ {
struct device_d *dev; struct device_d *dev;
struct fs_driver_d *fsdrv; struct fs_driver_d *fsdrv;
char *p = strdup(pathname); char *p = normalise_path(pathname);
char *freep = p; char *freep = p;
if (path_check_prereq(pathname, S_IFREG)) if (path_check_prereq(pathname, S_IFREG))
return errno; goto out;
dev = get_device_by_path(&p); dev = get_device_by_path(&p);
if (!dev) if (!dev)
@ -234,30 +305,27 @@ int open(const char *pathname, int flags)
FILE *f; FILE *f;
int exist; int exist;
struct stat s; struct stat s;
char *path; char *path = normalise_path(pathname);
char *freep; char *freep = path;
exist = (stat(pathname, &s) == 0) ? 1 : 0; exist = (stat(path, &s) == 0) ? 1 : 0;
if (exist && (s.st_mode & S_IFDIR)) { if (exist && (s.st_mode & S_IFDIR)) {
errno = -EISDIR; errno = -EISDIR;
return errno; goto out1;
} }
if (!exist && !(flags & O_CREAT)) { if (!exist && !(flags & O_CREAT)) {
errno = -ENOENT; errno = -ENOENT;
return errno; goto out1;
} }
f = get_file(); f = get_file();
if (!f) { if (!f) {
errno = -EMFILE; errno = -EMFILE;
return errno; goto out1;
} }
path = strdup(pathname);
freep = path;
dev = get_device_by_path(&path); dev = get_device_by_path(&path);
if (!dev) if (!dev)
goto out; goto out;
@ -273,7 +341,7 @@ int open(const char *pathname, int flags)
} }
if (!exist) { if (!exist) {
errno = fsdrv->create(dev, pathname, S_IFREG); errno = fsdrv->create(dev, path, S_IFREG);
if (errno) if (errno)
goto out; goto out;
} }
@ -297,6 +365,7 @@ int open(const char *pathname, int flags)
out: out:
put_file(f); put_file(f);
out1:
free(freep); free(freep);
return errno; return errno;
} }
@ -481,9 +550,7 @@ int umount(const char *pathname)
{ {
struct mtab_entry *entry = mtab; struct mtab_entry *entry = mtab;
struct mtab_entry *last = mtab; struct mtab_entry *last = mtab;
char *p = strdup(pathname); char *p = normalise_path(pathname);
normalise_path(p);
while(entry && strcmp(p, entry->path)) { while(entry && strcmp(p, entry->path)) {
last = entry; last = entry;
@ -505,7 +572,6 @@ int umount(const char *pathname)
unregister_device(entry->dev); unregister_device(entry->dev);
free(entry->dev->type_data); free(entry->dev->type_data);
free(entry); free(entry);
return 0; return 0;
} }
@ -514,7 +580,7 @@ struct dir *opendir(const char *pathname)
struct dir *dir = NULL; struct dir *dir = NULL;
struct device_d *dev; struct device_d *dev;
struct fs_driver_d *fsdrv; struct fs_driver_d *fsdrv;
char *p = strdup(pathname); char *p = normalise_path(pathname);
char *freep = p; char *freep = p;
if (path_check_prereq(pathname, S_IFDIR)) if (path_check_prereq(pathname, S_IFDIR))
@ -553,13 +619,11 @@ int stat(const char *filename, struct stat *s)
struct device_d *dev; struct device_d *dev;
struct fs_driver_d *fsdrv; struct fs_driver_d *fsdrv;
struct mtab_entry *e; struct mtab_entry *e;
char *buf = strdup(filename); char *f = normalise_path(filename);
char *f = buf; char *freep = f;
memset(s, 0, sizeof(struct stat)); memset(s, 0, sizeof(struct stat));
normalise_path(f);
e = get_mtab_entry_by_path(f); e = get_mtab_entry_by_path(f);
if (!e) { if (!e) {
errno = -ENOENT; errno = -ENOENT;
@ -579,7 +643,7 @@ int stat(const char *filename, struct stat *s)
errno = fsdrv->stat(dev, f, s); errno = fsdrv->stat(dev, f, s);
out: out:
free(buf); free(freep);
return errno; return errno;
} }
@ -587,11 +651,11 @@ int mkdir (const char *pathname)
{ {
struct fs_driver_d *fsdrv; struct fs_driver_d *fsdrv;
struct device_d *dev; struct device_d *dev;
char *p = strdup(pathname); char *p = normalise_path(pathname);
char *freep = p; char *freep = p;
if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST)) if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST))
return errno; goto out;
dev = get_device_by_path(&p); dev = get_device_by_path(&p);
if (!dev) if (!dev)
@ -613,11 +677,11 @@ int rmdir (const char *pathname)
{ {
struct fs_driver_d *fsdrv; struct fs_driver_d *fsdrv;
struct device_d *dev; struct device_d *dev;
char *p = strdup(pathname); char *p = normalise_path(pathname);
char *freep = p; char *freep = p;
if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY)) if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY))
return errno; goto out;
dev = get_device_by_path(&p); dev = get_device_by_path(&p);
if (!dev) if (!dev)

View File

@ -95,6 +95,9 @@ int rmdir (const char *pathname);
int mount (const char *device, const char *fsname, const char *path); int mount (const char *device, const char *fsname, const char *path);
int umount(const char *pathname); int umount(const char *pathname);
const char *getcwd(void);
int chdir(const char *pathname);
struct dir *opendir(const char *pathname); struct dir *opendir(const char *pathname);
struct dirent *readdir(struct dir *dir); struct dirent *readdir(struct dir *dir);
int closedir(struct dir *dir); int closedir(struct dir *dir);
@ -111,6 +114,6 @@ struct mtab_entry {
struct device_d *parent_device; struct device_d *parent_device;
}; };
void normalise_path(char *path); char *normalise_path(const char *path);
#endif /* __FS_H */ #endif /* __FS_H */