18ccd4a63SDavid du Colombier #include "headers.h"
28ccd4a63SDavid du Colombier
38ccd4a63SDavid du Colombier static SmbProcessResult
query(SmbSession * s,char * cmdname,char * filename,ushort infolevel,vlong cbo,Dir * d)48ccd4a63SDavid du Colombier query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
58ccd4a63SDavid du Colombier {
68ccd4a63SDavid du Colombier vlong ntatime, ntmtime;
78ccd4a63SDavid du Colombier ushort dosmode;
88ccd4a63SDavid du Colombier ulong fnlfixupoffset;
98ccd4a63SDavid du Colombier vlong allocsize;
108ccd4a63SDavid du Colombier
118ccd4a63SDavid du Colombier if (d == nil) {
128ccd4a63SDavid du Colombier smbseterror(s, ERRDOS, ERRbadfile);
138ccd4a63SDavid du Colombier return SmbProcessResultError;
148ccd4a63SDavid du Colombier }
158ccd4a63SDavid du Colombier
168ccd4a63SDavid du Colombier switch (infolevel) {
178ccd4a63SDavid du Colombier case SMB_QUERY_FILE_BASIC_INFO:
188ccd4a63SDavid du Colombier ntatime = smbplan9time2time(d->atime);
198ccd4a63SDavid du Colombier ntmtime = smbplan9time2time(d->mtime);
208ccd4a63SDavid du Colombier dosmode = smbplan9mode2dosattr(d->mode);
2186a363ceSDavid du Colombier
2286a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_BASIC_INFO\n");
2386a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "REPLY:\n");
2486a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
2586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
2686a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
2786a363ceSDavid du Colombier
288ccd4a63SDavid du Colombier if (!smbbufferputv(s->transaction.out.data, ntmtime)
298ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntatime)
308ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntmtime)
318ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntmtime)
328ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, dosmode))
338ccd4a63SDavid du Colombier return SmbProcessResultMisc;
348ccd4a63SDavid du Colombier break;
358ccd4a63SDavid du Colombier case SMB_QUERY_FILE_ALL_INFO:
368ccd4a63SDavid du Colombier ntatime = smbplan9time2time(d->atime);
378ccd4a63SDavid du Colombier ntmtime = smbplan9time2time(d->mtime);
388ccd4a63SDavid du Colombier dosmode = smbplan9mode2dosattr(d->mode);
398ccd4a63SDavid du Colombier allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
4086a363ceSDavid du Colombier
4186a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_ALL_INFO\n");
4286a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "REPLY:\n");
4386a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
4486a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
4586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
4686a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "allocsize=%d\n", allocsize);
4786a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->mode & DMDIR) != 0);
4886a363ceSDavid du Colombier
498ccd4a63SDavid du Colombier if (!smbbufferputv(s->transaction.out.data, ntmtime)
508ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntatime)
518ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntmtime)
528ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, ntmtime)
538ccd4a63SDavid du Colombier || !smbbufferputs(s->transaction.out.data, dosmode)
548ccd4a63SDavid du Colombier || !smbbufferputbytes(s->transaction.out.data, nil, 6)
558ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, allocsize)
568ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, d->length)
578ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0) // hard links - ha
588ccd4a63SDavid du Colombier || !smbbufferputb(s->transaction.out.data, 0) // TODO delete pending
598ccd4a63SDavid du Colombier || !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
608ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, d->qid.path)
618ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0) // EA size
628ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
638ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, cbo)
648ccd4a63SDavid du Colombier || !smbbufferputs(s->transaction.out.data, dosmode)
658ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0)) // alignment
668ccd4a63SDavid du Colombier return SmbProcessResultMisc;
678ccd4a63SDavid du Colombier fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
68b698dcfaSDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0)
69b698dcfaSDavid du Colombier || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
708ccd4a63SDavid du Colombier || !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
718ccd4a63SDavid du Colombier return SmbProcessResultMisc;
728ccd4a63SDavid du Colombier break;
738ccd4a63SDavid du Colombier case SMB_QUERY_FILE_STANDARD_INFO:
7486a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STANDARD_INFO\n");
7586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "REPLY:\n");
7686a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "length=%lld", d->length);
7786a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->qid.type & QTDIR) != 0);
7886a363ceSDavid du Colombier
798ccd4a63SDavid du Colombier if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
808ccd4a63SDavid du Colombier || !smbbufferputv(s->transaction.out.data, d->length)
818ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 1)
828ccd4a63SDavid du Colombier || !smbbufferputb(s->transaction.out.data, 0)
838ccd4a63SDavid du Colombier || !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
848ccd4a63SDavid du Colombier return SmbProcessResultMisc;
858ccd4a63SDavid du Colombier break;
868ccd4a63SDavid du Colombier case SMB_QUERY_FILE_EA_INFO:
8786a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_EA_INFO\n");
8886a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "REPLY:\n");
8986a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "ea_len=0\n");
908ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0))
918ccd4a63SDavid du Colombier return SmbProcessResultMisc;
928ccd4a63SDavid du Colombier break;
938ccd4a63SDavid du Colombier case SMB_QUERY_FILE_STREAM_INFO:
9486a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STREAM_INFO\n");
9586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "REPLY: failed\n");
968ccd4a63SDavid du Colombier /* don't do it, never will */
978ccd4a63SDavid du Colombier goto unknownlevel;
988ccd4a63SDavid du Colombier default:
998ccd4a63SDavid du Colombier smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
1008ccd4a63SDavid du Colombier unknownlevel:
10186a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "[not supported]\n");
1028ccd4a63SDavid du Colombier smbseterror(s, ERRDOS, ERRunknownlevel);
1038ccd4a63SDavid du Colombier return SmbProcessResultError;
1048ccd4a63SDavid du Colombier }
1058ccd4a63SDavid du Colombier return SmbProcessResultReply;
1068ccd4a63SDavid du Colombier }
1078ccd4a63SDavid du Colombier
1088ccd4a63SDavid du Colombier SmbProcessResult
smbtrans2querypathinformation(SmbSession * s,SmbHeader * h)1098ccd4a63SDavid du Colombier smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
1108ccd4a63SDavid du Colombier {
1118ccd4a63SDavid du Colombier SmbTree *t;
1128ccd4a63SDavid du Colombier SmbBuffer *b = nil;
1138ccd4a63SDavid du Colombier SmbProcessResult pr;
1148ccd4a63SDavid du Colombier ushort infolevel;
1158ccd4a63SDavid du Colombier Dir *d;
1168ccd4a63SDavid du Colombier char *path = nil;
1178ccd4a63SDavid du Colombier char *fullpath;
1188ccd4a63SDavid du Colombier
1198ccd4a63SDavid du Colombier t = smbidmapfind(s->tidmap, h->tid);
1208ccd4a63SDavid du Colombier if (t == nil) {
1218ccd4a63SDavid du Colombier smbseterror(s, ERRSRV, ERRinvtid);
1228ccd4a63SDavid du Colombier pr = SmbProcessResultError;
1238ccd4a63SDavid du Colombier goto done;
1248ccd4a63SDavid du Colombier }
1258ccd4a63SDavid du Colombier b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
1268ccd4a63SDavid du Colombier if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
1278ccd4a63SDavid du Colombier || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
1288ccd4a63SDavid du Colombier pr = SmbProcessResultMisc;
1298ccd4a63SDavid du Colombier goto done;
1308ccd4a63SDavid du Colombier }
13186a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
13286a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "path %s\n", path);
1338ccd4a63SDavid du Colombier fullpath = nil;
1348ccd4a63SDavid du Colombier smbstringprint(&fullpath, "%s%s", t->serv->path, path);
13586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
1368ccd4a63SDavid du Colombier d = dirstat(fullpath);
1378ccd4a63SDavid du Colombier pr = query(s, "path", path, infolevel, 0, d);
1388ccd4a63SDavid du Colombier free(d);
1398ccd4a63SDavid du Colombier free(fullpath);
1408ccd4a63SDavid du Colombier done:
1418ccd4a63SDavid du Colombier free(path);
1428ccd4a63SDavid du Colombier smbbufferfree(&b);
1438ccd4a63SDavid du Colombier return pr;
1448ccd4a63SDavid du Colombier }
1458ccd4a63SDavid du Colombier
1468ccd4a63SDavid du Colombier SmbProcessResult
smbtrans2queryfileinformation(SmbSession * s,SmbHeader * h)1478ccd4a63SDavid du Colombier smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
1488ccd4a63SDavid du Colombier {
1498ccd4a63SDavid du Colombier SmbTree *t;
1508ccd4a63SDavid du Colombier SmbFile *f;
1518ccd4a63SDavid du Colombier SmbBuffer *b = nil;
1528ccd4a63SDavid du Colombier SmbProcessResult pr;
1538ccd4a63SDavid du Colombier ushort fid;
1548ccd4a63SDavid du Colombier ushort infolevel;
155*f7b899b1SDavid du Colombier vlong o;
1568ccd4a63SDavid du Colombier Dir *d;
1578ccd4a63SDavid du Colombier
1588ccd4a63SDavid du Colombier t = smbidmapfind(s->tidmap, h->tid);
1598ccd4a63SDavid du Colombier if (t == nil) {
1608ccd4a63SDavid du Colombier smbseterror(s, ERRSRV, ERRinvtid);
1618ccd4a63SDavid du Colombier pr = SmbProcessResultError;
1628ccd4a63SDavid du Colombier goto done;
1638ccd4a63SDavid du Colombier }
1648ccd4a63SDavid du Colombier b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
1658ccd4a63SDavid du Colombier if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
1668ccd4a63SDavid du Colombier pr = SmbProcessResultMisc;
1678ccd4a63SDavid du Colombier goto done;
1688ccd4a63SDavid du Colombier }
16986a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "fid 0x%.4ux\n", fid);
17086a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
1718ccd4a63SDavid du Colombier f = smbidmapfind(s->fidmap, fid);
1728ccd4a63SDavid du Colombier if (f == nil) {
1738ccd4a63SDavid du Colombier smbseterror(s, ERRDOS, ERRbadfid);
1748ccd4a63SDavid du Colombier pr = SmbProcessResultError;
1758ccd4a63SDavid du Colombier goto done;
1768ccd4a63SDavid du Colombier }
177*f7b899b1SDavid du Colombier if(f->fd >= 0){
178*f7b899b1SDavid du Colombier o = seek(f->fd, 0, 1);
1798ccd4a63SDavid du Colombier d = dirfstat(f->fd);
180*f7b899b1SDavid du Colombier } else {
181*f7b899b1SDavid du Colombier char *fullpath = nil;
182*f7b899b1SDavid du Colombier
183*f7b899b1SDavid du Colombier o = 0;
184*f7b899b1SDavid du Colombier smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
185*f7b899b1SDavid du Colombier d = dirstat(fullpath);
186*f7b899b1SDavid du Colombier free(fullpath);
187*f7b899b1SDavid du Colombier }
188*f7b899b1SDavid du Colombier pr = query(s, "file", f->name, infolevel, o, d);
1898ccd4a63SDavid du Colombier free(d);
1908ccd4a63SDavid du Colombier done:
1918ccd4a63SDavid du Colombier smbbufferfree(&b);
1928ccd4a63SDavid du Colombier return pr;
1938ccd4a63SDavid du Colombier }
1948ccd4a63SDavid du Colombier
1958ccd4a63SDavid du Colombier SmbProcessResult
smbtrans2queryfsinformation(SmbSession * s,SmbHeader * h)1968ccd4a63SDavid du Colombier smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
1978ccd4a63SDavid du Colombier {
1988ccd4a63SDavid du Colombier SmbTree *t;
1998ccd4a63SDavid du Colombier ushort infolevel;
2008ccd4a63SDavid du Colombier SmbBuffer *b;
2018ccd4a63SDavid du Colombier SmbProcessResult pr;
2028ccd4a63SDavid du Colombier ulong fixup;
2038ccd4a63SDavid du Colombier ulong vnbase;
2048ccd4a63SDavid du Colombier
2058ccd4a63SDavid du Colombier t = smbidmapfind(s->tidmap, h->tid);
2068ccd4a63SDavid du Colombier if (t == nil) {
2078ccd4a63SDavid du Colombier smbseterror(s, ERRSRV, ERRinvtid);
2088ccd4a63SDavid du Colombier pr = SmbProcessResultError;
2098ccd4a63SDavid du Colombier goto done;
2108ccd4a63SDavid du Colombier }
2118ccd4a63SDavid du Colombier b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
2128ccd4a63SDavid du Colombier if (!smbbuffergets(b, &infolevel)) {
2138ccd4a63SDavid du Colombier misc:
2148ccd4a63SDavid du Colombier pr = SmbProcessResultMisc;
2158ccd4a63SDavid du Colombier goto done;
2168ccd4a63SDavid du Colombier }
2178ccd4a63SDavid du Colombier pr = SmbProcessResultReply;
2188ccd4a63SDavid du Colombier switch (infolevel) {
2198ccd4a63SDavid du Colombier case SMB_INFO_ALLOCATION:
22086a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_INFO_ALLOCATION\n");
2218ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0)
2228ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
2238ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0xffffffff)
2248ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0xffffffff)
2258ccd4a63SDavid du Colombier || !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
2268ccd4a63SDavid du Colombier goto misc;
2278ccd4a63SDavid du Colombier break;
2288ccd4a63SDavid du Colombier case SMB_INFO_VOLUME:
22986a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_INFO_VOLUME\n");
2308ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
2318ccd4a63SDavid du Colombier || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
2328ccd4a63SDavid du Colombier goto misc;
2338ccd4a63SDavid du Colombier break;
2348ccd4a63SDavid du Colombier case SMB_QUERY_FS_VOLUME_INFO:
23586a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_VOLUME_INFO\n");
2368ccd4a63SDavid du Colombier if (!smbbufferputv(s->transaction.out.data, 0)
2378ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
2388ccd4a63SDavid du Colombier goto misc;
2398ccd4a63SDavid du Colombier fixup = smbbufferwriteoffset(s->transaction.out.data);
2408ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0)
2418ccd4a63SDavid du Colombier || !smbbufferputs(s->transaction.out.data, 0))
2428ccd4a63SDavid du Colombier goto misc;
2438ccd4a63SDavid du Colombier vnbase = smbbufferwriteoffset(s->transaction.out.data);
2448ccd4a63SDavid du Colombier if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
2458ccd4a63SDavid du Colombier || !smbbufferfixupl(s->transaction.out.data, fixup,
2468ccd4a63SDavid du Colombier smbbufferwriteoffset(s->transaction.out.data) - vnbase))
2478ccd4a63SDavid du Colombier goto misc;
2488ccd4a63SDavid du Colombier break;
2498ccd4a63SDavid du Colombier case SMB_QUERY_FS_SIZE_INFO:
25086a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_SIZE_INFO\n");
251*f7b899b1SDavid du Colombier if (!smbbufferputv(s->transaction.out.data, 0LL)
252*f7b899b1SDavid du Colombier || !smbbufferputv(s->transaction.out.data, 0LL)
2538ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
2548ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
2558ccd4a63SDavid du Colombier goto misc;
2568ccd4a63SDavid du Colombier break;
2578ccd4a63SDavid du Colombier case SMB_QUERY_FS_ATTRIBUTE_INFO:
25886a363ceSDavid du Colombier translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_ATTRIBUTE_INFO\n");
2598ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 3)
2608ccd4a63SDavid du Colombier || !smbbufferputl(s->transaction.out.data, 255))
2618ccd4a63SDavid du Colombier goto misc;
2628ccd4a63SDavid du Colombier fixup = smbbufferwriteoffset(s->transaction.out.data);
2638ccd4a63SDavid du Colombier if (!smbbufferputl(s->transaction.out.data, 0)
2648ccd4a63SDavid du Colombier || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
2658ccd4a63SDavid du Colombier || !smbbufferfixuprelativel(s->transaction.out.data, fixup))
2668ccd4a63SDavid du Colombier goto misc;
2678ccd4a63SDavid du Colombier break;
2688ccd4a63SDavid du Colombier default:
2698ccd4a63SDavid du Colombier smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
2708ccd4a63SDavid du Colombier smbseterror(s, ERRDOS, ERRunknownlevel);
2718ccd4a63SDavid du Colombier pr = SmbProcessResultError;
2728ccd4a63SDavid du Colombier }
2738ccd4a63SDavid du Colombier done:
2748ccd4a63SDavid du Colombier smbbufferfree(&b);
2758ccd4a63SDavid du Colombier return pr;
2768ccd4a63SDavid du Colombier }
277