u9fs.c 31 KB

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