SmbProcessResult smbcomflush(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *) { SmbTree *t; SmbFile *f; ushort fid; Dir nulldir; if (h->wordcount != 1) return SmbProcessResultFormat; fid = smbnhgets(pdata); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); return SmbProcessResultError; } memset(&nulldir, 0xff, sizeof(nulldir)); nulldir.name = nulldir.uid = nulldir.gid = nulldir.muid = nil; dirfwstat(f->fd, &nulldir); return smbbufferputack(s->response, h, &s->peerinfo); }
SmbProcessResult smbcomcreatedirectory(SmbSession *s, SmbHeader *h, uint8_t *, SmbBuffer *b) { int fd; char *path; char *fullpath = nil; SmbTree *t; uint8_t fmt; if (h->wordcount != 0) return SmbProcessResultFormat; if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) return SmbProcessResultFormat; smblogprint(h->command, "smbcomcreatedirectory: %s\n", path); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } smbstringprint(&fullpath, "%s%s", t->serv->path, path); fd = create(fullpath, OREAD, DMDIR | 0775); if (fd < 0) { smblogprint(h->command, "smbcomcreatedirectory failed: %r\n"); smbseterror(s, ERRDOS, ERRnoaccess); free(path); return SmbProcessResultError; } close(fd); free(fullpath); free(path); return smbbufferputack(s->response, h, &s->peerinfo); }
SmbProcessResult smbcomdelete(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b) { SmbProcessResult pr; uint16_t sattr; uint8_t fmt; char *pattern = nil; char *dir = nil; char *name = nil; Reprog *r = nil; SmbTree *t; int x, count; SmbDirCache *dc = nil; if (h->wordcount != 1) return SmbProcessResultFormat; sattr = smbnhgets(pdata); if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) return SmbProcessResultFormat; smblogprint(SMB_COM_DELETE, "searchattributes: 0x%.4x\npattern:%s\n", sattr, pattern); smbpathsplit(pattern, &dir, &name); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } dc = smbmkdircache(t, dir); if (dc == nil) { pr = SmbProcessResultMisc; goto done; } r = smbmkrep(name); count = 0; for (x = 0; x < dc->n; x++) { if (!smbmatch(dc->buf[x].name, r)) continue; if (smbremovefile(t, dir, dc->buf[x].name) == 0) count++; } if (count == 0) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; } else pr = smbbufferputack(s->response,h, &s->peerinfo); done: free(pattern); free(dir); free(name); smbdircachefree(&dc); free(r); return pr; }
SmbProcessResult smbtrans2setfileinformation(SmbSession *s, SmbHeader *h) { SmbTree *t; ushort infolevel; SmbBuffer *b; SmbProcessResult pr; ushort fid; SmbFile *f; vlong newsize; uvlong atime, mtime; ulong attr; ulong mode; t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) { misc: pr = SmbProcessResultMisc; goto done; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); pr = SmbProcessResultError; goto done; } switch (infolevel) { case SMB_SET_FILE_ALLOCATION_INFO: case SMB_SET_FILE_END_OF_FILE_INFO: if (s->transaction.in.tdcount < 8) goto misc; newsize = smbnhgetv(s->transaction.in.data); pr = smbtruncatefile(s, f, newsize); if (pr == SmbProcessResultReply && !smbbufferputs(s->transaction.out.parameters, 0)) goto misc; break; case SMB_SET_FILE_BASIC_INFO: if (s->transaction.in.tdcount < 4 * 8 + 4) goto misc; atime = smbnhgetv(s->transaction.in.data + 8); mtime = smbnhgetv(s->transaction.in.data + 24); attr = smbnhgetv(s->transaction.in.data + 32); if (attr) { Dir *od = dirfstat(f->fd); if (od == nil) goto noaccess; mode = smbdosattr2plan9wstatmode(od->mode, attr); free(od); } else mode = 0xffffffff; if (atime || mtime || mode != 0xffffffff) { Dir d; memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; if (atime) d.atime = smbtime2plan9time(atime); if (mtime) d.mtime = smbtime2plan9time(mtime); d.mode = mode; if (dirfwstat(f->fd, &d) < 0) { noaccess: smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } } if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; case SMB_SET_FILE_DISPOSITION_INFO: if (s->transaction.in.tdcount < 1) goto misc; f->sf->deleteonclose = *s->transaction.in.data; if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; default: smblogprint(-1, "smbtrans2setfileinformation: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; break; } done: smbbufferfree(&b); return pr; }
SmbProcessResult smbtrans2setpathinformation(SmbSession *s, SmbHeader *h) { char *fullpath, *path; SmbTree *t; ushort infolevel; SmbBuffer *b; SmbProcessResult pr; ushort atime, adate, mtime, mdate; ulong attr; ulong mode; ulong size; // uvlong length; t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); path = nil; if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4) || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) { misc: pr = SmbProcessResultMisc; goto done; } fullpath = nil; smbstringprint(&fullpath, "%s%s", t->serv->path, path); translogprint(s->transaction.in.setup[0], "path %s\n", path); translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel); translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath); switch (infolevel) { case SMB_INFO_STANDARD: if (s->transaction.in.tdcount < 6 * 4 + 2 * 2) goto misc; adate = smbnhgets(s->transaction.in.data + 6); atime = smbnhgets(s->transaction.in.data + 4); mdate = smbnhgets(s->transaction.in.data + 10); mtime = smbnhgets(s->transaction.in.data + 8); size = smbnhgetl(s->transaction.in.data + 12); attr = smbnhgets(s->transaction.in.data + 20); if (attr) { Dir *od = dirstat(fullpath); if (od == nil) goto noaccess; mode = smbdosattr2plan9wstatmode(od->mode, attr); free(od); } else mode = 0xffffffff; translogprint(s->transaction.in.setup[0], "mode 0%od\n", mode); // if (size) // length = size; // else // length = ~0LL; translogprint(s->transaction.in.setup[0], "size %lld\n", size); translogprint(s->transaction.in.setup[0], "adate %d atime %d", adate, atime); translogprint(s->transaction.in.setup[0], "mdate %d mtime %d\n", mdate, mtime); if (size || adate || atime || mdate || mtime || mode != 0xffffffff) { Dir d; memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; if (adate || atime) d.atime = smbdatetime2plan9time(adate, atime, s->tzoff); if (mdate || mtime) d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff); d.mode = mode; d.length = size; if (dirwstat(fullpath, &d) < 0) { noaccess: smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } } if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; default: smblogprint(-1, "smbtrans2setpathinformation: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; break; } done: smbbufferfree(&b); return pr; }
SmbProcessResult smbcomwrite(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) { SmbTree *t; SmbFile *f; ushort fid; ushort count; ulong offset; long nb; ushort yacount; uchar fmt; if (h->wordcount != 5) return SmbProcessResultFormat; fid = smbnhgets(pdata); pdata += 2; count = smbnhgets(pdata); pdata += 2; offset = smbnhgetl(pdata); smblogprint(SMB_COM_WRITE, "smbcomwrite: fid 0x%.4ux count 0x%.4ux offset 0x%.8lux\n", fid, count, offset); if (!smbbuffergetb(b, &fmt) || fmt != 1 || !smbbuffergets(b, &yacount) || yacount != count || smbbufferreadspace(b) < count) return SmbProcessResultFormat; t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); return SmbProcessResultError; } if (!f->ioallowed) { smbseterror(s, ERRDOS, ERRbadaccess); return SmbProcessResultError; } if (count == 0) { SmbProcessResult pr = smbtruncatefile(s, f, offset); if (pr != SmbProcessResultReply) return pr; nb = 0; } else { seek(f->fd, offset, 0); nb = write(f->fd, smbbufferreadpointer(b), count); if (nb < 0) { smbseterror(s, ERRDOS, ERRnoaccess); return SmbProcessResultError; } } h->wordcount = 1; if (!smbbufferputheader(s->response, h, &s->peerinfo) || !smbbufferputs(s->response, nb) || !smbbufferputs(s->response, 0)) return SmbProcessResultMisc; return SmbProcessResultReply; }
SmbProcessResult smbcomwriteandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) { uchar andxcommand; ushort andxoffset; ulong andxoffsetfixup; SmbTree *t; SmbFile *f; ushort dataoff, fid, count; vlong offset; long nb; if (h->wordcount != 12 && h->wordcount != 14) return SmbProcessResultFormat; andxcommand = *pdata++; // andx command pdata++; // reserved andxoffset = smbnhgets(pdata); pdata += 2; // andx offset fid = smbnhgets(pdata); pdata += 2; // fid offset = smbnhgetl(pdata); pdata += 4; // offset in file pdata += 4; // timeout pdata += 2; // write mode pdata += 2; // (Remaining) bytes waiting to be written pdata += 2; // Reserved count = smbnhgets(pdata); pdata += 2; // LSBs of length dataoff = smbnhgets(pdata); pdata += 2; // offset to data in packet if (dataoff + count > smbbufferwriteoffset(b)) return SmbProcessResultFormat; if(h->wordcount == 14) offset |= (vlong)smbnhgetl(pdata)<<32; smblogprint(SMB_COM_WRITE_ANDX, "smbcomwriteandx: fid 0x%.4ux count 0x%.4ux offset 0x%.llux\n", fid, count, offset); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); return SmbProcessResultError; } if (!f->ioallowed) { smbseterror(s, ERRDOS, ERRbadaccess); return SmbProcessResultError; } seek(f->fd, offset, 0); nb = write(f->fd, smbbufferpointer(b, dataoff), count); if (nb < 0) { smbseterror(s, ERRDOS, ERRnoaccess); return SmbProcessResultError; } h->wordcount = 6; if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)) return SmbProcessResultMisc; if (!smbbufferputs(s->response, nb) // Count || !smbbufferputs(s->response, 0) // Available || !smbbufferputl(s->response, 0) // Reserved || !smbbufferputs(s->response, 0)) // byte count in reply return SmbProcessResultMisc; if (andxcommand != SMB_COM_NO_ANDX_COMMAND) return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b); return SmbProcessResultReply; }
SmbProcessResult smbcomsetinformation2(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *) { uint16_t fid, adate, atime, mdate, mtime; SmbTree *t; SmbFile *f; Dir d; if (h->wordcount != 7) return SmbProcessResultFormat; fid = smbnhgets(pdata); adate = smbnhgets(pdata + 6); atime = smbnhgets(pdata + 8); mdate = smbnhgets(pdata + 10); mtime = smbnhgets(pdata + 12); smblogprint(h->command, "smbcomsetinformation2: fid 0x%.4ux adate 0x%.4ux atime 0x%.4ux mdate 0x%.4ux mtime 0x%.4ux\n", fid, adate, atime, mdate, mtime); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); return SmbProcessResultError; } memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; if (adate || atime || mdate || mtime) { //smblogprint(-1, "smbcomsetinformation2: changing times not implemented\n"); // return SmbProcessResultUnimp; /* something to change */ if (!(adate && atime && mdate && mtime)) { /* some null entries */ uint16_t odate, otime; Dir *od = dirfstat(f->fd); if (od == nil) { smbseterror(s, ERRDOS, ERRnoaccess); return SmbProcessResultError; } if (adate || atime) { /* something changed in access time */ if (!(adate && atime)) { /* some nulls in access time */ smbplan9time2datetime(d.atime, s->tzoff, &odate, &otime); if (adate == 0) adate = odate; if (atime == 0) atime = otime; } d.atime = smbdatetime2plan9time(adate, atime, s->tzoff); } if (mdate || mtime) { /* something changed in modify time */ if (!(mdate && mtime)) { /* some nulls in modify time */ smbplan9time2datetime(d.mtime, s->tzoff, &odate, &otime); if (mdate == 0) mdate = odate; if (mtime == 0) mtime = otime; } d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff); } free(od); } if (dirfwstat(f->fd, &d) < 0) { smbseterror(s, ERRDOS, ERRnoaccess); return SmbProcessResultError; } } return smbbufferputack(s->response, h, &s->peerinfo); }
SmbProcessResult smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) { uchar andxcommand; ushort andxoffset; ulong andxoffsetfixup; ushort fid; uchar locktype; uchar oplocklevel; ulong timeout; ushort numberofunlocks; ushort numberoflocks; SmbTree *t; SmbFile *f; int l; SmbProcessResult pr; ulong backupoffset; int large; if (!smbcheckwordcount("comlockingandx", h, 8)) return SmbProcessResultFormat; andxcommand = *pdata++; pdata++; andxoffset = smbnhgets(pdata); pdata += 2; fid = smbnhgets(pdata); pdata += 2; locktype = *pdata++; oplocklevel = *pdata++; timeout = smbnhgetl(pdata); pdata += 4; numberofunlocks = smbnhgets(pdata); pdata += 2; numberoflocks = smbnhgets(pdata); smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n", fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks); large = locktype & 0x10; locktype &= ~0x10; if (locktype != 0 || oplocklevel != 0) { smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype); return SmbProcessResultUnimp; } if (oplocklevel != 0) { smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel); return SmbProcessResultUnimp; } t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); error: return SmbProcessResultError; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); goto error; } backupoffset = smbbufferreadoffset(b); for (l = 0; l < numberofunlocks; l++) { ushort pid; uvlong offset; uvlong length; if (!getlock(b, large, &pid, &offset, &length)) { pr = SmbProcessResultFormat; goto done; } smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n", pid, offset, length); smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); } for (l = 0; l < numberoflocks; l++) { ushort pid; uvlong offset; uvlong length; if (!getlock(b, large, &pid, &offset, &length)) { pr = SmbProcessResultFormat; goto done; } smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n", pid, offset, length); if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length)) break; } if (l < numberoflocks) { ushort i; ushort pid; uvlong offset; uvlong length; smbbufferreadbackup(b, backupoffset); for (i = 0; i < l; i++) { assert(getlock(b, large, &pid, &offset, &length)); smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); } smbseterror(s, ERRDOS, ERRlock); goto error; } h->wordcount = 2; if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup) || !smbbufferputs(s->response, 0)) { // bytecount 0 pr = SmbProcessResultMisc; goto done; } if (andxcommand != SMB_COM_NO_ANDX_COMMAND) pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b); else pr = SmbProcessResultReply; done: return pr; }
void smbsearchclosebyid(SmbSession *s, ushort sid) { smbsearchclose(s, smbidmapfind(s->sidmap, sid)); }
SmbProcessResult smbtrans2findnext2(SmbSession *s, SmbHeader *h) { SmbBuffer *b; int debug; ushort sid, scount, infolevel; ulong resumekey; ushort flags; char *filename = nil; SmbProcessResult pr; ushort e; ulong nameoffset; ushort eos; SmbTree *t; SmbSearch *search; debug = smboptable[h->command].debug || smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug || smbglobals.log.find; b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &sid) || !smbbuffergets(b, &scount) || !smbbuffergets(b, &infolevel) || !smbbuffergetl(b, &resumekey) || !smbbuffergets(b, &flags) || !smbbuffergetstring(b, h, 0, &filename)) { pr = SmbProcessResultFormat; goto done; } smblogprintif(debug, "smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n", sid, scount, infolevel, resumekey, flags, filename); if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; goto done; } t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } search = smbidmapfind(s->sidmap, sid); if (search == nil) { smbseterror(s, ERRDOS, ERRnofiles); pr = SmbProcessResultError; goto done; } if (search->t != t) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } if ((flags & (1 << 3)) == 0) { long i; if (filename == nil) { smbseterror(s, ERRDOS, ERRnofiles); pr = SmbProcessResultError; goto done; } for (i = 0; i < search->dc->n; i++) if (strcmp(search->dc->buf[i].name, filename) == 0) { search->dc->i = i + 1; break; } } populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset); eos = search->dc->i >= search->dc->n; if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos)) smbsearchclose(s, search); smbbufferputs(s->transaction.out.parameters, e); smbbufferputs(s->transaction.out.parameters, eos); smbbufferputs(s->transaction.out.parameters, 0); smbbufferputs(s->transaction.out.parameters, nameoffset); pr = SmbProcessResultReply; done: smbbufferfree(&b); free(filename); return pr; }
SmbProcessResult smbtrans2findfirst2(SmbSession *s, SmbHeader *h) { SmbBuffer *b; char *pattern = nil; char *dir = nil; char *name = nil; ushort searchattributes, searchcount, flags, informationlevel; ulong searchstoragetype; SmbDirCache *dc = nil; ushort e; ulong nameoffset; ushort eos; SmbSearch *search; SmbProcessResult pr; Reprog *r = nil; SmbTree *t; int debug; debug = smboptable[h->command].debug || smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug || smbglobals.log.find; poolcheck(mainmem); b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &searchattributes) || !smbbuffergets(b, &searchcount) || !smbbuffergets(b, &flags) || !smbbuffergets(b, &informationlevel) || !smbbuffergetl(b, &searchstoragetype) || !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) { pr = SmbProcessResultFormat; goto done; } smbloglock(); smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes); smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount); smblogprintif(debug, "flags: 0x%.4ux\n", flags); smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel); smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype); smblogprintif(debug, "pattern: %s\n", pattern); smblogunlock(); smbpathsplit(pattern, &dir, &name); if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; goto done; } t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } dc = smbmkdircache(t, dir); if (dc == nil) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } poolcheck(mainmem); r = smbmkrep(name); populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset); poolcheck(mainmem); eos = dc->i >= dc->n; if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos)) smbdircachefree(&dc); poolcheck(mainmem); if (dc) { /* create a search handle */ search = smbsearchnew(s, dc, r, t); r = nil; dc = nil; } else search = nil; smbbufferputs(s->transaction.out.parameters, search ? search->id : 0); smbbufferputs(s->transaction.out.parameters, e); smbbufferputs(s->transaction.out.parameters, eos); smbbufferputs(s->transaction.out.parameters, 0); smbbufferputs(s->transaction.out.parameters, nameoffset); pr = SmbProcessResultReply; done: smbbufferfree(&b); free(pattern); free(dir); free(name); smbdircachefree(&dc); free(r); return pr; }