int sp_lockfile(spfile *f, char *path) { f->creat = 0; f->fd = open(path, O_CREAT|O_WRONLY, 0600); if (spunlikely(f->fd == -1)) return -1; f->file = sp_strdup(f->a, path); if (spunlikely(f->file == NULL)) { close(f->fd); f->fd = -1; return -1; } struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = SEEK_SET; l.l_start = 0; l.l_len = 0; l.l_type = F_WRLCK; int rc = fcntl(f->fd, F_SETLK, &l); if (spunlikely(rc == -1)) { sp_fileclose(f); return 1; } return 0; }
static void spcfd_check_error(Spcfd *spcfd, Spfcall *rc) { char *ename; if (rc && rc->type == Rerror) { ename = sp_strdup(&rc->ename); if (ename) { sp_werror(ename, rc->ecode); free(ename); } } }
int spc_rpc(Spcfsys *fs, Spfcall *tc, Spfcall **rc) { char *ename; Spcrpc r; if (fs->fd < 0) return -1; if (rc) *rc = NULL; r.fs = fs; r.tc = tc; r.rc = NULL; r.ename = NULL; r.ecode = 0; spc_rpcnb(fs, tc, spc_rpc_cb, &r); while (!r.ename && !r.rc) sp_poll_once(); if (r.ename) { sp_werror(r.ename, r.ecode); goto error; } if (r.rc && r.rc->type == Rerror) { ename = sp_strdup(&r.rc->ename); if (ename) sp_werror(ename, r.rc->ecode); free(ename); goto error; } free(r.ename); if (rc) *rc = r.rc; else free(r.rc); return 0; error: if (r.ename != Enomem) free(r.ename); free(r.rc); return -1; }
static inline int sp_logopenof(spfile *f, char *path, int flags) { f->creat = 1; f->fd = open(path, flags, 0600); if (spunlikely(f->fd == -1)) return -1; f->file = sp_strdup(f->a, path); if (spunlikely(f->file == NULL)) { close(f->fd); f->fd = -1; return -1; } f->size = 0; f->used = 0; return 0; }
static inline int sp_mapopenof(spfile *f, char *path, int flags, uint64_t size) { #if _MSC_VER f->fd = sp_win_openfile(path, flags); #else f->fd = open(path, flags, 0600); #endif if (spunlikely(f->fd == -1)) return -1; f->file = sp_strdup(f->a, path); if (spunlikely(f->file == NULL)) { close(f->fd); f->fd = -1; return -1; } f->used = 0; f->creat = (flags & O_CREAT ? 1 : 0); int rc; if (!f->creat) { ssize_t sz = sp_mapsizeof(path); if (spunlikely(sz == -1)) goto err; f->size = sz; rc = sp_map(f, PROT_READ); if (spunlikely(rc == -1)) goto err; return 0; } f->size = 0; rc = sp_mapresize(f, size); if (spunlikely(rc == -1)) goto err; rc = sp_map(f, PROT_READ | PROT_WRITE); if (spunlikely(rc == -1)) goto err; return 0; err: close(f->fd); f->fd = -1; sp_free(f->a, f->file); f->file = NULL; return -1; }
static Spfcall* npfs_attach(Spfid *nfid, Spfid *nafid, Spstr *uname, Spstr *aname, u32 n_uname) { int err; Spfcall* ret; Fid *fid; Spqid qid; char *user; user = NULL; ret = NULL; if (nafid != NULL) { sp_werror(Enoauth, EIO); goto done; } fid = npfs_fidalloc(); fid->omode = -1; npfs_change_user(nfid->user); fid->omode = -1; if (aname->len==0 || *aname->str!='/') fid->path = strdup("/"); else fid->path = sp_strdup(aname); nfid->aux = fid; err = fidstat(fid); if (err < 0) { create_rerror(err); goto done; } ustat2qid(&fid->stat, &qid); ret = sp_create_rattach(&qid); sp_fid_incref(nfid); done: return ret; }
int sp_lockfile(spfile *f, char *path) { f->creat = 0; #ifdef _MSC_VER f->fd = sp_win_openfileshare(path, O_CREAT | O_WRONLY, 0); if (f->fd == -1 && GetLastError() == ERROR_SHARING_VIOLATION) return 1; // already locked #else f->fd = open(path, O_CREAT | O_WRONLY, 0600); #endif if (spunlikely(f->fd == -1)) return -1; f->file = sp_strdup(f->a, path); if (spunlikely(f->file == NULL)) { close(f->fd); f->fd = -1; return -1; } #ifdef _MSC_VER int rc = LockFile((HANDLE)_get_osfhandle(f->fd), 0, 0, 0xffffffff, 0xffffffff); if (spunlikely(rc == 0)) { sp_fileclose(f); return 1; } return 0; #else struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = SEEK_SET; l.l_start = 0; l.l_len = 0; l.l_type = F_WRLCK; int rc = fcntl(f->fd, F_SETLK, &l); if (spunlikely(rc == -1)) { sp_fileclose(f); return 1; } return 0; #endif }
static inline int sp_filecomplete(spfile *f) { if (f->creat == 0) return 0; /* remove .incomplete part */ f->creat = 0; char path[1024]; snprintf(path, sizeof(path), "%s", f->file); char *ext = strrchr(path, '.'); assert(ext != NULL); *ext = 0; int rc = rename(f->file, path); if (spunlikely(rc == -1)) return -1; char *p = sp_strdup(f->a, path); if (spunlikely(p == NULL)) return -1; sp_free(f->a, f->file); f->file = p; return 0; }
Spfcall * sp_auth(Spreq *req, Spfcall *tc) { int n; char *uname, *aname; Spconn *conn; Spsrv *srv; Spfid *afid; Spfcall *rc; Spuser *user; Spqid aqid; rc = NULL; aname = NULL; conn = req->conn; srv = conn->srv; afid = sp_fid_find(conn, tc->afid); if (afid) { sp_werror(Einuse, EIO); goto done; } afid = sp_fid_create(conn, tc->afid, NULL); if (!afid) goto done; else sp_fid_incref(afid); if (tc->uname.len && tc->n_uname==~0) { uname = sp_strdup(&tc->uname); if (!uname) goto done; user = (*srv->upool->uname2user)(srv->upool, uname); free(uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } tc->n_uname = user->uid; } else { user = (*srv->upool->uid2user)(srv->upool, tc->n_uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } } if (tc->aname.len) { aname = sp_strdup(&tc->aname); if (!aname) goto done; } else aname = NULL; afid->user = user; afid->type = Qtauth; if (srv->auth && srv->auth->startauth) n = (*srv->auth->startauth)(afid, aname, &aqid); else n = 0; if (n) { assert((aqid.type & Qtauth) != 0); rc = sp_create_rauth(&aqid); } else sp_werror(Enoauth, EIO); done: free(aname); if (!rc) sp_fid_decref(afid); return rc; }
Spfcall * sp_attach(Spreq *req, Spfcall *tc) { char *uname, *aname; Spconn *conn; Spsrv *srv; Spfid *fid, *afid; Spfcall *rc; Spuser *user; rc = NULL; aname = NULL; conn = req->conn; srv = conn->srv; afid = NULL; fid = sp_fid_find(conn, tc->fid); if (fid) { sp_werror(Einuse, EIO); goto done; } fid = sp_fid_create(conn, tc->fid, NULL); if (!fid) goto done; else sp_fid_incref(fid); req->fid = fid; afid = sp_fid_find(conn, tc->afid); if (!afid) { if (tc->afid!=NOFID) { sp_werror(Eunknownfid, EIO); goto done; } if (!afid->type&Qtauth) { sp_werror(Ebadusefid, EIO); goto done; } } else sp_fid_incref(afid); if (tc->uname.len && tc->n_uname==~0) { uname = sp_strdup(&tc->uname); if (!uname) goto done; user = srv->upool->uname2user(srv->upool, uname); free(uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } tc->n_uname = user->uid; } else { user = srv->upool->uid2user(srv->upool, tc->n_uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } } fid->user = user; if (tc->aname.len) { aname = sp_strdup(&tc->aname); if (!aname) goto done; } else aname = NULL; if (conn->srv->auth && conn->srv->auth->checkauth && !(*conn->srv->auth->checkauth)(fid, afid, aname)) goto done; rc = (*conn->srv->attach)(fid, afid, &tc->uname, &tc->aname, tc->n_uname); done: free(aname); sp_fid_decref(afid); return rc; }
static Spfcall* npfs_wstat(Spfid *fid, Spstat *stat) { int err; Fid *f; Spfcall *ret; uid_t uid; gid_t gid; char *npath, *p, *s; Spuser *user; Spgroup *group; struct utimbuf tb; ret = NULL; f = fid->aux; npfs_change_user(fid->user); err = fidstat(f); if (err < 0) { create_rerror(err); goto out; } if (fid->conn->dotu) { uid = stat->n_uid; gid = stat->n_gid; } else { uid = (uid_t) -1; gid = (gid_t) -1; } if (uid == -1 && stat->uid.len) { s = sp_strdup(&stat->uid); user = sp_uname2user(s); free(s); if (!user) { sp_werror(Eunknownuser, EIO); goto out; } uid = user->uid; } if (gid == -1 && stat->gid.len) { s = sp_strdup(&stat->gid); group = sp_gname2group(s); free(s); if (!group) { sp_werror(Eunknownuser, EIO); goto out; } gid = group->gid; } if (stat->mode != (u32)~0) { if (stat->mode&Dmdir && !S_ISDIR(f->stat.st_mode)) { sp_werror(Edirchange, EIO); goto out; } if (chmod(f->path, npstat2umode(stat, fid->conn->dotu)) < 0) { create_rerror(errno); goto out; } } if (stat->mtime != (u32)~0) { tb.actime = 0; tb.modtime = stat->mtime; if (utime(f->path, &tb) < 0) { create_rerror(errno); goto out; } } if (gid != -1) { if (chown(f->path, uid, gid) < 0) { create_rerror(errno); goto out; } } if (stat->name.len != 0) { p = strrchr(f->path, '/'); if (!p) p = f->path + strlen(f->path); npath = malloc(stat->name.len + (p - f->path) + 2); memcpy(npath, f->path, p - f->path); npath[p - f->path] = '/'; memcpy(npath + (p - f->path) + 1, stat->name.str, stat->name.len); npath[(p - f->path) + 1 + stat->name.len] = 0; if (strcmp(npath, f->path) != 0) { if (rename(f->path, npath) < 0) { create_rerror(errno); goto out; } free(f->path); f->path = npath; } } if (stat->length != ~0) { if (truncate(f->path, stat->length) < 0) { create_rerror(errno); goto out; } } ret = sp_create_rwstat(); out: return ret; }
static int npfs_create_special(Spfid *fid, char *path, u32 perm, Spstr *extension) { int nfid, err; int nmode, major, minor; char ctype; mode_t umode; Spfid *ofid; Fid *f, *of; char *ext; f = fid->aux; if (!perm&Dmnamedpipe && !extension->len) { sp_werror(Enoextension, EIO); return -1; } umode = np2umode(perm, extension, fid->conn->dotu); ext = sp_strdup(extension); if (perm & Dmsymlink) { if (symlink(ext, path) < 0) { err = errno; fprintf(stderr, "symlink %s %s %d\n", ext, path, err); create_rerror(err); goto error; } } else if (perm & Dmlink) { if (sscanf(ext, "%d", &nfid) == 0) { sp_werror(Eformat, EIO); goto error; } ofid = sp_fid_find(fid->conn, nfid); if (!ofid) { sp_werror(Eunknownfid, EIO); goto error; } of = ofid->aux; if (link(of->path, path) < 0) { create_rerror(errno); goto error; } } else if (perm & Dmdevice) { if (sscanf(ext, "%c %u %u", &ctype, &major, &minor) != 3) { sp_werror(Eformat, EIO); goto error; } nmode = 0; switch (ctype) { case 'c': nmode = S_IFCHR; break; case 'b': nmode = S_IFBLK; break; default: sp_werror(Eformat, EIO); goto error; } nmode |= perm & 0777; if (mknod(path, nmode, makedev(major, minor)) < 0) { create_rerror(errno); goto error; } } else if (perm & Dmnamedpipe) { if (mknod(path, S_IFIFO | (umode&0777), 0) < 0) { create_rerror(errno); goto error; } } f->omode = 0; if (!perm&Dmsymlink && chmod(path, umode)<0) { create_rerror(errno); goto error; } free(ext); return 0; error: free(ext); return -1; }