xref: /plan9/sys/src/cmd/aquarela/smbtrans2find.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include "headers.h"
2*8ccd4a63SDavid du Colombier #include <pool.h>
3*8ccd4a63SDavid du Colombier 
4*8ccd4a63SDavid du Colombier void
smbsearchfree(SmbSearch ** searchp)5*8ccd4a63SDavid du Colombier smbsearchfree(SmbSearch **searchp)
6*8ccd4a63SDavid du Colombier {
7*8ccd4a63SDavid du Colombier 	SmbSearch *search = *searchp;
8*8ccd4a63SDavid du Colombier 	if (search) {
9*8ccd4a63SDavid du Colombier 		smbdircachefree(&search->dc);
10*8ccd4a63SDavid du Colombier 		free(search->rep);
11*8ccd4a63SDavid du Colombier 		free(search);
12*8ccd4a63SDavid du Colombier 		*searchp = nil;
13*8ccd4a63SDavid du Colombier 	}
14*8ccd4a63SDavid du Colombier }
15*8ccd4a63SDavid du Colombier 
16*8ccd4a63SDavid du Colombier void
smbsearchclose(SmbSession * s,SmbSearch * search)17*8ccd4a63SDavid du Colombier smbsearchclose(SmbSession *s, SmbSearch *search)
18*8ccd4a63SDavid du Colombier {
19*8ccd4a63SDavid du Colombier 	if (search) {
20*8ccd4a63SDavid du Colombier 		smblogprintif(smbglobals.log.sids, "smbsearchclose: tid 0x%.4ux sid 0x%.4ux\n", search->t->id, search->id);
21*8ccd4a63SDavid du Colombier 		smbidmapremove(s->sidmap, search);
22*8ccd4a63SDavid du Colombier 		smbsearchfree(&search);
23*8ccd4a63SDavid du Colombier 	}
24*8ccd4a63SDavid du Colombier }
25*8ccd4a63SDavid du Colombier 
26*8ccd4a63SDavid du Colombier void
smbsearchclosebyid(SmbSession * s,ushort sid)27*8ccd4a63SDavid du Colombier smbsearchclosebyid(SmbSession *s, ushort sid)
28*8ccd4a63SDavid du Colombier {
29*8ccd4a63SDavid du Colombier 	smbsearchclose(s,  smbidmapfind(s->sidmap, sid));
30*8ccd4a63SDavid du Colombier }
31*8ccd4a63SDavid du Colombier 
32*8ccd4a63SDavid du Colombier SmbSearch *
smbsearchnew(SmbSession * s,SmbDirCache * dc,Reprog * r,SmbTree * t)33*8ccd4a63SDavid du Colombier smbsearchnew(SmbSession *s, SmbDirCache *dc, Reprog *r, SmbTree *t)
34*8ccd4a63SDavid du Colombier {
35*8ccd4a63SDavid du Colombier 	SmbSearch *search;
36*8ccd4a63SDavid du Colombier 	if (s->sidmap == nil)
37*8ccd4a63SDavid du Colombier 		s->sidmap = smbidmapnew();
38*8ccd4a63SDavid du Colombier 	search = smbemalloc(sizeof(SmbSearch));
39*8ccd4a63SDavid du Colombier 	smbidmapadd(s->sidmap, search);
40*8ccd4a63SDavid du Colombier 	search->dc = dc;
41*8ccd4a63SDavid du Colombier 	search->rep = r;
42*8ccd4a63SDavid du Colombier 	search->t = t;
43*8ccd4a63SDavid du Colombier 	smblogprintif(smbglobals.log.sids, "smbsearchnew: 0x%.4ux\n", search->id);
44*8ccd4a63SDavid du Colombier 	return search;
45*8ccd4a63SDavid du Colombier }
46*8ccd4a63SDavid du Colombier 
47*8ccd4a63SDavid du Colombier static int
standardflatten(SmbSession * s,SmbBuffer * b,Dir * d,ulong * nameoffsetp)48*8ccd4a63SDavid du Colombier standardflatten(SmbSession *s, SmbBuffer *b, Dir *d, ulong *nameoffsetp)
49*8ccd4a63SDavid du Colombier {
50*8ccd4a63SDavid du Colombier 	ushort mdate, mtime;
51*8ccd4a63SDavid du Colombier 	ushort adate, atime;
52*8ccd4a63SDavid du Colombier 	ushort fnlfixupoffset;
53*8ccd4a63SDavid du Colombier 
54*8ccd4a63SDavid du Colombier 	smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
55*8ccd4a63SDavid du Colombier 	smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
56*8ccd4a63SDavid du Colombier 	if (!smbbufferputs(b, mdate)
57*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, mtime)
58*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, adate)
59*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, atime)
60*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, mdate)
61*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, mtime)
62*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, d->length)
63*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, 512)			// ha
64*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(b, (d->qid.type & QTDIR) ? 0x10 : 0))
65*8ccd4a63SDavid du Colombier 		return 0;
66*8ccd4a63SDavid du Colombier 	fnlfixupoffset = smbbufferwriteoffset(b);
67*8ccd4a63SDavid du Colombier 	if (!smbbufferputs(b, 0))
68*8ccd4a63SDavid du Colombier 		return 0;
69*8ccd4a63SDavid du Colombier 	*nameoffsetp = smbbufferwriteoffset(b);
70*8ccd4a63SDavid du Colombier 	if (!smbbufferputstring(b, &s->peerinfo, 0, d->name))
71*8ccd4a63SDavid du Colombier 		return 0;
72*8ccd4a63SDavid du Colombier 	return smbbufferfixuprelatives(b, fnlfixupoffset);
73*8ccd4a63SDavid du Colombier }
74*8ccd4a63SDavid du Colombier 
75*8ccd4a63SDavid du Colombier static int
findbothflatten(SmbBuffer * b,SmbPeerInfo * p,Dir * d,ulong resumekey,ulong * nameoffsetp)76*8ccd4a63SDavid du Colombier findbothflatten(SmbBuffer *b, SmbPeerInfo *p, Dir *d, ulong resumekey, ulong *nameoffsetp)
77*8ccd4a63SDavid du Colombier {
78*8ccd4a63SDavid du Colombier 	vlong mtime, atime;
79*8ccd4a63SDavid du Colombier 	ulong fixup;
80*8ccd4a63SDavid du Colombier 
81*8ccd4a63SDavid du Colombier 	fixup = smbbufferwriteoffset(b);
82*8ccd4a63SDavid du Colombier 	mtime = smbplan9time2time(d->mtime);
83*8ccd4a63SDavid du Colombier 	atime = smbplan9time2time(d->atime);
84*8ccd4a63SDavid du Colombier poolcheck(mainmem);
85*8ccd4a63SDavid du Colombier 	if (!smbbufferputl(b, 0)
86*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, resumekey)
87*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, mtime)
88*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, atime)
89*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, mtime)
90*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, mtime)
91*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, d->length)
92*8ccd4a63SDavid du Colombier 		|| !smbbufferputv(b, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))			// ha
93*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, (d->qid.type & QTDIR) ? 0x10 : 0x80)
94*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, smbstringlen(p, d->name))
95*8ccd4a63SDavid du Colombier 		|| !smbbufferputl(b, 0)
96*8ccd4a63SDavid du Colombier 		|| !smbbufferputb(b, 0)
97*8ccd4a63SDavid du Colombier 		|| !smbbufferputb(b, 0)
98*8ccd4a63SDavid du Colombier 		|| !smbbufferfill(b, 0, 24))
99*8ccd4a63SDavid du Colombier 		return 0;
100*8ccd4a63SDavid du Colombier poolcheck(mainmem);
101*8ccd4a63SDavid du Colombier 	*nameoffsetp = smbbufferwriteoffset(b);
102*8ccd4a63SDavid du Colombier 	if (!smbbufferputstring(b, p, 0, d->name) || !smbbufferalignl2(b, 2))
103*8ccd4a63SDavid du Colombier 		return 0;
104*8ccd4a63SDavid du Colombier poolcheck(mainmem);
105*8ccd4a63SDavid du Colombier 	return smbbufferfixuprelativeinclusivel(b, fixup);
106*8ccd4a63SDavid du Colombier }
107*8ccd4a63SDavid du Colombier 
108*8ccd4a63SDavid du Colombier static void
populate(SmbSession * s,SmbDirCache * dc,Reprog * r,ushort informationlevel,ushort flags,ushort scount,ushort * ep,ulong * nameoffsetp)109*8ccd4a63SDavid du Colombier populate(SmbSession *s, SmbDirCache *dc, Reprog *r, ushort informationlevel, ushort flags, ushort scount,
110*8ccd4a63SDavid du Colombier 	ushort *ep, ulong *nameoffsetp)
111*8ccd4a63SDavid du Colombier {
112*8ccd4a63SDavid du Colombier 	ushort e;
113*8ccd4a63SDavid du Colombier 	ulong nameoffset;
114*8ccd4a63SDavid du Colombier 	e = 0;
115*8ccd4a63SDavid du Colombier 	nameoffset = 0;
116*8ccd4a63SDavid du Colombier 	while (dc->i < dc->n && e < scount) {
117*8ccd4a63SDavid du Colombier 		ulong backup;
118*8ccd4a63SDavid du Colombier 		int rv;
119*8ccd4a63SDavid du Colombier 
120*8ccd4a63SDavid du Colombier 		if (!smbmatch(dc->buf[dc->i].name, r)) {
121*8ccd4a63SDavid du Colombier 			dc->i++;
122*8ccd4a63SDavid du Colombier 			continue;
123*8ccd4a63SDavid du Colombier 		}
124*8ccd4a63SDavid du Colombier 		rv = 0;
125*8ccd4a63SDavid du Colombier 		backup = smbbufferwriteoffset(s->transaction.out.data);
126*8ccd4a63SDavid du Colombier 		switch (informationlevel) {
127*8ccd4a63SDavid du Colombier 		case SMB_INFO_STANDARD:
128*8ccd4a63SDavid du Colombier 			if (flags & SMB_FIND_RETURN_RESUME_KEYS) {
129*8ccd4a63SDavid du Colombier 				if (!smbbufferputl(s->transaction.out.data, dc->i)) {
130*8ccd4a63SDavid du Colombier 					rv = 0;
131*8ccd4a63SDavid du Colombier 					break;
132*8ccd4a63SDavid du Colombier 				}
133*8ccd4a63SDavid du Colombier 			}
134*8ccd4a63SDavid du Colombier 			rv = standardflatten(s, s->transaction.out.data, dc->buf + dc->i, &nameoffset);
135*8ccd4a63SDavid du Colombier 			break;
136*8ccd4a63SDavid du Colombier 		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
137*8ccd4a63SDavid du Colombier 			rv = findbothflatten(s->transaction.out.data, &s->peerinfo, dc->buf + dc->i, dc->i, &nameoffset);
138*8ccd4a63SDavid du Colombier 			break;
139*8ccd4a63SDavid du Colombier 		}
140*8ccd4a63SDavid du Colombier 		if (rv == 0) {
141*8ccd4a63SDavid du Colombier 			smbbufferwritebackup(s->transaction.out.data, backup);
142*8ccd4a63SDavid du Colombier 			break;
143*8ccd4a63SDavid du Colombier 		}
144*8ccd4a63SDavid du Colombier 		dc->i++;
145*8ccd4a63SDavid du Colombier 		e++;
146*8ccd4a63SDavid du Colombier 	}
147*8ccd4a63SDavid du Colombier 	*ep = e;
148*8ccd4a63SDavid du Colombier 	*nameoffsetp = nameoffset;
149*8ccd4a63SDavid du Colombier }
150*8ccd4a63SDavid du Colombier 
151*8ccd4a63SDavid du Colombier SmbProcessResult
smbtrans2findfirst2(SmbSession * s,SmbHeader * h)152*8ccd4a63SDavid du Colombier smbtrans2findfirst2(SmbSession *s, SmbHeader *h)
153*8ccd4a63SDavid du Colombier {
154*8ccd4a63SDavid du Colombier 	SmbBuffer *b;
155*8ccd4a63SDavid du Colombier 	char *pattern = nil;
156*8ccd4a63SDavid du Colombier 	char *dir = nil;
157*8ccd4a63SDavid du Colombier 	char *name = nil;
158*8ccd4a63SDavid du Colombier 	ushort searchattributes, searchcount, flags, informationlevel;
159*8ccd4a63SDavid du Colombier 	ulong searchstoragetype;
160*8ccd4a63SDavid du Colombier 	SmbDirCache *dc = nil;
161*8ccd4a63SDavid du Colombier 	ushort e;
162*8ccd4a63SDavid du Colombier 	ulong nameoffset;
163*8ccd4a63SDavid du Colombier 	ushort eos;
164*8ccd4a63SDavid du Colombier 	SmbSearch *search;
165*8ccd4a63SDavid du Colombier 	SmbProcessResult pr;
166*8ccd4a63SDavid du Colombier 	Reprog *r = nil;
167*8ccd4a63SDavid du Colombier 	SmbTree *t;
168*8ccd4a63SDavid du Colombier 	int debug;
169*8ccd4a63SDavid du Colombier 
170*8ccd4a63SDavid du Colombier 	debug = smboptable[h->command].debug
171*8ccd4a63SDavid du Colombier 		|| smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug
172*8ccd4a63SDavid du Colombier 		|| smbglobals.log.find;
173*8ccd4a63SDavid du Colombier poolcheck(mainmem);
174*8ccd4a63SDavid du Colombier 	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
175*8ccd4a63SDavid du Colombier 	if (!smbbuffergets(b, &searchattributes)
176*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &searchcount)
177*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &flags)
178*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &informationlevel)
179*8ccd4a63SDavid du Colombier 		|| !smbbuffergetl(b, &searchstoragetype)
180*8ccd4a63SDavid du Colombier 		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) {
181*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultFormat;
182*8ccd4a63SDavid du Colombier 		goto done;
183*8ccd4a63SDavid du Colombier 	}
184*8ccd4a63SDavid du Colombier 	smbloglock();
185*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes);
186*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount);
187*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "flags: 0x%.4ux\n", flags);
188*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel);
189*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype);
190*8ccd4a63SDavid du Colombier 	smblogprintif(debug, "pattern: %s\n", pattern);
191*8ccd4a63SDavid du Colombier 	smblogunlock();
192*8ccd4a63SDavid du Colombier 	smbpathsplit(pattern, &dir, &name);
193*8ccd4a63SDavid du Colombier 	if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
194*8ccd4a63SDavid du Colombier 		smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel);
195*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRunknownlevel);
196*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
197*8ccd4a63SDavid du Colombier 		goto done;
198*8ccd4a63SDavid du Colombier 	}
199*8ccd4a63SDavid du Colombier 
200*8ccd4a63SDavid du Colombier 	t = smbidmapfind(s->tidmap, h->tid);
201*8ccd4a63SDavid du Colombier 	if (t == nil) {
202*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRSRV, ERRinvtid);
203*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
204*8ccd4a63SDavid du Colombier 		goto done;
205*8ccd4a63SDavid du Colombier 	}
206*8ccd4a63SDavid du Colombier 
207*8ccd4a63SDavid du Colombier 	dc = smbmkdircache(t, dir);
208*8ccd4a63SDavid du Colombier 	if (dc == nil) {
209*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRnoaccess);
210*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
211*8ccd4a63SDavid du Colombier 		goto done;
212*8ccd4a63SDavid du Colombier 	}
213*8ccd4a63SDavid du Colombier poolcheck(mainmem);
214*8ccd4a63SDavid du Colombier 	r = smbmkrep(name);
215*8ccd4a63SDavid du Colombier 	populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset);
216*8ccd4a63SDavid du Colombier poolcheck(mainmem);
217*8ccd4a63SDavid du Colombier 	eos = dc->i >= dc->n;
218*8ccd4a63SDavid du Colombier 	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
219*8ccd4a63SDavid du Colombier 		smbdircachefree(&dc);
220*8ccd4a63SDavid du Colombier poolcheck(mainmem);
221*8ccd4a63SDavid du Colombier 	if (dc) {
222*8ccd4a63SDavid du Colombier 		/* create a search handle */
223*8ccd4a63SDavid du Colombier 		search = smbsearchnew(s, dc, r, t);
224*8ccd4a63SDavid du Colombier 		r = nil;
225*8ccd4a63SDavid du Colombier 		dc = nil;
226*8ccd4a63SDavid du Colombier 	}
227*8ccd4a63SDavid du Colombier 	else
228*8ccd4a63SDavid du Colombier 		search = nil;
229*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, search ? search->id : 0);
230*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, e);
231*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, eos);
232*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, 0);
233*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, nameoffset);
234*8ccd4a63SDavid du Colombier 	pr = SmbProcessResultReply;
235*8ccd4a63SDavid du Colombier done:
236*8ccd4a63SDavid du Colombier 	smbbufferfree(&b);
237*8ccd4a63SDavid du Colombier 	free(pattern);
238*8ccd4a63SDavid du Colombier 	free(dir);
239*8ccd4a63SDavid du Colombier 	free(name);
240*8ccd4a63SDavid du Colombier 	smbdircachefree(&dc);
241*8ccd4a63SDavid du Colombier 	free(r);
242*8ccd4a63SDavid du Colombier 	return pr;
243*8ccd4a63SDavid du Colombier }
244*8ccd4a63SDavid du Colombier 
245*8ccd4a63SDavid du Colombier SmbProcessResult
smbtrans2findnext2(SmbSession * s,SmbHeader * h)246*8ccd4a63SDavid du Colombier smbtrans2findnext2(SmbSession *s, SmbHeader *h)
247*8ccd4a63SDavid du Colombier {
248*8ccd4a63SDavid du Colombier 	SmbBuffer *b;
249*8ccd4a63SDavid du Colombier 	int debug;
250*8ccd4a63SDavid du Colombier 	ushort sid, scount, infolevel;
251*8ccd4a63SDavid du Colombier 	ulong resumekey;
252*8ccd4a63SDavid du Colombier 	ushort flags;
253*8ccd4a63SDavid du Colombier 	char *filename = nil;
254*8ccd4a63SDavid du Colombier 	SmbProcessResult pr;
255*8ccd4a63SDavid du Colombier 	ushort e;
256*8ccd4a63SDavid du Colombier 	ulong nameoffset;
257*8ccd4a63SDavid du Colombier 	ushort eos;
258*8ccd4a63SDavid du Colombier 	SmbTree *t;
259*8ccd4a63SDavid du Colombier 	SmbSearch *search;
260*8ccd4a63SDavid du Colombier 
261*8ccd4a63SDavid du Colombier 	debug = smboptable[h->command].debug
262*8ccd4a63SDavid du Colombier 		|| smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug
263*8ccd4a63SDavid du Colombier 		|| smbglobals.log.find;
264*8ccd4a63SDavid du Colombier 	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
265*8ccd4a63SDavid du Colombier 	if (!smbbuffergets(b, &sid)
266*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &scount)
267*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &infolevel)
268*8ccd4a63SDavid du Colombier 		|| !smbbuffergetl(b, &resumekey)
269*8ccd4a63SDavid du Colombier 		|| !smbbuffergets(b, &flags)
270*8ccd4a63SDavid du Colombier 		|| !smbbuffergetstring(b, h, 0, &filename)) {
271*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultFormat;
272*8ccd4a63SDavid du Colombier 		goto done;
273*8ccd4a63SDavid du Colombier 	}
274*8ccd4a63SDavid du Colombier 	smblogprintif(debug,
275*8ccd4a63SDavid du Colombier 		"smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n",
276*8ccd4a63SDavid du Colombier 		sid, scount, infolevel, resumekey, flags, filename);
277*8ccd4a63SDavid du Colombier 
278*8ccd4a63SDavid du Colombier 	if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
279*8ccd4a63SDavid du Colombier 		smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel);
280*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRunknownlevel);
281*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
282*8ccd4a63SDavid du Colombier 		goto done;
283*8ccd4a63SDavid du Colombier 	}
284*8ccd4a63SDavid du Colombier 
285*8ccd4a63SDavid du Colombier 	t = smbidmapfind(s->tidmap, h->tid);
286*8ccd4a63SDavid du Colombier 	if (t == nil) {
287*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRSRV, ERRinvtid);
288*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
289*8ccd4a63SDavid du Colombier 		goto done;
290*8ccd4a63SDavid du Colombier 	}
291*8ccd4a63SDavid du Colombier 
292*8ccd4a63SDavid du Colombier 	search = smbidmapfind(s->sidmap, sid);
293*8ccd4a63SDavid du Colombier 	if (search == nil) {
294*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRnofiles);
295*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
296*8ccd4a63SDavid du Colombier 		goto done;
297*8ccd4a63SDavid du Colombier 	}
298*8ccd4a63SDavid du Colombier 
299*8ccd4a63SDavid du Colombier 	if (search->t != t) {
300*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRSRV, ERRinvtid);
301*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
302*8ccd4a63SDavid du Colombier 		goto done;
303*8ccd4a63SDavid du Colombier 	}
304*8ccd4a63SDavid du Colombier 
305*8ccd4a63SDavid du Colombier 	if ((flags & (1 << 3)) == 0) {
306*8ccd4a63SDavid du Colombier 		long i;
307*8ccd4a63SDavid du Colombier 		if (filename == nil) {
308*8ccd4a63SDavid du Colombier 			smbseterror(s, ERRDOS, ERRnofiles);
309*8ccd4a63SDavid du Colombier 			pr = SmbProcessResultError;
310*8ccd4a63SDavid du Colombier 			goto done;
311*8ccd4a63SDavid du Colombier 		}
312*8ccd4a63SDavid du Colombier 		for (i = 0; i < search->dc->n; i++)
313*8ccd4a63SDavid du Colombier 			if (strcmp(search->dc->buf[i].name, filename) == 0) {
314*8ccd4a63SDavid du Colombier 				search->dc->i = i + 1;
315*8ccd4a63SDavid du Colombier 				break;
316*8ccd4a63SDavid du Colombier 			}
317*8ccd4a63SDavid du Colombier 	}
318*8ccd4a63SDavid du Colombier 
319*8ccd4a63SDavid du Colombier 	populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset);
320*8ccd4a63SDavid du Colombier 
321*8ccd4a63SDavid du Colombier 	eos = search->dc->i >= search->dc->n;
322*8ccd4a63SDavid du Colombier 	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
323*8ccd4a63SDavid du Colombier 		smbsearchclose(s, search);
324*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, e);
325*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, eos);
326*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, 0);
327*8ccd4a63SDavid du Colombier 	smbbufferputs(s->transaction.out.parameters, nameoffset);
328*8ccd4a63SDavid du Colombier 	pr = SmbProcessResultReply;
329*8ccd4a63SDavid du Colombier done:
330*8ccd4a63SDavid du Colombier 	smbbufferfree(&b);
331*8ccd4a63SDavid du Colombier 	free(filename);
332*8ccd4a63SDavid du Colombier 	return pr;
333*8ccd4a63SDavid du Colombier }
334