Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/aquarela/smbcomwrite.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "headers.h"
2
 
3
#define INMEMORYTRUNCTHRESH (256 * 1024)
4
 
5
static int
6
dirfwstatlength(int fd, vlong offset)
7
{
8
	Dir d;
9
	memset(&d, 0xff, sizeof(d));
10
	d.name = d.uid = d.gid = d.muid = nil;
11
	d.length = offset;
12
	return dirfwstat(fd, &d);
13
}
14
 
15
SmbProcessResult
16
smbtruncatefile(SmbSession *s, SmbFile *f, vlong offset)
17
{
18
	Dir *d;
19
	ulong o;
20
	uchar *db = nil;
21
	vlong length;
22
	int rv;
23
	SmbProcessResult pr;
24
 
25
	d = dirfstat(f->fd);
26
	assert(d);
27
	length = d->length;
28
	free(d);
29
 
30
	if (length == offset)
31
		return SmbProcessResultReply;
32
 
33
	rv = dirfwstatlength(f->fd, offset);
34
	if (rv == 0) {
35
		pr = SmbProcessResultReply;
36
		goto done;
37
	}
38
//smblogprint(-1, "dirfwstatlength failed: %r\n");
39
	if (length > offset) {
40
		int nfd;
41
		char *fullpath;
42
		if (offset > INMEMORYTRUNCTHRESH) {
43
			smblogprint(-1, "smbcomwrite: truncation beyond %lud not supported\n", offset);
44
			pr = SmbProcessResultUnimp;
45
			goto done;
46
		}
47
		db = smbemalloc(offset);
48
		if (pread(f->fd, db, offset, 0) != offset) {
49
			pr = SmbProcessResultMisc;
50
			goto done;
51
		}
52
		fullpath = nil;
53
		smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
54
		nfd = open(fullpath, f->p9mode | OTRUNC);
55
		free(fullpath);
56
		if (nfd < 0) {
57
			smbseterror(s, ERRDOS, ERRnoaccess);
58
			pr = SmbProcessResultError;
59
			goto done;
60
		}
61
		close(nfd);
62
		if (pwrite(f->fd, db, offset, 0) != offset) {
63
			pr = SmbProcessResultMisc;
64
			goto done;
65
		}
66
		pr = SmbProcessResultReply;
67
	}
68
	else {
69
		db = smbemalloc(16384);
70
		memset(db, 0, 16384);
71
		o = length;
72
		while (o < offset) {
73
			long tt = 16384;
74
			if (tt > offset - o)
75
				tt = offset - o;
76
			if (pwrite(f->fd, db, tt, o) != tt) {
77
				smbseterror(s, ERRDOS, ERRnoaccess);
78
				pr = SmbProcessResultError;
79
				goto done;
80
			}
81
			o += tt;
82
		}
83
		pr = SmbProcessResultReply;
84
	}
85
done:
86
	free(db);
87
	return pr;
88
}
89
 
