Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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;
                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;
}