svn_rev_406
let normalise path allocate the string instead of changing the original one
This commit is contained in:
parent
e6a048eb57
commit
014678f7a0
150
fs/fs.c
150
fs/fs.c
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue