diff options
author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2012-08-21 17:21:33 +0800 |
---|---|---|
committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2012-09-05 03:22:13 +0800 |
commit | 65d4f485eb53e18d2832260ce4e56799e54fc2da (patch) | |
tree | 31af0f36af14b730fabb788f742737cec83ad517 /fs | |
parent | 99684498ecf919cdf91378f278eb459cb6299b8d (diff) | |
download | barebox-65d4f485eb53e18d2832260ce4e56799e54fc2da.tar.gz barebox-65d4f485eb53e18d2832260ce4e56799e54fc2da.tar.xz |
fs: add symlink support
Limit it's support to existing file only
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs.c | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -927,6 +927,57 @@ out: } EXPORT_SYMBOL(readlink); +int symlink(const char *pathname, const char *newpath) +{ + struct fs_driver_d *fsdrv; + struct fs_device_d *fsdev; + char *p; + char *freep = normalise_path(pathname); + int ret; + struct stat s; + + if (!freep) + return -ENOMEM; + + if (!stat(freep, &s) && S_ISDIR(s.st_mode)) { + ret = -ENOSYS; + goto out; + } + + free(freep); + freep = p = normalise_path(newpath); + + if (!p) + return -ENOMEM; + + ret = lstat(p, &s); + if (!ret) { + ret = -EEXIST; + goto out; + } + + fsdev = get_fs_device_and_root_path(&p); + if (!fsdev) { + ret = -ENODEV; + goto out; + } + fsdrv = fsdev->driver; + + if (fsdrv->symlink) { + ret = fsdrv->symlink(&fsdev->dev, pathname, p); + } else { + ret = -EPERM; + } + +out: + free(freep); + if (ret) + errno = -ret; + + return ret; +} +EXPORT_SYMBOL(symlink); + static int fs_match(struct device_d *dev, struct driver_d *drv) { return strcmp(dev->name, drv->name) ? -1 : 0; |