123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- #include "headers.h"
- static SmbProcessResult
- query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
- {
- vlong ntatime, ntmtime;
- ushort dosmode;
- ulong fnlfixupoffset;
- vlong allocsize;
- if (d == nil) {
- smbseterror(s, ERRDOS, ERRbadfile);
- return SmbProcessResultError;
- }
- switch (infolevel) {
- case SMB_QUERY_FILE_BASIC_INFO:
- ntatime = smbplan9time2time(d->atime);
- ntmtime = smbplan9time2time(d->mtime);
- dosmode = smbplan9mode2dosattr(d->mode);
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_BASIC_INFO\n");
- translogprint(s->transaction.in.setup[0], "REPLY:\n");
- translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
- translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
- translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
- if (!smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputv(s->transaction.out.data, ntatime)
- || !smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputl(s->transaction.out.data, dosmode))
- // || !smbbufferputl(s->transaction.out.data, 0))
- return SmbProcessResultMisc;
- break;
- case SMB_QUERY_FILE_ALL_INFO:
- ntatime = smbplan9time2time(d->atime);
- ntmtime = smbplan9time2time(d->mtime);
- dosmode = smbplan9mode2dosattr(d->mode);
- allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_ALL_INFO\n");
- translogprint(s->transaction.in.setup[0], "REPLY:\n");
- translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
- translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
- translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
- translogprint(s->transaction.in.setup[0], "allocsize=%d\n", allocsize);
- translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->mode & DMDIR) != 0);
- if (!smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputv(s->transaction.out.data, ntatime)
- || !smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputv(s->transaction.out.data, ntmtime)
- || !smbbufferputs(s->transaction.out.data, dosmode)
- || !smbbufferputbytes(s->transaction.out.data, nil, 6)
- || !smbbufferputv(s->transaction.out.data, allocsize)
- || !smbbufferputv(s->transaction.out.data, d->length)
- || !smbbufferputl(s->transaction.out.data, 0) // hard links - ha
- || !smbbufferputb(s->transaction.out.data, 0) // TODO delete pending
- || !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
- || !smbbufferputv(s->transaction.out.data, d->qid.path)
- || !smbbufferputl(s->transaction.out.data, 0) // EA size
- || !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
- || !smbbufferputv(s->transaction.out.data, cbo)
- || !smbbufferputs(s->transaction.out.data, dosmode)
- || !smbbufferputl(s->transaction.out.data, 0)) // alignment
- return SmbProcessResultMisc;
- fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
- if (!smbbufferputl(s->transaction.out.data, 0)
- || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
- || !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
- return SmbProcessResultMisc;
- break;
- case SMB_QUERY_FILE_STANDARD_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STANDARD_INFO\n");
- translogprint(s->transaction.in.setup[0], "REPLY:\n");
- translogprint(s->transaction.in.setup[0], "length=%lld", d->length);
- translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->qid.type & QTDIR) != 0);
- if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
- || !smbbufferputv(s->transaction.out.data, d->length)
- || !smbbufferputl(s->transaction.out.data, 1)
- || !smbbufferputb(s->transaction.out.data, 0)
- || !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
- return SmbProcessResultMisc;
- break;
- case SMB_QUERY_FILE_EA_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_EA_INFO\n");
- translogprint(s->transaction.in.setup[0], "REPLY:\n");
- translogprint(s->transaction.in.setup[0], "ea_len=0\n");
- if (!smbbufferputl(s->transaction.out.data, 0))
- return SmbProcessResultMisc;
- break;
- case SMB_QUERY_FILE_STREAM_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STREAM_INFO\n");
- translogprint(s->transaction.in.setup[0], "REPLY: failed\n");
- /* don't do it, never will */
- goto unknownlevel;
- default:
- smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
- unknownlevel:
- translogprint(s->transaction.in.setup[0], "[not supported]\n");
- smbseterror(s, ERRDOS, ERRunknownlevel);
- return SmbProcessResultError;
- }
- return SmbProcessResultReply;
- }
- SmbProcessResult
- smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
- {
- SmbTree *t;
- SmbBuffer *b = nil;
- SmbProcessResult pr;
- ushort infolevel;
- Dir *d;
- char *path = nil;
- char *fullpath;
- 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, &infolevel) || !smbbuffergetbytes(b, nil, 4)
- || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
- pr = SmbProcessResultMisc;
- goto done;
- }
- translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
- translogprint(s->transaction.in.setup[0], "path %s\n", path);
- fullpath = nil;
- smbstringprint(&fullpath, "%s%s", t->serv->path, path);
- translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
- d = dirstat(fullpath);
- pr = query(s, "path", path, infolevel, 0, d);
- free(d);
- free(fullpath);
- done:
- free(path);
- smbbufferfree(&b);
- return pr;
- }
- SmbProcessResult
- smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
- {
- SmbTree *t;
- SmbFile *f;
- SmbBuffer *b = nil;
- SmbProcessResult pr;
- ushort fid;
- ushort infolevel;
- Dir *d;
- 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)) {
- pr = SmbProcessResultMisc;
- goto done;
- }
- translogprint(s->transaction.in.setup[0], "fid 0x%.4ux\n", fid);
- translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
- f = smbidmapfind(s->fidmap, fid);
- if (f == nil) {
- smbseterror(s, ERRDOS, ERRbadfid);
- pr = SmbProcessResultError;
- goto done;
- }
- d = dirfstat(f->fd);
- pr = query(s, "file", f->name, infolevel, seek(f->fd, 0, 1), d);
- free(d);
- done:
- smbbufferfree(&b);
- return pr;
- }
- SmbProcessResult
- smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
- {
- SmbTree *t;
- ushort infolevel;
- SmbBuffer *b;
- SmbProcessResult pr;
- ulong fixup;
- ulong vnbase;
- 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, &infolevel)) {
- misc:
- pr = SmbProcessResultMisc;
- goto done;
- }
- pr = SmbProcessResultReply;
- switch (infolevel) {
- case SMB_INFO_ALLOCATION:
- translogprint(s->transaction.in.setup[0], "SMB_INFO_ALLOCATION\n");
- if (!smbbufferputl(s->transaction.out.data, 0)
- || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
- || !smbbufferputl(s->transaction.out.data, 0xffffffff)
- || !smbbufferputl(s->transaction.out.data, 0xffffffff)
- || !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
- goto misc;
- break;
- case SMB_INFO_VOLUME:
- translogprint(s->transaction.in.setup[0], "SMB_INFO_VOLUME\n");
- if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
- || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
- goto misc;
- break;
- case SMB_QUERY_FS_VOLUME_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_VOLUME_INFO\n");
- if (!smbbufferputv(s->transaction.out.data, 0)
- || !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
- goto misc;
- fixup = smbbufferwriteoffset(s->transaction.out.data);
- if (!smbbufferputl(s->transaction.out.data, 0)
- || !smbbufferputs(s->transaction.out.data, 0))
- goto misc;
- vnbase = smbbufferwriteoffset(s->transaction.out.data);
- if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
- || !smbbufferfixupl(s->transaction.out.data, fixup,
- smbbufferwriteoffset(s->transaction.out.data) - vnbase))
- goto misc;
- break;
- case SMB_QUERY_FS_SIZE_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_SIZE_INFO\n");
- if (!smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
- || !smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
- || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
- || !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
- goto misc;
- break;
- case SMB_QUERY_FS_ATTRIBUTE_INFO:
- translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_ATTRIBUTE_INFO\n");
- if (!smbbufferputl(s->transaction.out.data, 3)
- || !smbbufferputl(s->transaction.out.data, 255))
- goto misc;
- fixup = smbbufferwriteoffset(s->transaction.out.data);
- if (!smbbufferputl(s->transaction.out.data, 0)
- || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
- || !smbbufferfixuprelativel(s->transaction.out.data, fixup))
- goto misc;
- break;
- default:
- smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
- smbseterror(s, ERRDOS, ERRunknownlevel);
- pr = SmbProcessResultError;
- }
- done:
- smbbufferfree(&b);
- return pr;
- }
|