From c248a99fccc830822ca49b23439b0c61f974b2cc Mon Sep 17 00:00:00 2001 From: Reuben Thomas Date: Thu, 13 Mar 2008 23:26:36 +0000 Subject: Return sensible error codes from plpfuse, and fix one or two functions that were setting errno (which is apparently wrong for FUSE). --- plpfuse/fuse.c | 149 ++++++++++++++++------------------------- plpfuse/main.cc | 193 +++++++++++++++++++++++++++++++++++++---------------- plpfuse/rfsv_api.h | 36 +++++----- 3 files changed, 208 insertions(+), 170 deletions(-) (limited to 'plpfuse') diff --git a/plpfuse/fuse.c b/plpfuse/fuse.c index 876b629..f9633ab 100644 --- a/plpfuse/fuse.c +++ b/plpfuse/fuse.c @@ -7,8 +7,6 @@ See the file COPYING. */ -/* FIXME: Map errors sensibly from EPOC to UNIX */ - #ifdef HAVE_CONFIG_H #include #endif @@ -21,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -29,8 +26,6 @@ #include "plpfuse.h" #include "rfsv_api.h" -#define NO_PSION ENOMEDIUM - /* Name of our extended attribute */ #define XATTR_NAME "user.psion" @@ -187,7 +182,7 @@ dircount(const char *path, long *count) *count = 0; debuglog("dircount: %s", path); debuglog("RFSV dir %s", path); - if ((ret = rfsv_dir(dirname(path), &e))) + if ((ret = rfsv_dir(dirname(path), &e)) != 0) return ret; while (e) { struct stat st; @@ -208,16 +203,16 @@ dircount(const char *path, long *count) static int getlinks(const char *path, struct stat *st) { long dcount; - - if (dircount(path, &dcount)) - return rfsv_isalive() ? -ENOENT : -NO_PSION; - st->st_nlink = dcount + 2; - return 0; + int ret = dircount(path, &dcount); + if (ret == 0) + st->st_nlink = dcount + 2; + return ret; } static int plp_getattr(const char *path, struct stat *st) { char xattr[XATTR_MAXLEN + 1]; + int ret = 0; debuglog("plp_getattr `%s'", ++path); @@ -230,7 +225,7 @@ static int plp_getattr(const char *path, struct stat *st) st->st_nlink++; debuglog("root has %d links", st->st_nlink); } else - return rfsv_isalive() ? -ENOENT : -NO_PSION; + return rfsv_isalive() ? -ENOENT : -ENOMEDIUM; } else { long pattr, psize, ptime; @@ -249,22 +244,20 @@ static int plp_getattr(const char *path, struct stat *st) pattr2attr(PSI_A_DIR, 0, 0, st, xattr); return getlinks(path, st); } else - return rfsv_isalive() ? -ENOENT : -NO_PSION; + return rfsv_isalive() ? -ENOENT : -ENOMEDIUM; } debuglog("getattr: fileordir"); - if (rfsv_getattr(path, &pattr, &psize, &ptime)) - return rfsv_isalive() ? -ENOENT : -NO_PSION; - else { + if ((ret = rfsv_getattr(path, &pattr, &psize, &ptime)) == 0) { pattr2attr(pattr, psize, ptime, st, xattr); debuglog(" attrs Psion: %x %d %d, UNIX modes: %o, xattrs: %s", pattr, psize, ptime, st->st_mode, xattr); if (st->st_nlink > 1) - return getlinks(path, st); + ret = getlinks(path, st); } } - debuglog("getattr: return OK"); - return 0; + debuglog("getattr: returned %d", ret); + return ret; } static int plp_access(const char *path, int mask) @@ -311,9 +304,10 @@ static int plp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, } } } else { + int ret; debuglog("RFSV dir `%s'", dirname(path)); - if (rfsv_dir(dirname(path), &e)) - return rfsv_isalive() ? -ENOENT : -NO_PSION; + if ((ret = rfsv_dir(dirname(path), &e)) != 0) + return ret; debuglog("scanning contents"); while (e) { @@ -338,48 +332,35 @@ static int plp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int plp_mknod(const char *path, mode_t mode, dev_t dev) { - u_int32_t phandle; + int ret = -EINVAL; debuglog("plp_mknod `%s' %o", ++path, mode); if (S_ISREG(mode) && dev == 0) { - if (rfsv_fcreate(0x200, path, &phandle)) - return rfsv_isalive() ? -ENAMETOOLONG : -NO_PSION; - rfsv_fclose(phandle); - } else - return -EINVAL; + u_int32_t phandle; + if ((ret = rfsv_fcreate(0x200, path, &phandle)) == 0) + rfsv_fclose(phandle); + } - return 0; + return ret; } static int plp_mkdir(const char *path, mode_t mode) { debuglog("plp_mkdir `%s' %o", ++path, mode); - - if (rfsv_mkdir(path)) - return rfsv_isalive() ? -ENAMETOOLONG : -NO_PSION; - - return 0; + return rfsv_mkdir(path); } static int plp_unlink(const char *path) { debuglog("plp_unlink `%s'", ++path); - - if (rfsv_remove(path)) - return rfsv_isalive() ? -EACCES : -NO_PSION; - - return 0; + return rfsv_remove(path); } static int plp_rmdir(const char *path) { debuglog("plp_rmdir `%s'", ++path); - - if (rfsv_rmdir(path)) - return rfsv_isalive() ? -EACCES : -NO_PSION; - - return 0; + return rfsv_rmdir(path); } static int plp_symlink(const char *from, const char *to) @@ -391,12 +372,8 @@ static int plp_symlink(const char *from, const char *to) static int plp_rename(const char *from, const char *to) { debuglog("plp_rename `%s' -> `%s'", ++from, ++to); - rfsv_remove(to); - if (rfsv_rename(from, to)) - return rfsv_isalive() ? -EACCES : -NO_PSION; - - return 0; + return rfsv_rename(from, to); } static int plp_link(const char *from, const char *to) @@ -407,22 +384,22 @@ static int plp_link(const char *from, const char *to) static int plp_chmod(const char *path, mode_t mode) { + int ret; long psisattr, psidattr, pattr, psize, ptime; struct stat st; char xattr[XATTR_MAXLEN + 1]; debuglog("plp_chmod `%s'", ++path); - if (rfsv_getattr(path, &pattr, &psize, &ptime)) - return rfsv_isalive() ? -ENOENT : -NO_PSION; - pattr2attr(pattr, psize, ptime, &st, xattr); - attr2pattr(st.st_mode, mode, "", "", &psisattr, &psidattr); - debuglog(" UNIX old, new: %o, %o; Psion set, clear: %x, %x", st.st_mode, mode, psisattr, psidattr); - if (rfsv_setattr(path, psisattr, psidattr)) - return rfsv_isalive() ? -EACCES : -NO_PSION; + if ((ret = rfsv_getattr(path, &pattr, &psize, &ptime)) == 0) { + pattr2attr(pattr, psize, ptime, &st, xattr); + attr2pattr(st.st_mode, mode, "", "", &psisattr, &psidattr); + debuglog(" UNIX old, new: %o, %o; Psion set, clear: %x, %x", st.st_mode, mode, psisattr, psidattr); + if ((ret = rfsv_setattr(path, psisattr, psidattr)) == 0) + debuglog("chmod succeeded"); + } - debuglog("chmod succeeded"); - return 0; + return ret; } static int plp_getxattr(const char *path, const char *name, char *value, size_t size) @@ -431,11 +408,13 @@ static int plp_getxattr(const char *path, const char *name, char *value, size_t if (strcmp(name, XATTR_NAME) == 0) { if (size >= XATTR_MAXLEN) { long pattr, psize, ptime; - if (rfsv_getattr(path, &pattr, &psize, &ptime)) - return rfsv_isalive() ? -ENOENT : -NO_PSION; - pattr2xattr(pattr, value); - debuglog("getxattr succeeded: %s", value); - return strlen(value); + int ret; + if ((ret = rfsv_getattr(path, &pattr, &psize, &ptime)) == 0) { + pattr2xattr(pattr, value); + debuglog("getxattr succeeded: %s", value); + return strlen(value); + } else + return ret; } else { debuglog("only gave %d bytes, need %d", size, XATTR_MAXLEN); return XATTR_MAXLEN; @@ -448,13 +427,12 @@ static int plp_setxattr(const char *path, const char *name, const char *value, s { debuglog("plp_setxattr `%s'", ++path); if (strcmp(name, XATTR_NAME) == 0) { + int ret; long psisattr, psidattr; char oxattr[XATTR_MAXLEN + 1], nxattr[XATTR_MAXLEN + 1]; - if (flags & XATTR_CREATE) { - errno = EEXIST; - return -1; - } + if (flags & XATTR_CREATE) + return -EEXIST; strncpy(nxattr, value, size < XATTR_MAXLEN ? size : XATTR_MAXLEN); nxattr[XATTR_MAXLEN] = '\0'; @@ -463,17 +441,16 @@ static int plp_setxattr(const char *path, const char *name, const char *value, s psisattr = psidattr = 0; xattr2pattr(&psisattr, &psidattr, oxattr, value); debuglog("attrs set %x delete %x; %s, %s", psisattr, psidattr, oxattr, value); - if (rfsv_setattr(path, psisattr, psidattr)) - return rfsv_isalive() ? -EACCES : -NO_PSION; + if ((ret = rfsv_setattr(path, psisattr, psidattr)) != 0) + return ret; debuglog("setxattr succeeded"); return 0; } else { if (flags & XATTR_REPLACE) - errno = ENOATTR; + return -ENOATTR; else - errno = ENOTSUP; - return -1; + return -ENOTSUP; } } @@ -488,8 +465,8 @@ static int plp_listxattr(const char *path, char *list, size_t size) static int plp_removexattr(const char *path, const char *name) { debuglog("plp_removexattr `%s'", ++path); - errno = ENOTSUP; - return -1; + (void)name; + return -ENOTSUP; } static int plp_chown(const char *path, uid_t uid, gid_t gid) @@ -502,23 +479,14 @@ static int plp_chown(const char *path, uid_t uid, gid_t gid) static int plp_truncate(const char *path, off_t size) { - (void)size; debuglog("plp_truncate `%s'", ++path); - - if (rfsv_setsize(path, 0)) - return rfsv_isalive() ? -EPERM : -NO_PSION; - - return 0; + return rfsv_setsize(path, size); } static int plp_utimens(const char *path, const struct timespec ts[2]) { debuglog("plp_utimens `%s'", ++path); - - if (rfsv_setmtime(path, ts[1].tv_sec)) - return rfsv_isalive() ? -EPERM : -NO_PSION; - - return 0; + return rfsv_setmtime(path, ts[1].tv_sec); } static int plp_open(const char *path, struct fuse_file_info *fi) @@ -535,11 +503,8 @@ static int plp_read(const char *path, char *buf, size_t size, off_t offset, (void)fi; debuglog("plp_read `%s' offset %lld size %ld", ++path, offset, size); - - if ((read = rfsv_read(buf, (long)offset, size, path)) < 0) - return rfsv_isalive() ? -ENOENT : -NO_PSION; - - debuglog("read %ld bytes", read); + read = rfsv_read(buf, (long)offset, size, path); + debuglog("read returned %ld", read); return read; } @@ -550,10 +515,8 @@ static int plp_write(const char *path, const char *buf, size_t size, (void)fi; debuglog("plp_write `%s' offset %lld size %ld", ++path, offset, size); - if ((written = rfsv_write(buf, offset, size, path)) < 0) - return rfsv_isalive() ? -ENOSPC : -NO_PSION; - - debuglog("wrote %ld bytes", written); + written = rfsv_write(buf, offset, size, path); + debuglog("write returned %ld", written); return written; } diff --git a/plpfuse/main.cc b/plpfuse/main.cc index 769577c..5ff2f78 100644 --- a/plpfuse/main.cc +++ b/plpfuse/main.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include "rfsv_api.h" @@ -60,21 +61,103 @@ static rpcs *r; static rpcsfactory *rp; static bufferStore owner; -long rfsv_isalive() { +/* Translate EPOC/SIBO error to UNIX error code, leaving positive + numbers alone */ +int epocerr_to_errno(long epocerr) { + int unixerr = (int)epocerr; + + if (epocerr < 0) { + switch (epocerr) { + case rfsv::E_PSI_GEN_NONE: + unixerr = 0; + break; + case rfsv::E_PSI_FILE_EXIST: + unixerr = -EEXIST; + break; + case rfsv::E_PSI_FILE_NXIST: + case rfsv::E_PSI_FILE_DIR: + unixerr = -ENOENT; + break; + case rfsv::E_PSI_FILE_WRITE: + case rfsv::E_PSI_FILE_READ: + case rfsv::E_PSI_FILE_EOF: // Can't err = EOF as it's not an error code + case rfsv::E_PSI_FILE_ALLOC: // FIXME: No idea what this is + case rfsv::E_PSI_FILE_UNKNOWN: + case rfsv::E_PSI_FILE_DIRFULL: + unixerr = -EPERM; + break; + case rfsv::E_PSI_FILE_FULL: + unixerr = -ENOSPC; + break; + case rfsv::E_PSI_FILE_NAME: + case rfsv::E_PSI_FILE_RECORD: + case rfsv::E_PSI_FILE_VOLUME: + unixerr = -EINVAL; + break; + case rfsv::E_PSI_FILE_ACCESS: + case rfsv::E_PSI_FILE_LOCKED: + case rfsv::E_PSI_FILE_RDONLY: + case rfsv::E_PSI_FILE_PROTECT: + unixerr = -EACCES; + break; + case rfsv::E_PSI_GEN_INUSE: + case rfsv::E_PSI_FILE_DEVICE: + case rfsv::E_PSI_FILE_PENDING: + case rfsv::E_PSI_FILE_NOTREADY: + unixerr = -EBUSY; + break; + case rfsv::E_PSI_FILE_INV: + case rfsv::E_PSI_FILE_RETRAN: + case rfsv::E_PSI_FILE_LINE: + case rfsv::E_PSI_FILE_INACT: + case rfsv::E_PSI_FILE_PARITY: + case rfsv::E_PSI_FILE_FRAME: + case rfsv::E_PSI_FILE_OVERRUN: + case rfsv::E_PSI_FILE_CORRUPT: + case rfsv::E_PSI_FILE_INVALID: + case rfsv::E_PSI_FILE_ABORT: + case rfsv::E_PSI_FILE_ERASE: + case rfsv::E_PSI_FILE_NDISC: + case rfsv::E_PSI_FILE_DRIVER: + case rfsv::E_PSI_FILE_COMPLETION: + default: + unixerr = -EIO; + break; + case rfsv::E_PSI_FILE_CANCEL: + unixerr = -EINTR; + break; + case rfsv::E_PSI_FILE_DISC: + case rfsv::E_PSI_FILE_CONNECT: + unixerr = -ENODEV; + break; + case rfsv::E_PSI_FILE_TOOBIG: + unixerr = -EFBIG; + break; + case rfsv::E_PSI_FILE_HANDLE: + unixerr = -EBADF; + break; + } + } + + debuglog("EPOC error %ld became UNIX code %d", epocerr, unixerr); + return unixerr; +} + +int rfsv_isalive(void) { if (!a) { if (!(a = rf->create(true))) return 0; } - return (a->getStatus() == rfsv::E_PSI_GEN_NONE); + return a->getStatus() == rfsv::E_PSI_GEN_NONE; } -long rfsv_dir(const char *file, dentry **e) { +int rfsv_dir(const char *file, dentry **e) { PlpDir entries; dentry *tmp; long ret; if (!a) - return -1; + return -ENODEV; ret = a->dir(file, entries); for (int i = 0; i < entries.size(); i++) { @@ -82,76 +165,76 @@ long rfsv_dir(const char *file, dentry **e) { tmp = *e; *e = (dentry *)calloc(1, sizeof(dentry)); if (!*e) - return -1; + return -ENODEV; (*e)->time = pe.getPsiTime().getTime(); (*e)->size = pe.getSize(); (*e)->attr = pe.getAttr(); (*e)->name = strdup(pe.getName()); (*e)->next = tmp; } - return ret; + return epocerr_to_errno(ret); } -long rfsv_dircount(const char *file, u_int32_t *count) { +int rfsv_dircount(const char *file, u_int32_t *count) { if (!a) - return -1; - return a->dircount(file, *count); + return -ENODEV; + return epocerr_to_errno(a->dircount(file, *count)); } -long rfsv_rmdir(const char *name) { +int rfsv_rmdir(const char *name) { if (!a) - return -1; - return a->rmdir(name); + return -ENODEV; + return epocerr_to_errno(a->rmdir(name)); } -long rfsv_mkdir(const char *file) { +int rfsv_mkdir(const char *file) { if (!a) - return -1; - return a->mkdir(file); + return -ENODEV; + return epocerr_to_errno(a->mkdir(file)); } -long rfsv_remove(const char *file) { +int rfsv_remove(const char *file) { if (!a) - return -1; - return a->remove(file); + return -ENODEV; + return epocerr_to_errno(a->remove(file)); } -long rfsv_fclose(long handle) { +int rfsv_fclose(long handle) { if (!a) - return -1; - return a->fclose(handle); + return -ENODEV; + return epocerr_to_errno(a->fclose(handle)); } -long rfsv_fcreate(long attr, const char *file, u_int32_t *handle) { +int rfsv_fcreate(long attr, const char *file, u_int32_t *handle) { u_int32_t ph; long ret; if (!a) - return -1; + return -ENODEV; ret = a->fcreatefile(attr, file, ph); *handle = ph; - return ret; + return epocerr_to_errno(ret); } -long rfsv_open(const char *name, long mode, u_int32_t *handle) { +int rfsv_open(const char *name, long mode, u_int32_t *handle) { long ret, retry; if (!a) - return -1; + return -ENODEV; if (mode == O_RDONLY) mode = rfsv::PSI_O_RDONLY; else mode = rfsv::PSI_O_RDWR; for (retry = 100; retry > 0 && (ret = a->fopen(a->opMode(mode), name, *handle)) != rfsv::E_PSI_GEN_NONE; retry--) usleep(20000); - return ret; + return epocerr_to_errno(ret); } -long rfsv_read(char *buf, long offset, long len, const char *name) { +int rfsv_read(char *buf, long offset, long len, const char *name) { u_int32_t ret = 0, r_offset, handle; if (!a) - return -1; + return -ENODEV; if ((ret = rfsv_open(name, O_RDONLY, &handle))) return ret; if (a->fseek(handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE || @@ -159,14 +242,14 @@ long rfsv_read(char *buf, long offset, long len, const char *name) { a->fread(handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE) ret = -1; rfsv_fclose(handle); - return ret; + return epocerr_to_errno(ret); } -long rfsv_write(const char *buf, long offset, long len, const char *name) { +int rfsv_write(const char *buf, long offset, long len, const char *name) { u_int32_t ret = 0, r_offset, handle; if (!a) - return -1; + return -ENODEV; if ((ret = rfsv_open(name, O_RDWR, &handle))) return ret; if (a->fseek(handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE || @@ -174,70 +257,62 @@ long rfsv_write(const char *buf, long offset, long len, const char *name) { a->fwrite(handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE) ret = -1; rfsv_fclose(handle); - return ret; + return epocerr_to_errno(ret); } -long rfsv_setmtime(const char *name, long time) { +int rfsv_setmtime(const char *name, long time) { if (!a) - return -1; - return a->fsetmtime(name, PsiTime(time)); + return -ENODEV; + return epocerr_to_errno(a->fsetmtime(name, PsiTime(time))); } -long rfsv_setsize(const char *name, long size) { +int rfsv_setsize(const char *name, long size) { u_int32_t ph; long ret; if (!a) - return -1; + return -ENODEV; ret = a->fopen(a->opMode(rfsv::PSI_O_RDWR), name, ph); if (!ret) { ret = a->fsetsize(ph, size); a->fclose(ph); } - return ret; + return epocerr_to_errno(ret); } -long rfsv_setattr(const char *name, long sattr, long dattr) { +int rfsv_setattr(const char *name, long sattr, long dattr) { if (!a) - return -1; - return a->fsetattr(name, sattr, dattr); + return -ENODEV; + return epocerr_to_errno(a->fsetattr(name, sattr, dattr)); } -long rfsv_getattr(const char *name, long *attr, long *size, long *time) { +int rfsv_getattr(const char *name, long *attr, long *size, long *time) { long res; PlpDirent e; if (!a) - return -1; + return -ENODEV; res = a->fgeteattr(name, e); *attr = e.getAttr(); *size = e.getSize(); *time = e.getPsiTime().getTime(); - return res; -} - -long rfsv_statdev(char letter) { - PlpDrive drive; - - if (!a) - return -1; - return (a->devinfo(letter, drive) != rfsv::E_PSI_GEN_NONE); + return epocerr_to_errno(res); } -long rfsv_rename(const char *oldname, const char *newname) { +int rfsv_rename(const char *oldname, const char *newname) { if (!a) - return -1; - return a->rename(oldname, newname); + return -ENODEV; + return epocerr_to_errno(a->rename(oldname, newname)); } -long rfsv_drivelist(int *cnt, device **dlist) { +int rfsv_drivelist(int *cnt, device **dlist) { *dlist = NULL; u_int32_t devbits; long ret; int i; if (!a) - return -1; + return -ENODEV; ret = a->devlist(devbits); if (ret == 0) for (i = 0; i < 26; i++) { @@ -258,7 +333,7 @@ long rfsv_drivelist(int *cnt, device **dlist) { } devbits >>= 1; } - return ret; + return epocerr_to_errno(ret); } static void diff --git a/plpfuse/rfsv_api.h b/plpfuse/rfsv_api.h index 8e23196..37f27a5 100644 --- a/plpfuse/rfsv_api.h +++ b/plpfuse/rfsv_api.h @@ -29,24 +29,24 @@ extern "C" { #include "plpfuse.h" -extern long rfsv_dir(const char *name, dentry **e); -extern long rfsv_mkdir(const char *name); -extern long rfsv_rmdir(const char *name); -extern long rfsv_remove(const char *name); -extern long rfsv_rename(const char *oldname, const char *newname); -extern long rfsv_open(const char *name, long mode, u_int32_t *handle); -extern long rfsv_fclose(long handle); -extern long rfsv_fcreate(long attr, const char *name, u_int32_t *handle); -extern long rfsv_read(char *buf, long offset, long len, const char *name); -extern long rfsv_write(const char *buf, long offset, long len, const char *name); -extern long rfsv_getattr(const char *name, long *attr, long *size, long *time); -extern long rfsv_setattr(const char *name, long sattr, long dattr); -extern long rfsv_setsize(const char *name, long size); -extern long rfsv_setmtime(const char *name, long time); -extern long rfsv_drivelist(int *cnt, device **devlist); -extern long rfsv_dircount(const char *name, long *count); -extern long rfsv_statdev(char letter); -extern long rfsv_isalive(void); +extern int psierr_to_errno(long psierr); +extern int rfsv_dir(const char *name, dentry **e); +extern int rfsv_mkdir(const char *name); +extern int rfsv_rmdir(const char *name); +extern int rfsv_remove(const char *name); +extern int rfsv_rename(const char *oldname, const char *newname); +extern int rfsv_open(const char *name, long mode, u_int32_t *handle); +extern int rfsv_fclose(long handle); +extern int rfsv_fcreate(long attr, const char *name, u_int32_t *handle); +extern int rfsv_read(char *buf, long offset, long len, const char *name); +extern int rfsv_write(const char *buf, long offset, long len, const char *name); +extern int rfsv_getattr(const char *name, long *attr, long *size, long *time); +extern int rfsv_setattr(const char *name, long sattr, long dattr); +extern int rfsv_setsize(const char *name, long size); +extern int rfsv_setmtime(const char *name, long time); +extern int rfsv_drivelist(int *cnt, device **devlist); +extern int rfsv_dircount(const char *name, long *count); +extern int rfsv_isalive(void); /* File attributes, C-style */ #define PSI_A_RDONLY 0x0001 -- cgit v1.2.3