Windows: Update fs newcell and add VIOCNEWCELL2
[openafs.git] / src / WINNT / afsd / smb_ioctl.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #include <windows.h>
14 #include <stdlib.h>
15 #include <malloc.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <time.h>
19 #include <strsafe.h>
20
21 #include <osi.h>
22
23 #include "afsd.h"
24
25 #include "smb.h"
26
27 #include "cm_rpc.h"
28 #include "afs/afsrpc.h"
29 #include "afs/auth.h"
30
31 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
32
33 void 
34 smb_InitIoctl(void)
35 {
36     int i;
37     for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
38         smb_ioctlProcsp[i] = NULL;
39
40     smb_ioctlProcsp[VIOCGETAL] = smb_IoctlGetACL;
41     smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = smb_IoctlGetFileCellName;
42     smb_ioctlProcsp[VIOCSETAL] = smb_IoctlSetACL;
43     smb_ioctlProcsp[VIOC_FLUSHVOLUME] = smb_IoctlFlushVolume;
44     smb_ioctlProcsp[VIOCFLUSH] = smb_IoctlFlushFile;
45     smb_ioctlProcsp[VIOCSETVOLSTAT] = smb_IoctlSetVolumeStatus;
46     smb_ioctlProcsp[VIOCGETVOLSTAT] = smb_IoctlGetVolumeStatus;
47     smb_ioctlProcsp[VIOCWHEREIS] = smb_IoctlWhereIs;
48     smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = smb_IoctlStatMountPoint;
49     smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = smb_IoctlDeleteMountPoint;
50     smb_ioctlProcsp[VIOCCKSERV] = smb_IoctlCheckServers;
51     smb_ioctlProcsp[VIOC_GAG] = smb_IoctlGag;
52     smb_ioctlProcsp[VIOCCKBACK] = smb_IoctlCheckVolumes;
53     smb_ioctlProcsp[VIOCSETCACHESIZE] = smb_IoctlSetCacheSize;
54     smb_ioctlProcsp[VIOCGETCACHEPARMS] = smb_IoctlGetCacheParms;
55     smb_ioctlProcsp[VIOCGETCELL] = smb_IoctlGetCell;
56     smb_ioctlProcsp[VIOCNEWCELL] = smb_IoctlNewCell;
57     smb_ioctlProcsp[VIOC_GET_WS_CELL] = smb_IoctlGetWsCell;
58     smb_ioctlProcsp[VIOC_AFS_SYSNAME] = smb_IoctlSysName;
59     smb_ioctlProcsp[VIOC_GETCELLSTATUS] = smb_IoctlGetCellStatus;
60     smb_ioctlProcsp[VIOC_SETCELLSTATUS] = smb_IoctlSetCellStatus;
61     smb_ioctlProcsp[VIOC_SETSPREFS] = smb_IoctlSetSPrefs;
62     smb_ioctlProcsp[VIOC_GETSPREFS] = smb_IoctlGetSPrefs;
63     smb_ioctlProcsp[VIOC_STOREBEHIND] = smb_IoctlStoreBehind;
64     smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = smb_IoctlCreateMountPoint;
65     smb_ioctlProcsp[VIOC_TRACECTL] = smb_IoctlTraceControl;
66     smb_ioctlProcsp[VIOCSETTOK] = smb_IoctlSetToken;
67     smb_ioctlProcsp[VIOCGETTOK] = smb_IoctlGetTokenIter;
68     smb_ioctlProcsp[VIOCNEWGETTOK] = smb_IoctlGetToken;
69     smb_ioctlProcsp[VIOCDELTOK] = smb_IoctlDelToken;
70     smb_ioctlProcsp[VIOCDELALLTOK] = smb_IoctlDelAllToken;
71     smb_ioctlProcsp[VIOC_SYMLINK] = smb_IoctlSymlink;
72     smb_ioctlProcsp[VIOC_LISTSYMLINK] = smb_IoctlListlink;
73     smb_ioctlProcsp[VIOC_DELSYMLINK] = smb_IoctlDeletelink;
74     smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = smb_IoctlMakeSubmount;
75     smb_ioctlProcsp[VIOC_GETRXKCRYPT] = smb_IoctlGetRxkcrypt;
76     smb_ioctlProcsp[VIOC_SETRXKCRYPT] = smb_IoctlSetRxkcrypt;
77     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
78     smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = smb_IoctlMemoryDump;
79     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
80     smb_ioctlProcsp[VIOC_FLUSHALL] = smb_IoctlFlushAllVolumes;
81     smb_ioctlProcsp[VIOCGETFID] = smb_IoctlGetFid;
82     smb_ioctlProcsp[VIOCGETOWNER] = smb_IoctlGetOwner;
83     smb_ioctlProcsp[VIOC_RXSTAT_PROC] = smb_IoctlRxStatProcess;
84     smb_ioctlProcsp[VIOC_RXSTAT_PEER] = smb_IoctlRxStatPeer;
85     smb_ioctlProcsp[VIOC_UUIDCTL] = smb_IoctlUUIDControl;
86     smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = smb_IoctlPathAvailability;
87     smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
88     smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
89     smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
90     smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
91     smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
92     smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
93 }       
94
95 /* called to make a fid structure into an IOCTL fid structure */
96 void 
97 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
98 {
99     smb_ioctl_t *iop;
100     cm_space_t *copyPrefix;
101
102     lock_ObtainMutex(&fidp->mx);
103     fidp->flags |= SMB_FID_IOCTL;
104     fidp->scp = &cm_data.fakeSCache;
105     cm_HoldSCache(fidp->scp);
106     if (fidp->ioctlp == NULL) {
107         iop = malloc(sizeof(*iop));
108         memset(iop, 0, sizeof(*iop));
109         fidp->ioctlp = iop;
110         iop->fidp = fidp;
111     }
112     if (prefix) {
113         copyPrefix = cm_GetSpace();
114         memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
115         fidp->ioctlp->prefix = copyPrefix;
116     }
117     lock_ReleaseMutex(&fidp->mx);
118 }
119
120 /* called when we receive a read call, does the send of the received data if
121  * this is the first read call.  This is the function that actually makes the
122  * call to the ioctl code.
123  */
124 afs_int32
125 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
126 {
127     afs_int32 opcode;
128     smb_ioctlProc_t *procp = NULL;
129     afs_int32 code;
130
131     if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
132         ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
133         ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAOUT;
134
135         /* do the call now, or fail if we didn't get an opcode, or
136          * enough of an opcode.
137          */
138         if (ioctlp->ioctl.inCopied < sizeof(afs_int32)) 
139             return CM_ERROR_INVAL;
140         memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
141         ioctlp->ioctl.inDatap += sizeof(afs_int32);
142
143         osi_Log1(afsd_logp, "smb_IoctlPrepareRead opcode 0x%x", opcode);
144         /* check for opcode out of bounds */
145         if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS) {
146             osi_Log0(afsd_logp, "smb_IoctlPrepareRead - invalid opcode");
147             return CM_ERROR_TOOBIG;
148         }
149
150         /* check for no such proc */
151         procp = smb_ioctlProcsp[opcode];
152         if (procp == NULL) {
153             osi_Log0(afsd_logp, "smb_IoctlPrepareRead - unassigned opcode");
154             return CM_ERROR_INVAL;
155         }
156         /* otherwise, make the call */
157         ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
158         code = (*procp)(ioctlp, userp);
159         osi_Log1(afsd_logp, "smb_IoctlPrepareRead operation returns code 0x%x", code);
160
161         /* copy in return code */
162         memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
163     } else if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAOUT)) {
164         osi_Log0(afsd_logp, "Ioctl invalid state - dataout expected");
165         return CM_ERROR_INVAL;
166     }
167
168     return 0;
169 }
170
171 /* called when we receive a write call.  If this is the first write call after
172  * a series of reads (or the very first call), then we start a new call.
173  * We also ensure that things are properly initialized for the start of a call.
174  */
175 void 
176 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
177 {
178     /* make sure the buffer(s) are allocated */
179     if (!ioctlp->ioctl.inAllocp) 
180         ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
181     if (!ioctlp->ioctl.outAllocp)
182         ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
183
184     /* Fixes fs la problem.  We do a StrToOEM later and if this data isn't initialized we get memory issues. */
185     (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
186     (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
187
188     /* and make sure that we've reset our state for the new incoming request */
189     if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
190         ioctlp->ioctl.inCopied = 0;
191         ioctlp->ioctl.outCopied = 0;
192         ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
193         ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
194         ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
195         ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAOUT;
196     }
197 }       
198
199 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
200 afs_int32
201 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
202 {
203     smb_ioctl_t *iop;
204     long count;
205     afs_int32 leftToCopy;
206     char *op;
207     afs_int32 code;
208     cm_user_t *userp;
209
210     iop = fidp->ioctlp;
211     count = smb_GetSMBParm(inp, 1);
212     userp = smb_GetUserFromVCP(vcp, inp);
213
214     /* Identify tree */
215     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
216     if(code) {
217         cm_ReleaseUser(userp);
218         return CM_ERROR_NOSUCHPATH;
219     }
220
221     /* turn the connection around, if required */
222     code = smb_IoctlPrepareRead(fidp, iop, userp);
223
224     if (code) {
225         cm_ReleaseUser(userp);
226         return code;
227     }
228
229     leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
230     if (leftToCopy < 0) {
231         osi_Log0(afsd_logp, "smb_IoctlRead leftToCopy went negative");
232         cm_ReleaseUser(userp);
233         return CM_ERROR_INVAL;
234     }
235     if (count > leftToCopy)
236         count = leftToCopy;
237
238     /* now set the parms for a read of count bytes */
239     smb_SetSMBParm(outp, 0, count);
240     smb_SetSMBParm(outp, 1, 0);
241     smb_SetSMBParm(outp, 2, 0);
242     smb_SetSMBParm(outp, 3, 0);
243     smb_SetSMBParm(outp, 4, 0);
244
245     smb_SetSMBDataLength(outp, count+3);
246
247     op = smb_GetSMBData(outp, NULL);
248     *op++ = 1;
249     *op++ = (char)(count & 0xff);
250     *op++ = (char)((count >> 8) & 0xff);
251
252     /* now copy the data into the response packet */
253     memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
254
255     /* and adjust the counters */
256     iop->ioctl.outCopied += count;
257
258     cm_ReleaseUser(userp);
259
260     return 0;
261 }
262
263 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
264  * file descriptor.
265  */
266 afs_int32
267 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
268 {
269     smb_ioctl_t *iop;
270     long count;
271     afs_int32 code;
272     char *op;
273     int inDataBlockCount;
274
275     code = 0;
276     count = smb_GetSMBParm(inp, 1);
277     iop = fidp->ioctlp;
278         
279     smb_IoctlPrepareWrite(fidp, iop);
280
281     op = smb_GetSMBData(inp, NULL);
282     op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
283         
284     if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
285         code = CM_ERROR_TOOBIG;
286         goto done;
287     }
288         
289     /* copy data */
290     memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
291         
292     /* adjust counts */
293     iop->ioctl.inCopied += count;
294
295   done:
296     /* return # of bytes written */
297     if (code == 0) {
298         smb_SetSMBParm(outp, 0, count);
299         smb_SetSMBDataLength(outp, 0);
300     }
301
302     return code;
303 }       
304
305 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
306  * file descriptor.
307  */
308 afs_int32
309 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
310 {
311     smb_ioctl_t *iop;
312     long count;
313     afs_int32 code;
314     char *op;
315     int inDataBlockCount;
316
317     code = 0;
318     count = smb_GetSMBParm(inp, 10);
319     iop = fidp->ioctlp;
320
321     smb_IoctlPrepareWrite(fidp, iop);
322
323     op = inp->data + smb_GetSMBParm(inp, 11);
324     inDataBlockCount = count;
325
326     if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
327         code = CM_ERROR_TOOBIG;
328         goto done;
329     }
330         
331     /* copy data */
332     memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
333
334     /* adjust counts */
335     iop->ioctl.inCopied += count;
336
337   done:
338     /* return # of bytes written */
339     if (code == 0) {
340         smb_SetSMBParm(outp, 2, count);
341         smb_SetSMBParm(outp, 3, 0); /* reserved */
342         smb_SetSMBParm(outp, 4, 0); /* reserved */
343         smb_SetSMBParm(outp, 5, 0); /* reserved */
344         smb_SetSMBDataLength(outp, 0);
345     }
346
347     return code;
348 }       
349
350
351 /* called from V3 read to handle IOCTL descriptor reads */
352 afs_int32
353 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
354 {
355     smb_ioctl_t *iop;
356     unsigned short count;
357     afs_int32 code;
358     long leftToCopy;
359     char *op;
360     cm_user_t *userp;
361     smb_user_t *uidp;
362
363     iop = fidp->ioctlp;
364     count = smb_GetSMBParm(inp, 5);
365         
366     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
367     if (!uidp)
368         return CM_ERROR_BADSMB;
369     userp = smb_GetUserFromUID(uidp);
370     osi_assertx(userp != NULL, "null cm_user_t");
371     iop->uidp = uidp;
372     if (uidp && uidp->unp) {
373         osi_Log3(afsd_logp, "Ioctl uid %d user %x name %S",
374                   uidp->userID, userp,
375                   osi_LogSaveClientString(afsd_logp, uidp->unp->name));
376     } else {
377         if (uidp)
378             osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
379                      uidp->userID, userp);
380         else
381             osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
382                      userp);
383     }
384
385     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
386     if (code) {
387         if (uidp)
388             smb_ReleaseUID(uidp);
389         cm_ReleaseUser(userp);
390         return CM_ERROR_NOSUCHPATH;
391     }
392
393     code = smb_IoctlPrepareRead(fidp, iop, userp);
394     if (uidp) {
395         iop->uidp = 0;
396         smb_ReleaseUID(uidp);
397     }
398     if (code) {
399         cm_ReleaseUser(userp);
400         return code;
401     }
402
403     leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
404     if (leftToCopy < 0) {
405         osi_Log0(afsd_logp, "smb_IoctlV3Read leftToCopy went negative");
406         cm_ReleaseUser(userp);
407         return CM_ERROR_INVAL;
408     }
409     if (count > leftToCopy) 
410         count = (unsigned short)leftToCopy;
411         
412     /* 0 and 1 are reserved for request chaining, were setup by our caller,
413      * and will be further filled in after we return.
414      */
415     smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
416     smb_SetSMBParm(outp, 3, 0); /* resvd */
417     smb_SetSMBParm(outp, 4, 0); /* resvd */
418     smb_SetSMBParm(outp, 5, count);     /* # of bytes we're going to read */
419     /* fill in #6 when we have all the parameters' space reserved */
420     smb_SetSMBParm(outp, 7, 0); /* resv'd */
421     smb_SetSMBParm(outp, 8, 0); /* resv'd */
422     smb_SetSMBParm(outp, 9, 0); /* resv'd */
423     smb_SetSMBParm(outp, 10, 0);        /* resv'd */
424     smb_SetSMBParm(outp, 11, 0);        /* reserved */
425
426     /* get op ptr after putting in the last parm, since otherwise we don't
427      * know where the data really is.
428      */
429     op = smb_GetSMBData(outp, NULL);
430         
431     /* now fill in offset from start of SMB header to first data byte (to op) */
432     smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
433
434     /* set the packet data length the count of the # of bytes */
435     smb_SetSMBDataLength(outp, count);
436         
437     /* now copy the data into the response packet */
438     memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
439
440     /* and adjust the counters */
441     iop->ioctl.outCopied += count;
442
443     /* and cleanup things */
444     cm_ReleaseUser(userp);
445
446     return 0;
447 }       
448
449 /* called from Read Raw to handle IOCTL descriptor reads */
450 afs_int32
451 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
452                  smb_packet_t *outp)
453 {
454     smb_ioctl_t *iop;
455     long leftToCopy;
456     NCB *ncbp;
457     afs_int32 code;
458     cm_user_t *userp;
459     smb_user_t *uidp;
460
461     iop = fidp->ioctlp;
462
463     userp = smb_GetUserFromVCP(vcp, inp);
464
465     /* Log the user */
466     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
467     if (uidp && uidp->unp) {
468         osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
469                  uidp->userID, userp,
470                  osi_LogSaveClientString(afsd_logp, uidp->unp->name));
471     } else if (uidp) {
472         osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
473                  uidp->userID, userp);
474     } else {
475         osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
476                   userp);
477     }
478     if (uidp) 
479         smb_ReleaseUID(uidp);
480
481     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
482     if (code) {
483         code = CM_ERROR_NOSUCHPATH;
484         goto done;
485     }
486
487     code = smb_IoctlPrepareRead(fidp, iop, userp);
488     if (code) {
489         goto done;
490     }
491
492     leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
493     if (leftToCopy < 0) {
494         osi_Log0(afsd_logp, "smb_IoctlReadRaw leftToCopy went negative");
495         code = CM_ERROR_INVAL;
496         goto done;
497     }
498
499     ncbp = outp->ncbp;
500     memset(ncbp, 0, sizeof(NCB));
501
502     ncbp->ncb_length = (unsigned short) leftToCopy;
503     ncbp->ncb_lsn = (unsigned char) vcp->lsn;
504     ncbp->ncb_command = NCBSEND;
505     /*ncbp->ncb_lana_num = smb_LANadapter;*/
506     ncbp->ncb_lana_num = vcp->lana;
507
508     ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
509     code = Netbios(ncbp);
510
511     if (code != 0)
512         osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
513
514   done:
515     cm_ReleaseUser(userp);
516
517     return code;
518 }
519
520 /* parse the passed-in file name and do a namei on it.  If we fail,
521  * return an error code, otherwise return the vnode located in *scpp.
522  */
523 #define CM_PARSE_FLAG_LITERAL 1
524
525 afs_int32
526 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
527                    cm_scache_t **scpp, afs_uint32 flags)
528 {
529     long code;
530     cm_scache_t  *substRootp = NULL;
531     cm_scache_t  *iscp = NULL;
532     char      *inPath;
533     clientchar_t *relativePath = NULL;
534     clientchar_t *lastComponent = NULL;
535     afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
536
537     inPath = ioctlp->ioctl.inDatap;
538     /* setup the next data value for the caller to use */
539     ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
540
541     osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
542
543     /* This is usually the file name, but for StatMountPoint it is the path. */
544     /* ioctlp->ioctl.inDatap can be either of the form:
545      *    \path\.
546      *    \path\file
547      *    \\netbios-name\submount\path\.
548      *    \\netbios-name\submount\path\file
549      */
550
551     /* We do not perform path name translation on the ioctl path data
552      * because these paths were not translated by Windows through the
553      * file system API.  Therefore, they are not OEM characters but
554      * whatever the display character set is.
555      */
556
557     // TranslateExtendedChars(relativePath);
558
559     /* This is usually nothing, but for StatMountPoint it is the file name. */
560     // TranslateExtendedChars(ioctlp->ioctl.inDatap);
561
562     /* If the string starts with our UTF-8 prefix (which is the
563        sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
564        strings), we assume that the provided path is UTF-8.  Otherwise
565        we have to convert the string to UTF-8, since that is what we
566        want to use everywhere else.*/
567
568     if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
569         /* String is UTF-8 */
570         inPath += utf8_prefix_size;
571         ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
572
573         relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
574     } else {
575         int cch;
576
577         /* Not a UTF-8 string */
578         /* TODO: If this is an OEM string, we should convert it to
579            UTF-8. */
580         if (smb_StoreAnsiFilenames) {
581             cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
582 #ifdef DEBUG
583             osi_assert(cch > 0);
584 #endif
585             relativePath = malloc(cch * sizeof(clientchar_t));
586             cm_AnsiToClientString(inPath, -1, relativePath, cch);
587         } else {
588             TranslateExtendedChars(inPath);
589
590             cch = cm_OemToClientString(inPath, -1, NULL, 0);
591 #ifdef DEBUG
592             osi_assert(cch > 0);
593 #endif
594             relativePath = malloc(cch * sizeof(clientchar_t));
595             cm_OemToClientString(inPath, -1, relativePath, cch);
596         }
597     }
598
599     if (relativePath[0] == relativePath[1] &&
600         relativePath[1] == '\\' && 
601         !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
602                            cm_ClientStrLen(cm_NetbiosNameC))) 
603     {
604         clientchar_t shareName[256];
605         clientchar_t *sharePath;
606         int shareFound, i;
607
608         /* We may have found a UNC path. 
609          * If the first component is the NetbiosName,
610          * then throw out the second component (the submount)
611          * since it had better expand into the value of ioctl->tidPathp
612          */
613         clientchar_t * p;
614         p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;                    /* buffer overflow vuln.? */
615         if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
616             p += 4;
617
618         for (i = 0; *p && *p != '\\'; i++,p++ ) {
619             shareName[i] = *p;
620         }
621         p++;                    /* skip past trailing slash */
622         shareName[i] = 0;       /* terminate string */
623
624         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
625         if ( shareFound ) {
626             /* we found a sharename, therefore use the resulting path */
627             code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
628                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
629                             userp, sharePath, reqp, &substRootp);
630             free(sharePath);
631             if (code) {
632                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
633                 if (relativePath)
634                     free(relativePath);
635                 return code;
636             }
637
638             lastComponent = cm_ClientStrRChr(p,  '\\');
639             if (lastComponent && (lastComponent - p) > 1 &&
640                 cm_ClientStrLen(lastComponent) > 1) {
641                 *lastComponent = '\0';
642                 lastComponent++;
643
644                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
645                                 userp, NULL, reqp, &iscp);
646                 if (code == 0)
647                     code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
648                                     userp, NULL, reqp, scpp);
649                 if (iscp)
650                     cm_ReleaseSCache(iscp);
651             } else {
652                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
653                                 userp, NULL, reqp, scpp);
654             }
655             cm_ReleaseSCache(substRootp);
656             if (code) {
657                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
658                 if (relativePath)
659                     free(relativePath);
660                 return code;
661             }
662         } else {
663             /* otherwise, treat the name as a cellname mounted off the afs root.
664              * This requires that we reconstruct the shareName string with 
665              * leading and trailing slashes.
666              */
667             p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
668             if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
669                 p += 4;
670
671             shareName[0] = '/';
672             for (i = 1; *p && *p != '\\'; i++,p++ ) {
673                 shareName[i] = *p;
674             }
675             p++;                    /* skip past trailing slash */
676             shareName[i++] = '/';       /* add trailing slash */
677             shareName[i] = 0;       /* terminate string */
678
679
680             code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
681                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
682                             userp, shareName, reqp, &substRootp);
683             if (code) {
684                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
685                 if (relativePath)
686                     free(relativePath);
687                 return code;
688             }
689
690             lastComponent = cm_ClientStrRChr(p,  '\\');
691             if (lastComponent && (lastComponent - p) > 1 &&
692                 cm_ClientStrLen(lastComponent) > 1) {
693                 *lastComponent = '\0';
694                 lastComponent++;
695
696                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
697                                 userp, NULL, reqp, &iscp);
698                 if (code == 0)
699                     code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
700                                     userp, NULL, reqp, scpp);
701                 if (iscp)
702                     cm_ReleaseSCache(iscp);
703             } else {
704                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
705                                 userp, NULL, reqp, scpp);
706             }
707
708             if (code) {
709                 cm_ReleaseSCache(substRootp);
710                 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
711                 if (relativePath)
712                     free(relativePath);
713                 return code;
714             }
715         }
716     } else {
717         code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
718                          CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
719                          userp, ioctlp->tidPathp, reqp, &substRootp);
720         if (code) {
721             osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
722             if (relativePath)
723                 free(relativePath);
724             return code;
725         }
726         
727         lastComponent = cm_ClientStrRChr(relativePath,  '\\');
728         if (lastComponent && (lastComponent - relativePath) > 1 &&
729             cm_ClientStrLen(lastComponent) > 1) {
730             *lastComponent = '\0';
731             lastComponent++;
732
733             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
734                             userp, NULL, reqp, &iscp);
735             if (code == 0)
736                 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
737                                 userp, NULL, reqp, scpp);
738             if (iscp)
739                 cm_ReleaseSCache(iscp);
740         } else {
741             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
742                             userp, NULL, reqp, scpp);
743         }
744         if (code) {
745             cm_ReleaseSCache(substRootp);
746             osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
747             if (relativePath)
748                 free(relativePath);
749             return code;
750         }
751     }
752
753     if (substRootp)
754         cm_ReleaseSCache(substRootp);
755
756     /* and return success */
757     osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
758
759     if (relativePath)
760         free(relativePath);
761     return 0;
762 }
763
764
765
766 #define LEAF_SIZE 256
767 /* parse the passed-in file name and do a namei on its parent.  If we fail,
768  * return an error code, otherwise return the vnode located in *scpp.
769  */
770 afs_int32
771 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
772                      cm_scache_t **scpp, clientchar_t *leafp)
773 {
774     long code;
775     clientchar_t tbuffer[1024];
776     clientchar_t *tp, *jp;
777     cm_scache_t *substRootp = NULL;
778     clientchar_t *inpathp = NULL;
779     char *inpathdatap;
780
781     inpathdatap = ioctlp->ioctl.inDatap;
782
783     /* If the string starts with our UTF-8 prefix (which is the
784        sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
785        strings), we assume that the provided path is UTF-8.  Otherwise
786        we have to convert the string to UTF-8, since that is what we
787        want to use everywhere else.*/
788
789     if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
790
791         /* String is UTF-8 */
792         inpathdatap += utf8_prefix_size;
793         ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
794
795         inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
796     } else {
797         int cch;
798
799         /* Not a UTF-8 string */
800         /* TODO: If this is an OEM string, we should convert it to
801            UTF-8. */
802         if (smb_StoreAnsiFilenames) {
803             cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
804 #ifdef DEBUG
805             osi_assert(cch > 0);
806 #endif
807             inpathp = malloc(cch * sizeof(clientchar_t));
808             cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
809         } else {
810             TranslateExtendedChars(inpathdatap);
811
812             cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
813 #ifdef DEBUG
814             osi_assert(cch > 0);
815 #endif
816             inpathp = malloc(cch * sizeof(clientchar_t));
817             cm_OemToClientString(inpathdatap, -1, inpathp, cch);
818         }
819     }
820
821     cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
822     tp = cm_ClientStrRChr(tbuffer, '\\');
823     jp = cm_ClientStrRChr(tbuffer, '/');
824     if (!tp)
825         tp = jp;
826     else if (jp && (tp - tbuffer) < (jp - tbuffer))
827         tp = jp;
828     if (!tp) {
829         cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
830         if (leafp)
831             cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
832     }
833     else {
834         *tp = 0;
835         if (leafp) 
836             cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
837     }
838
839     free(inpathp);
840     inpathp = NULL;             /* We don't need this from this point on */
841
842     if (tbuffer[0] == tbuffer[1] &&
843         tbuffer[1] == '\\' && 
844         !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
845                            cm_ClientStrLen(cm_NetbiosNameC))) 
846     {
847         clientchar_t shareName[256];
848         clientchar_t *sharePath;
849         int shareFound, i;
850
851         /* We may have found a UNC path. 
852          * If the first component is the NetbiosName,
853          * then throw out the second component (the submount)
854          * since it had better expand into the value of ioctl->tidPathp
855          */
856         clientchar_t * p;
857         p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
858         if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
859             p += 4;
860
861         for (i = 0; *p && *p != '\\'; i++,p++ ) {
862             shareName[i] = *p;
863         }
864         p++;                    /* skip past trailing slash */
865         shareName[i] = 0;       /* terminate string */
866
867         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
868         if ( shareFound ) {
869             /* we found a sharename, therefore use the resulting path */
870             code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
871                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
872                             userp, sharePath, reqp, &substRootp);
873             free(sharePath);
874             if (code) return code;
875
876             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
877                             userp, NULL, reqp, scpp);
878             cm_ReleaseSCache(substRootp);
879             if (code) return code;
880         } else {
881             /* otherwise, treat the name as a cellname mounted off the afs root.
882              * This requires that we reconstruct the shareName string with 
883              * leading and trailing slashes.
884              */
885             p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
886             if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
887                 p += 4;
888
889             shareName[0] = '/';
890             for (i = 1; *p && *p != '\\'; i++,p++ ) {
891                 shareName[i] = *p;
892             }
893             p++;                    /* skip past trailing slash */
894             shareName[i++] = '/';       /* add trailing slash */
895             shareName[i] = 0;       /* terminate string */
896
897             code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
898                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
899                             userp, shareName, reqp, &substRootp);
900             if (code) return code;
901
902             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
903                             userp, NULL, reqp, scpp);
904             cm_ReleaseSCache(substRootp);
905             if (code) return code;
906         }
907     } else {
908         code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
909                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
910                         userp, ioctlp->tidPathp, reqp, &substRootp);
911         if (code) return code;
912
913         code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
914                         userp, NULL, reqp, scpp);
915         cm_ReleaseSCache(substRootp);
916         if (code) return code;
917     }
918
919     /* # of bytes of path */
920     code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
921     ioctlp->ioctl.inDatap += code;
922
923     /* and return success */
924     return 0;
925 }
926
927 afs_int32 
928 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
929 {
930     char *saveDataPtr;
931     char *tp;
932     int ticketLen;
933     char *ticket;
934     int ctSize;
935     struct ClearToken ct;
936     cm_cell_t *cellp;
937     cm_ucell_t *ucellp;
938     afs_uuid_t uuid;
939     int flags;
940     char sessionKey[8];
941     int release_userp = 0;
942     clientchar_t *uname = NULL;
943     clientchar_t *smbname = NULL;
944     clientchar_t *wdir = NULL;
945     afs_int32 code = 0;
946
947     saveDataPtr = ioctlp->ioctl.inDatap;
948
949     cm_SkipIoctlPath(&ioctlp->ioctl);
950
951     tp = ioctlp->ioctl.inDatap;
952
953     /* ticket length */
954     memcpy(&ticketLen, tp, sizeof(ticketLen));
955     tp += sizeof(ticketLen);
956     if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
957         return CM_ERROR_INVAL;
958
959     /* remember ticket and skip over it for now */
960     ticket = tp;
961     tp += ticketLen;
962
963     /* clear token size */
964     memcpy(&ctSize, tp, sizeof(ctSize));
965     tp += sizeof(ctSize);
966     if (ctSize != sizeof(struct ClearToken))
967         return CM_ERROR_INVAL;
968
969     /* clear token */
970     memcpy(&ct, tp, ctSize);
971     tp += ctSize;
972     if (ct.AuthHandle == -1)
973         ct.AuthHandle = 999;    /* more rxvab compat stuff */
974
975     /* more stuff, if any */
976     if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
977         /* flags:  logon flag */
978         memcpy(&flags, tp, sizeof(int));
979         tp += sizeof(int);
980
981         /* cell name */
982         {
983             fschar_t * cellnamep;
984             clientchar_t * temp;
985
986             temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
987             cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
988             cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
989             free(cellnamep);
990             free(temp);
991         }
992
993         if (!cellp) {
994             code = CM_ERROR_NOSUCHCELL;
995             goto done;
996         }
997         tp += strlen(tp) + 1;
998
999         /* user name */
1000         uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1001         tp += strlen(tp) + 1;
1002
1003         if (flags & PIOCTL_LOGON) {
1004             /* SMB user name with which to associate tokens */
1005             smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1006             osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
1007                      osi_LogSaveClientString(smb_logp,uname),
1008                      osi_LogSaveClientString(smb_logp,smbname));
1009             fprintf(stderr, "SMB name = %S\n", smbname);
1010             tp += strlen(tp) + 1;
1011         } else {
1012             osi_Log1(smb_logp,"cm_IoctlSetToken for user [%S]",
1013                      osi_LogSaveClientString(smb_logp, uname));
1014         }
1015
1016         /* uuid */
1017         memcpy(&uuid, tp, sizeof(uuid));
1018         if (!cm_FindTokenEvent(uuid, sessionKey)) {
1019             code = CM_ERROR_INVAL;
1020             goto done;
1021         }
1022     } else {
1023         cellp = cm_data.rootCellp;
1024         osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1025     }
1026
1027     if (flags & PIOCTL_LOGON) {
1028         userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
1029                                      SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1030         release_userp = 1;
1031     }
1032
1033     /* store the token */
1034     lock_ObtainMutex(&userp->mx);
1035     ucellp = cm_GetUCell(userp, cellp);
1036     osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1037     ucellp->ticketLen = ticketLen;
1038     if (ucellp->ticketp)
1039         free(ucellp->ticketp);  /* Discard old token if any */
1040     ucellp->ticketp = malloc(ticketLen);
1041     memcpy(ucellp->ticketp, ticket, ticketLen);
1042     /*
1043      * Get the session key from the RPC, rather than from the pioctl.
1044      */
1045     /*
1046     memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1047     */
1048     memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1049     ucellp->kvno = ct.AuthHandle;
1050     ucellp->expirationTime = ct.EndTimestamp;
1051     ucellp->gen++;
1052 #ifdef QUERY_AFSID
1053     ucellp->uid = ANONYMOUSID;
1054 #endif
1055     if (uname) {
1056         cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1057 #ifdef QUERY_AFSID
1058         cm_UsernameToId(uname, ucellp, &ucellp->uid);
1059 #endif
1060     }
1061     ucellp->flags |= CM_UCELLFLAG_RXKAD;
1062     lock_ReleaseMutex(&userp->mx);
1063
1064     if (flags & PIOCTL_LOGON) {
1065         ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1066     }
1067
1068     cm_ResetACLCache(cellp, userp);
1069
1070   done:
1071     if (release_userp)
1072         cm_ReleaseUser(userp);
1073
1074     if (uname)
1075         free(uname);
1076
1077     if (smbname)
1078         free(smbname);
1079
1080     return code;
1081 }
1082
1083
1084
1085 afs_int32
1086 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
1087 {
1088     smb_user_t *uidp = ioctlp->uidp;
1089
1090     if (uidp && uidp->unp) {
1091         int cch;
1092
1093         cch = cm_ClientStringToUtf8(uidp->unp->name,
1094                                     -1,
1095                                     ioctlp->ioctl.outDatap,
1096                                     (SMB_IOCTL_MAXDATA -
1097                                      (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1098                                     / sizeof(cm_utf8char_t));
1099
1100         ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1101     }
1102
1103     return 0;
1104 }
1105
1106 afs_int32 
1107 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1108 {
1109     cm_scache_t *scp;
1110     afs_int32 code;
1111     cm_req_t req;
1112     cm_ioctlQueryOptions_t *optionsp;
1113     afs_uint32 flags = 0;
1114
1115     smb_InitReq(&req);
1116
1117     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1118     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1119         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1120
1121     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1122         cm_fid_t fid;
1123         cm_SkipIoctlPath(&ioctlp->ioctl);
1124         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1125                   optionsp->fid.vnode, optionsp->fid.unique);
1126         code = cm_GetSCache(&fid, &scp, userp, &req);
1127     } else {
1128         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1129     }
1130
1131     if (code) 
1132         return code;
1133
1134     code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1135
1136     cm_ReleaseSCache(scp);
1137     return code;
1138 }
1139
1140 afs_int32 
1141 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1142 {
1143     cm_scache_t *scp;
1144     afs_int32 code;
1145     cm_req_t req;
1146     afs_uint32 flags = 0;
1147
1148     smb_InitReq(&req);
1149
1150     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1151     if (code) 
1152         return code;
1153
1154     code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1155
1156     cm_ReleaseSCache(scp);
1157     return code;
1158 }
1159
1160 afs_int32
1161 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1162 {
1163     afs_int32 code;
1164     cm_scache_t *scp;
1165     cm_req_t req;
1166     cm_ioctlQueryOptions_t *optionsp;
1167     afs_uint32 flags = 0;
1168
1169     smb_InitReq(&req);
1170
1171     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1172     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1173         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1174
1175     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1176         cm_fid_t fid;
1177         cm_SkipIoctlPath(&ioctlp->ioctl);
1178         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1179                   optionsp->fid.vnode, optionsp->fid.unique);
1180         code = cm_GetSCache(&fid, &scp, userp, &req);
1181     } else {
1182         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1183     }
1184     if (code) 
1185         return code;
1186
1187     code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1188
1189     cm_ReleaseSCache(scp);
1190
1191     return code;
1192 }
1193
1194 afs_int32 
1195 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1196 {
1197     cm_req_t req;
1198
1199     smb_InitReq(&req);
1200
1201     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1202
1203     return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1204 }
1205
1206 afs_int32 
1207 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
1208 {
1209     afs_int32 code;
1210     cm_scache_t *scp;
1211     cm_req_t req;
1212     cm_ioctlQueryOptions_t *optionsp;
1213     afs_uint32 flags = 0;
1214
1215     smb_InitReq(&req);
1216
1217     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1218     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1219         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1220
1221     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1222         cm_fid_t fid;
1223         cm_SkipIoctlPath(&ioctlp->ioctl);
1224         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1225                   optionsp->fid.vnode, optionsp->fid.unique);
1226         code = cm_GetSCache(&fid, &scp, userp, &req);
1227     } else {
1228         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1229     }
1230     if (code) 
1231         return code;
1232
1233     code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1234
1235     cm_ReleaseSCache(scp);
1236
1237     return code;
1238 }
1239
1240 afs_int32 
1241 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
1242 {
1243     afs_int32 code;
1244     cm_scache_t *scp;
1245     cm_req_t req;
1246     cm_ioctlQueryOptions_t *optionsp;
1247     afs_uint32 flags = 0;
1248
1249     smb_InitReq(&req);
1250
1251     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1252     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1253         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1254
1255     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1256         cm_fid_t fid;
1257         cm_SkipIoctlPath(&ioctlp->ioctl);
1258         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1259                   optionsp->fid.vnode, optionsp->fid.unique);
1260         code = cm_GetSCache(&fid, &scp, userp, &req);
1261     } else {
1262         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1263     }
1264     if (code) 
1265         return code;
1266
1267     code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1268
1269     cm_ReleaseSCache(scp);
1270     return code;
1271 }
1272
1273 afs_int32 
1274 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1275 {
1276     afs_int32 code;
1277     cm_scache_t *scp;
1278     cm_req_t req;
1279
1280     smb_InitReq(&req);
1281
1282     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1283     if (code) return code;
1284
1285     code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1286     cm_ReleaseSCache(scp);
1287
1288     return code;
1289 }
1290
1291 afs_int32 
1292 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1293 {
1294     afs_int32 code;
1295     cm_scache_t *scp;
1296     cm_ioctlQueryOptions_t *optionsp;
1297     afs_uint32 flags = 0;
1298     cm_req_t req;
1299
1300     smb_InitReq(&req);
1301
1302     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1303     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1304         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1305
1306     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1307         cm_fid_t fid;
1308         cm_SkipIoctlPath(&ioctlp->ioctl);
1309         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1310                   optionsp->fid.vnode, optionsp->fid.unique);
1311         code = cm_GetSCache(&fid, &scp, userp, &req);
1312     } else {
1313         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1314     }
1315     if (code) 
1316         return code;
1317
1318     code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1319
1320     cm_ReleaseSCache(scp);
1321
1322     return code;
1323 }
1324
1325 afs_int32 
1326 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
1327 {
1328     afs_int32 code;
1329     cm_scache_t *scp;
1330     cm_req_t req;
1331     cm_ioctlQueryOptions_t * optionsp;
1332     afs_uint32 flags = 0;
1333
1334     smb_InitReq(&req);
1335
1336     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1337     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1338         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1339
1340     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1341     if (code) 
1342         return code;
1343
1344     code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1345
1346     cm_ReleaseSCache(scp);
1347
1348     return code;
1349 }
1350
1351 afs_int32 
1352 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp)
1353 {
1354     afs_int32 code;
1355     cm_scache_t *scp;
1356     cm_req_t req;
1357     cm_ioctlQueryOptions_t * optionsp;
1358     afs_uint32 flags = 0;
1359
1360     smb_InitReq(&req);
1361
1362     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1363     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1364         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1365
1366     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1367         cm_fid_t fid;
1368         cm_SkipIoctlPath(&ioctlp->ioctl);
1369         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1370                   optionsp->fid.vnode, optionsp->fid.unique);
1371         code = cm_GetSCache(&fid, &scp, userp, &req);
1372     } else {
1373         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1374     }
1375     if (code) 
1376         return code;
1377
1378     code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1379
1380     cm_ReleaseSCache(scp);
1381
1382     return code;
1383 }
1384
1385 afs_int32 
1386 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1387 {
1388     afs_int32 code;
1389     cm_scache_t *scp;
1390     cm_req_t req;
1391     cm_ioctlQueryOptions_t *optionsp;
1392     afs_uint32 flags = 0;
1393
1394     smb_InitReq(&req);
1395
1396     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1397     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1398         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1399
1400     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1401         cm_fid_t fid;
1402         cm_SkipIoctlPath(&ioctlp->ioctl);
1403         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1404                   optionsp->fid.vnode, optionsp->fid.unique);
1405         code = cm_GetSCache(&fid, &scp, userp, &req);
1406     } else {
1407         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1408     }
1409     if (code) 
1410         return code;
1411
1412     code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1413
1414     cm_ReleaseSCache(scp);
1415
1416     return code;
1417 }
1418
1419 afs_int32 
1420 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1421 {
1422     afs_int32 code;
1423     cm_scache_t *scp;
1424     cm_req_t req;
1425     cm_ioctlQueryOptions_t *optionsp;
1426     afs_uint32 flags = 0;
1427
1428     smb_InitReq(&req);
1429
1430     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1431     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1432         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1433
1434     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1435         cm_fid_t fid;
1436         cm_SkipIoctlPath(&ioctlp->ioctl);
1437         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1438                   optionsp->fid.vnode, optionsp->fid.unique);
1439         code = cm_GetSCache(&fid, &scp, userp, &req);
1440     } else {
1441         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1442     }
1443     if (code) 
1444         return code;
1445
1446     code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1447
1448     cm_ReleaseSCache(scp);
1449
1450     return code;
1451 }
1452
1453
1454 afs_int32 
1455 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1456 {
1457     afs_int32 code;
1458     cm_scache_t *dscp;
1459     cm_req_t req;
1460
1461     smb_InitReq(&req);
1462
1463     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1464     if (code)
1465         return code;
1466
1467     code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1468
1469     cm_ReleaseSCache(dscp);
1470
1471     return code;
1472 }
1473
1474 afs_int32 
1475 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1476 {
1477     afs_int32 code;
1478     cm_scache_t *dscp;
1479     cm_req_t req;
1480
1481     smb_InitReq(&req);
1482
1483     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1484     if (code) 
1485         return code;
1486
1487     code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1488
1489     cm_ReleaseSCache(dscp);
1490
1491     return code;
1492 }
1493
1494 afs_int32 
1495 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1496 {
1497     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1498
1499     return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1500 }
1501
1502 afs_int32 
1503 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1504 {
1505     /* we don't print anything superfluous, so we don't support the gag call */
1506     return CM_ERROR_INVAL;
1507 }
1508
1509 afs_int32 
1510 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1511 {
1512     cm_SkipIoctlPath(&ioctlp->ioctl);
1513
1514     return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1515 }
1516
1517 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1518 {
1519     cm_SkipIoctlPath(&ioctlp->ioctl);
1520
1521     return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1522 }
1523
1524
1525 afs_int32 
1526 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1527 {
1528     cm_SkipIoctlPath(&ioctlp->ioctl);
1529        
1530     return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1531 }
1532
1533 afs_int32 
1534 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1535 {
1536     cm_SkipIoctlPath(&ioctlp->ioctl);
1537        
1538     return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1539 }
1540
1541 afs_int32 
1542 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1543 {
1544     cm_SkipIoctlPath(&ioctlp->ioctl);
1545
1546     return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1547 }
1548
1549 afs_int32 
1550 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1551 {
1552     cm_SkipIoctlPath(&ioctlp->ioctl);
1553
1554     return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1555 }
1556
1557 afs_int32 
1558 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp)
1559 {
1560     cm_SkipIoctlPath(&ioctlp->ioctl);
1561
1562     return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1563 }
1564
1565 afs_int32
1566 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1567 {
1568     cm_SkipIoctlPath(&ioctlp->ioctl);
1569
1570     return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1571 }
1572
1573 afs_int32 
1574 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1575 {
1576     cm_SkipIoctlPath(&ioctlp->ioctl);
1577
1578     return cm_IoctlSysName(&ioctlp->ioctl, userp);
1579 }
1580
1581 afs_int32 
1582 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1583 {
1584     cm_SkipIoctlPath(&ioctlp->ioctl);
1585
1586     return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1587 }
1588
1589 afs_int32 
1590 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1591 {
1592     cm_SkipIoctlPath(&ioctlp->ioctl);
1593
1594     return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1595 }
1596
1597 afs_int32
1598 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1599 {
1600     cm_SkipIoctlPath(&ioctlp->ioctl);
1601
1602     return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1603 }
1604
1605 afs_int32
1606 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1607 {
1608     cm_SkipIoctlPath(&ioctlp->ioctl);
1609
1610     return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1611 }
1612
1613 afs_int32
1614 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1615 {
1616     /* we ignore default asynchrony since we only have one way
1617      * of doing this today.
1618      */
1619     return 0;
1620 }       
1621
1622 afs_int32
1623 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1624 {
1625     afs_int32 code;
1626     cm_scache_t *dscp;
1627     clientchar_t leaf[LEAF_SIZE];
1628     cm_req_t req;
1629
1630     smb_InitReq(&req);
1631         
1632     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1633     if (code)
1634         return code;
1635
1636     code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1637
1638     cm_ReleaseSCache(dscp);
1639     return code;
1640 }
1641
1642 afs_int32
1643 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1644 {
1645     afs_int32 code;
1646     cm_scache_t *dscp;
1647     clientchar_t leaf[LEAF_SIZE];
1648     cm_req_t req;
1649
1650     smb_InitReq(&req);
1651
1652     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1653     if (code) return code;
1654
1655     code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1656
1657     cm_ReleaseSCache(dscp);
1658
1659     return code;
1660 }
1661
1662 afs_int32 
1663 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1664 {
1665     afs_int32 code;
1666     cm_scache_t *dscp;
1667     cm_req_t req;
1668
1669     smb_InitReq(&req);
1670
1671     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1672     if (code) return code;
1673
1674     code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1675
1676     cm_ReleaseSCache(dscp);
1677     return code;
1678 }
1679
1680 afs_int32 
1681 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1682 {/*CHECK FOR VALID SYMLINK*/
1683     afs_int32 code;
1684     cm_scache_t *dscp;
1685     cm_req_t req;
1686
1687     smb_InitReq(&req);
1688
1689     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1690     if (code) return code;
1691
1692     code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1693
1694     cm_ReleaseSCache(dscp);
1695
1696     return code;
1697 }
1698
1699 afs_int32 
1700 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1701 {
1702     afs_int32 code;
1703     cm_scache_t *dscp;
1704     cm_req_t req;
1705
1706     smb_InitReq(&req);
1707
1708     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1709     if (code) return code;
1710
1711     code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1712
1713     cm_ReleaseSCache(dscp);
1714
1715     return code;
1716 }
1717
1718 afs_int32 
1719 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
1720 {
1721     cm_SkipIoctlPath(&ioctlp->ioctl);
1722
1723     return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1724 }
1725
1726 afs_int32
1727 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1728 {
1729     cm_SkipIoctlPath(&ioctlp->ioctl);
1730
1731     return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1732 }
1733
1734
1735 afs_int32
1736 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1737 {
1738     cm_SkipIoctlPath(&ioctlp->ioctl);
1739
1740     return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1741 }
1742
1743
1744 afs_int32
1745 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1746 {
1747     cm_SkipIoctlPath(&ioctlp->ioctl);
1748
1749     return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1750 }
1751
1752
1753 afs_int32
1754 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp)
1755 {
1756     cm_SkipIoctlPath(&ioctlp->ioctl);
1757
1758     return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1759 }
1760
1761 afs_int32
1762 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1763 {
1764     cm_SkipIoctlPath(&ioctlp->ioctl);
1765
1766     return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1767 }
1768
1769 afs_int32
1770 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1771 {
1772     cm_SkipIoctlPath(&ioctlp->ioctl);
1773
1774     return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1775 }
1776
1777 afs_int32
1778 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
1779 {
1780     cm_SkipIoctlPath(&ioctlp->ioctl);
1781
1782     return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1783 }
1784
1785
1786 afs_int32
1787 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
1788 {
1789     cm_SkipIoctlPath(&ioctlp->ioctl);
1790
1791     return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1792 }
1793
1794 afs_int32
1795 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1796 {
1797     cm_SkipIoctlPath(&ioctlp->ioctl);
1798
1799     return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1800 }
1801
1802 afs_int32
1803 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1804 {
1805     cm_SkipIoctlPath(&ioctlp->ioctl);
1806
1807     return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1808 }
1809
1810
1811 afs_int32
1812 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
1813 {
1814     cm_SkipIoctlPath(&ioctlp->ioctl);
1815
1816     return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1817 }
1818
1819 afs_int32
1820 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
1821 {
1822     afs_int32 code;
1823     cm_scache_t *scp;
1824     cm_req_t req;
1825     cm_ioctlQueryOptions_t *optionsp;
1826     afs_uint32 flags = 0;
1827
1828     smb_InitReq(&req);
1829
1830     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1831     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1832         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1833
1834     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1835         cm_fid_t fid;
1836         cm_SkipIoctlPath(&ioctlp->ioctl);
1837         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, 
1838                   optionsp->fid.vnode, optionsp->fid.unique);
1839         code = cm_GetSCache(&fid, &scp, userp, &req);
1840     } else {
1841         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1842     }
1843     if (code) 
1844         return code;
1845
1846     code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1847     cm_ReleaseSCache(scp);
1848     return code;
1849 }
1850
1851 afs_int32
1852 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
1853 {
1854     cm_req_t req;
1855
1856     smb_InitReq(&req);
1857
1858     cm_SkipIoctlPath(&ioctlp->ioctl);
1859
1860     return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
1861 }
1862
1863 /* 
1864  * VIOC_SETOWNER
1865  * 
1866  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1867  *
1868  */
1869 afs_int32 
1870 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1871 {
1872     afs_int32 code;
1873     cm_scache_t *scp;
1874     cm_req_t req;
1875     cm_ioctlQueryOptions_t *optionsp;
1876     afs_uint32 flags = 0;
1877
1878     smb_InitReq(&req);
1879
1880     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1881     if (optionsp) {
1882         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1883             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1884
1885         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1886             cm_fid_t fid;
1887             cm_SkipIoctlPath(&ioctlp->ioctl);
1888             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1889                        optionsp->fid.vnode, optionsp->fid.unique);
1890             code = cm_GetSCache(&fid, &scp, userp, &req);
1891         } else {
1892             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1893         }
1894         if (code) 
1895             return code;
1896
1897         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1898     }
1899
1900     code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
1901
1902     cm_ReleaseSCache(scp);
1903
1904     return code;
1905 }
1906
1907 /* 
1908  * VIOC_GETOWNER
1909  * 
1910  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1911  *
1912  */
1913 afs_int32 
1914 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp)
1915 {
1916     afs_int32 code;
1917     cm_scache_t *scp;
1918     cm_req_t req;
1919     cm_ioctlQueryOptions_t *optionsp;
1920     afs_uint32 flags = 0;
1921
1922     smb_InitReq(&req);
1923
1924     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1925     if (optionsp) {
1926         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1927             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1928
1929         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1930             cm_fid_t fid;
1931             cm_SkipIoctlPath(&ioctlp->ioctl);
1932             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1933                        optionsp->fid.vnode, optionsp->fid.unique);
1934             code = cm_GetSCache(&fid, &scp, userp, &req);
1935         } else {
1936             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1937         }
1938         if (code) 
1939             return code;
1940
1941         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1942     }
1943
1944     code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
1945
1946     cm_ReleaseSCache(scp);
1947
1948     return code;
1949 }
1950
1951
1952