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 <fcntl.h>
#include <xfuncs.h>
#include <init.h>
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)

View File

@ -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 */