u9fs.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702
  1. /* already in plan9.h #include <sys/types.h> *//* for struct passwd, struct group, struct stat ... */
  2. /* plan9.h is first to get the large file support definitions as early as possible */
  3. #include <plan9.h>
  4. #include <sys/stat.h> /* for stat, umask */
  5. #include <stdlib.h> /* for malloc */
  6. #include <string.h> /* for strcpy, memmove */
  7. #include <pwd.h> /* for getpwnam, getpwuid */
  8. #include <grp.h> /* for getgrnam, getgrgid */
  9. #include <unistd.h> /* for gethostname, pread, pwrite, read, write */
  10. #include <utime.h> /* for utime */
  11. #include <dirent.h> /* for readdir */
  12. #include <errno.h> /* for errno */
  13. #include <stdio.h> /* for remove [sic] */
  14. #include <fcntl.h> /* for O_RDONLY, etc. */
  15. #include <sys/socket.h> /* various networking crud */
  16. #include <netinet/in.h>
  17. #include <netdb.h>
  18. #include <fcall.h>
  19. #include <oldfcall.h>
  20. #include <u9fs.h>
  21. /* #ifndef because can be given in makefile */
  22. #ifndef DEFAULTLOG
  23. #define DEFAULTLOG "/tmp/u9fs.log"
  24. #endif
  25. char *logfile = DEFAULTLOG;
  26. #define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m))
  27. enum {
  28. Tdot = 1,
  29. Tdotdot
  30. };
  31. enum {
  32. P9P1,
  33. P9P2000
  34. };
  35. typedef struct User User;
  36. struct User {
  37. int id;
  38. gid_t defaultgid;
  39. char *name;
  40. char **mem; /* group members */
  41. int nmem;
  42. User *next;
  43. };
  44. struct Fid {
  45. int fid;
  46. char *path;
  47. struct stat st;
  48. User *u;
  49. int omode;
  50. DIR *dir;
  51. int diroffset;
  52. int fd;
  53. struct dirent *dirent;
  54. Fid *next;
  55. Fid *prev;
  56. int auth;
  57. void *authmagic;
  58. };
  59. void* emalloc(size_t);
  60. void* erealloc(void*, size_t);
  61. char* estrdup(char*);
  62. char* estrpath(char*, char*);
  63. void sysfatal(char*, ...);
  64. int okuser(char*);
  65. void rversion(Fcall*, Fcall*);
  66. void rauth(Fcall*, Fcall*);
  67. void rattach(Fcall*, Fcall*);
  68. void rflush(Fcall*, Fcall*);
  69. void rclone(Fcall*, Fcall*);
  70. void rwalk(Fcall*, Fcall*);
  71. void ropen(Fcall*, Fcall*);
  72. void rcreate(Fcall*, Fcall*);
  73. void rread(Fcall*, Fcall*);
  74. void rwrite(Fcall*, Fcall*);
  75. void rclunk(Fcall*, Fcall*);
  76. void rstat(Fcall*, Fcall*);
  77. void rwstat(Fcall*, Fcall*);
  78. void rclwalk(Fcall*, Fcall*);
  79. void rremove(Fcall*, Fcall*);
  80. User* uname2user(char*);
  81. User* gname2user(char*);
  82. User* uid2user(int);
  83. User* gid2user(int);
  84. Fid* newfid(int, char**);
  85. Fid* oldfidex(int, int, char**);
  86. Fid* oldfid(int, char**);
  87. int fidstat(Fid*, char**);
  88. void freefid(Fid*);
  89. int userchange(User*, char**);
  90. int userwalk(User*, char**, char*, Qid*, char**);
  91. int useropen(Fid*, int, char**);
  92. int usercreate(Fid*, char*, int, long, char**);
  93. int userremove(Fid*, char**);
  94. int userperm(User*, char*, int, int);
  95. int useringroup(User*, User*);
  96. Qid stat2qid(struct stat*);
  97. void getfcallold(int, Fcall*, int);
  98. void putfcallold(int, Fcall*);
  99. char Eauth[] = "authentication failed";
  100. char Ebadfid[] = "fid unknown or out of range";
  101. char Ebadoffset[] = "bad offset in directory read";
  102. char Ebadusefid[] = "bad use of fid";
  103. char Edirchange[] = "wstat can't convert between files and directories";
  104. char Eexist[] = "file or directory already exists";
  105. char Efidactive[] = "fid already in use";
  106. char Enotdir[] = "not a directory";
  107. char Enotingroup[] = "not a member of proposed group";
  108. char Enotowner[] = "only owner can change group in wstat";
  109. char Eperm[] = "permission denied";
  110. char Especial0[] = "already attached without access to special files";
  111. char Especial1[] = "already attached with access to special files";
  112. char Especial[] = "no access to special file";
  113. char Etoolarge[] = "i/o count too large";
  114. char Eunknowngroup[] = "unknown group";
  115. char Eunknownuser[] = "unknown user";
  116. char Ewstatbuffer[] = "bogus wstat buffer";
  117. ulong msize = IOHDRSZ+8192;
  118. uchar* rxbuf;
  119. uchar* txbuf;
  120. void* databuf;
  121. int connected;
  122. int devallowed;
  123. char* autharg;
  124. char* defaultuser;
  125. char hostname[256];
  126. char remotehostname[256];
  127. int chatty9p = 0;
  128. int network = 1;
  129. int old9p = -1;
  130. int authed;
  131. User* none;
  132. Auth *authmethods[] = { /* first is default */
  133. &authrhosts,
  134. &authp9any,
  135. &authnone,
  136. };
  137. Auth *auth;
  138. void
  139. getfcallnew(int fd, Fcall *fc, int have)
  140. {
  141. int len;
  142. if(have > BIT32SZ)
  143. sysfatal("cannot happen");
  144. if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have)
  145. sysfatal("couldn't read message");
  146. len = GBIT32(rxbuf);
  147. if(len <= BIT32SZ)
  148. sysfatal("bogus message");
  149. len -= BIT32SZ;
  150. if(readn(fd, rxbuf+BIT32SZ, len) != len)
  151. sysfatal("short message");
  152. if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ)
  153. sysfatal("badly sized message type %d", rxbuf[0]);
  154. }
  155. void
  156. getfcallold(int fd, Fcall *fc, int have)
  157. {
  158. int len, n;
  159. if(have > 3)
  160. sysfatal("cannot happen");
  161. if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have)
  162. sysfatal("couldn't read message");
  163. len = oldhdrsize(rxbuf[0]);
  164. if(len < 3)
  165. sysfatal("bad message %d", rxbuf[0]);
  166. if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3)
  167. sysfatal("couldn't read message");
  168. n = iosize(rxbuf);
  169. if(readn(fd, rxbuf+len, n) != n)
  170. sysfatal("couldn't read message");
  171. len += n;
  172. if(convM2Sold(rxbuf, len, fc) != len)
  173. sysfatal("badly sized message type %d", rxbuf[0]);
  174. }
  175. void
  176. putfcallnew(int wfd, Fcall *tx)
  177. {
  178. uint n;
  179. if((n = convS2M(tx, txbuf, msize)) == 0)
  180. sysfatal("couldn't format message type %d", tx->type);
  181. if(write(wfd, txbuf, n) != n)
  182. sysfatal("couldn't send message");
  183. }
  184. void
  185. putfcallold(int wfd, Fcall *tx)
  186. {
  187. uint n;
  188. if((n = convS2Mold(tx, txbuf, msize)) == 0)
  189. sysfatal("couldn't format message type %d", tx->type);
  190. if(write(wfd, txbuf, n) != n)
  191. sysfatal("couldn't send message");
  192. }
  193. void
  194. getfcall(int fd, Fcall *fc)
  195. {
  196. if(old9p == 1){
  197. getfcallold(fd, fc, 0);
  198. return;
  199. }
  200. if(old9p == 0){
  201. getfcallnew(fd, fc, 0);
  202. return;
  203. }
  204. /* auto-detect */
  205. if(readn(fd, rxbuf, 3) != 3)
  206. sysfatal("couldn't read message");
  207. /* is it an old (9P1) message? */
  208. if(50 <= rxbuf[0] && rxbuf[0] <= 87 && (rxbuf[0]&1)==0 && GBIT16(rxbuf+1) == 0xFFFF){
  209. old9p = 1;
  210. getfcallold(fd, fc, 3);
  211. return;
  212. }
  213. getfcallnew(fd, fc, 3);
  214. old9p = 0;
  215. }
  216. void
  217. seterror(Fcall *f, char *error)
  218. {
  219. f->type = Rerror;
  220. f->ename = error ? error : "programmer error";
  221. }
  222. int
  223. isowner(User *u, Fid *f)
  224. {
  225. return u->id == f->st.st_uid;
  226. }
  227. void
  228. serve(int rfd, int wfd)
  229. {
  230. Fcall rx, tx;
  231. for(;;){
  232. getfcall(rfd, &rx);
  233. if(chatty9p)
  234. fprint(2, "<- %F\n", &rx);
  235. memset(&tx, 0, sizeof tx);
  236. tx.type = rx.type+1;
  237. tx.tag = rx.tag;
  238. switch(rx.type){
  239. case Tflush:
  240. break;
  241. case Tversion:
  242. rversion(&rx, &tx);
  243. break;
  244. case Tauth:
  245. rauth(&rx, &tx);
  246. break;
  247. case Tattach:
  248. rattach(&rx, &tx);
  249. break;
  250. case Twalk:
  251. rwalk(&rx, &tx);
  252. break;
  253. case Tstat:
  254. tx.stat = databuf;
  255. rstat(&rx, &tx);
  256. break;
  257. case Twstat:
  258. rwstat(&rx, &tx);
  259. break;
  260. case Topen:
  261. ropen(&rx, &tx);
  262. break;
  263. case Tcreate:
  264. rcreate(&rx, &tx);
  265. break;
  266. case Tread:
  267. tx.data = databuf;
  268. rread(&rx, &tx);
  269. break;
  270. case Twrite:
  271. rwrite(&rx, &tx);
  272. break;
  273. case Tclunk:
  274. rclunk(&rx, &tx);
  275. break;
  276. case Tremove:
  277. rremove(&rx, &tx);
  278. break;
  279. default:
  280. fprint(2, "unknown message %F\n", &rx);
  281. seterror(&tx, "bad message");
  282. break;
  283. }
  284. if(chatty9p)
  285. fprint(2, "-> %F\n", &tx);
  286. (old9p ? putfcallold : putfcallnew)(wfd, &tx);
  287. }
  288. }
  289. void
  290. rversion(Fcall *rx, Fcall *tx)
  291. {
  292. if(msize > rx->msize)
  293. msize = rx->msize;
  294. tx->msize = msize;
  295. if(strncmp(rx->version, "9P", 2) != 0)
  296. tx->version = "unknown";
  297. else
  298. tx->version = "9P2000";
  299. }
  300. void
  301. rauth(Fcall *rx, Fcall *tx)
  302. {
  303. char *e;
  304. if((e = auth->auth(rx, tx)) != nil)
  305. seterror(tx, e);
  306. }
  307. void
  308. rattach(Fcall *rx, Fcall *tx)
  309. {
  310. char *e;
  311. Fid *fid;
  312. User *u;
  313. if(rx->aname == nil)
  314. rx->aname = "";
  315. if(strcmp(rx->aname, "device") == 0){
  316. if(connected && !devallowed){
  317. seterror(tx, Especial0);
  318. return;
  319. }
  320. devallowed = 1;
  321. }else{
  322. if(connected && devallowed){
  323. seterror(tx, Especial1);
  324. return;
  325. }
  326. }
  327. if(strcmp(rx->uname, "none") == 0){
  328. if(authed == 0){
  329. seterror(tx, Eauth);
  330. return;
  331. }
  332. } else {
  333. if((e = auth->attach(rx, tx)) != nil){
  334. seterror(tx, e);
  335. return;
  336. }
  337. authed++;
  338. }
  339. if((fid = newfid(rx->fid, &e)) == nil){
  340. seterror(tx, e);
  341. return;
  342. }
  343. fid->path = estrdup("/");
  344. if(fidstat(fid, &e) < 0){
  345. seterror(tx, e);
  346. freefid(fid);
  347. return;
  348. }
  349. if(defaultuser)
  350. rx->uname = defaultuser;
  351. if((u = uname2user(rx->uname)) == nil
  352. || (!defaultuser && u->id == 0)){
  353. /* we don't know anyone named root... */
  354. seterror(tx, Eunknownuser);
  355. freefid(fid);
  356. return;
  357. }
  358. fid->u = u;
  359. tx->qid = stat2qid(&fid->st);
  360. return;
  361. }
  362. void
  363. rwalk(Fcall *rx, Fcall *tx)
  364. {
  365. int i;
  366. char *path, *e;
  367. Fid *fid, *nfid;
  368. e = nil;
  369. if((fid = oldfid(rx->fid, &e)) == nil){
  370. seterror(tx, e);
  371. return;
  372. }
  373. if(fid->omode != -1){
  374. seterror(tx, Ebadusefid);
  375. return;
  376. }
  377. if(fidstat(fid, &e) < 0){
  378. seterror(tx, e);
  379. return;
  380. }
  381. if(!S_ISDIR(fid->st.st_mode) && rx->nwname){
  382. seterror(tx, Enotdir);
  383. return;
  384. }
  385. nfid = nil;
  386. if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){
  387. seterror(tx, e);
  388. return;
  389. }
  390. path = estrdup(fid->path);
  391. e = nil;
  392. for(i=0; i<rx->nwname; i++)
  393. if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0)
  394. break;
  395. if(i == rx->nwname){ /* successful clone or walk */
  396. tx->nwqid = i;
  397. if(nfid){
  398. nfid->path = path;
  399. nfid->u = fid->u;
  400. }else{
  401. free(fid->path);
  402. fid->path = path;
  403. }
  404. }else{
  405. if(i > 0) /* partial walk? */
  406. tx->nwqid = i;
  407. else
  408. seterror(tx, e);
  409. if(nfid) /* clone implicit new fid */
  410. freefid(nfid);
  411. free(path);
  412. }
  413. return;
  414. }
  415. void
  416. ropen(Fcall *rx, Fcall *tx)
  417. {
  418. char *e;
  419. Fid *fid;
  420. if((fid = oldfid(rx->fid, &e)) == nil){
  421. seterror(tx, e);
  422. return;
  423. }
  424. if(fid->omode != -1){
  425. seterror(tx, Ebadusefid);
  426. return;
  427. }
  428. if(fidstat(fid, &e) < 0){
  429. seterror(tx, e);
  430. return;
  431. }
  432. if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){
  433. seterror(tx, Especial);
  434. return;
  435. }
  436. if(useropen(fid, rx->mode, &e) < 0){
  437. seterror(tx, e);
  438. return;
  439. }
  440. tx->iounit = 0;
  441. tx->qid = stat2qid(&fid->st);
  442. }
  443. void
  444. rcreate(Fcall *rx, Fcall *tx)
  445. {
  446. char *e;
  447. Fid *fid;
  448. if((fid = oldfid(rx->fid, &e)) == nil){
  449. seterror(tx, e);
  450. return;
  451. }
  452. if(fid->omode != -1){
  453. seterror(tx, Ebadusefid);
  454. return;
  455. }
  456. if(fidstat(fid, &e) < 0){
  457. seterror(tx, e);
  458. return;
  459. }
  460. if(!S_ISDIR(fid->st.st_mode)){
  461. seterror(tx, Enotdir);
  462. return;
  463. }
  464. if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){
  465. seterror(tx, e);
  466. return;
  467. }
  468. if(fidstat(fid, &e) < 0){
  469. seterror(tx, e);
  470. return;
  471. }
  472. tx->iounit = 0;
  473. tx->qid = stat2qid(&fid->st);
  474. }
  475. uchar
  476. modebyte(struct stat *st)
  477. {
  478. uchar b;
  479. b = 0;
  480. if(S_ISDIR(st->st_mode))
  481. b |= QTDIR;
  482. /* no way to test append-only */
  483. /* no real way to test exclusive use, but mark devices as such */
  484. if(S_ISSPECIAL(st->st_mode))
  485. b |= QTEXCL;
  486. return b;
  487. }
  488. ulong
  489. plan9mode(struct stat *st)
  490. {
  491. return ((ulong)modebyte(st)<<24) | (st->st_mode & 0777);
  492. }
  493. /*
  494. * this is for chmod, so don't worry about S_IFDIR
  495. */
  496. mode_t
  497. unixmode(Dir *d)
  498. {
  499. return (mode_t)(d->mode&0777);
  500. }
  501. Qid
  502. stat2qid(struct stat *st)
  503. {
  504. uchar *p, *ep, *q;
  505. Qid qid;
  506. /*
  507. * For now, ignore the device number.
  508. */
  509. qid.path = 0;
  510. p = (uchar*)&qid.path;
  511. ep = p+sizeof(qid.path);
  512. q = p+sizeof(ino_t);
  513. if(q > ep){
  514. fprint(2, "warning: inode number too big\n");
  515. q = ep;
  516. }
  517. memmove(p, &st->st_ino, q-p);
  518. q = q+sizeof(dev_t);
  519. if(q > ep){
  520. /* fprint(2, "warning: inode number + device number too big %d+%d\n", sizeof(ino_t), sizeof(dev_t)); */
  521. q = ep - sizeof(dev_t);
  522. if(q < p)
  523. fprint(2, "warning: device number too big by itself\n");
  524. else
  525. *(dev_t*)q ^= st->st_dev;
  526. }
  527. qid.vers = st->st_mtime ^ (st->st_size << 8);
  528. qid.type = modebyte(st);
  529. return qid;
  530. }
  531. void
  532. stat2dir(char *path, struct stat *st, Dir *d)
  533. {
  534. User *u;
  535. char *q;
  536. memset(d, 0, sizeof(*d));
  537. d->qid = stat2qid(st);
  538. d->mode = plan9mode(st);
  539. d->atime = st->st_atime;
  540. d->mtime = st->st_mtime;
  541. d->length = st->st_size;
  542. d->uid = (u = uid2user(st->st_uid)) ? u->name : "???";
  543. d->gid = (u = gid2user(st->st_gid)) ? u->name : "???";
  544. d->muid = "";
  545. if((q = strrchr(path, '/')) != nil)
  546. d->name = q+1;
  547. else
  548. d->name = path;
  549. }
  550. void
  551. rread(Fcall *rx, Fcall *tx)
  552. {
  553. char *e, *path;
  554. uchar *p, *ep;
  555. int n;
  556. Fid *fid;
  557. Dir d;
  558. struct stat st;
  559. if(rx->count > msize-IOHDRSZ){
  560. seterror(tx, Etoolarge);
  561. return;
  562. }
  563. if((fid = oldfidex(rx->fid, -1, &e)) == nil){
  564. seterror(tx, e);
  565. return;
  566. }
  567. if (fid->auth) {
  568. char *e;
  569. e = auth->read(rx, tx);
  570. if (e)
  571. seterror(tx, e);
  572. return;
  573. }
  574. if(fid->omode == -1 || (fid->omode&3) == OWRITE){
  575. seterror(tx, Ebadusefid);
  576. return;
  577. }
  578. if(fid->dir){
  579. if(rx->offset != fid->diroffset){
  580. if(rx->offset != 0){
  581. seterror(tx, Ebadoffset);
  582. return;
  583. }
  584. rewinddir(fid->dir);
  585. fid->diroffset = 0;
  586. }
  587. p = (uchar*)tx->data;
  588. ep = (uchar*)tx->data+rx->count;
  589. for(;;){
  590. if(p+BIT16SZ >= ep)
  591. break;
  592. if(fid->dirent == nil) /* one entry cache for when convD2M fails */
  593. if((fid->dirent = readdir(fid->dir)) == nil)
  594. break;
  595. if(strcmp(fid->dirent->d_name, ".") == 0
  596. || strcmp(fid->dirent->d_name, "..") == 0){
  597. fid->dirent = nil;
  598. continue;
  599. }
  600. path = estrpath(fid->path, fid->dirent->d_name);
  601. memset(&st, 0, sizeof st);
  602. if(stat(path, &st) < 0){
  603. fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno));
  604. fid->dirent = nil;
  605. free(path);
  606. continue;
  607. }
  608. free(path);
  609. stat2dir(fid->dirent->d_name, &st, &d);
  610. if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ)
  611. break;
  612. p += n;
  613. fid->dirent = nil;
  614. }
  615. tx->count = p - (uchar*)tx->data;
  616. fid->diroffset += tx->count;
  617. }else{
  618. if((n = pread(fid->fd, tx->data, rx->count, rx->offset)) < 0){
  619. seterror(tx, strerror(errno));
  620. return;
  621. }
  622. tx->count = n;
  623. }
  624. }
  625. void
  626. rwrite(Fcall *rx, Fcall *tx)
  627. {
  628. char *e;
  629. Fid *fid;
  630. int n;
  631. if(rx->count > msize-IOHDRSZ){
  632. seterror(tx, Etoolarge);
  633. return;
  634. }
  635. if((fid = oldfidex(rx->fid, -1, &e)) == nil){
  636. seterror(tx, e);
  637. return;
  638. }
  639. if (fid->auth) {
  640. char *e;
  641. e = auth->write(rx, tx);
  642. if (e)
  643. seterror(tx, e);
  644. return;
  645. }
  646. if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){
  647. seterror(tx, Ebadusefid);
  648. return;
  649. }
  650. if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){
  651. seterror(tx, strerror(errno));
  652. return;
  653. }
  654. tx->count = n;
  655. }
  656. void
  657. rclunk(Fcall *rx, Fcall *tx)
  658. {
  659. char *e;
  660. Fid *fid;
  661. if((fid = oldfidex(rx->fid, -1, &e)) == nil){
  662. seterror(tx, e);
  663. return;
  664. }
  665. if (fid->auth) {
  666. if (auth->clunk) {
  667. e = (*auth->clunk)(rx, tx);
  668. if (e) {
  669. seterror(tx, e);
  670. return;
  671. }
  672. }
  673. }
  674. else if(fid->omode != -1 && fid->omode&ORCLOSE)
  675. remove(fid->path);
  676. freefid(fid);
  677. }
  678. void
  679. rremove(Fcall *rx, Fcall *tx)
  680. {
  681. char *e;
  682. Fid *fid;
  683. if((fid = oldfid(rx->fid, &e)) == nil){
  684. seterror(tx, e);
  685. return;
  686. }
  687. if(userremove(fid, &e) < 0)
  688. seterror(tx, e);
  689. freefid(fid);
  690. }
  691. void
  692. rstat(Fcall *rx, Fcall *tx)
  693. {
  694. char *e;
  695. Fid *fid;
  696. Dir d;
  697. if((fid = oldfid(rx->fid, &e)) == nil){
  698. seterror(tx, e);
  699. return;
  700. }
  701. if(fidstat(fid, &e) < 0){
  702. seterror(tx, e);
  703. return;
  704. }
  705. stat2dir(fid->path, &fid->st, &d);
  706. if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ)
  707. seterror(tx, "convD2M fails");
  708. }
  709. void
  710. rwstat(Fcall *rx, Fcall *tx)
  711. {
  712. char *e;
  713. char *p, *old, *new, *dir;
  714. gid_t gid;
  715. Dir d;
  716. Fid *fid;
  717. if((fid = oldfid(rx->fid, &e)) == nil){
  718. seterror(tx, e);
  719. return;
  720. }
  721. /*
  722. * wstat is supposed to be atomic.
  723. * we check all the things we can before trying anything.
  724. * still, if we are told to truncate a file and rename it and only
  725. * one works, we're screwed. in such cases we leave things
  726. * half broken and return an error. it's hardly perfect.
  727. */
  728. if((old9p ? convM2Dold : convM2D)(rx->stat, rx->nstat, &d, (char*)rx->stat) <= BIT16SZ){
  729. seterror(tx, Ewstatbuffer);
  730. return;
  731. }
  732. if(fidstat(fid, &e) < 0){
  733. seterror(tx, e);
  734. return;
  735. }
  736. /*
  737. * The casting is necessary because d.mode is ulong and might,
  738. * on some systems, be 64 bits. We only want to compare the
  739. * bottom 32 bits, since that's all that gets sent in the protocol.
  740. *
  741. * Same situation for d.mtime and d.length (although that last check
  742. * is admittedly superfluous, given the current lack of 128-bit machines).
  743. */
  744. gid = (gid_t)-1;
  745. if(d.gid[0] != '\0'){
  746. User *g;
  747. g = gname2user(d.gid);
  748. if(g == nil){
  749. seterror(tx, Eunknowngroup);
  750. return;
  751. }
  752. gid = (gid_t)g->id;
  753. if(groupchange(fid->u, gid2user(gid), &e) < 0){
  754. seterror(tx, e);
  755. return;
  756. }
  757. }
  758. if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){
  759. seterror(tx, Edirchange);
  760. return;
  761. }
  762. if(strcmp(fid->path, "/") == 0){
  763. seterror(tx, "no wstat of root");
  764. return;
  765. }
  766. /*
  767. * try things in increasing order of harm to the file.
  768. * mtime should come after truncate so that if you
  769. * do both the mtime actually takes effect, but i'd rather
  770. * leave truncate until last.
  771. * (see above comment about atomicity).
  772. */
  773. if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){
  774. if(chatty9p)
  775. fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d));
  776. seterror(tx, strerror(errno));
  777. return;
  778. }
  779. if((u32int)d.mtime != (u32int)~0){
  780. struct utimbuf t;
  781. t.actime = 0;
  782. t.modtime = d.mtime;
  783. if(utime(fid->path, &t) < 0){
  784. if(chatty9p)
  785. fprint(2, "utime(%s) failed\n", fid->path);
  786. seterror(tx, strerror(errno));
  787. return;
  788. }
  789. }
  790. if(gid != (gid_t)-1 && gid != fid->st.st_gid){
  791. if(chown(fid->path, (uid_t)-1, gid) < 0){
  792. if(chatty9p)
  793. fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid);
  794. seterror(tx, strerror(errno));
  795. return;
  796. }
  797. }
  798. if(d.name[0]){
  799. old = fid->path;
  800. dir = estrdup(fid->path);
  801. if((p = strrchr(dir, '/')) > dir)
  802. *p = '\0';
  803. else{
  804. seterror(tx, "whoops: can't happen in u9fs");
  805. return;
  806. }
  807. new = estrpath(dir, d.name);
  808. if(strcmp(old, new) != 0 && rename(old, new) < 0){
  809. if(chatty9p)
  810. fprint(2, "rename(%s, %s) failed\n", old, new);
  811. seterror(tx, strerror(errno));
  812. free(new);
  813. free(dir);
  814. return;
  815. }
  816. fid->path = new;
  817. free(old);
  818. free(dir);
  819. }
  820. if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){
  821. fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length);
  822. seterror(tx, strerror(errno));
  823. return;
  824. }
  825. }
  826. /*
  827. * we keep a table by numeric id. by name lookups happen infrequently
  828. * while by-number lookups happen once for every directory entry read
  829. * and every stat request.
  830. */
  831. User *utab[64];
  832. User *gtab[64];
  833. User*
  834. adduser(struct passwd *p)
  835. {
  836. User *u;
  837. u = emalloc(sizeof(*u));
  838. u->id = p->pw_uid;
  839. u->name = estrdup(p->pw_name);
  840. u->next = utab[p->pw_uid%nelem(utab)];
  841. u->defaultgid = p->pw_gid;
  842. utab[p->pw_uid%nelem(utab)] = u;
  843. return u;
  844. }
  845. int
  846. useringroup(User *u, User *g)
  847. {
  848. int i;
  849. for(i=0; i<g->nmem; i++)
  850. if(strcmp(g->mem[i], u->name) == 0)
  851. return 1;
  852. /*
  853. * Hack around common Unix problem that everyone has
  854. * default group "user" but /etc/group lists no members.
  855. */
  856. if(u->defaultgid == g->id)
  857. return 1;
  858. return 0;
  859. }
  860. User*
  861. addgroup(struct group *g)
  862. {
  863. User *u;
  864. char **p;
  865. int n;
  866. u = emalloc(sizeof(*u));
  867. n = 0;
  868. for(p=g->gr_mem; *p; p++)
  869. n++;
  870. u->mem = emalloc(sizeof(u->mem[0])*n);
  871. n = 0;
  872. for(p=g->gr_mem; *p; p++)
  873. u->mem[n++] = estrdup(*p);
  874. u->nmem = n;
  875. u->id = g->gr_gid;
  876. u->name = estrdup(g->gr_name);
  877. u->next = gtab[g->gr_gid%nelem(gtab)];
  878. gtab[g->gr_gid%nelem(gtab)] = u;
  879. return u;
  880. }
  881. User*
  882. uname2user(char *name)
  883. {
  884. int i;
  885. User *u;
  886. struct passwd *p;
  887. for(i=0; i<nelem(utab); i++)
  888. for(u=utab[i]; u; u=u->next)
  889. if(strcmp(u->name, name) == 0)
  890. return u;
  891. if((p = getpwnam(name)) == nil)
  892. return nil;
  893. return adduser(p);
  894. }
  895. User*
  896. uid2user(int id)
  897. {
  898. User *u;
  899. struct passwd *p;
  900. for(u=utab[id%nelem(utab)]; u; u=u->next)
  901. if(u->id == id)
  902. return u;
  903. if((p = getpwuid(id)) == nil)
  904. return nil;
  905. return adduser(p);
  906. }
  907. User*
  908. gname2user(char *name)
  909. {
  910. int i;
  911. User *u;
  912. struct group *g;
  913. for(i=0; i<nelem(gtab); i++)
  914. for(u=gtab[i]; u; u=u->next)
  915. if(strcmp(u->name, name) == 0)
  916. return u;
  917. if((g = getgrnam(name)) == nil)
  918. return nil;
  919. return addgroup(g);
  920. }
  921. User*
  922. gid2user(int id)
  923. {
  924. User *u;
  925. struct group *g;
  926. for(u=gtab[id%nelem(gtab)]; u; u=u->next)
  927. if(u->id == id)
  928. return u;
  929. if((g = getgrgid(id)) == nil)
  930. return nil;
  931. return addgroup(g);
  932. }
  933. void
  934. sysfatal(char *fmt, ...)
  935. {
  936. char buf[1024];
  937. va_list va, temp;
  938. va_start(va, fmt);
  939. va_copy(temp, va);
  940. doprint(buf, buf+sizeof buf, fmt, &temp);
  941. va_end(temp);
  942. va_end(va);
  943. fprint(2, "u9fs: %s\n", buf);
  944. fprint(2, "last unix error: %s\n", strerror(errno));
  945. exit(1);
  946. }
  947. void*
  948. emalloc(size_t n)
  949. {
  950. void *p;
  951. if(n == 0)
  952. n = 1;
  953. p = malloc(n);
  954. if(p == 0)
  955. sysfatal("malloc(%ld) fails", (long)n);
  956. memset(p, 0, n);
  957. return p;
  958. }
  959. void*
  960. erealloc(void *p, size_t n)
  961. {
  962. if(p == 0)
  963. p = malloc(n);
  964. else
  965. p = realloc(p, n);
  966. if(p == 0)
  967. sysfatal("realloc(..., %ld) fails", (long)n);
  968. return p;
  969. }
  970. char*
  971. estrdup(char *p)
  972. {
  973. p = strdup(p);
  974. if(p == 0)
  975. sysfatal("strdup(%.20s) fails", p);
  976. return p;
  977. }
  978. char*
  979. estrpath(char *p, char *q)
  980. {
  981. char *r, *s;
  982. if(strcmp(q, "..") == 0){
  983. r = estrdup(p);
  984. if((s = strrchr(r, '/')) && s > r)
  985. *s = '\0';
  986. else if(s == r)
  987. s[1] = '\0';
  988. return r;
  989. }
  990. r = emalloc(strlen(p)+1+strlen(q)+1);
  991. strcpy(r, p);
  992. if(r[0]=='\0' || r[strlen(r)-1] != '/')
  993. strcat(r, "/");
  994. strcat(r, q);
  995. return r;
  996. }
  997. Fid *fidtab[1];
  998. Fid*
  999. lookupfid(int fid)
  1000. {
  1001. Fid *f;
  1002. for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next)
  1003. if(f->fid == fid)
  1004. return f;
  1005. return nil;
  1006. }
  1007. Fid*
  1008. newfid(int fid, char **ep)
  1009. {
  1010. Fid *f;
  1011. if(lookupfid(fid) != nil){
  1012. *ep = Efidactive;
  1013. return nil;
  1014. }
  1015. f = emalloc(sizeof(*f));
  1016. f->next = fidtab[fid%nelem(fidtab)];
  1017. if(f->next)
  1018. f->next->prev = f;
  1019. fidtab[fid%nelem(fidtab)] = f;
  1020. f->fid = fid;
  1021. f->fd = -1;
  1022. f->omode = -1;
  1023. return f;
  1024. }
  1025. Fid*
  1026. newauthfid(int fid, void *magic, char **ep)
  1027. {
  1028. Fid *af;
  1029. af = newfid(fid, ep);
  1030. if (af == nil)
  1031. return nil;
  1032. af->auth = 1;
  1033. af->authmagic = magic;
  1034. return af;
  1035. }
  1036. Fid*
  1037. oldfidex(int fid, int auth, char **ep)
  1038. {
  1039. Fid *f;
  1040. if((f = lookupfid(fid)) == nil){
  1041. *ep = Ebadfid;
  1042. return nil;
  1043. }
  1044. if (auth != -1 && f->auth != auth) {
  1045. *ep = Ebadfid;
  1046. return nil;
  1047. }
  1048. if (!f->auth) {
  1049. if(userchange(f->u, ep) < 0)
  1050. return nil;
  1051. }
  1052. return f;
  1053. }
  1054. Fid*
  1055. oldfid(int fid, char **ep)
  1056. {
  1057. return oldfidex(fid, 0, ep);
  1058. }
  1059. Fid*
  1060. oldauthfid(int fid, void **magic, char **ep)
  1061. {
  1062. Fid *af;
  1063. af = oldfidex(fid, 1, ep);
  1064. if (af == nil)
  1065. return nil;
  1066. *magic = af->authmagic;
  1067. return af;
  1068. }
  1069. void
  1070. freefid(Fid *f)
  1071. {
  1072. if(f->prev)
  1073. f->prev->next = f->next;
  1074. else
  1075. fidtab[f->fid%nelem(fidtab)] = f->next;
  1076. if(f->next)
  1077. f->next->prev = f->prev;
  1078. if(f->dir)
  1079. closedir(f->dir);
  1080. if(f->fd)
  1081. close(f->fd);
  1082. free(f->path);
  1083. free(f);
  1084. }
  1085. int
  1086. fidstat(Fid *fid, char **ep)
  1087. {
  1088. if(stat(fid->path, &fid->st) < 0){
  1089. fprint(2, "fidstat(%s) failed\n", fid->path);
  1090. if(ep)
  1091. *ep = strerror(errno);
  1092. return -1;
  1093. }
  1094. if(S_ISDIR(fid->st.st_mode))
  1095. fid->st.st_size = 0;
  1096. return 0;
  1097. }
  1098. int
  1099. userchange(User *u, char **ep)
  1100. {
  1101. if(defaultuser)
  1102. return 0;
  1103. if(setreuid(0, 0) < 0){
  1104. fprint(2, "setreuid(0, 0) failed\n");
  1105. *ep = "cannot setuid back to root";
  1106. return -1;
  1107. }
  1108. /*
  1109. * Initgroups does not appear to be SUSV standard.
  1110. * But it exists on SGI and on Linux, which makes me
  1111. * think it's standard enough. We have to do something
  1112. * like this, and the closest other function I can find is
  1113. * setgroups (which initgroups eventually calls).
  1114. * Setgroups is the same as far as standardization though,
  1115. * so we're stuck using a non-SUSV call. Sigh.
  1116. */
  1117. if(initgroups(u->name, u->defaultgid) < 0)
  1118. fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno));
  1119. if(setreuid(-1, u->id) < 0){
  1120. fprint(2, "setreuid(-1, %s) failed\n", u->name);
  1121. *ep = strerror(errno);
  1122. return -1;
  1123. }
  1124. return 0;
  1125. }
  1126. /*
  1127. * We do our own checking here, then switch to root temporarily
  1128. * to set our gid. In a perfect world, you'd be allowed to set your
  1129. * egid to any of the supplemental groups of your euid, but this
  1130. * is not the case on Linux 2.2.14 (and perhaps others).
  1131. *
  1132. * This is a race, of course, but it's a race against processes
  1133. * that can edit the group lists. If you can do that, you can
  1134. * change your own group without our help.
  1135. */
  1136. int
  1137. groupchange(User *u, User *g, char **ep)
  1138. {
  1139. if(g == nil)
  1140. return -1;
  1141. if(!useringroup(u, g)){
  1142. if(chatty9p)
  1143. fprint(2, "%s not in group %s\n", u->name, g->name);
  1144. *ep = Enotingroup;
  1145. return -1;
  1146. }
  1147. setreuid(0,0);
  1148. if(setregid(-1, g->id) < 0){
  1149. fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id);
  1150. *ep = strerror(errno);
  1151. return -1;
  1152. }
  1153. if(userchange(u, ep) < 0)
  1154. return -1;
  1155. return 0;
  1156. }
  1157. /*
  1158. * An attempt to enforce permissions by looking at the
  1159. * file system. Separation of checking permission and
  1160. * actually performing the action is a terrible idea, of
  1161. * course, so we use setreuid for most of the permission
  1162. * enforcement. This is here only so we can give errors
  1163. * on open(ORCLOSE) in some cases.
  1164. */
  1165. int
  1166. userperm(User *u, char *path, int type, int need)
  1167. {
  1168. char *p, *q;
  1169. int i, have;
  1170. struct stat st;
  1171. User *g;
  1172. switch(type){
  1173. default:
  1174. fprint(2, "bad type %d in userperm\n", type);
  1175. return -1;
  1176. case Tdot:
  1177. if(stat(path, &st) < 0){
  1178. fprint(2, "userperm: stat(%s) failed\n", path);
  1179. return -1;
  1180. }
  1181. break;
  1182. case Tdotdot:
  1183. p = estrdup(path);
  1184. if((q = strrchr(p, '/'))==nil){
  1185. fprint(2, "userperm(%s, ..): bad path\n", p);
  1186. free(p);
  1187. return -1;
  1188. }
  1189. if(q > p)
  1190. *q = '\0';
  1191. else
  1192. *(q+1) = '\0';
  1193. if(stat(p, &st) < 0){
  1194. fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n",
  1195. p, path);
  1196. free(p);
  1197. return -1;
  1198. }
  1199. free(p);
  1200. break;
  1201. }
  1202. if(u == none){
  1203. fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode);
  1204. have = st.st_mode&7;
  1205. if((have&need)==need)
  1206. return 0;
  1207. return -1;
  1208. }
  1209. have = st.st_mode&7;
  1210. if((uid_t)u->id == st.st_uid)
  1211. have |= (st.st_mode>>6)&7;
  1212. if((have&need)==need)
  1213. return 0;
  1214. if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */
  1215. return -1;
  1216. g = gid2user(st.st_gid);
  1217. for(i=0; i<g->nmem; i++){
  1218. if(strcmp(g->mem[i], u->name) == 0){
  1219. have |= (st.st_mode>>3)&7;
  1220. break;
  1221. }
  1222. }
  1223. if((have&need)==need)
  1224. return 0;
  1225. return -1;
  1226. }
  1227. int
  1228. userwalk(User *u, char **path, char *elem, Qid *qid, char **ep)
  1229. {
  1230. char *npath;
  1231. struct stat st;
  1232. npath = estrpath(*path, elem);
  1233. if(stat(npath, &st) < 0){
  1234. free(npath);
  1235. *ep = strerror(errno);
  1236. return -1;
  1237. }
  1238. *qid = stat2qid(&st);
  1239. free(*path);
  1240. *path = npath;
  1241. return 0;
  1242. }
  1243. int
  1244. useropen(Fid *fid, int omode, char **ep)
  1245. {
  1246. int a, o;
  1247. /*
  1248. * Check this anyway, to try to head off problems later.
  1249. */
  1250. if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){
  1251. *ep = Eperm;
  1252. return -1;
  1253. }
  1254. switch(omode&3){
  1255. default:
  1256. *ep = "programmer error";
  1257. return -1;
  1258. case OREAD:
  1259. a = R_OK;
  1260. o = O_RDONLY;
  1261. break;
  1262. case ORDWR:
  1263. a = R_OK|W_OK;
  1264. o = O_RDWR;
  1265. break;
  1266. case OWRITE:
  1267. a = W_OK;
  1268. o = O_WRONLY;
  1269. break;
  1270. case OEXEC:
  1271. a = X_OK;
  1272. o = O_RDONLY;
  1273. break;
  1274. }
  1275. if(omode & OTRUNC){
  1276. a |= W_OK;
  1277. o |= O_TRUNC;
  1278. }
  1279. if(S_ISDIR(fid->st.st_mode)){
  1280. if(a != R_OK){
  1281. fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode);
  1282. *ep = Eperm;
  1283. return -1;
  1284. }
  1285. if((fid->dir = opendir(fid->path)) == nil){
  1286. *ep = strerror(errno);
  1287. return -1;
  1288. }
  1289. }else{
  1290. /*
  1291. * This is wrong because access used the real uid
  1292. * and not the effective uid. Let the open sort it out.
  1293. *
  1294. if(access(fid->path, a) < 0){
  1295. *ep = strerror(errno);
  1296. return -1;
  1297. }
  1298. *
  1299. */
  1300. if((fid->fd = open(fid->path, o)) < 0){
  1301. *ep = strerror(errno);
  1302. return -1;
  1303. }
  1304. }
  1305. fid->omode = omode;
  1306. return 0;
  1307. }
  1308. int
  1309. usercreate(Fid *fid, char *elem, int omode, long perm, char **ep)
  1310. {
  1311. int o, m;
  1312. char *opath, *npath;
  1313. struct stat st, parent;
  1314. if(stat(fid->path, &parent) < 0){
  1315. *ep = strerror(errno);
  1316. return -1;
  1317. }
  1318. /*
  1319. * Change group so that created file has expected group
  1320. * by Plan 9 semantics. If that fails, might as well go
  1321. * with the user's default group.
  1322. */
  1323. if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0
  1324. && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0)
  1325. return -1;
  1326. m = (perm & DMDIR) ? 0777 : 0666;
  1327. perm = perm & (~m | (fid->st.st_mode & m));
  1328. npath = estrpath(fid->path, elem);
  1329. if(perm & DMDIR){
  1330. if((omode&~ORCLOSE) != OREAD){
  1331. *ep = Eperm;
  1332. free(npath);
  1333. return -1;
  1334. }
  1335. if(stat(npath, &st) >= 0 || errno != ENOENT){
  1336. *ep = Eexist;
  1337. free(npath);
  1338. return -1;
  1339. }
  1340. /* race */
  1341. if(mkdir(npath, perm&0777) < 0){
  1342. *ep = strerror(errno);
  1343. free(npath);
  1344. return -1;
  1345. }
  1346. if((fid->dir = opendir(npath)) == nil){
  1347. *ep = strerror(errno);
  1348. remove(npath); /* race */
  1349. free(npath);
  1350. return -1;
  1351. }
  1352. }else{
  1353. o = O_CREAT|O_EXCL;
  1354. switch(omode&3){
  1355. default:
  1356. *ep = "programmer error";
  1357. return -1;
  1358. case OREAD:
  1359. case OEXEC:
  1360. o |= O_RDONLY;
  1361. break;
  1362. case ORDWR:
  1363. o |= O_RDWR;
  1364. break;
  1365. case OWRITE:
  1366. o |= O_WRONLY;
  1367. break;
  1368. }
  1369. if(omode & OTRUNC)
  1370. o |= O_TRUNC;
  1371. if((fid->fd = open(npath, o, perm&0777)) < 0){
  1372. if(chatty9p)
  1373. fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777);
  1374. *ep = strerror(errno);
  1375. free(npath);
  1376. return -1;
  1377. }
  1378. }
  1379. opath = fid->path;
  1380. fid->path = npath;
  1381. if(fidstat(fid, ep) < 0){
  1382. fprint(2, "stat after create on %s failed\n", npath);
  1383. remove(npath); /* race */
  1384. free(npath);
  1385. fid->path = opath;
  1386. if(fid->fd >= 0){
  1387. close(fid->fd);
  1388. fid->fd = -1;
  1389. }else{
  1390. closedir(fid->dir);
  1391. fid->dir = nil;
  1392. }
  1393. return -1;
  1394. }
  1395. fid->omode = omode;
  1396. free(opath);
  1397. return 0;
  1398. }
  1399. int
  1400. userremove(Fid *fid, char **ep)
  1401. {
  1402. if(remove(fid->path) < 0){
  1403. *ep = strerror(errno);
  1404. return -1;
  1405. }
  1406. return 0;
  1407. }
  1408. void
  1409. usage(void)
  1410. {
  1411. fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n");
  1412. exit(1);
  1413. }
  1414. int
  1415. main(int argc, char **argv)
  1416. {
  1417. char *authtype;
  1418. int i;
  1419. int fd;
  1420. int logflag;
  1421. auth = authmethods[0];
  1422. logflag = O_WRONLY|O_APPEND|O_CREAT;
  1423. ARGBEGIN{
  1424. case 'D':
  1425. chatty9p = 1;
  1426. break;
  1427. case 'a':
  1428. authtype = EARGF(usage());
  1429. auth = nil;
  1430. for(i=0; i<nelem(authmethods); i++)
  1431. if(strcmp(authmethods[i]->name, authtype)==0)
  1432. auth = authmethods[i];
  1433. if(auth == nil)
  1434. sysfatal("unknown auth type '%s'", authtype);
  1435. break;
  1436. case 'A':
  1437. autharg = EARGF(usage());
  1438. break;
  1439. case 'l':
  1440. logfile = EARGF(usage());
  1441. break;
  1442. case 'm':
  1443. msize = strtol(EARGF(usage()), 0, 0);
  1444. break;
  1445. case 'n':
  1446. network = 0;
  1447. break;
  1448. case 'u':
  1449. defaultuser = EARGF(usage());
  1450. break;
  1451. case 'z':
  1452. logflag |= O_TRUNC;
  1453. }ARGEND
  1454. if(argc > 1)
  1455. usage();
  1456. fd = open(logfile, logflag, 0666);
  1457. if(fd < 0)
  1458. sysfatal("cannot open log '%s'", logfile);
  1459. if(dup2(fd, 2) < 0)
  1460. sysfatal("cannot dup fd onto stderr");
  1461. fprint(2, "u9fs\nkill %d\n", (int)getpid());
  1462. fmtinstall('F', fcallconv);
  1463. fmtinstall('D', dirconv);
  1464. fmtinstall('M', dirmodeconv);
  1465. rxbuf = emalloc(msize);
  1466. txbuf = emalloc(msize);
  1467. databuf = emalloc(msize);
  1468. if(auth->init)
  1469. auth->init();
  1470. if(network)
  1471. getremotehostname(remotehostname, sizeof remotehostname);
  1472. if(gethostname(hostname, sizeof hostname) < 0)
  1473. strcpy(hostname, "gnot");
  1474. umask(0);
  1475. if(argc == 1)
  1476. if(chroot(argv[0]) < 0)
  1477. sysfatal("chroot '%s' failed", argv[0]);
  1478. none = uname2user("none");
  1479. serve(0, 1);
  1480. return 0;
  1481. }