90
SmbProcessResult
91
smbcomwrite(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
92
{
93
	SmbTree *t;
94
	SmbFile *f;
95
	ushort fid;
96
	ushort count;
97
	ulong offset;
98
	long nb;
99
	ushort yacount;
100
	uchar fmt;
101
 
102
	if (h->wordcount != 5)
103
		return SmbProcessResultFormat;
104
 
105
	fid = smbnhgets(pdata); pdata += 2;
106
	count = smbnhgets(pdata); pdata += 2;
107
	offset = smbnhgetl(pdata);
108
 
109
	smblogprint(SMB_COM_WRITE, "smbcomwrite: fid 0x%.4ux count 0x%.4ux offset 0x%.8lux\n",
110
		fid, count, offset);
111
 
112
	if (!smbbuffergetb(b, &fmt)
113
		|| fmt != 1
114
		|| !smbbuffergets(b, &yacount)
115
		|| yacount != count
116
		|| smbbufferreadspace(b) < count)
117
		return SmbProcessResultFormat;
118
 
119
	t = smbidmapfind(s->tidmap, h->tid);
120
	if (t == nil) {
121
		smbseterror(s, ERRSRV, ERRinvtid);
122
		return SmbProcessResultError;
123
	}
124
	f = smbidmapfind(s->fidmap, fid);
125
	if (f == nil) {
126
		smbseterror(s, ERRDOS, ERRbadfid);
127
		return SmbProcessResultError;
128
	}
129
 
130
	if (!f->ioallowed) {
131
		smbseterror(s, ERRDOS, ERRbadaccess);
132
		return SmbProcessResultError;
133
	}
134
 
135
	if (count == 0) {
136
		SmbProcessResult pr = smbtruncatefile(s, f, offset);
137
		if (pr != SmbProcessResultReply)
138
			return pr;
139
		nb = 0;
140
	}
141
	else {
142
		seek(f->fd, offset, 0);
143
		nb = write(f->fd, smbbufferreadpointer(b), count);
144
		if (nb < 0) {
145
			smbseterror(s, ERRDOS, ERRnoaccess);
146
			return SmbProcessResultError;
147
		}
148
	}
149
	h->wordcount = 1;
150
	if (!smbbufferputheader(s->response, h, &s->peerinfo)
151
		|| !smbbufferputs(s->response, nb)
152
		|| !smbbufferputs(s->response, 0))
153
		return SmbProcessResultMisc;
154
	return SmbProcessResultReply;
155
}
156
 
157
SmbProcessResult
158
smbcomwriteandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
159
{
160
	uchar andxcommand;
161
	ushort andxoffset;
162
	ulong andxoffsetfixup;
163
	SmbTree *t;
164
	SmbFile *f;
165
	ushort dataoff, fid, count;
166
	vlong offset;
167
	long nb;
168
 
169
	if (h->wordcount != 12 && h->wordcount != 14)
170
		return SmbProcessResultFormat;
171
 
172
	andxcommand = *pdata++;				// andx command
173
	pdata++;					// reserved 
174
	andxoffset = smbnhgets(pdata); pdata += 2;	// andx offset
175
	fid = smbnhgets(pdata); pdata += 2;		// fid
176
	offset = smbnhgetl(pdata); pdata += 4;		// offset in file
177
	pdata += 4;					// timeout
178
	pdata += 2;					// write mode
179
	pdata += 2;					// (Remaining) bytes waiting to be written
180
	pdata += 2;					// Reserved
181
	count = smbnhgets(pdata); pdata += 2;		// LSBs of length
182
	dataoff = smbnhgets(pdata); pdata += 2;		// offset to data in packet
183
	if (dataoff + count > smbbufferwriteoffset(b))
184
		return SmbProcessResultFormat;
185
	if(h->wordcount == 14)
186
		offset |= (vlong)smbnhgetl(pdata)<<32;
187
 
188
	smblogprint(SMB_COM_WRITE_ANDX, "smbcomwriteandx: fid 0x%.4ux count 0x%.4ux offset 0x%.llux\n",
189
		fid, count, offset);
190
 
191
 
192
	t = smbidmapfind(s->tidmap, h->tid);
193
	if (t == nil) {
194
		smbseterror(s, ERRSRV, ERRinvtid);
195
		return SmbProcessResultError;
196
	}
197
	f = smbidmapfind(s->fidmap, fid);
198
	if (f == nil) {
199
		smbseterror(s, ERRDOS, ERRbadfid);
200
		return SmbProcessResultError;
201
	}
202
 
203
	if (!f->ioallowed) {
204
		smbseterror(s, ERRDOS, ERRbadaccess);
205
		return SmbProcessResultError;
206
	}
207
 
208
	seek(f->fd, offset, 0);
209
	nb = write(f->fd, smbbufferpointer(b, dataoff), count);
210
	if (nb < 0) {
211
		smbseterror(s, ERRDOS, ERRnoaccess);
212
		return SmbProcessResultError;
213
	}
214
 
215
	h->wordcount = 6;
216
	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
217
		return SmbProcessResultMisc;
218
 
219
	if (!smbbufferputs(s->response, nb)			// Count
220
		|| !smbbufferputs(s->response, 0)		// Available
221
		|| !smbbufferputl(s->response, 0)		// Reserved
222
		|| !smbbufferputs(s->response, 0))		// byte count in reply
223
		return SmbProcessResultMisc;
224
 
225
	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
226
		return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
227
 
228
	return SmbProcessResultReply;
229
}