smbtrans2find.c 8.8 KB

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