You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
|
Jul
(1) |
Aug
|
Sep
(6) |
Oct
|
Nov
(11) |
Dec
(5) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
(7) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(9) |
Dec
(4) |
2010 |
Jan
(4) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
From: <li...@us...> - 2008-07-17 17:21:27
|
Revision: 7 http://npfs.svn.sourceforge.net/npfs/?rev=7&view=rev Author: lionkov Date: 2008-07-17 17:20:51 +0000 (Thu, 17 Jul 2008) Log Message: ----------- Fix the non-blocking read and write oprations. Modified Paths: -------------- spfs/trunk/include/spclient.h spfs/trunk/libspclient/examples/9ls.c spfs/trunk/libspclient/examples/9read.c spfs/trunk/libspclient/examples/9read2.c spfs/trunk/libspclient/examples/9write.c spfs/trunk/libspclient/readnb.c spfs/trunk/libspclient/writenb.c Added Paths: ----------- spfs/trunk/libspclient/examples/9readnb.c Modified: spfs/trunk/include/spclient.h =================================================================== --- spfs/trunk/include/spclient.h 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/include/spclient.h 2008-07-17 17:20:51 UTC (rev 7) @@ -54,6 +54,10 @@ int spc_dirread(Spcfid *fid, Spwstat **stat); Spwstat *spc_stat(Spcfsys *fs, char *path); int spc_wstat(Spcfsys *fs, char *path, Spwstat *wst); +int spc_readnb(Spcfid *fid, u8 *buf, u32 count, u64 offset, + void (*cb)(void *, int), void *cba); +int spc_writenb(Spcfid *fid, u8 *buf, u32 count, u64 offset, + void (*cb)(void *, int), void *cba); Spcfd *spcfd_add(Spcfid *fid, void (*notify)(Spcfd *, void *), void *aux); Spcfd *spcfd_add_fd(int fd, void (*notify)(Spcfd *, void *), void *aux); void spcfd_remove(Spcfd *spcfd); Modified: spfs/trunk/libspclient/examples/9ls.c =================================================================== --- spfs/trunk/libspclient/examples/9ls.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/examples/9ls.c 2008-07-17 17:20:51 UTC (rev 7) @@ -50,19 +50,13 @@ int i, n; int c; char *addr; - char *uname, *path; + char *path; Spuser *user; Spcfsys *fs; Spcfid *fid; Spwstat *stat; - user = sp_uid2user(geteuid()); - if (!user) { - fprintf(stderr, "cannot retrieve user %d\n", geteuid()); - exit(1); - } - - uname = user->uname; + user = sp_unix_users->uid2user(sp_unix_users, geteuid()); while ((c = getopt(argc, argv, "dp:")) != -1) { switch (c) { case 'd': @@ -70,7 +64,7 @@ break; case 'u': - uname = optarg; + user = sp_unix_users->uname2user(sp_unix_users, optarg); break; default: @@ -78,7 +72,10 @@ } } - + if (!user) { + fprintf(stderr, "cannot retrieve user\n"); + exit(1); + } if (argc - optind < 2) usage(); @@ -86,7 +83,7 @@ addr = argv[optind]; path = argv[optind+1]; - fs = spc_netmount(addr, uname, 564); + fs = spc_netmount(addr, user, 564, NULL, NULL); fid = spc_open(fs, path, Oread); if (!fid) { Modified: spfs/trunk/libspclient/examples/9read.c =================================================================== --- spfs/trunk/libspclient/examples/9read.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/examples/9read.c 2008-07-17 17:20:51 UTC (rev 7) @@ -47,19 +47,13 @@ int i, n, off; int c; char *addr; - char *uname, *path; + char *path; Spuser *user; Spcfsys *fs; Spcfid *fid; char buf[512]; - user = sp_uid2user(geteuid()); - if (!user) { - fprintf(stderr, "cannot retrieve user %d\n", geteuid()); - exit(1); - } - - uname = user->uname; + user = sp_unix_users->uid2user(sp_unix_users, geteuid()); while ((c = getopt(argc, argv, "dp:")) != -1) { switch (c) { case 'd': @@ -67,15 +61,18 @@ break; case 'u': - uname = optarg; + user = sp_unix_users->uname2user(sp_unix_users, optarg); break; default: usage(); } } - + if (!user) { + fprintf(stderr, "cannot retrieve user %d\n", geteuid()); + exit(1); + } if (argc - optind < 2) usage(); @@ -83,7 +80,7 @@ addr = argv[optind]; path = argv[optind+1]; - fs = spc_netmount(addr, uname, 564); + fs = spc_netmount(addr, user, 564, NULL, NULL); fid = spc_open(fs, path, Oread); if (!fid) { fprintf(stderr, "cannot open\n"); Modified: spfs/trunk/libspclient/examples/9read2.c =================================================================== --- spfs/trunk/libspclient/examples/9read2.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/examples/9read2.c 2008-07-17 17:20:51 UTC (rev 7) @@ -73,18 +73,12 @@ { int c; char *addr; - char *uname, *path; + char *path; Spuser *user; Spcfsys *fs; Spcfid *fid; - user = sp_uid2user(geteuid()); - if (!user) { - fprintf(stderr, "cannot retrieve user %d\n", geteuid()); - exit(1); - } - - uname = user->uname; + user = sp_unix_users->uid2user(sp_unix_users, geteuid()); while ((c = getopt(argc, argv, "dp:")) != -1) { switch (c) { case 'd': @@ -92,15 +86,18 @@ break; case 'u': - uname = optarg; + user = sp_unix_users->uname2user(sp_unix_users, optarg); break; default: usage(); } } - + if (!user) { + fprintf(stderr, "cannot retrieve user %d\n", geteuid()); + exit(1); + } if (argc - optind < 2) usage(); @@ -108,7 +105,7 @@ addr = argv[optind]; path = argv[optind+1]; - fs = spc_netmount(addr, uname, 564); + fs = spc_netmount(addr, user, 564, NULL, NULL); fid = spc_open(fs, path, Oread); if (!fid) { fprintf(stderr, "cannot open\n"); Added: spfs/trunk/libspclient/examples/9readnb.c =================================================================== --- spfs/trunk/libspclient/examples/9readnb.c (rev 0) +++ spfs/trunk/libspclient/examples/9readnb.c 2008-07-17 17:20:51 UTC (rev 7) @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2005 by Latchesar Ionkov <lu...@io...> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#define _XOPEN_SOURCE 600 +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <assert.h> + +#include "spfs.h" +#include "spclient.h" + +#define BSIZE 8192 + +extern int spc_chatty; + +static int done; +static Spcfid *fid; +static u64 offset; +static u8 buf1[BSIZE]; +static u8 buf2[BSIZE]; +static u8 buf3[BSIZE]; +static u8 buf4[BSIZE]; +static int cnt; + +static int readnb(void *buf); + +static void +usage() +{ + fprintf(stderr, "9readnb -d addr path\n"); + exit(1); +} + +static void +cb(void *a, int count) +{ + u8 *buf; + + buf = a; + fprintf(stderr, "cb %d\n", count); + if (count < 0) { + fprintf(stderr, "error\n"); + done++; + } else if (count > 0) { + write(1, buf, count); + cnt += count; + fprintf(stderr, "%d\n", cnt); + readnb(buf); + } else + done++; +} + +static int +readnb(void *buf) +{ + u64 off; + + off = offset; + offset += BSIZE; + + if (spc_readnb(fid, buf, BSIZE, off, cb, buf) < 0) + return -1; + + return 0; +} + +int +main(int argc, char **argv) +{ + int ecode; + int c; + char *addr; + char *ename, *path; + Spuser *user; + Spcfsys *fs; + + user = sp_unix_users->uid2user(sp_unix_users, geteuid()); + while ((c = getopt(argc, argv, "dp:")) != -1) { + switch (c) { + case 'd': + spc_chatty = 1; + break; + + case 'u': + user = sp_unix_users->uname2user(sp_unix_users, optarg); + break; + + default: + usage(); + } + } + + if (!user) { + fprintf(stderr, "cannot retrieve user %d\n", geteuid()); + exit(1); + } + + if (argc - optind < 2) + usage(); + + addr = argv[optind]; + path = argv[optind+1]; + + fs = spc_netmount(addr, user, 564, NULL, NULL); + fid = spc_open(fs, path, Oread); + if (!fid) { + fprintf(stderr, "cannot open\n"); + exit(1); + } + + if (readnb(buf1) < 0) + goto error; + + if (readnb(buf2) < 0) + goto error; + + if (readnb(buf3) < 0) + goto error; + + if (readnb(buf4) < 0) + goto error; + + while (done < 4) + sp_poll_once(); + + spc_close(fid); + spc_umount(fs); + + return 0; + +error: + sp_rerror(&ename, &ecode); + fprintf(stderr, "Error: %s\n", ename); + return -1; + +} + Modified: spfs/trunk/libspclient/examples/9write.c =================================================================== --- spfs/trunk/libspclient/examples/9write.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/examples/9write.c 2008-07-17 17:20:51 UTC (rev 7) @@ -47,19 +47,13 @@ int i, n, off; int c; char *addr; - char *uname, *path; + char *path; Spuser *user; Spcfsys *fs; Spcfid *fid; char buf[512]; - user = sp_uid2user(geteuid()); - if (!user) { - fprintf(stderr, "cannot retrieve user %d\n", geteuid()); - exit(1); - } - - uname = user->uname; + user = sp_unix_users->uid2user(sp_unix_users, geteuid()); while ((c = getopt(argc, argv, "dp:")) != -1) { switch (c) { case 'd': @@ -67,15 +61,18 @@ break; case 'u': - uname = optarg; + user = sp_unix_users->uname2user(sp_unix_users, optarg); break; default: usage(); } } - + if (!user) { + fprintf(stderr, "cannot retrieve user %d\n", geteuid()); + exit(1); + } if (argc - optind < 2) usage(); @@ -83,7 +80,7 @@ addr = argv[optind]; path = argv[optind+1]; - fs = spc_netmount(addr, uname, 564); + fs = spc_netmount(addr, user, 564, NULL, NULL); fid = spc_open(fs, path, Owrite); if (!fid) { fid = spc_create(fs, path, 0666, Owrite); Modified: spfs/trunk/libspclient/readnb.c =================================================================== --- spfs/trunk/libspclient/readnb.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/readnb.c 2008-07-17 17:20:51 UTC (rev 7) @@ -49,7 +49,6 @@ int n; Spcfid *fid; Spcfsys *fs; - Spfcall *fc; fid = r->fid; fs = fid->fsys; @@ -58,12 +57,12 @@ if (n == 0) n = fs->msize - IOHDRSZ; - if (n > (r->count - r->offset)) - n = r->count - r->offset; + if (n > r->count) + n = r->count; r->tc = sp_create_tread(fid->fid, r->offset, n); if (spc_rpcnb(fs, r->tc, spc_read_cb, r) < 0) { - free(fc); + free(r->tc); return -1; } @@ -73,29 +72,24 @@ static void spc_read_cb(void *cba, Spfcall *rc) { - int ecode; - char *ename; + int n; Spcread *r; r = cba; free(r->tc); - sp_rerror(&ename, &ecode); - if (ename) { + if (sp_haserror()) { + free(rc); (*r->cb)(r->cba, -1); return; } - memmove(r->buf + r->offset, rc->data, rc->count); - r->offset += rc->count; - if (!rc->count || r->offset==r->count) { - (*r->cb)(r->cba, r->offset); - free(rc); - return; - } + n = rc->count; + if (n > r->count) + n = r->count; + memmove(r->buf, rc->data, n); + (*r->cb)(r->cba, n); free(rc); - if (spc_send_read_request(r) < 0) - (*r->cb)(r->cba, -1); } int @@ -109,13 +103,17 @@ return -1; r->fid = fid; - r->offset = 0; + r->offset = offset; r->count = count; r->buf = buf; r->cb = cb; r->cba = cba; r->tc = NULL; - spc_send_read_request(r); + if (spc_send_read_request(r) < 0) { + free(r); + return -1; + } + return 0; } Modified: spfs/trunk/libspclient/writenb.c =================================================================== --- spfs/trunk/libspclient/writenb.c 2008-05-05 16:54:51 UTC (rev 6) +++ spfs/trunk/libspclient/writenb.c 2008-07-17 17:20:51 UTC (rev 7) @@ -49,7 +49,6 @@ int n; Spcfid *fid; Spcfsys *fs; - Spfcall *fc; fid = r->fid; fs = fid->fsys; @@ -58,12 +57,12 @@ if (n == 0) n = fs->msize - IOHDRSZ; - if (n > (r->count - r->offset)) - n = r->count - r->offset; + if (n > r->count) + n = r->count; r->tc = sp_create_twrite(fid->fid, r->offset, n, r->buf + r->offset); if (spc_rpcnb(fs, r->tc, spc_write_cb, r) < 0) { - free(fc); + free(r->tc); return -1; } @@ -73,28 +72,22 @@ static void spc_write_cb(void *cba, Spfcall *rc) { - int ecode; - char *ename; + int n; Spcwrite *r; r = cba; free(r->tc); - sp_rerror(&ename, &ecode); - if (ename) { + if (sp_haserror()) { (*r->cb)(r->cba, -1); return; } - r->offset += rc->count; - if (!rc->count || r->offset==r->count) { - (*r->cb)(r->cba, r->offset); - free(rc); - return; - } + n = rc->count; + if (n > r->count) + n = r->count; + (*r->cb)(r->cba, n); free(rc); - if (spc_send_write_request(r) < 0) - (*r->cb)(r->cba, -1); } int @@ -115,6 +108,10 @@ r->cba = cba; r->tc = NULL; - spc_send_write_request(r); + if (spc_send_write_request(r) < 0) { + free(r); + return -1; + } + return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <li...@us...> - 2008-05-05 16:55:07
|
Revision: 6 http://npfs.svn.sourceforge.net/npfs/?rev=6&view=rev Author: lionkov Date: 2008-05-05 09:54:51 -0700 (Mon, 05 May 2008) Log Message: ----------- add files missing from the previous checkin Added Paths: ----------- spfs/trunk/libspclient/wstat.c Added: spfs/trunk/libspclient/wstat.c =================================================================== --- spfs/trunk/libspclient/wstat.c (rev 0) +++ spfs/trunk/libspclient/wstat.c 2008-05-05 16:54:51 UTC (rev 6) @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 by Latchesar Ionkov <lu...@io...> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include "spfs.h" +#include "spclient.h" +#include "spcimpl.h" + +int +spc_wstat(Spcfsys *fs, char *path, Spwstat *wst) +{ + Spfcall *tc, *rc; + Spcfid *fid; + Spwstat *st; + + st = NULL; + fid = spc_walk(fs, path); + if (!fid) + return -1; + + tc = sp_create_twstat(fid->fid, wst, fs->dotu); + if (spc_rpc(fs, tc, &rc) < 0) { + free(tc); + spc_close(fid); + return -1; + } + + free(tc); + free(rc); + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <li...@us...> - 2008-05-05 16:53:06
|
Revision: 5 http://npfs.svn.sourceforge.net/npfs/?rev=5&view=rev Author: lionkov Date: 2008-05-05 09:53:12 -0700 (Mon, 05 May 2008) Log Message: ----------- add files missing from the previous patch. Added Paths: ----------- npfs/trunk/libnpfs/fcall.c npfs/trunk/libnpfs/pvusers.c npfs/trunk/libnpfs/uxusers.c Added: npfs/trunk/libnpfs/fcall.c =================================================================== --- npfs/trunk/libnpfs/fcall.c (rev 0) +++ npfs/trunk/libnpfs/fcall.c 2008-05-05 16:53:12 UTC (rev 5) @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2005 by Latchesar Ionkov <lu...@io...> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <pthread.h> +#include <errno.h> +#include <assert.h> +#include "npfs.h" +#include "npfsimpl.h" + +char *Eunknownfid = "unknown fid"; +char *Ennomem = "no memory"; /* avoid conflict with libspfs' Enomem */ +char *Enoauth = "no authentication required"; +char *Enotimpl = "not implemented"; +char *Einuse = "fid already exists"; +char *Ebadusefid = "bad use of fid"; +char *Enotdir = "not a directory"; +char *Etoomanywnames = "too many wnames"; +char *Eperm = "permission denied"; +char *Etoolarge = "i/o count too large"; +char *Ebadoffset = "bad offset in directory read"; +char *Edirchange = "cannot convert between files and directories"; +char *Enotfound = "file not found"; +char *Eopen = "file alread exclusively opened"; +char *Eexist = "file or directory already exists"; +char *Enotempty = "directory not empty"; +char *Eunknownuser = "unknown user"; + +Npfcall * +np_version(Npreq *req, Npfcall *tc) +{ + if (tc->msize < IOHDRSZ + 1) { + np_werror("msize too small", EIO); + return NULL; + } + + return (*req->conn->srv->version)(req->conn, tc->msize, &tc->version); +} + +Npfcall * +np_auth(Npreq *req, Npfcall *tc) +{ + int n; + char *uname, *aname; + Npconn *conn; + Npsrv *srv; + Npfid *afid; + Npfcall *rc; + Npuser *user; + Npqid aqid; + + rc = NULL; + aname = NULL; + conn = req->conn; + srv = conn->srv; + afid = np_fid_find(conn, tc->afid); + if (afid) { + np_werror(Einuse, EIO); + goto done; + } + + afid = np_fid_create(conn, tc->afid, NULL); + if (!afid) + goto done; + else + np_fid_incref(afid); + + if (tc->uname.len && tc->n_uname==~0) { + uname = np_strdup(&tc->uname); + if (!uname) + goto done; + + user = (*srv->upool->uname2user)(srv->upool, uname); + free(uname); + if (!user) { + np_werror(Eunknownuser, EIO); + goto done; + } + tc->n_uname = user->uid; + } else { + user = (*srv->upool->uid2user)(srv->upool, tc->n_uname); + if (!user) { + np_werror(Eunknownuser, EIO); + goto done; + } + } + + if (tc->aname.len) { + aname = np_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 = np_create_rauth(&aqid); + } else + np_werror(Enoauth, EIO); +done: + free(aname); + if (!rc) + np_fid_decref(afid); + return rc; +} + +Npfcall * +np_attach(Npreq *req, Npfcall *tc) +{ + char *uname, *aname; + Npconn *conn; + Npsrv *srv; + Npfid *fid, *afid; + Npfcall *rc; + Npuser *user; + + rc = NULL; + aname = NULL; + conn = req->conn; + srv = conn->srv; + afid = NULL; + fid = np_fid_find(conn, tc->fid); + if (fid) { + np_werror(Einuse, EIO); + goto done; + } + + fid = np_fid_create(conn, tc->fid, NULL); + if (!fid) + goto done; + else + np_fid_incref(fid); + + req->fid = fid; + afid = np_fid_find(conn, tc->afid); + if (!afid) { + if (tc->afid!=NOFID) { + np_werror(Eunknownfid, EIO); + goto done; + } + + if (!afid->type&Qtauth) { + np_werror(Ebadusefid, EIO); + goto done; + } + } else + np_fid_incref(afid); + + if (tc->uname.len && tc->n_uname==~0) { + uname = np_strdup(&tc->uname); + if (!uname) + goto done; + + user = srv->upool->uname2user(srv->upool, uname); + free(uname); + if (!user) { + np_werror(Eunknownuser, EIO); + goto done; + } + + tc->n_uname = user->uid; + } else { + user = srv->upool->uid2user(srv->upool, tc->n_uname); + if (!user) { + np_werror(Eunknownuser, EIO); + goto done; + } + } + + fid->user = user; + if (tc->aname.len) { + aname = np_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); + +done: + free(aname); + np_fid_decref(afid); + return rc; +} + +Npfcall* +np_flush(Npreq *req, Npfcall *tc) +{ + u16 oldtag; + Npreq *creq; + Npconn *conn; + Npfcall *ret; + + ret = NULL; + conn = req->conn; + oldtag = tc->oldtag; + pthread_mutex_lock(&conn->srv->lock); + // check pending requests + for(creq = conn->srv->reqs_first; creq != NULL; creq = creq->next) { + if (creq->conn==conn && creq->tag==oldtag) { + np_srv_remove_req(conn->srv, creq); + pthread_mutex_lock(&creq->lock); + np_conn_respond(creq); /* doesn't send anything */ + pthread_mutex_unlock(&creq->lock); + np_req_unref(creq); + ret = np_create_rflush(); + creq = NULL; + goto done; + } + } + + // check working requests + creq = conn->srv->workreqs; + while (creq != NULL) { + if (creq->conn==conn && creq->tag==oldtag) { + np_req_ref(creq); + pthread_mutex_lock(&creq->lock); + req->flushreq = creq->flushreq; + creq->flushreq = req; + pthread_mutex_unlock(&creq->lock); + goto done; + } + creq = creq->next; + } + + // if not found, return Rflush + if (!creq) + ret = np_create_rflush(); + +done: + pthread_mutex_unlock(&conn->srv->lock); + + // if working request found, try to flush it + if (creq && req->conn->srv->flush) { + (*req->conn->srv->flush)(creq); + np_req_unref(creq); + } + + return ret; +} + +Npfcall * +np_walk(Npreq *req, Npfcall *tc) +{ + int i; + Npconn *conn; + Npfid *fid, *newfid; + Npfcall *rc; + Npqid wqids[MAXWELEM]; + + rc = NULL; + conn = req->conn; + newfid = NULL; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (!fid->type&Qtdir) { + np_werror(Enotdir, ENOTDIR); + goto done; + } + + if (fid->omode != (u16) ~0) { + np_werror(Ebadusefid, EIO); + goto done; + } + + if (tc->nwname > MAXWELEM) { + np_werror(Etoomanywnames, EIO); + goto done; + } + + if (tc->fid != tc->newfid) { + newfid = np_fid_find(conn, tc->newfid); + if (newfid) { + np_werror(Einuse, EIO); + goto done; + } + newfid = np_fid_create(conn, tc->newfid, NULL); + if (!newfid) { + np_werror(Ennomem, ENOMEM); + goto done; + } + + if (!(*conn->srv->clone)(fid, newfid)) + goto done; + + np_user_incref(fid->user); + newfid->user = fid->user; + newfid->type = fid->type; + } else + newfid = fid; + + np_fid_incref(newfid); + for(i = 0; i < tc->nwname;) { + if (!(*conn->srv->walk)(newfid, &tc->wnames[i], &wqids[i])) + break; + + newfid->type = wqids[i].type; + i++; + + if (i<(tc->nwname) && !newfid->type&Qtdir) + break; + } + + if (i==0 && tc->nwname!=0) + goto done; + + np_werror(NULL, 0); + if (tc->fid != tc->newfid) + np_fid_incref(newfid); + rc = np_create_rwalk(i, wqids); + +done: + np_fid_decref(newfid); + return rc; +} + +Npfcall * +np_open(Npreq *req, Npfcall *tc) +{ + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (fid->omode != (u16)~0) { + np_werror(Ebadusefid, EIO); + goto done; + } + + if (fid->type&Qtdir && tc->mode != Oread) { + np_werror(Eperm, EPERM); + goto done; + } + + rc = (*conn->srv->open)(fid, tc->mode); + fid->omode = tc->mode; +done: +// np_fid_decref(fid); + return rc; +} + +Npfcall * +np_create(Npreq *req, Npfcall *tc) +{ + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (fid->omode != (u16)~0) { + np_werror(Ebadusefid, EIO); + goto done; + } + + if (!fid->type&Qtdir) { + np_werror(Enotdir, ENOTDIR); + goto done; + } + + if (tc->perm&Dmdir && tc->mode!=Oread) { + np_werror(Eperm, EPERM); + goto done; + } + + if (tc->perm&(Dmnamedpipe|Dmsymlink|Dmlink|Dmdevice|Dmsocket) + && !fid->conn->dotu) { + np_werror(Eperm, EPERM); + goto done; + } + + rc = (*conn->srv->create)(fid, &tc->name, tc->perm, tc->mode, + &tc->extension); + if (rc && rc->type == Rcreate) { + fid->omode = tc->mode; + fid->type = rc->qid.type; + } + +done: +// np_fid_decref(fid); + return rc; +} + +Npfcall * +np_read(Npreq *req, Npfcall *tc) +{ + int n; + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (tc->count+IOHDRSZ > conn->msize) { + np_werror(Etoolarge, EIO); + goto done; + } + + if (fid->type&Qtauth) { + if (conn->srv->auth) { + rc = np_alloc_rread(tc->count); + if (!rc) + goto done; + + n = conn->srv->auth->read(fid, tc->offset, tc->count, rc->data); + if (n >= 0) + np_set_rread_count(rc, n); + else { + free(rc); + rc = NULL; + } + } else + np_werror(Ebadusefid, EIO); + + goto done; + } + + if (fid->omode==(u16)~0 || (fid->omode&3)==Owrite) { + np_werror(Ebadusefid, EIO); + goto done; + } + + if (fid->type&Qtdir && tc->offset != fid->diroffset) { + np_werror(Ebadoffset, EIO); + goto done; + } + + rc = (*conn->srv->read)(fid, tc->offset, tc->count, req); + +done: + return rc; +} + +Npfcall * +np_write(Npreq *req, Npfcall *tc) +{ + int n; + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (fid->type&Qtauth) { + if (conn->srv->auth) { + n = conn->srv->auth->write(fid, tc->offset, + tc->count, tc->data); + if (n >= 0) + rc = np_create_rwrite(n); + + goto done; + } else { + np_werror(Ebadusefid, EIO); + goto done; + } + } + + if (fid->omode==(u16)~0 || fid->type&Qtdir || (fid->omode&3)==Oread) { + np_werror(Ebadusefid, EIO); + goto done; + } + + if (tc->count+IOHDRSZ > conn->msize) { + np_werror(Etoolarge, EIO); + goto done; + } + + rc = (*conn->srv->write)(fid, tc->offset, tc->count, tc->data, req); + +done: + return rc; +} + +Npfcall * +np_clunk(Npreq *req, Npfcall *tc) +{ + int n; + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (fid->type&Qtauth) { + if (conn->srv->auth) { + n = conn->srv->auth->clunk(fid); + if (n) + rc = np_create_rclunk(); + } else + np_werror(Ebadusefid, EIO); + + goto done; + } + + if (fid->omode!=(u16)~0 && fid->omode==Orclose) { + rc = (*conn->srv->remove)(fid); + if (rc->type == Rerror) + goto done; + free(rc); + rc = np_create_rclunk(); + } else + rc = (*conn->srv->clunk)(fid); + + if (rc && rc->type == Rclunk) + np_fid_decref(fid); + +done: + return rc; +} + +Npfcall * +np_remove(Npreq *req, Npfcall *tc) +{ + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + rc = (*conn->srv->remove)(fid); + if (rc && rc->type == Rremove) + np_fid_decref(fid); + +done: + return rc; +} + +Npfcall * +np_stat(Npreq *req, Npfcall *tc) +{ + Npconn *conn; + Npfid *fid; + Npfcall *rc; + + rc = NULL; + conn = req->conn; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + rc = (*conn->srv->stat)(fid); + +done: +// np_fid_decref(fid); + return rc; +} + +Npfcall * +np_wstat(Npreq *req, Npfcall *tc) +{ + Npconn *conn; + Npfid *fid; + Npfcall *rc; + Npstat *stat; + + rc = NULL; + conn = req->conn; + stat = &tc->stat; + fid = np_fid_find(conn, tc->fid); + if (!fid) { + np_werror(Eunknownfid, EIO); + goto done; + } else + np_fid_incref(fid); + + req->fid = fid; + if (stat->type != (u16)~0 || stat->dev != (u32)~0 + || stat->qid.version != (u32)~0 + || stat->qid.path != (u64)~0 ) { + np_werror(Eperm, EPERM); + goto done; + } + + if ((fid->type&Qtdir && !stat->mode&Dmdir) + || (!fid->type&Qtdir&&stat->mode&Dmdir)) { + np_werror(Edirchange, EPERM); + goto done; + } + + rc = (*conn->srv->wstat)(fid, &tc->stat); +done: +// np_fid_decref(fid); + return rc; +} Added: npfs/trunk/libnpfs/pvusers.c =================================================================== --- npfs/trunk/libnpfs/pvusers.c (rev 0) +++ npfs/trunk/libnpfs/pvusers.c 2008-05-05 16:53:12 UTC (rev 5) @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2006 by Latchesar Ionkov <lu...@io...> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pwd.h> +#include <grp.h> +#include <errno.h> +#include <pthread.h> +#include "npfs.h" +#include "npfsimpl.h" + +typedef struct Upool Upool; + +struct Upool { + pthread_mutex_t lock; + Npuser* users; + Npgroup* groups; +}; + +static char *Euserexists = "user exists"; +static char *Egroupexists = "group exists"; + +static Npuser *np_priv_uname2user(Npuserpool *up, char *uname); +static Npuser *np_priv_uid2user(Npuserpool *up, u32 uid); +static Npgroup *np_priv_gname2group(Npuserpool *up, char *gname); +static Npgroup *np_priv_gid2group(Npuserpool *up, u32 gid); +static int np_priv_ismember(Npuserpool *up, Npuser *u, Npgroup *g); +static void np_priv_udestroy(Npuserpool *up, Npuser *); +static void np_priv_gdestroy(Npuserpool *up, Npgroup *); + +Npuserpool * +np_priv_userpool_create() +{ + Npuserpool *up; + Upool *upp; + + up = np_malloc(sizeof(Npuserpool) + sizeof(Upool)); + if (!up) + return NULL; + + upp = (Upool *) ((char *)up + sizeof(Npuserpool)); + pthread_mutex_init(&upp->lock, NULL); + upp->users = NULL; + upp->groups = NULL; + + up->aux = upp; + up->uname2user = np_priv_uname2user; + up->uid2user = np_priv_uid2user; + up->gname2group = np_priv_gname2group; + up->gid2group = np_priv_gid2group; + up->ismember = np_priv_ismember; + up->udestroy = np_priv_udestroy; + up->gdestroy = np_priv_gdestroy; + + return up; +} + +Npuser * +np_priv_user_add(Npuserpool *up, char *uname, u32 uid, void *aux) +{ + Npuser *u; + Upool *upp; + + upp = up->aux; + u = up->uname2user(up, uname); + if (u) { + np_user_decref(u); + np_werror("%s:%s", EIO, uname, Euserexists); + return NULL; + } + + u = up->uid2user(up, uid); + if (u) { + np_user_decref(u); + np_werror("%d:%s", EIO, uid, Euserexists); + return NULL; + } + + u = np_malloc(sizeof(*u) + strlen(uname) + 1); + if (!u) + return NULL; + + u->refcount = 1; + u->upool = up; + u->uid = uid; + u->uname = (char *)u + sizeof(*u); + strcpy(u->uname, uname); + u->dfltgroup = NULL; + u->ngroups = 0; + u->groups = NULL; + u->aux = aux; + pthread_mutex_init(&u->lock, NULL); + pthread_mutex_lock(&upp->lock); + u->next = upp->users; + upp->users = u; + pthread_mutex_unlock(&upp->lock); + + np_user_incref(u); + return u; +} + +void np_priv_user_del(Npuser *u) +{ + Npuser *tu, *pu; + Upool *upp; + + upp = u->upool->aux; + + if (!upp->users) + return; + + pthread_mutex_lock(&upp->lock); + for(pu = NULL, tu = upp->users; tu != NULL; pu = tu, tu = tu->next) + if (tu == u) + break; + + if (!pu) + upp->users = u->next; + else + pu->next = u->next; + pthread_mutex_unlock(&upp->lock); + + np_user_decref(u); +} + +int +np_priv_user_setdfltgroup(Npuser *u, Npgroup *g) +{ + if (u->dfltgroup) + np_group_decref(u->dfltgroup); + + u->dfltgroup = g; /* refcount should be adjusted already */ + return 0; +} + +Npgroup * +np_priv_group_add(Npuserpool *up, char *gname, u32 gid) +{ + Npgroup *g; + Upool *upp; + + upp = up->aux; + g = up->gname2group(up, gname); + if (g) { + np_group_decref(g); + np_werror("%s:%s", EIO, gname, Egroupexists); + return NULL; + } + + g = up->gid2group(up, gid); + if (g) { + np_group_decref(g); + np_werror("%d:%s", EIO, gid, Egroupexists); + return NULL; + } + + g = np_malloc(sizeof(*g) + strlen(gname) + 1); + if (!g) + return NULL; + + g->refcount = 1; + g->upool = up; + g->gid = gid; + g->gname = (char *)g + sizeof(*g); + if (pthread_mutex_init(&g->lock, 0)){ + fprintf(stderr, "%s: pthread_mutex_init failed\n", __FUNCTION__); + exit(1); + } + strcpy(g->gname, gname); + + pthread_mutex_lock(&upp->lock); + g->next = upp->groups; + upp->groups = g; + pthread_mutex_unlock(&upp->lock); + + np_group_incref(g); + return g; +} + +void +np_priv_group_del(Npgroup *g) +{ + Npgroup *tg, *pg; + Upool *upp; + + upp = g->upool->aux; + + if (!upp->groups) + return; + + pthread_mutex_lock(&upp->lock); + for(pg = NULL, tg = upp->groups; tg != NULL; pg = tg, tg = tg->next) + if (tg == g) + break; + + if (!pg) + upp->groups = g->next; + else + pg->next = g->next; + + pthread_mutex_unlock(&upp->lock); + np_group_decref(g); +} + +int +np_priv_group_adduser(Npgroup *g, Npuser *u) +{ + Npgroup **grps; + + if (u->upool->ismember(u->upool, u, g)) + return 0; + + pthread_mutex_lock(&g->lock); + grps = realloc(u->groups, sizeof(Npgroup *) * (u->ngroups + 1)); + if (!grps) { + np_werror(Ennomem, ENOMEM); + pthread_mutex_unlock(&g->lock); + return -1; + } + + grps[u->ngroups] = g; /* refcount should be updated already */ + u->ngroups++; + u->groups = grps; + pthread_mutex_unlock(&g->lock); + return 0; +} + +int +np_priv_group_deluser(Npgroup *g, Npuser *u) +{ + int i; + + pthread_mutex_lock(&g->lock); + for(i = 0; i < u->ngroups; i++) + if (u->groups[i] == g) { + memmove(&u->groups[i], &u->groups[i+1], + sizeof(Npgroup*) * (u->ngroups - i - 1)); + + u->ngroups--; + break; + } + pthread_mutex_lock(&g->lock); + + return 0; +} + +static Npuser * +np_priv_uname2user(Npuserpool *up, char *uname) +{ + Npuser *u; + Upool *upp; + + upp = up->aux; + pthread_mutex_lock(&upp->lock); + for(u = upp->users; u != NULL; u = u->next) + if (strcmp(u->uname, uname) == 0) { + np_user_incref(u); + break; + } + pthread_mutex_unlock(&upp->lock); + + return u; +} + +static Npuser * +np_priv_uid2user(Npuserpool *up, u32 uid) +{ + Npuser *u; + Upool *upp; + + upp = up->aux; + pthread_mutex_lock(&upp->lock); + for(u = upp->users; u != NULL; u = u->next) + if (u->uid == uid) { + np_user_incref(u); + break; + } + pthread_mutex_unlock(&upp->lock); + + return u; +} + +static Npgroup * +np_priv_gname2group(Npuserpool *up, char *gname) +{ + Npgroup *g; + Upool *upp; + + upp = up->aux; + pthread_mutex_lock(&upp->lock); + for(g = upp->groups; g != NULL; g = g->next) + if (strcmp(g->gname, gname) == 0) { + np_group_incref(g); + break; + } + pthread_mutex_unlock(&upp->lock); + + return g; +} + +static Npgroup * +np_priv_gid2group(Npuserpool *up, u32 gid) +{ + Npgroup *g; + Upool *upp; + + upp = up->aux; + pthread_mutex_lock(&upp->lock); + for(g = upp->groups; g != NULL; g = g->next) + if (g->gid == gid) { + np_group_incref(g); + break; + } + pthread_mutex_unlock(&upp->lock); + + return g; +} + +static int +np_priv_ismember(Npuserpool *up, Npuser *u, Npgroup *g) +{ + int i; + + pthread_mutex_lock(&u->lock); + for(i = 0; i < u->ngroups; i++) + if (u->groups[i] == g) { + pthread_mutex_unlock(&u->lock); + return 1; + } + + pthread_mutex_unlock(&u->lock); + return 0; +} + +static void +np_priv_udestroy(Npuserpool *up, Npuser *u) +{ +} + +static void +np_priv_gdestroy(Npuserpool *up, Npgroup *g) +{ +} Added: npfs/trunk/libnpfs/uxusers.c =================================================================== --- npfs/trunk/libnpfs/uxusers.c (rev 0) +++ npfs/trunk/libnpfs/uxusers.c 2008-05-05 16:53:12 UTC (rev 5) @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2006 by Latchesar Ionkov <lu...@io...> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pwd.h> +#include <grp.h> +#include <errno.h> +#include <pthread.h> +#include "npfs.h" +#include "npfsimpl.h" + +static Npuser *np_unix_uname2user(Npuserpool *, char *uname); +static Npuser *np_unix_uid2user(Npuserpool *, u32 uid); +static Npgroup *np_unix_gname2group(Npuserpool *, char *gname); +static Npgroup *np_unix_gid2group(Npuserpool *, u32 gid); +static int np_unix_ismember(Npuserpool *, Npuser *u, Npgroup *g); +static void np_unix_udestroy(Npuserpool *, Npuser *); +static void np_unix_gdestroy(Npuserpool *, Npgroup *); +static int np_init_user_groups(Npuser *u); + +static Npuserpool upool = { + .uname2user = np_unix_uname2user, + .uid2user = np_unix_uid2user, + .gname2group = np_unix_gname2group, + .gid2group = np_unix_gid2group, + .ismember = np_unix_ismember, + .udestroy = np_unix_udestroy, + .gdestroy = np_unix_gdestroy, +}; + +Npuserpool *np_unix_users = &upool; + +static struct Npusercache { + int init; + int hsize; + Npuser** htable; + pthread_mutex_t lock; +} usercache = { 0 }; + +static struct Npgroupcache { + int init; + int hsize; + Npgroup** htable; + pthread_mutex_t lock; +} groupcache = { 0 }; + +static void +initusercache(void) +{ + if (!usercache.init) { + usercache.hsize = 64; + usercache.htable = calloc(usercache.hsize, sizeof(Npuser *)); + usercache.init = 1; + + } +} + +static void +initgroupcache(void) +{ + if (!groupcache.init) { + groupcache.hsize = 64; + groupcache.htable = calloc(groupcache.hsize, sizeof(Npgroup *)); + if (!groupcache.htable) { + np_werror(Ennomem, ENOMEM); + return; + } + groupcache.init = 1; + } +} + +static Npuser * +np_unix_uname2user(Npuserpool *up, char *uname) +{ + int i, n; + struct passwd pw, *pwp; + int bufsize; + char *buf; + Npuser *u; + + pthread_mutex_lock(&usercache.lock); + if (!usercache.init) + initusercache(); + + for(i = 0; i<usercache.hsize; i++) + for(u = usercache.htable[i]; u != NULL; u = u->next) + if (strcmp(uname, u->uname) == 0) + break; + pthread_mutex_unlock(&usercache.lock); + + if (u) + goto done; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize < 256) + bufsize = 256; + + buf = np_malloc(bufsize); + if (!buf) + return NULL; + + i = getpwnam_r(uname, &pw, buf, bufsize, &pwp); + if (i) { + np_uerror(i); + free(buf); + return NULL; + } + + u = np_malloc(sizeof(*u) + strlen(pw.pw_name) + 1); + if (!u) { + free(buf); + return NULL; + } + + pthread_mutex_init(&u->lock, NULL); + u->refcount = 1; + u->upool = up; + u->uid = pw.pw_uid; + u->uname = (char *)u + sizeof(*u); + strcpy(u->uname, pw.pw_name); + u->dfltgroup = (*up->gid2group)(up, pw.pw_gid); + + u->ngroups = 0; + u->groups = NULL; + np_init_user_groups(u); + free(buf); + + pthread_mutex_lock(&usercache.lock); + n = u->uid % usercache.hsize; + u->next = usercache.htable[n]; + usercache.htable[n] = u; + pthread_mutex_unlock(&usercache.lock); + +done: + np_user_incref(u); + return u; +} + +static Npuser * +np_unix_uid2user(Npuserpool *up, u32 uid) +{ + int n, i; + Npuser *u; + struct passwd pw, *pwp; + int bufsize; + char *buf; + + pthread_mutex_lock(&usercache.lock); + if (!usercache.init) + initusercache(); + + n = uid % usercache.hsize; + for(u = usercache.htable[n]; u != NULL; u = u->next) + if (u->uid == uid) + break; + pthread_mutex_unlock(&usercache.lock); + + if (u) + goto done; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize < 256) + bufsize = 256; + + buf = np_malloc(bufsize); + if (!buf) + return NULL; + + i = getpwuid_r(uid, &pw, buf, bufsize, &pwp); + if (i) { + np_uerror(i); + free(buf); + return NULL; + } + + u = np_malloc(sizeof(*u) + strlen(pw.pw_name) + 1); + if (!u) { + free(buf); + return NULL; + } + + pthread_mutex_init(&u->lock, NULL); + u->refcount = 1; + u->upool = up; + u->uid = uid; + u->uname = (char *)u + sizeof(*u); + strcpy(u->uname, pw.pw_name); + u->dfltgroup = up->gid2group(up, pw.pw_gid); + + u->ngroups = 0; + u->groups = NULL; + np_init_user_groups(u); + free(buf); + + pthread_mutex_lock(&usercache.lock); + u->next = usercache.htable[n]; + usercache.htable[n] = u; + pthread_mutex_unlock(&usercache.lock); + +done: + np_user_incref(u); + return u; +} + +static Npgroup * +np_unix_gname2group(Npuserpool *up, char *gname) +{ + int i, n, bufsize; + Npgroup *g; + struct group grp, *pgrp; + char *buf; + + pthread_mutex_lock(&groupcache.lock); + if (!groupcache.init) + initgroupcache(); + + for(i = 0; i < groupcache.hsize; i++) + for(g = groupcache.htable[i]; g != NULL; g = g->next) + if (strcmp(g->gname, gname) == 0) + break; + pthread_mutex_unlock(&groupcache.lock); + + if (g) + goto done; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize < 256) + bufsize = 256; + + buf = np_malloc(bufsize); + if (!buf) + return NULL; + + i = getgrnam_r(gname, &grp, buf, bufsize, &pgrp); + if (i) { + np_uerror(i); + free(buf); + return NULL; + } + + g = np_malloc(sizeof(*g) + strlen(grp.gr_name) + 1); + if (!g) { + free(buf); + return NULL; + } + + g->refcount = 1; + g->upool = up; + g->gid = grp.gr_gid; + g->gname = (char *)g + sizeof(*g); + strcpy(g->gname, grp.gr_name); + + pthread_mutex_lock(&groupcache.lock); + n = g->gid % groupcache.hsize; + g->next = groupcache.htable[n]; + groupcache.htable[n] = g; + pthread_mutex_unlock(&groupcache.lock); + + free(buf); + +done: + np_group_incref(g); + return g; +} + +static Npgroup * +np_unix_gid2group(Npuserpool *up, u32 gid) +{ + int n, err; + Npgroup *g; + struct group grp, *pgrp; + int bufsize; + char *buf; + + pthread_mutex_lock(&groupcache.lock); + if (!groupcache.init) + initgroupcache(); + + n = gid % groupcache.hsize; + for(g = groupcache.htable[n]; g != NULL; g = g->next) + if (g->gid == gid) + break; + pthread_mutex_unlock(&groupcache.lock); + + if (g) + goto done; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize < 256) + bufsize = 256; + + buf = np_malloc(bufsize); + if (!buf) + return NULL; + + err = getgrgid_r(gid, &grp, buf, bufsize, &pgrp); + if (err) { + np_uerror(err); + free(buf); + return NULL; + } + + g = np_malloc(sizeof(*g) + strlen(grp.gr_name) + 1); + if (!g) { + free(buf); + return NULL; + } + + pthread_mutex_init(&g->lock, NULL); + g->refcount = 1; + g->upool = up; + g->gid = grp.gr_gid; + g->gname = (char *)g + sizeof(*g); + strcpy(g->gname, grp.gr_name); + + pthread_mutex_lock(&groupcache.lock); + g->next = groupcache.htable[n]; + groupcache.htable[n] = g; + pthread_mutex_unlock(&groupcache.lock); + + free(buf); + +done: + np_group_incref(g); + return g; +} + +static int +np_unix_ismember(Npuserpool *up, Npuser *u, Npgroup *g) +{ + int i; + + if (!u->groups && np_init_user_groups(u)<0) + return -1; + + for(i = 0; i < u->ngroups; i++) { + if (g == u->groups[i]) + return 1; + } + + return 0; +} + +static void +np_unix_udestroy(Npuserpool *up, Npuser *u) +{ +} + +static void +np_unix_gdestroy(Npuserpool *up, Npgroup *g) +{ +} + +static int +np_init_user_groups(Npuser *u) +{ + int i, n=0; + int maxgroups = 256; /* warning: configurable in kernel */ + Npgroup **grps; + struct group *g; + gid_t gids[maxgroups]; + + free(u->groups); + u->ngroups = 0; + + setgrent(); + + if(u->dfltgroup) { + gids[0] = u->dfltgroup->gid; + n++; + } + + while ((g = getgrent()) != NULL) { + for (i = 0; g->gr_mem[i]; i++) { + if (strcmp(u->uname, g->gr_mem[0]) == 0) { + n++; + if(n < maxgroups) + gids[n] = g->gr_gid; + } + } + } + + endgrent(); + + grps = np_malloc(sizeof(*grps) * n); + if (!grps) { + free(gids); + return -1; + } + + for(i = 0; i < n; i++) { + grps[i] = u->upool->gid2group(u->upool, gids[i]); + if (grps[i]) { + free(grps); + return -1; + } + } + + u->groups = grps; + u->ngroups = n; + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |