1 #include "headers.h"
2
3 SmbProcessResult
smbtrans2setfileinformation(SmbSession * s,SmbHeader * h)4 smbtrans2setfileinformation(SmbSession *s, SmbHeader *h)
5 {
6 SmbTree *t;
7 ushort infolevel;
8 SmbBuffer *b;
9 SmbProcessResult pr;
10 ushort fid;
11 SmbFile *f;
12 vlong newsize;
13 uvlong atime, mtime;
14 ulong attr;
15 ulong mode;
16
17 t = smbidmapfind(s->tidmap, h->tid);
18 if (t == nil) {
19 smbseterror(s, ERRSRV, ERRinvtid);
20 pr = SmbProcessResultError;
21 goto done;
22 }
23 b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
24 if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
25 misc:
26 pr = SmbProcessResultMisc;
27 goto done;
28 }
29
30 f = smbidmapfind(s->fidmap, fid);
31 if (f == nil) {
32 smbseterror(s, ERRDOS, ERRbadfid);
33 pr = SmbProcessResultError;
34 goto done;
35 }
36
37 switch (infolevel) {
38 case SMB_SET_FILE_ALLOCATION_INFO:
39 case SMB_SET_FILE_END_OF_FILE_INFO:
40 if (s->transaction.in.tdcount < 8)
41 goto misc;
42 newsize = smbnhgetv(s->transaction.in.data);
43 pr = smbtruncatefile(s, f, newsize);
44 if (pr == SmbProcessResultReply && !smbbufferputs(s->transaction.out.parameters, 0))
45 goto misc;
46 break;
47
48 case SMB_SET_FILE_BASIC_INFO:
49 if (s->transaction.in.tdcount < 4 * 8 + 4)
50 goto misc;
51 atime = smbnhgetv(s->transaction.in.data + 8);
52 mtime = smbnhgetv(s->transaction.in.data + 24);
53 attr = smbnhgetv(s->transaction.in.data + 32);
54 if (attr) {
55 Dir *od = dirfstat(f->fd);
56 if (od == nil)
57 goto noaccess;
58 mode = smbdosattr2plan9wstatmode(od->mode, attr);
59 free(od);
60 }
61 else
62 mode = 0xffffffff;
63 if (atime || mtime || mode != 0xffffffff) {
64 Dir d;
65 memset(&d, 0xff, sizeof(d));
66 d.name = d.uid = d.gid = d.muid = nil;
67 if (atime)
68 d.atime = smbtime2plan9time(atime);
69 if (mtime)
70 d.mtime = smbtime2plan9time(mtime);
71 d.mode = mode;
72 if (dirfwstat(f->fd, &d) < 0) {
73 noaccess:
74 smbseterror(s, ERRDOS, ERRnoaccess);
75 pr = SmbProcessResultError;
76 goto done;
77 }
78 }
79 if (!smbbufferputs(s->transaction.out.parameters, 0))
80 goto misc;
81 pr = SmbProcessResultReply;
82 break;
83
84 case SMB_SET_FILE_DISPOSITION_INFO:
85 if (s->transaction.in.tdcount < 1)
86 goto misc;
87 f->sf->deleteonclose = *s->transaction.in.data;
88 if (!smbbufferputs(s->transaction.out.parameters, 0))
89 goto misc;
90 pr = SmbProcessResultReply;
91 break;
92
93 default:
94 smblogprint(-1, "smbtrans2setfileinformation: infolevel 0x%.4ux not implemented\n", infolevel);
95 smbseterror(s, ERRDOS, ERRunknownlevel);
96 pr = SmbProcessResultError;
97 break;
98 }
99 done:
100 smbbufferfree(&b);
101 return pr;
102 }
103
104 SmbProcessResult
smbtrans2setpathinformation(SmbSession * s,SmbHeader * h)105 smbtrans2setpathinformation(SmbSession *s, SmbHeader *h)
106 {
107 char *fullpath, *path;
108 SmbTree *t;
109 ushort infolevel;
110 SmbBuffer *b;
111 SmbProcessResult pr;
112 ushort atime, adate, mtime, mdate;
113 ulong attr;
114 ulong mode;
115 ulong size;
116 // uvlong length;
117
118 t = smbidmapfind(s->tidmap, h->tid);
119 if (t == nil) {
120 smbseterror(s, ERRSRV, ERRinvtid);
121 pr = SmbProcessResultError;
122 goto done;
123 }
124 b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
125 path = nil;
126 if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
127 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
128 misc:
129 pr = SmbProcessResultMisc;
130 goto done;
131 }
132
133 fullpath = nil;
134 smbstringprint(&fullpath, "%s%s", t->serv->path, path);
135
136 translogprint(s->transaction.in.setup[0], "path %s\n", path);
137 translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
138 translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
139
140 switch (infolevel) {
141 case SMB_INFO_STANDARD:
142 if (s->transaction.in.tdcount < 6 * 4 + 2 * 2)
143 goto misc;
144 adate = smbnhgets(s->transaction.in.data + 6);
145 atime = smbnhgets(s->transaction.in.data + 4);
146 mdate = smbnhgets(s->transaction.in.data + 10);
147 mtime = smbnhgets(s->transaction.in.data + 8);
148 size = smbnhgetl(s->transaction.in.data + 12);
149 attr = smbnhgets(s->transaction.in.data + 20);
150 if (attr) {
151 Dir *od = dirstat(fullpath);
152 if (od == nil)
153 goto noaccess;
154 mode = smbdosattr2plan9wstatmode(od->mode, attr);
155 free(od);
156 }
157 else
158 mode = 0xffffffff;
159 translogprint(s->transaction.in.setup[0], "mode 0%od\n", mode);
160
161 // if (size)
162 // length = size;
163 // else
164 // length = ~0LL;
165
166 translogprint(s->transaction.in.setup[0], "size %lld\n", size);
167 translogprint(s->transaction.in.setup[0], "adate %d atime %d", adate, atime);
168 translogprint(s->transaction.in.setup[0], "mdate %d mtime %d\n", mdate, mtime);
169
170 if (size || adate || atime || mdate || mtime || mode != 0xffffffff) {
171 Dir d;
172 memset(&d, 0xff, sizeof(d));
173 d.name = d.uid = d.gid = d.muid = nil;
174 if (adate || atime)
175 d.atime = smbdatetime2plan9time(adate, atime, s->tzoff);
176 if (mdate || mtime)
177 d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff);
178 d.mode = mode;
179 d.length = size;
180 if (dirwstat(fullpath, &d) < 0) {
181 noaccess:
182 smbseterror(s, ERRDOS, ERRnoaccess);
183 pr = SmbProcessResultError;
184 goto done;
185 }
186 }
187 if (!smbbufferputs(s->transaction.out.parameters, 0))
188 goto misc;
189 pr = SmbProcessResultReply;
190 break;
191
192 default:
193 smblogprint(-1, "smbtrans2setpathinformation: infolevel 0x%.4ux not implemented\n", infolevel);
194 smbseterror(s, ERRDOS, ERRunknownlevel);
195 pr = SmbProcessResultError;
196 break;
197 }
198 done:
199 smbbufferfree(&b);
200 return pr;
201 }
202