#include "headers.h"
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;
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;
}
|