u9fs.c 31 KB

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