smbtrans2find.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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. #include "headers.h"
  10. #include <pool.h>
  11. void
  12. smbsearchfree(SmbSearch **searchp)
  13. {
  14. SmbSearch *search = *searchp;
  15. if (search) {
  16. smbdircachefree(&search->dc);
  17. free(search->rep);
  18. free(search);
  19. *searchp = nil;
  20. }
  21. }
  22. void
  23. smbsearchclose(SmbSession *s, SmbSearch *search)
  24. {
  25. if (search) {
  26. smblogprintif(smbglobals.log.sids, "smbsearchclose: tid 0x%.4x sid 0x%.4x\n", search->t->id, search->id);
  27. smbidmapremove(s->sidmap, search);
  28. smbsearchfree(&search);
  29. }
  30. }
  31. void
  32. smbsearchclosebyid(SmbSession *s, uint16_t sid)
  33. {
  34. smbsearchclose(s, smbidmapfind(s->sidmap, sid));
  35. }
  36. SmbSearch *
  37. smbsearchnew(SmbSession *s, SmbDirCache *dc, Reprog *r, SmbTree *t)
  38. {
  39. SmbSearch *search;
  40. if (s->sidmap == nil)
  41. s->sidmap = smbidmapnew();
  42. search = smbemalloc(sizeof(SmbSearch));
  43. smbidmapadd(s->sidmap, search);
  44. search->dc = dc;
  45. search->rep = r;
  46. search->t = t;
  47. smblogprintif(smbglobals.log.sids, "smbsearchnew: 0x%.4x\n", search->id);
  48. return search;
  49. }
  50. static int
  51. standardflatten(SmbSession *s, SmbBuffer *b, Dir *d, uint32_t *nameoffsetp)
  52. {
  53. uint16_t mdate, mtime;
  54. uint16_t adate, atime;
  55. uint16_t fnlfixupoffset;
  56. smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
  57. smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
  58. if (!smbbufferputs(b, mdate)
  59. || !smbbufferputs(b, mtime)
  60. || !smbbufferputs(b, adate)
  61. || !smbbufferputs(b, atime)
  62. || !smbbufferputs(b, mdate)
  63. || !smbbufferputs(b, mtime)
  64. || !smbbufferputl(b, d->length)
  65. || !smbbufferputl(b, 512) // ha
  66. || !smbbufferputs(b, (d->qid.type & QTDIR) ? 0x10 : 0))
  67. return 0;
  68. fnlfixupoffset = smbbufferwriteoffset(b);
  69. if (!smbbufferputs(b, 0))
  70. return 0;
  71. *nameoffsetp = smbbufferwriteoffset(b);
  72. if (!smbbufferputstring(b, &s->peerinfo, 0, d->name))
  73. return 0;
  74. return smbbufferfixuprelatives(b, fnlfixupoffset);
  75. }
  76. static int
  77. findbothflatten(SmbBuffer *b, SmbPeerInfo *p, Dir *d, uint32_t resumekey,
  78. uint32_t *nameoffsetp)
  79. {
  80. int64_t mtime, atime;
  81. uint32_t fixup;
  82. fixup = smbbufferwriteoffset(b);
  83. mtime = smbplan9time2time(d->mtime);
  84. atime = smbplan9time2time(d->atime);
  85. poolcheck(mainmem);
  86. if (!smbbufferputl(b, 0)
  87. || !smbbufferputl(b, resumekey)
  88. || !smbbufferputv(b, mtime)
  89. || !smbbufferputv(b, atime)
  90. || !smbbufferputv(b, mtime)
  91. || !smbbufferputv(b, mtime)
  92. || !smbbufferputv(b, d->length)
  93. || !smbbufferputv(b, smbl2roundupint64_t(d->length, smbglobals.l2allocationsize)) // ha
  94. || !smbbufferputl(b, (d->qid.type & QTDIR) ? 0x10 : 0x80)
  95. || !smbbufferputl(b, smbstringlen(p, d->name))
  96. || !smbbufferputl(b, 0)
  97. || !smbbufferputb(b, 0)
  98. || !smbbufferputb(b, 0)
  99. || !smbbufferfill(b, 0, 24))
  100. return 0;
  101. poolcheck(mainmem);
  102. *nameoffsetp = smbbufferwriteoffset(b);
  103. if (!smbbufferputstring(b, p, 0, d->name) || !smbbufferalignl2(b, 2))
  104. return 0;
  105. poolcheck(mainmem);
  106. return smbbufferfixuprelativeinclusivel(b, fixup);
  107. }
  108. static void
  109. populate(SmbSession *s, SmbDirCache *dc, Reprog *r, uint16_t informationlevel,
  110. uint16_t flags, uint16_t scount,
  111. uint16_t *ep, uint32_t *nameoffsetp)
  112. {
  113. uint16_t e;
  114. uint32_t nameoffset;
  115. e = 0;
  116. nameoffset = 0;
  117. while (dc->i < dc->n && e < scount) {
  118. uint32_t backup;
  119. int rv;
  120. if (!smbmatch(dc->buf[dc->i].name, r)) {
  121. dc->i++;
  122. continue;
  123. }
  124. rv = 0;
  125. backup = smbbufferwriteoffset(s->transaction.out.data);
  126. switch (informationlevel) {
  127. case SMB_INFO_STANDARD:
  128. if (flags & SMB_FIND_RETURN_RESUME_KEYS) {
  129. if (!smbbufferputl(s->transaction.out.data, dc->i)) {
  130. rv = 0;
  131. break;
  132. }
  133. }
  134. rv = standardflatten(s, s->transaction.out.data, dc->buf + dc->i, &nameoffset);
  135. break;
  136. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  137. rv = findbothflatten(s->transaction.out.data, &s->peerinfo, dc->buf + dc->i, dc->i, &nameoffset);
  138. break;
  139. }
  140. if (rv == 0) {
  141. smbbufferwritebackup(s->transaction.out.data, backup);
  142. break;
  143. }
  144. dc->i++;
  145. e++;
  146. }
  147. *ep = e;
  148. *nameoffsetp = nameoffset;
  149. }
  150. SmbProcessResult
  151. smbtrans2findfirst2(SmbSession *s, SmbHeader *h)
  152. {
  153. SmbBuffer *b;
  154. char *pattern = nil;
  155. char *dir = nil;
  156. char *name = nil;
  157. uint16_t searchattributes, searchcount, flags, informationlevel;
  158. uint32_t searchstoragetype;
  159. SmbDirCache *dc = nil;
  160. uint16_t e;
  161. uint32_t nameoffset;
  162. uint16_t eos;
  163. SmbSearch *search;
  164. SmbProcessResult pr;
  165. Reprog *r = nil;
  166. SmbTree *t;
  167. int debug;
  168. debug = smboptable[h->command].debug
  169. || smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug
  170. || smbglobals.log.find;
  171. poolcheck(mainmem);
  172. b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  173. if (!smbbuffergets(b, &searchattributes)
  174. || !smbbuffergets(b, &searchcount)
  175. || !smbbuffergets(b, &flags)
  176. || !smbbuffergets(b, &informationlevel)
  177. || !smbbuffergetl(b, &searchstoragetype)
  178. || !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) {
  179. pr = SmbProcessResultFormat;
  180. goto done;
  181. }
  182. smbloglock();
  183. smblogprintif(debug, "searchattributes: 0x%.4x\n", searchattributes);
  184. smblogprintif(debug, "searchcount: 0x%.4x\n", searchcount);
  185. smblogprintif(debug, "flags: 0x%.4x\n", flags);
  186. smblogprintif(debug, "informationlevel: 0x%.4x\n", informationlevel);
  187. smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype);
  188. smblogprintif(debug, "pattern: %s\n", pattern);
  189. smblogunlock();
  190. smbpathsplit(pattern, &dir, &name);
  191. if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  192. smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4x not implemented\n", informationlevel);
  193. smbseterror(s, ERRDOS, ERRunknownlevel);
  194. pr = SmbProcessResultError;
  195. goto done;
  196. }
  197. t = smbidmapfind(s->tidmap, h->tid);
  198. if (t == nil) {
  199. smbseterror(s, ERRSRV, ERRinvtid);
  200. pr = SmbProcessResultError;
  201. goto done;
  202. }
  203. dc = smbmkdircache(t, dir);
  204. if (dc == nil) {
  205. smbseterror(s, ERRDOS, ERRnoaccess);
  206. pr = SmbProcessResultError;
  207. goto done;
  208. }
  209. poolcheck(mainmem);
  210. r = smbmkrep(name);
  211. populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset);
  212. poolcheck(mainmem);
  213. eos = dc->i >= dc->n;
  214. if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
  215. smbdircachefree(&dc);
  216. poolcheck(mainmem);
  217. if (dc) {
  218. /* create a search handle */
  219. search = smbsearchnew(s, dc, r, t);
  220. r = nil;
  221. dc = nil;
  222. }
  223. else
  224. search = nil;
  225. smbbufferputs(s->transaction.out.parameters, search ? search->id : 0);
  226. smbbufferputs(s->transaction.out.parameters, e);
  227. smbbufferputs(s->transaction.out.parameters, eos);
  228. smbbufferputs(s->transaction.out.parameters, 0);
  229. smbbufferputs(s->transaction.out.parameters, nameoffset);
  230. pr = SmbProcessResultReply;
  231. done:
  232. smbbufferfree(&b);
  233. free(pattern);
  234. free(dir);
  235. free(name);
  236. smbdircachefree(&dc);
  237. free(r);
  238. return pr;
  239. }
  240. SmbProcessResult
  241. smbtrans2findnext2(SmbSession *s, SmbHeader *h)
  242. {
  243. SmbBuffer *b;
  244. int debug;
  245. uint16_t sid, scount, infolevel;
  246. uint32_t resumekey;
  247. uint16_t flags;
  248. char *filename = nil;
  249. SmbProcessResult pr;
  250. uint16_t e;
  251. uint32_t nameoffset;
  252. uint16_t eos;
  253. SmbTree *t;
  254. SmbSearch *search;
  255. debug = smboptable[h->command].debug
  256. || smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug
  257. || smbglobals.log.find;
  258. b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  259. if (!smbbuffergets(b, &sid)
  260. || !smbbuffergets(b, &scount)
  261. || !smbbuffergets(b, &infolevel)
  262. || !smbbuffergetl(b, &resumekey)
  263. || !smbbuffergets(b, &flags)
  264. || !smbbuffergetstring(b, h, 0, &filename)) {
  265. pr = SmbProcessResultFormat;
  266. goto done;
  267. }
  268. smblogprintif(debug,
  269. "smbtrans2findnext2: sid %d scount %d infolevel 0x%.4x resumekey %lu flags 0x%.4x filename %s\n",
  270. sid, scount, infolevel, resumekey, flags, filename);
  271. if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  272. smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4x not implemented\n", infolevel);
  273. smbseterror(s, ERRDOS, ERRunknownlevel);
  274. pr = SmbProcessResultError;
  275. goto done;
  276. }
  277. t = smbidmapfind(s->tidmap, h->tid);
  278. if (t == nil) {
  279. smbseterror(s, ERRSRV, ERRinvtid);
  280. pr = SmbProcessResultError;
  281. goto done;
  282. }
  283. search = smbidmapfind(s->sidmap, sid);
  284. if (search == nil) {
  285. smbseterror(s, ERRDOS, ERRnofiles);
  286. pr = SmbProcessResultError;
  287. goto done;
  288. }
  289. if (search->t != t) {
  290. smbseterror(s, ERRSRV, ERRinvtid);
  291. pr = SmbProcessResultError;
  292. goto done;
  293. }
  294. if ((flags & (1 << 3)) == 0) {
  295. int32_t i;
  296. if (filename == nil) {
  297. smbseterror(s, ERRDOS, ERRnofiles);
  298. pr = SmbProcessResultError;
  299. goto done;
  300. }
  301. for (i = 0; i < search->dc->n; i++)
  302. if (strcmp(search->dc->buf[i].name, filename) == 0) {
  303. search->dc->i = i + 1;
  304. break;
  305. }
  306. }
  307. populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset);
  308. eos = search->dc->i >= search->dc->n;
  309. if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
  310. smbsearchclose(s, search);
  311. smbbufferputs(s->transaction.out.parameters, e);
  312. smbbufferputs(s->transaction.out.parameters, eos);
  313. smbbufferputs(s->transaction.out.parameters, 0);
  314. smbbufferputs(s->transaction.out.parameters, nameoffset);
  315. pr = SmbProcessResultReply;
  316. done:
  317. smbbufferfree(&b);
  318. free(filename);
  319. return pr;
  320. }