nfs.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
  10. #include <u.h>
  11. #include <libc.h>
  12. #include <bio.h>
  13. #include <fcall.h>
  14. #include <thread.h>
  15. #include <9p.h>
  16. #include <sunrpc.h>
  17. #include <nfs3.h>
  18. SunClient *nfscli;
  19. SunClient *mntcli;
  20. char *defaultpath = "/";
  21. Channel *fschan;
  22. char *sys;
  23. int verbose;
  24. int readplus = 0;
  25. typedef struct Auth Auth;
  26. struct Auth
  27. {
  28. int ref;
  29. uchar *data;
  30. int ndata;
  31. };
  32. typedef struct FidAux FidAux;
  33. struct FidAux
  34. {
  35. Nfs3Handle handle;
  36. u64int cookie; /* for continuing directory reads */
  37. char *name; /* botch: for remove and rename */
  38. Nfs3Handle parent; /* botch: for remove and rename */
  39. char err[ERRMAX]; /* for walk1 */
  40. Auth *auth;
  41. };
  42. /*
  43. * various RPCs. here is where we'd insert support for NFS v2
  44. */
  45. void
  46. portCall(SunCall *c, PortCallType type)
  47. {
  48. c->rpc.prog = PortProgram;
  49. c->rpc.vers = PortVersion;
  50. c->rpc.proc = type>>1;
  51. c->rpc.iscall = !(type&1);
  52. c->type = type;
  53. }
  54. int
  55. getport(SunClient *client, uint prog, uint vers, uint prot, uint *port)
  56. {
  57. PortTGetport tx;
  58. PortRGetport rx;
  59. memset(&tx, 0, sizeof tx);
  60. portCall(&tx.call, PortCallTGetport);
  61. tx.map.prog = prog;
  62. tx.map.vers = vers;
  63. tx.map.prot = prot;
  64. memset(&rx, 0, sizeof rx);
  65. portCall(&rx.call, PortCallRGetport);
  66. if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
  67. return -1;
  68. *port = rx.port;
  69. return 0;
  70. }
  71. void
  72. mountCall(Auth *a, SunCall *c, NfsMount3CallType type)
  73. {
  74. c->rpc.iscall = !(type&1);
  75. c->rpc.proc = type>>1;
  76. c->rpc.prog = NfsMount3Program;
  77. c->rpc.vers = NfsMount3Version;
  78. if(c->rpc.iscall && a){
  79. c->rpc.cred.flavor = SunAuthSys;
  80. c->rpc.cred.data = a->data;
  81. c->rpc.cred.ndata = a->ndata;
  82. }
  83. c->type = type;
  84. }
  85. int
  86. mountNull(uint32_t tag)
  87. {
  88. NfsMount3TNull tx;
  89. NfsMount3RNull rx;
  90. memset(&tx, 0, sizeof tx);
  91. mountCall(nil, &tx.call, NfsMount3CallTNull);
  92. memset(&rx, 0, sizeof rx);
  93. mountCall(nil, &rx.call, NfsMount3CallTNull);
  94. return sunClientRpc(mntcli, tag, &tx.call, &rx.call, nil);
  95. }
  96. int
  97. mountMnt(Auth *a, uint32_t tag, char *path, Nfs3Handle *h)
  98. {
  99. uchar *freeme;
  100. NfsMount3TMnt tx;
  101. NfsMount3RMnt rx;
  102. memset(&tx, 0, sizeof tx);
  103. mountCall(a, &tx.call, NfsMount3CallTMnt);
  104. tx.path = path;
  105. memset(&rx, 0, sizeof rx);
  106. mountCall(a, &rx.call, NfsMount3CallRMnt);
  107. if(sunClientRpc(mntcli, tag, &tx.call, &rx.call, &freeme) < 0)
  108. return -1;
  109. if(rx.status != Nfs3Ok){
  110. nfs3Errstr(rx.status);
  111. return -1;
  112. }
  113. if(verbose)print("handle %.*H\n", rx.len, rx.handle);
  114. if(rx.len >= Nfs3MaxHandleSize){
  115. free(freeme);
  116. werrstr("server-returned handle too long");
  117. return -1;
  118. }
  119. memmove(h->h, rx.handle, rx.len);
  120. h->len = rx.len;
  121. free(freeme);
  122. return 0;
  123. }
  124. void
  125. nfs3Call(Auth *a, SunCall *c, Nfs3CallType type)
  126. {
  127. c->rpc.iscall = !(type&1);
  128. c->rpc.proc = type>>1;
  129. c->rpc.prog = Nfs3Program;
  130. c->rpc.vers = Nfs3Version;
  131. if(c->rpc.iscall && a){
  132. c->rpc.cred.flavor = SunAuthSys;
  133. c->rpc.cred.data = a->data;
  134. c->rpc.cred.ndata = a->ndata;
  135. }
  136. c->type = type;
  137. }
  138. int
  139. nfsNull(uint32_t tag)
  140. {
  141. Nfs3TNull tx;
  142. Nfs3RNull rx;
  143. memset(&tx, 0, sizeof tx);
  144. nfs3Call(nil, &tx.call, Nfs3CallTNull);
  145. memset(&rx, 0, sizeof rx);
  146. nfs3Call(nil, &rx.call, Nfs3CallTNull);
  147. return sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil);
  148. }
  149. int
  150. nfsGetattr(Auth *a, uint32_t tag, Nfs3Handle *h, Nfs3Attr *attr)
  151. {
  152. Nfs3TGetattr tx;
  153. Nfs3RGetattr rx;
  154. memset(&tx, 0, sizeof tx);
  155. nfs3Call(a, &tx.call, Nfs3CallTGetattr);
  156. tx.handle = *h;
  157. memset(&rx, 0, sizeof rx);
  158. nfs3Call(a, &rx.call, Nfs3CallRGetattr);
  159. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  160. return -1;
  161. if(rx.status != Nfs3Ok){
  162. nfs3Errstr(rx.status);
  163. return -1;
  164. }
  165. *attr = rx.attr;
  166. return 0;
  167. }
  168. int
  169. nfsAccess(Auth *a, uint32_t tag, Nfs3Handle *h, uint32_t want,
  170. uint32_t *got, u1int *have, Nfs3Attr *attr)
  171. {
  172. Nfs3TAccess tx;
  173. Nfs3RAccess rx;
  174. memset(&tx, 0, sizeof tx);
  175. nfs3Call(a, &tx.call, Nfs3CallTAccess);
  176. tx.handle = *h;
  177. tx.access = want;
  178. memset(&rx, 0, sizeof rx);
  179. nfs3Call(a, &rx.call, Nfs3CallRAccess);
  180. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  181. return -1;
  182. if(rx.status != Nfs3Ok){
  183. nfs3Errstr(rx.status);
  184. return -1;
  185. }
  186. *got = rx.access;
  187. *have = rx.haveAttr;
  188. if(rx.haveAttr)
  189. *attr = rx.attr;
  190. return 0;
  191. }
  192. int
  193. nfsMkdir(Auth *a, uint32_t tag, Nfs3Handle *h, char *name, Nfs3Handle *nh,
  194. uint32_t mode, uint gid,
  195. u1int *have, Nfs3Attr *attr)
  196. {
  197. Nfs3TMkdir tx;
  198. Nfs3RMkdir rx;
  199. memset(&tx, 0, sizeof tx);
  200. nfs3Call(a, &tx.call, Nfs3CallTMkdir);
  201. tx.handle = *h;
  202. tx.name = name;
  203. tx.attr.setMode = 1;
  204. tx.attr.mode = mode;
  205. tx.attr.setGid = 1;
  206. tx.attr.gid = gid;
  207. memset(&rx, 0, sizeof rx);
  208. nfs3Call(a, &rx.call, Nfs3CallRMkdir);
  209. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  210. return -1;
  211. if(rx.status != Nfs3Ok){
  212. nfs3Errstr(rx.status);
  213. return -1;
  214. }
  215. if(!rx.haveHandle){
  216. werrstr("nfs mkdir did not return handle");
  217. return -1;
  218. }
  219. *nh = rx.handle;
  220. *have = rx.haveAttr;
  221. if(rx.haveAttr)
  222. *attr = rx.attr;
  223. return 0;
  224. }
  225. int
  226. nfsCreate(Auth *a, uint32_t tag, Nfs3Handle *h, char *name, Nfs3Handle *nh,
  227. uint32_t mode, uint gid,
  228. u1int *have, Nfs3Attr *attr)
  229. {
  230. Nfs3TCreate tx;
  231. Nfs3RCreate rx;
  232. memset(&tx, 0, sizeof tx);
  233. nfs3Call(a, &tx.call, Nfs3CallTCreate);
  234. tx.handle = *h;
  235. tx.name = name;
  236. tx.attr.setMode = 1;
  237. tx.attr.mode = mode;
  238. tx.attr.setGid = 1;
  239. tx.attr.gid = gid;
  240. memset(&rx, 0, sizeof rx);
  241. nfs3Call(a, &rx.call, Nfs3CallRCreate);
  242. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  243. return -1;
  244. if(rx.status != Nfs3Ok){
  245. nfs3Errstr(rx.status);
  246. return -1;
  247. }
  248. if(!rx.haveHandle){
  249. werrstr("nfs create did not return handle");
  250. return -1;
  251. }
  252. *nh = rx.handle;
  253. *have = rx.haveAttr;
  254. if(rx.haveAttr)
  255. *attr = rx.attr;
  256. return 0;
  257. }
  258. int
  259. nfsRead(Auth *a, uint32_t tag, Nfs3Handle *h, u32int count, u64int offset,
  260. uchar **pp, u32int *pcount, uchar **pfreeme)
  261. {
  262. uchar *freeme;
  263. Nfs3TRead tx;
  264. Nfs3RRead rx;
  265. memset(&tx, 0, sizeof tx);
  266. nfs3Call(a, &tx.call, Nfs3CallTRead);
  267. tx.handle = *h;
  268. tx.count = count;
  269. tx.offset = offset;
  270. memset(&rx, 0, sizeof rx);
  271. nfs3Call(a, &rx.call, Nfs3CallRRead);
  272. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, &freeme) < 0)
  273. return -1;
  274. if(rx.status != Nfs3Ok){
  275. nfs3Errstr(rx.status);
  276. return -1;
  277. }
  278. if(rx.count != rx.ndata){
  279. werrstr("nfs read returned count=%ud ndata=%ud", (uint)rx.count, (uint)rx.ndata);
  280. free(freeme);
  281. return -1;
  282. }
  283. *pfreeme = freeme;
  284. *pcount = rx.count;
  285. *pp = rx.data;
  286. return 0;
  287. }
  288. int
  289. nfsWrite(Auth *a, uint32_t tag, Nfs3Handle *h, uchar *data, u32int count,
  290. u64int offset, u32int *pcount)
  291. {
  292. Nfs3TWrite tx;
  293. Nfs3RWrite rx;
  294. memset(&tx, 0, sizeof tx);
  295. nfs3Call(a, &tx.call, Nfs3CallTWrite);
  296. tx.handle = *h;
  297. tx.count = count;
  298. tx.offset = offset;
  299. tx.data = data;
  300. tx.ndata = count;
  301. memset(&rx, 0, sizeof rx);
  302. nfs3Call(a, &rx.call, Nfs3CallRWrite);
  303. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  304. return -1;
  305. if(rx.status != Nfs3Ok){
  306. nfs3Errstr(rx.status);
  307. return -1;
  308. }
  309. *pcount = rx.count;
  310. return 0;
  311. }
  312. int
  313. nfsRmdir(Auth *a, uint32_t tag, Nfs3Handle *h, char *name)
  314. {
  315. Nfs3TRmdir tx;
  316. Nfs3RRmdir rx;
  317. memset(&tx, 0, sizeof tx);
  318. nfs3Call(a, &tx.call, Nfs3CallTRmdir);
  319. tx.handle = *h;
  320. tx.name = name;
  321. memset(&rx, 0, sizeof rx);
  322. nfs3Call(a, &rx.call, Nfs3CallRRmdir);
  323. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  324. return -1;
  325. if(rx.status != Nfs3Ok){
  326. nfs3Errstr(rx.status);
  327. return -1;
  328. }
  329. return 0;
  330. }
  331. int
  332. nfsRemove(Auth *a, uint32_t tag, Nfs3Handle *h, char *name)
  333. {
  334. Nfs3TRemove tx;
  335. Nfs3RRemove rx;
  336. memset(&tx, 0, sizeof tx);
  337. nfs3Call(a, &tx.call, Nfs3CallTRemove);
  338. tx.handle = *h;
  339. tx.name = name;
  340. memset(&rx, 0, sizeof rx);
  341. nfs3Call(a, &rx.call, Nfs3CallRRemove);
  342. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  343. return -1;
  344. if(rx.status != Nfs3Ok){
  345. nfs3Errstr(rx.status);
  346. return -1;
  347. }
  348. return 0;
  349. }
  350. int
  351. nfsRename(Auth *a, uint32_t tag, Nfs3Handle *h, char *name, Nfs3Handle *th,
  352. char *tname)
  353. {
  354. Nfs3TRename tx;
  355. Nfs3RRename rx;
  356. memset(&tx, 0, sizeof tx);
  357. nfs3Call(a, &tx.call, Nfs3CallTRename);
  358. tx.from.handle = *h;
  359. tx.from.name = name;
  360. tx.to.handle = *th;
  361. tx.to.name = tname;
  362. memset(&rx, 0, sizeof rx);
  363. nfs3Call(a, &rx.call, Nfs3CallRRename);
  364. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  365. return -1;
  366. if(rx.status != Nfs3Ok){
  367. nfs3Errstr(rx.status);
  368. return -1;
  369. }
  370. return 0;
  371. }
  372. int
  373. nfsSetattr(Auth *a, uint32_t tag, Nfs3Handle *h, Nfs3SetAttr *attr)
  374. {
  375. Nfs3TSetattr tx;
  376. Nfs3RSetattr rx;
  377. memset(&tx, 0, sizeof tx);
  378. nfs3Call(a, &tx.call, Nfs3CallTSetattr);
  379. tx.handle = *h;
  380. tx.attr = *attr;
  381. memset(&rx, 0, sizeof rx);
  382. nfs3Call(a, &rx.call, Nfs3CallRSetattr);
  383. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  384. return -1;
  385. if(rx.status != Nfs3Ok){
  386. nfs3Errstr(rx.status);
  387. return -1;
  388. }
  389. return 0;
  390. }
  391. int
  392. nfsCommit(Auth *a, uint32_t tag, Nfs3Handle *h)
  393. {
  394. Nfs3TCommit tx;
  395. Nfs3RCommit rx;
  396. memset(&tx, 0, sizeof tx);
  397. nfs3Call(a, &tx.call, Nfs3CallTCommit);
  398. tx.handle = *h;
  399. memset(&rx, 0, sizeof rx);
  400. nfs3Call(a, &rx.call, Nfs3CallRCommit);
  401. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  402. return -1;
  403. if(rx.status != Nfs3Ok){
  404. nfs3Errstr(rx.status);
  405. return -1;
  406. }
  407. return 0;
  408. }
  409. int
  410. nfsLookup(Auth *a, uint32_t tag, Nfs3Handle *h, char *name, Nfs3Handle *nh,
  411. u1int *have, Nfs3Attr *attr)
  412. {
  413. Nfs3TLookup tx;
  414. Nfs3RLookup rx;
  415. memset(&tx, 0, sizeof tx);
  416. nfs3Call(a, &tx.call, Nfs3CallTLookup);
  417. tx.handle = *h;
  418. tx.name = name;
  419. memset(&rx, 0, sizeof rx);
  420. nfs3Call(a, &rx.call, Nfs3CallRLookup);
  421. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
  422. return -1;
  423. if(rx.status != Nfs3Ok){
  424. nfs3Errstr(rx.status);
  425. return -1;
  426. }
  427. *nh = rx.handle;
  428. *have = rx.haveAttr;
  429. if(rx.haveAttr)
  430. *attr = rx.attr;
  431. return 0;
  432. }
  433. int
  434. nfsReadDirPlus(Auth *a, uint32_t tag, Nfs3Handle *h, u32int count,
  435. u64int cookie, uchar **pp,
  436. u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
  437. {
  438. Nfs3TReadDirPlus tx;
  439. Nfs3RReadDirPlus rx;
  440. memset(&tx, 0, sizeof tx);
  441. nfs3Call(a, &tx.call, Nfs3CallTReadDirPlus);
  442. tx.handle = *h;
  443. tx.maxCount = count;
  444. tx.dirCount = 1000;
  445. tx.cookie = cookie;
  446. memset(&rx, 0, sizeof rx);
  447. nfs3Call(a, &rx.call, Nfs3CallRReadDirPlus);
  448. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
  449. return -1;
  450. if(rx.status != Nfs3Ok){
  451. free(*pfreeme);
  452. *pfreeme = 0;
  453. nfs3Errstr(rx.status);
  454. return -1;
  455. }
  456. *unpack = nfs3EntryPlusUnpack;
  457. *pcount = rx.count;
  458. *pp = rx.data;
  459. return 0;
  460. }
  461. int
  462. nfsReadDir(Auth *a, uint32_t tag, Nfs3Handle *h, u32int count,
  463. u64int cookie, uchar **pp,
  464. u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
  465. {
  466. /* BUG: try readdirplus */
  467. char e[ERRMAX];
  468. Nfs3TReadDir tx;
  469. Nfs3RReadDir rx;
  470. if(readplus!=-1){
  471. if(nfsReadDirPlus(a, tag, h, count, cookie, pp, pcount, unpack, pfreeme) == 0){
  472. readplus = 1;
  473. return 0;
  474. }
  475. if(readplus == 0){
  476. rerrstr(e, sizeof e);
  477. if(strstr(e, "procedure unavailable") || strstr(e, "not supported"))
  478. readplus = -1;
  479. }
  480. if(readplus == 0)
  481. fprint(2, "readdirplus: %r\n");
  482. }
  483. if(readplus == 1)
  484. return -1;
  485. memset(&tx, 0, sizeof tx);
  486. nfs3Call(a, &tx.call, Nfs3CallTReadDir);
  487. tx.handle = *h;
  488. tx.count = count;
  489. tx.cookie = cookie;
  490. memset(&rx, 0, sizeof rx);
  491. nfs3Call(a, &rx.call, Nfs3CallRReadDir);
  492. if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
  493. return -1;
  494. if(rx.status != Nfs3Ok){
  495. free(*pfreeme);
  496. *pfreeme = 0;
  497. nfs3Errstr(rx.status);
  498. return -1;
  499. }
  500. /* readplus failed but read succeeded */
  501. readplus = -1;
  502. *unpack = nfs3EntryUnpack;
  503. *pcount = rx.count;
  504. *pp = rx.data;
  505. return 0;
  506. }
  507. /*
  508. * name <-> int translation
  509. */
  510. typedef struct Map Map;
  511. typedef struct User User;
  512. typedef struct Group Group;
  513. Map *map;
  514. Map emptymap;
  515. struct User
  516. {
  517. char *name;
  518. uint uid;
  519. uint gid;
  520. uint g[16];
  521. uint ng;
  522. uchar *auth;
  523. int nauth;
  524. };
  525. struct Group
  526. {
  527. char *name; /* same pos as in User struct */
  528. uint gid; /* same pos as in User struct */
  529. };
  530. struct Map
  531. {
  532. int nuser;
  533. int ngroup;
  534. User *user;
  535. User **ubyname;
  536. User **ubyid;
  537. Group *group;
  538. Group **gbyname;
  539. Group **gbyid;
  540. };
  541. User*
  542. finduser(User **u, int nu, char *s)
  543. {
  544. int lo, hi, mid, n;
  545. hi = nu;
  546. lo = 0;
  547. while(hi > lo){
  548. mid = (lo+hi)/2;
  549. n = strcmp(u[mid]->name, s);
  550. if(n == 0)
  551. return u[mid];
  552. if(n < 0)
  553. lo = mid+1;
  554. else
  555. hi = mid;
  556. }
  557. return nil;
  558. }
  559. int
  560. strtoid(User **u, int nu, char *s, u32int *id)
  561. {
  562. u32int x;
  563. char *p;
  564. User *uu;
  565. x = strtoul(s, &p, 10);
  566. if(*s != 0 && *p == 0){
  567. *id = x;
  568. return 0;
  569. }
  570. uu = finduser(u, nu, s);
  571. if(uu == nil)
  572. return -1;
  573. *id = uu->uid;
  574. return 0;
  575. }
  576. char*
  577. idtostr(User **u, int nu, u32int id)
  578. {
  579. char buf[32];
  580. int lo, hi, mid;
  581. hi = nu;
  582. lo = 0;
  583. while(hi > lo){
  584. mid = (lo+hi)/2;
  585. if(u[mid]->uid == id)
  586. return estrdup9p(u[mid]->name);
  587. if(u[mid]->uid < id)
  588. lo = mid+1;
  589. else
  590. hi = mid;
  591. }
  592. snprint(buf, sizeof buf, "%ud", id);
  593. return estrdup9p(buf);
  594. }
  595. char*
  596. uidtostr(u32int uid)
  597. {
  598. return idtostr(map->ubyid, map->nuser, uid);
  599. }
  600. char*
  601. gidtostr(u32int gid)
  602. {
  603. return idtostr((User**)map->gbyid, map->ngroup, gid);
  604. }
  605. int
  606. strtouid(char *s, u32int *id)
  607. {
  608. return strtoid(map->ubyname, map->nuser, s, id);
  609. }
  610. int
  611. strtogid(char *s, u32int *id)
  612. {
  613. return strtoid((User**)map->gbyid, map->ngroup, s, id);
  614. }
  615. int
  616. idcmp(const void *va, const void *vb)
  617. {
  618. User **a, **b;
  619. a = (User**)va;
  620. b = (User**)vb;
  621. return (*a)->uid - (*b)->uid;
  622. }
  623. int
  624. namecmp(const void *va, const void *vb)
  625. {
  626. User **a, **b;
  627. a = (User**)va;
  628. b = (User**)vb;
  629. return strcmp((*a)->name, (*b)->name);
  630. }
  631. void
  632. closemap(Map *m)
  633. {
  634. int i;
  635. for(i=0; i<m->nuser; i++){
  636. free(m->user[i].name);
  637. free(m->user[i].auth);
  638. }
  639. for(i=0; i<m->ngroup; i++)
  640. free(m->group[i].name);
  641. free(m->user);
  642. free(m->group);
  643. free(m->ubyid);
  644. free(m->ubyname);
  645. free(m->gbyid);
  646. free(m->gbyname);
  647. free(m);
  648. }
  649. Map*
  650. readmap(char *passwd, char *group)
  651. {
  652. char *s, *f[10], *p, *nextp, *name;
  653. uchar *q, *eq;
  654. int i, n, nf, line, uid, gid;
  655. Biobuf *b;
  656. Map *m;
  657. User *u;
  658. Group *g;
  659. SunAuthUnix au;
  660. m = emalloc(sizeof(Map));
  661. if((b = Bopen(passwd, OREAD)) == nil){
  662. free(m);
  663. return nil;
  664. }
  665. line = 0;
  666. for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
  667. line++;
  668. if(s[0] == '#')
  669. continue;
  670. nf = getfields(s, f, nelem(f), 0, ":");
  671. if(nf < 4)
  672. continue;
  673. name = f[0];
  674. uid = strtol(f[2], &p, 10);
  675. if(f[2][0] == 0 || *p != 0){
  676. fprint(2, "%s:%d: non-numeric id in third field\n", passwd, line);
  677. continue;
  678. }
  679. gid = strtol(f[3], &p, 10);
  680. if(f[3][0] == 0 || *p != 0){
  681. fprint(2, "%s:%d: non-numeric id in fourth field\n", passwd, line);
  682. continue;
  683. }
  684. if(m->nuser%32 == 0)
  685. m->user = erealloc(m->user, (m->nuser+32)*sizeof(m->user[0]));
  686. u = &m->user[m->nuser++];
  687. u->name = estrdup9p(name);
  688. u->uid = uid;
  689. u->gid = gid;
  690. u->ng = 0;
  691. u->auth = 0;
  692. u->nauth = 0;
  693. }
  694. Bterm(b);
  695. m->ubyname = emalloc(m->nuser*sizeof(User*));
  696. m->ubyid = emalloc(m->nuser*sizeof(User*));
  697. for(i=0; i<m->nuser; i++){
  698. m->ubyname[i] = &m->user[i];
  699. m->ubyid[i] = &m->user[i];
  700. }
  701. qsort(m->ubyname, m->nuser, sizeof(m->ubyname[0]), namecmp);
  702. qsort(m->ubyid, m->nuser, sizeof(m->ubyid[0]), idcmp);
  703. if((b = Bopen(group, OREAD)) == nil){
  704. closemap(m);
  705. return nil;
  706. }
  707. line = 0;
  708. for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
  709. line++;
  710. if(s[0] == '#')
  711. continue;
  712. nf = getfields(s, f, nelem(f), 0, ":");
  713. if(nf < 4)
  714. continue;
  715. name = f[0];
  716. gid = strtol(f[2], &p, 10);
  717. if(f[2][0] == 0 || *p != 0){
  718. fprint(2, "%s:%d: non-numeric id in third field\n", group, line);
  719. continue;
  720. }
  721. if(m->ngroup%32 == 0)
  722. m->group = erealloc(m->group, (m->ngroup+32)*sizeof(m->group[0]));
  723. g = &m->group[m->ngroup++];
  724. g->name = estrdup9p(name);
  725. g->gid = gid;
  726. for(p=f[3]; *p; p=nextp){
  727. if((nextp = strchr(p, ',')) != nil)
  728. *nextp++ = 0;
  729. else
  730. nextp = p+strlen(p);
  731. u = finduser(m->ubyname, m->nuser, p);
  732. if(u == nil){
  733. if(verbose)
  734. fprint(2, "%s:%d: unknown user %s\n", group, line, p);
  735. continue;
  736. }
  737. if(u->ng >= nelem(u->g)){
  738. fprint(2, "%s:%d: user %s is in too many groups; ignoring %s\n", group, line, p, name);
  739. continue;
  740. }
  741. u->g[u->ng++] = gid;
  742. }
  743. }
  744. Bterm(b);
  745. m->gbyname = emalloc(m->ngroup*sizeof(Group*));
  746. m->gbyid = emalloc(m->ngroup*sizeof(Group*));
  747. for(i=0; i<m->ngroup; i++){
  748. m->gbyname[i] = &m->group[i];
  749. m->gbyid[i] = &m->group[i];
  750. }
  751. qsort(m->gbyname, m->ngroup, sizeof(m->gbyname[0]), namecmp);
  752. qsort(m->gbyid, m->ngroup, sizeof(m->gbyid[0]), idcmp);
  753. for(i=0; i<m->nuser; i++){
  754. au.stamp = 0;
  755. au.sysname = sys;
  756. au.uid = m->user[i].uid;
  757. au.gid = m->user[i].gid;
  758. memmove(au.g, m->user[i].g, sizeof au.g);
  759. au.ng = m->user[i].ng;
  760. n = sunAuthUnixSize(&au);
  761. q = emalloc(n);
  762. eq = q+n;
  763. m->user[i].auth = q;
  764. m->user[i].nauth = n;
  765. if(sunAuthUnixPack(q, eq, &q, &au) < 0 || q != eq){
  766. fprint(2, "sunAuthUnixPack failed for %s\n", m->user[i].name);
  767. free(m->user[i].auth);
  768. m->user[i].auth = 0;
  769. m->user[i].nauth = 0;
  770. }
  771. }
  772. return m;
  773. }
  774. Auth*
  775. mkauth(char *user)
  776. {
  777. Auth *a;
  778. uchar *p;
  779. int n;
  780. SunAuthUnix au;
  781. User *u;
  782. u = finduser(map->ubyname, map->nuser, user);
  783. if(u == nil || u->nauth == 0){
  784. /* nobody */
  785. au.stamp = 0;
  786. au.uid = -1;
  787. au.gid = -1;
  788. au.ng = 0;
  789. au.sysname = sys;
  790. n = sunAuthUnixSize(&au);
  791. a = emalloc(sizeof(Auth)+n);
  792. a->data = (uchar*)&a[1];
  793. a->ndata = n;
  794. if(sunAuthUnixPack(a->data, a->data+a->ndata, &p, &au) < 0
  795. || p != a->data+a->ndata){
  796. free(a);
  797. return nil;
  798. }
  799. a->ref = 1;
  800. if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
  801. return a;
  802. }
  803. a = emalloc(sizeof(Auth)+u->nauth);
  804. a->data = (uchar*)&a[1];
  805. a->ndata = u->nauth;
  806. memmove(a->data, u->auth, a->ndata);
  807. a->ref = 1;
  808. if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
  809. return a;
  810. }
  811. void
  812. freeauth(Auth *a)
  813. {
  814. if(--a->ref > 0)
  815. return;
  816. free(a);
  817. }
  818. /*
  819. * 9P server
  820. */
  821. void
  822. responderrstr(Req *r)
  823. {
  824. char e[ERRMAX];
  825. rerrstr(e, sizeof e);
  826. respond(r, e);
  827. }
  828. void
  829. fsdestroyfid(Fid *fid)
  830. {
  831. FidAux *aux;
  832. aux = fid->aux;
  833. if(aux == nil)
  834. return;
  835. freeauth(aux->auth);
  836. free(aux->name);
  837. free(aux);
  838. }
  839. void
  840. attrToQid(Nfs3Attr *attr, Qid *qid)
  841. {
  842. qid->path = attr->fileid;
  843. qid->vers = attr->mtime.sec;
  844. qid->type = 0;
  845. if(attr->type == Nfs3FileDir)
  846. qid->type |= QTDIR;
  847. }
  848. void
  849. attrToDir(Nfs3Attr *attr, Dir *d)
  850. {
  851. d->mode = attr->mode & 0777;
  852. if(attr->type == Nfs3FileDir)
  853. d->mode |= DMDIR;
  854. d->uid = uidtostr(attr->uid);
  855. d->gid = gidtostr(attr->gid);
  856. d->length = attr->size;
  857. attrToQid(attr, &d->qid);
  858. d->mtime = attr->mtime.sec;
  859. d->atime = attr->atime.sec;
  860. d->muid = nil;
  861. }
  862. void
  863. fsattach(Req *r)
  864. {
  865. char *path;
  866. Auth *auth;
  867. FidAux *aux;
  868. Nfs3Attr attr;
  869. Nfs3Handle h;
  870. path = r->ifcall.aname;
  871. if(path==nil || path[0]==0)
  872. path = defaultpath;
  873. auth = mkauth(r->ifcall.uname);
  874. if(mountMnt(auth, r->tag, path, &h) < 0
  875. || nfsGetattr(auth, r->tag, &h, &attr) < 0){
  876. freeauth(auth);
  877. responderrstr(r);
  878. return;
  879. }
  880. aux = emalloc(sizeof(FidAux));
  881. aux->auth = auth;
  882. aux->handle = h;
  883. aux->cookie = 0;
  884. aux->name = nil;
  885. memset(&aux->parent, 0, sizeof aux->parent);
  886. r->fid->aux = aux;
  887. attrToQid(&attr, &r->fid->qid);
  888. r->ofcall.qid = r->fid->qid;
  889. respond(r, nil);
  890. }
  891. void
  892. fsopen(Req *r)
  893. {
  894. FidAux *aux;
  895. Nfs3Attr attr;
  896. Nfs3SetAttr sa;
  897. u1int have;
  898. uint32_t a, b;
  899. aux = r->fid->aux;
  900. a = 0;
  901. switch(r->ifcall.mode&OMASK){
  902. case OREAD:
  903. a = 0x0001;
  904. break;
  905. case OWRITE:
  906. a = 0x0004;
  907. break;
  908. case ORDWR:
  909. a = 0x0001|0x0004;
  910. break;
  911. case OEXEC:
  912. a = 0x20;
  913. break;
  914. }
  915. if(r->ifcall.mode&OTRUNC)
  916. a |= 0x0004;
  917. if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0
  918. || (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){
  919. Error:
  920. responderrstr(r);
  921. return;
  922. }
  923. if(a != b){
  924. respond(r, "permission denied");
  925. return;
  926. }
  927. if(r->ifcall.mode&OTRUNC){
  928. memset(&sa, 0, sizeof sa);
  929. sa.setSize = 1;
  930. if(nfsSetattr(aux->auth, r->tag, &aux->handle, &sa) < 0)
  931. goto Error;
  932. }
  933. attrToQid(&attr, &r->fid->qid);
  934. r->ofcall.qid = r->fid->qid;
  935. respond(r, nil);
  936. }
  937. void
  938. fscreate(Req *r)
  939. {
  940. FidAux *aux;
  941. u1int have;
  942. Nfs3Attr attr;
  943. Nfs3Handle h;
  944. uint32_t mode;
  945. uint gid;
  946. int (*mk)(Auth*, uint32_t, Nfs3Handle*, char*, Nfs3Handle*,
  947. uint32_t, uint, u1int*, Nfs3Attr*);
  948. aux = r->fid->aux;
  949. /*
  950. * Plan 9 has no umask, so let's use the
  951. * parent directory bits like Plan 9 does.
  952. * What the heck, let's inherit the group too.
  953. * (Unix will let us set the group to anything
  954. * since we're the owner!)
  955. */
  956. if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
  957. responderrstr(r);
  958. return;
  959. }
  960. mode = r->ifcall.perm&0777;
  961. if(r->ifcall.perm&DMDIR)
  962. mode &= (attr.mode&0666) | ~0666;
  963. else
  964. mode &= (attr.mode&0777) | ~0777;
  965. gid = attr.gid;
  966. if(r->ifcall.perm&DMDIR)
  967. mk = nfsMkdir;
  968. else
  969. mk = nfsCreate;
  970. if((*mk)(aux->auth, r->tag, &aux->handle, r->ifcall.name, &h, mode, gid, &have, &attr) < 0
  971. || (!have && nfsGetattr(aux->auth, r->tag, &h, &attr) < 0)){
  972. responderrstr(r);
  973. return;
  974. }
  975. attrToQid(&attr, &r->fid->qid);
  976. aux->parent = aux->handle;
  977. aux->handle = h;
  978. free(aux->name);
  979. aux->name = estrdup9p(r->ifcall.name);
  980. r->ofcall.qid = r->fid->qid;
  981. respond(r, nil);
  982. }
  983. void
  984. fsreaddir(Req *r)
  985. {
  986. FidAux *aux;
  987. uchar *p, *freeme, *ep, *p9, *ep9;
  988. char *s;
  989. uint count;
  990. int n, (*unpack)(uchar*, uchar*, uchar**, Nfs3Entry*);
  991. Nfs3Entry e;
  992. u64int cookie;
  993. Dir d;
  994. aux = r->fid->aux;
  995. /*
  996. * r->ifcall.count seems a reasonable estimate to
  997. * how much NFS entry data we want. is it?
  998. */
  999. if(r->ifcall.offset)
  1000. cookie = aux->cookie;
  1001. else
  1002. cookie = 0;
  1003. if(nfsReadDir(aux->auth, r->tag, &aux->handle, r->ifcall.count, cookie,
  1004. &p, &count, &unpack, &freeme) < 0){
  1005. responderrstr(r);
  1006. return;
  1007. }
  1008. ep = p+count;
  1009. p9 = (uchar*)r->ofcall.data;
  1010. ep9 = p9+r->ifcall.count;
  1011. /*
  1012. * BUG: Issue all of the stat requests in parallel.
  1013. */
  1014. while(p < ep && p9 < ep9){
  1015. if((*unpack)(p, ep, &p, &e) < 0)
  1016. break;
  1017. aux->cookie = e.cookie;
  1018. if(strcmp(e.name, ".") == 0 || strcmp(e.name, "..") == 0)
  1019. continue;
  1020. for(s=e.name; (uchar)*s >= ' '; s++)
  1021. ;
  1022. if(*s != 0) /* bad character in name */
  1023. continue;
  1024. if(!e.haveAttr && !e.haveHandle)
  1025. if(nfsLookup(aux->auth, r->tag, &aux->handle, e.name, &e.handle, &e.haveAttr, &e.attr) < 0)
  1026. continue;
  1027. if(!e.haveAttr)
  1028. if(nfsGetattr(aux->auth, r->tag, &e.handle, &e.attr) < 0)
  1029. continue;
  1030. memset(&d, 0, sizeof d);
  1031. attrToDir(&e.attr, &d);
  1032. d.name = e.name;
  1033. if((n = convD2M(&d, p9, ep9-p9)) <= BIT16SZ)
  1034. break;
  1035. p9 += n;
  1036. }
  1037. free(freeme);
  1038. r->ofcall.count = p9 - (uchar*)r->ofcall.data;
  1039. respond(r, nil);
  1040. }
  1041. void
  1042. fsread(Req *r)
  1043. {
  1044. uchar *p, *freeme;
  1045. uint count;
  1046. FidAux *aux;
  1047. if(r->fid->qid.type&QTDIR){
  1048. fsreaddir(r);
  1049. return;
  1050. }
  1051. aux = r->fid->aux;
  1052. if(nfsRead(aux->auth, r->tag, &aux->handle, r->ifcall.count, r->ifcall.offset, &p, &count, &freeme) < 0){
  1053. responderrstr(r);
  1054. return;
  1055. }
  1056. r->ofcall.data = (char*)p;
  1057. r->ofcall.count = count;
  1058. respond(r, nil);
  1059. free(freeme);
  1060. }
  1061. void
  1062. fswrite(Req *r)
  1063. {
  1064. uint count;
  1065. FidAux *aux;
  1066. aux = r->fid->aux;
  1067. if(nfsWrite(aux->auth, r->tag, &aux->handle, (uchar*)r->ifcall.data, r->ifcall.count, r->ifcall.offset, &count) < 0){
  1068. responderrstr(r);
  1069. return;
  1070. }
  1071. r->ofcall.count = count;
  1072. respond(r, nil);
  1073. }
  1074. void
  1075. fsremove(Req *r)
  1076. {
  1077. int n;
  1078. FidAux *aux;
  1079. aux = r->fid->aux;
  1080. if(aux->name == nil){
  1081. respond(r, "nfs3client botch -- don't know parent handle in remove");
  1082. return;
  1083. }
  1084. if(r->fid->qid.type&QTDIR)
  1085. n = nfsRmdir(aux->auth, r->tag, &aux->parent, aux->name);
  1086. else
  1087. n = nfsRemove(aux->auth, r->tag, &aux->parent, aux->name);
  1088. if(n < 0){
  1089. responderrstr(r);
  1090. return;
  1091. }
  1092. respond(r, nil);
  1093. }
  1094. void
  1095. fsstat(Req *r)
  1096. {
  1097. FidAux *aux;
  1098. Nfs3Attr attr;
  1099. aux = r->fid->aux;
  1100. if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
  1101. responderrstr(r);
  1102. return;
  1103. }
  1104. memset(&r->d, 0, sizeof r->d);
  1105. attrToDir(&attr, &r->d);
  1106. r->d.name = estrdup9p(aux->name ? aux->name : "???");
  1107. respond(r, nil);
  1108. }
  1109. void
  1110. fswstat(Req *r)
  1111. {
  1112. int op, sync;
  1113. FidAux *aux;
  1114. Nfs3SetAttr attr;
  1115. memset(&attr, 0, sizeof attr);
  1116. aux = r->fid->aux;
  1117. /* Fill out stat first to catch errors */
  1118. op = 0;
  1119. sync = 1;
  1120. if(~r->d.mode){
  1121. if(r->d.mode&(DMAPPEND|DMEXCL)){
  1122. respond(r, "wstat -- DMAPPEND and DMEXCL bits not supported");
  1123. return;
  1124. }
  1125. op = 1;
  1126. sync = 0;
  1127. attr.setMode = 1;
  1128. attr.mode = r->d.mode & 0777;
  1129. }
  1130. if(r->d.uid && r->d.uid[0]){
  1131. attr.setUid = 1;
  1132. if(strtouid(r->d.uid, &attr.uid) < 0){
  1133. respond(r, "wstat -- unknown uid");
  1134. return;
  1135. }
  1136. op = 1;
  1137. sync = 0;
  1138. }
  1139. if(r->d.gid && r->d.gid[0]){
  1140. attr.setGid = 1;
  1141. if(strtogid(r->d.gid, &attr.gid) < 0){
  1142. respond(r, "wstat -- unknown gid");
  1143. return;
  1144. }
  1145. op = 1;
  1146. sync = 0;
  1147. }
  1148. if(~r->d.length){
  1149. attr.setSize = 1;
  1150. attr.size = r->d.length;
  1151. op = 1;
  1152. sync = 0;
  1153. }
  1154. if(~r->d.mtime){
  1155. attr.setMtime = Nfs3SetTimeClient;
  1156. attr.mtime.sec = r->d.mtime;
  1157. op = 1;
  1158. sync = 0;
  1159. }
  1160. if(~r->d.atime){
  1161. attr.setAtime = Nfs3SetTimeClient;
  1162. attr.atime.sec = r->d.atime;
  1163. op = 1;
  1164. sync = 0;
  1165. }
  1166. /* Try rename first because it's more likely to fail (?) */
  1167. if(r->d.name && r->d.name[0]){
  1168. if(aux->name == nil){
  1169. respond(r, "nfsclient botch -- don't know parent handle in rename");
  1170. return;
  1171. }
  1172. if(nfsRename(aux->auth, r->tag, &aux->parent, aux->name, &aux->parent, r->d.name) < 0){
  1173. responderrstr(r);
  1174. return;
  1175. }
  1176. free(aux->name);
  1177. aux->name = estrdup9p(r->d.name);
  1178. sync = 0;
  1179. }
  1180. /*
  1181. * Now we have a problem. The rename succeeded
  1182. * but the setattr could fail. Sic transit atomicity.
  1183. */
  1184. if(op){
  1185. if(nfsSetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
  1186. responderrstr(r);
  1187. return;
  1188. }
  1189. }
  1190. if(sync){
  1191. /* NFS commit */
  1192. if(nfsCommit(aux->auth, r->tag, &aux->handle) < 0){
  1193. responderrstr(r);
  1194. return;
  1195. }
  1196. }
  1197. respond(r, nil);
  1198. }
  1199. char*
  1200. fswalk1(Fid *fid, char *name, void *v)
  1201. {
  1202. u1int have;
  1203. uint32_t tag;
  1204. FidAux *aux;
  1205. Nfs3Attr attr;
  1206. Nfs3Handle h;
  1207. tag = *(uint32_t*)v;
  1208. aux = fid->aux;
  1209. if(nfsLookup(aux->auth, tag, &aux->handle, name, &h, &have, &attr) < 0
  1210. || (!have && nfsGetattr(aux->auth, tag, &h, &attr) < 0)){
  1211. rerrstr(aux->err, sizeof aux->err);
  1212. return aux->err;
  1213. }
  1214. aux->parent = aux->handle;
  1215. aux->handle = h;
  1216. free(aux->name);
  1217. if(strcmp(name, "..") == 0)
  1218. aux->name = nil;
  1219. else
  1220. aux->name = estrdup9p(name);
  1221. attrToQid(&attr, &fid->qid);
  1222. return nil;
  1223. }
  1224. char*
  1225. fsclone(Fid *fid, Fid *newfid, void*)
  1226. {
  1227. FidAux *a, *na;
  1228. a = fid->aux;
  1229. na = emalloc9p(sizeof(FidAux));
  1230. *na = *a;
  1231. if(na->name)
  1232. na->name = estrdup9p(na->name);
  1233. newfid->aux = na;
  1234. if(na->auth)
  1235. na->auth->ref++;
  1236. return nil;
  1237. }
  1238. void
  1239. fswalk(Req *r)
  1240. {
  1241. walkandclone(r, fswalk1, fsclone, &r->tag);
  1242. }
  1243. void
  1244. fsflush(Req *r)
  1245. {
  1246. Req *or;
  1247. /*
  1248. * Send on the flush channel(s).
  1249. * The library will make sure the response
  1250. * is delayed as necessary.
  1251. */
  1252. or = r->oldreq;
  1253. if(nfscli)
  1254. sendul(nfscli->flushchan, (uint32_t)or->tag);
  1255. if(mntcli)
  1256. sendul(mntcli->flushchan, (uint32_t)or->tag);
  1257. respond(r, nil);
  1258. }
  1259. void
  1260. fsdispatch(void *v)
  1261. {
  1262. Req *r;
  1263. r = v;
  1264. switch(r->ifcall.type){
  1265. default: respond(r, "unknown type"); break;
  1266. case Tattach: fsattach(r); break;
  1267. case Topen: fsopen(r); break;
  1268. case Tcreate: fscreate(r); break;
  1269. case Tread: fsread(r); break;
  1270. case Twrite: fswrite(r); break;
  1271. case Tremove: fsremove(r); break;
  1272. case Tflush: fsflush(r); break;
  1273. case Tstat: fsstat(r); break;
  1274. case Twstat: fswstat(r); break;
  1275. case Twalk: fswalk(r); break;
  1276. }
  1277. }
  1278. void
  1279. fsthread(void*)
  1280. {
  1281. Req *r;
  1282. while((r = recvp(fschan)) != nil)
  1283. threadcreate(fsdispatch, r, SunStackSize);
  1284. }
  1285. void
  1286. fssend(Req *r)
  1287. {
  1288. sendp(fschan, r);
  1289. }
  1290. void
  1291. fsdie(Srv*)
  1292. {
  1293. threadexitsall(nil);
  1294. }
  1295. Srv fs =
  1296. {
  1297. .destroyfid = fsdestroyfid,
  1298. .attach= fssend,
  1299. .open= fssend,
  1300. .create= fssend,
  1301. .read= fssend,
  1302. .write= fssend,
  1303. .remove= fssend,
  1304. .flush= fssend,
  1305. .stat= fssend,
  1306. .wstat= fssend,
  1307. .walk= fssend,
  1308. .end= fsdie
  1309. };
  1310. void
  1311. usage(void)
  1312. {
  1313. fprint(2, "usage: nfs [-DRv] [-p perm] [-s srvname] [-u passwd group] addr [addr]\n");
  1314. fprint(2, "\taddr - address of portmapper server\n");
  1315. fprint(2, "\taddr addr - addresses of mount server and nfs server\n");
  1316. exits("usage");
  1317. }
  1318. char*
  1319. netchangeport(char *addr, uint port, char *buf, uint nbuf)
  1320. {
  1321. char *r;
  1322. strecpy(buf, buf+nbuf, addr);
  1323. r = strrchr(buf, '!');
  1324. if(r == nil)
  1325. return nil;
  1326. r++;
  1327. seprint(r, buf+nbuf, "%ud", port);
  1328. return buf;
  1329. }
  1330. char mbuf[256], nbuf[256];
  1331. char *mountaddr, *nfsaddr;
  1332. Channel *csync;
  1333. int chattyrpc;
  1334. void dialproc(void*);
  1335. void
  1336. threadmain(int argc, char **argv)
  1337. {
  1338. char *srvname, *passwd, *group, *addr, *p;
  1339. SunClient *cli;
  1340. int proto;
  1341. uint mport, nport;
  1342. ulong perm;
  1343. Dir d;
  1344. perm = 0600;
  1345. passwd = nil;
  1346. group = nil;
  1347. srvname = nil;
  1348. sys = sysname();
  1349. if(sys == nil)
  1350. sys = "plan9";
  1351. ARGBEGIN{
  1352. default:
  1353. usage();
  1354. case 'D':
  1355. chatty9p++;
  1356. break;
  1357. case 'R':
  1358. chattyrpc++;
  1359. break;
  1360. case 'p':
  1361. perm = strtol(EARGF(usage()), &p, 8);
  1362. if(perm==0 || *p != 0)
  1363. usage();
  1364. break;
  1365. case 's':
  1366. srvname = EARGF(usage());
  1367. break;
  1368. case 'u':
  1369. passwd = EARGF(usage());
  1370. group = EARGF(usage());
  1371. break;
  1372. case 'v':
  1373. verbose++;
  1374. break;
  1375. }ARGEND
  1376. if(argc != 1 && argc != 2)
  1377. usage();
  1378. if(srvname == nil)
  1379. srvname = argv[0];
  1380. fmtinstall('B', sunRpcFmt);
  1381. fmtinstall('C', sunCallFmt);
  1382. fmtinstall('H', encodefmt);
  1383. sunFmtInstall(&portProg);
  1384. sunFmtInstall(&nfs3Prog);
  1385. sunFmtInstall(&nfsMount3Prog);
  1386. if(passwd && (map = readmap(passwd, group)) == nil)
  1387. fprint(2, "warning: reading %s and %s: %r\n", passwd, group);
  1388. if(map == nil)
  1389. map = &emptymap;
  1390. if(argc == 1){
  1391. addr = netmkaddr(argv[0], "udp", "portmap");
  1392. if((cli = sunDial(addr)) == nil)
  1393. sysfatal("dial %s: %r", addr);
  1394. cli->chatty = chattyrpc;
  1395. sunClientProg(cli, &portProg);
  1396. if(strstr(addr, "udp!"))
  1397. proto = PortProtoUdp;
  1398. else
  1399. proto = PortProtoTcp;
  1400. if(getport(cli, NfsMount3Program, NfsMount3Version, proto, &mport) < 0)
  1401. sysfatal("lookup mount program port: %r");
  1402. if(getport(cli, Nfs3Program, Nfs3Version, proto, &nport) < 0)
  1403. sysfatal("lookup nfs program port: %r");
  1404. sunClientClose(cli);
  1405. mountaddr = netchangeport(addr, mport, mbuf, sizeof mbuf);
  1406. nfsaddr = netchangeport(addr, nport, nbuf, sizeof nbuf);
  1407. strcat(mountaddr, "!r");
  1408. strcat(nfsaddr, "!r");
  1409. if(verbose)
  1410. fprint(2, "nfs %s %s\n", mountaddr, nfsaddr);
  1411. }else{
  1412. mountaddr = argv[0];
  1413. nfsaddr = argv[1];
  1414. }
  1415. /* have to dial in another proc because it creates threads */
  1416. csync = chancreate(sizeof(void*), 0);
  1417. proccreate(dialproc, nil, SunStackSize);
  1418. recvp(csync);
  1419. threadpostmountsrv(&fs, srvname, nil, 0);
  1420. if(perm != 0600){
  1421. p = smprint("/srv/%s", srvname);
  1422. if(p){
  1423. nulldir(&d);
  1424. d.mode = perm;
  1425. dirwstat(p, &d);
  1426. }
  1427. }
  1428. threadexits(nil);
  1429. }
  1430. void
  1431. dialproc(void*)
  1432. {
  1433. rfork(RFNAMEG);
  1434. rfork(RFNOTEG);
  1435. if((mntcli = sunDial(mountaddr)) == nil)
  1436. sysfatal("dial mount program at %s: %r", mountaddr);
  1437. mntcli->chatty = chattyrpc;
  1438. sunClientProg(mntcli, &nfsMount3Prog);
  1439. if(mountNull(0) < 0)
  1440. sysfatal("execute nop with mnt server at %s: %r", mountaddr);
  1441. if((nfscli = sunDial(nfsaddr)) == nil)
  1442. sysfatal("dial nfs program at %s: %r", nfsaddr);
  1443. nfscli->chatty = chattyrpc;
  1444. sunClientProg(nfscli, &nfs3Prog);
  1445. if(nfsNull(0) < 0)
  1446. sysfatal("execute nop with nfs server at %s: %r", nfsaddr);
  1447. fschan = chancreate(sizeof(Req*), 0);
  1448. threadcreate(fsthread, nil, SunStackSize);
  1449. sendp(csync, 0);
  1450. }