2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afs/param.h>
16 #include <sys/socket.h>
28 #include "afsd_init.h"
29 #include <WINNT\afsreg.h>
32 #include "cm_server.h"
45 #include <..\afsrdr\kif.h>
52 /* Copied from afs_tokens.h */
53 #define PIOCTL_LOGON 0x1
56 osi_mutex_t cm_Afsdsbmt_Lock;
58 extern afs_int32 cryptall;
59 extern char cm_NetbiosName[];
61 extern void afsi_log(char *pattern, ...);
63 void cm_InitIoctl(void)
65 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
68 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
72 lock_ObtainWrite(&scp->bufCreateLock);
73 code = buf_FlushCleanPages(scp, userp, reqp);
75 lock_ObtainMutex(&scp->mx);
76 scp->cbServerp = NULL;
80 cm_FreeAllACLEnts(scp);
82 /* Force mount points and symlinks to be re-evaluated */
83 scp->mountPointStringp[0] = '\0';
85 lock_ReleaseMutex(&scp->mx);
87 lock_ReleaseWrite(&scp->bufCreateLock);
88 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
92 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
98 lock_ObtainWrite(&cm_scacheLock);
99 cm_HoldSCacheNoLock(scp);
100 parent_fid = scp->fid;
101 parent_fid.vnode = scp->parentVnode;
102 parent_fid.unique = scp->parentUnique;
103 cm_ReleaseSCacheNoLock(scp);
105 for (i=0; i<cm_data.hashTableSize; i++) {
106 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
107 if (!cm_FidCmp(&scp->fid, &parent_fid)) {
108 cm_HoldSCacheNoLock(scp);
109 lock_ReleaseWrite(&cm_scacheLock);
111 /* now flush the file */
112 code = cm_FlushFile(scp, userp, reqp);
113 lock_ObtainWrite(&cm_scacheLock);
114 cm_ReleaseSCacheNoLock(scp);
118 lock_ReleaseWrite(&cm_scacheLock);
124 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
130 lock_ObtainWrite(&cm_scacheLock);
131 for (i=0; i<cm_data.hashTableSize; i++) {
132 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
133 if (scp->fid.volume == volume && scp->fid.cell == cell) {
134 cm_HoldSCacheNoLock(scp);
135 lock_ReleaseWrite(&cm_scacheLock);
137 /* now flush the file */
138 code = cm_FlushFile(scp, userp, reqp);
139 lock_ObtainWrite(&cm_scacheLock);
140 cm_ReleaseSCacheNoLock(scp);
144 lock_ReleaseWrite(&cm_scacheLock);
150 * cm_ResetACLCache -- invalidate ACL info for a user that has just
151 * obtained or lost tokens
153 void cm_ResetACLCache(cm_user_t *userp)
158 lock_ObtainWrite(&cm_scacheLock);
159 for (hash=0; hash < cm_data.hashTableSize; hash++) {
160 for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
161 cm_HoldSCacheNoLock(scp);
162 lock_ReleaseWrite(&cm_scacheLock);
163 lock_ObtainMutex(&scp->mx);
164 cm_InvalidateACLUser(scp, userp);
165 lock_ReleaseMutex(&scp->mx);
166 lock_ObtainWrite(&cm_scacheLock);
167 cm_ReleaseSCacheNoLock(scp);
170 lock_ReleaseWrite(&cm_scacheLock);
174 * TranslateExtendedChars - This is a fix for TR 54482.
176 * If an extended character (80 - FF) is entered into a file
177 * or directory name in Windows, the character is translated
178 * into the OEM character map before being passed to us. Why
179 * this occurs is unknown. Our pioctl functions must match
180 * this translation for paths given via our own commands (like
181 * fs). If we do not do this, then we will try to perform an
182 * operation on a non-translated path, which we will fail to
183 * find, since the path was created with the translated chars.
184 * This function performs the required translation.
186 void TranslateExtendedChars(char *str)
199 while (*p) *p++ &= 0x7f; /* turn off high bit; probably not right */
203 /* parse the passed-in file name and do a namei on it. If we fail,
204 * return an error code, otherwise return the vnode located in *scpp.
206 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
210 cm_scache_t *substRootp;
211 char * relativePath = ioctlp->inDatap;
213 char * absRoot[MAX_PATH];
215 wchar_t absRoot_w[MAX_PATH];
218 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
220 /* This is usually the file name, but for StatMountPoint it is the path. */
221 /* ioctlp->inDatap can be either of the form:
224 * \\netbios-name\submount\path\.
225 * \\netbios-name\submount\path\file
227 TranslateExtendedChars(relativePath);
230 /* we have passed the whole path, including the afs prefix.
231 when the pioctl call is made, we perform an ioctl to afsrdr
232 and it returns the correct (full) path. therefore, there is
233 no drive letter, and the path is absolute. */
234 code = cm_NameI(cm_data.rootSCachep, relativePath,
235 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
236 userp, "", reqp, scpp);
241 /* # of bytes of path */
242 code = strlen(ioctlp->inDatap) + 1;
243 ioctlp->inDatap += code;
245 /* This is usually nothing, but for StatMountPoint it is the file name. */
246 TranslateExtendedChars(ioctlp->inDatap);
251 if (relativePath[0] == relativePath[1] &&
252 relativePath[1] == '\\' &&
253 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
259 /* We may have found a UNC path.
260 * If the first component is the NetbiosName,
261 * then throw out the second component (the submount)
262 * since it had better expand into the value of ioctl->tidPathp
265 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
266 if ( !_strnicmp("all", p, 3) )
269 for (i = 0; *p && *p != '\\'; i++,p++ ) {
272 p++; /* skip past trailing slash */
273 shareName[i] = 0; /* terminate string */
275 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
277 /* we found a sharename, therefore use the resulting path */
278 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
279 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
280 userp, sharePath, reqp, &substRootp);
285 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
286 userp, NULL, reqp, scpp);
290 /* otherwise, treat the name as a cellname mounted off the afs root.
291 * This requires that we reconstruct the shareName string with
292 * leading and trailing slashes.
294 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
295 if ( !_strnicmp("all", p, 3) )
299 for (i = 1; *p && *p != '\\'; i++,p++ ) {
302 p++; /* skip past trailing slash */
303 shareName[i++] = '/'; /* add trailing slash */
304 shareName[i] = 0; /* terminate string */
307 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
308 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
309 userp, shareName, reqp, &substRootp);
313 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
314 userp, NULL, reqp, scpp);
319 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
320 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
321 userp, ioctlp->tidPathp, reqp, &substRootp);
325 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
326 userp, NULL, reqp, scpp);
331 /* # of bytes of path */
332 code = (long)strlen(ioctlp->inDatap) + 1;
333 ioctlp->inDatap += code;
335 /* This is usually nothing, but for StatMountPoint it is the file name. */
336 TranslateExtendedChars(ioctlp->inDatap);
338 /* and return success */
342 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
346 temp = (long) strlen(ioctlp->inDatap) + 1;
347 ioctlp->inDatap += temp;
351 /* format the specified path to look like "/afs/<cellname>/usr", by
352 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
353 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
354 * intentionally returned as "/afs/"--this makes submount manipulation
355 * easier (because we can always jump past the initial "/afs" to find
356 * the AFS path that should be written into afsdsbmt.ini).
358 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
361 char bslash_mountRoot[256];
363 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
364 bslash_mountRoot[0] = '\\';
366 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
367 StringCbCopy(outpathp, outlen, inpathp);
368 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
369 StringCbCopy(outpathp, outlen, inpathp);
370 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
371 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
372 else // inpathp looks like "<cell>/usr"
373 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
375 for (cp = outpathp; *cp != 0; ++cp) {
380 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
381 outpathp[strlen(outpathp)-1] = 0;
384 if (!strcmpi (outpathp, cm_mountRoot)) {
385 StringCbCopy(outpathp, outlen, cm_mountRoot);
389 #define LEAF_SIZE 256
390 /* parse the passed-in file name and do a namei on its parent. If we fail,
391 * return an error code, otherwise return the vnode located in *scpp.
393 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
394 cm_scache_t **scpp, char *leafp)
399 cm_scache_t *substRootp;
401 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
402 tp = strrchr(tbuffer, '\\');
403 jp = strrchr(tbuffer, '/');
406 else if (jp && (tp - tbuffer) < (jp - tbuffer))
409 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
411 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
416 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
419 if (tbuffer[0] == tbuffer[1] &&
420 tbuffer[1] == '\\' &&
421 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
427 /* We may have found a UNC path.
428 * If the first component is the NetbiosName,
429 * then throw out the second component (the submount)
430 * since it had better expand into the value of ioctl->tidPathp
433 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
434 if ( !_strnicmp("all", p, 3) )
437 for (i = 0; *p && *p != '\\'; i++,p++ ) {
440 p++; /* skip past trailing slash */
441 shareName[i] = 0; /* terminate string */
443 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
445 /* we found a sharename, therefore use the resulting path */
446 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
447 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
448 userp, sharePath, reqp, &substRootp);
450 if (code) return code;
452 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
453 userp, NULL, reqp, scpp);
454 if (code) return code;
456 /* otherwise, treat the name as a cellname mounted off the afs root.
457 * This requires that we reconstruct the shareName string with
458 * leading and trailing slashes.
460 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
461 if ( !_strnicmp("all", p, 3) )
465 for (i = 1; *p && *p != '\\'; i++,p++ ) {
468 p++; /* skip past trailing slash */
469 shareName[i++] = '/'; /* add trailing slash */
470 shareName[i] = 0; /* terminate string */
472 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
473 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
474 userp, shareName, reqp, &substRootp);
475 if (code) return code;
477 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
478 userp, NULL, reqp, scpp);
479 if (code) return code;
482 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
483 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
484 userp, ioctlp->tidPathp, reqp, &substRootp);
485 if (code) return code;
487 code = cm_NameI(substRootp, tbuffer, CM_FLAG_FOLLOW,
488 userp, NULL, reqp, scpp);
489 if (code) return code;
492 /* # of bytes of path */
493 code = (long)strlen(ioctlp->inDatap) + 1;
494 ioctlp->inDatap += code;
496 /* and return success */
500 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
505 AFSFetchStatus fileStatus;
511 struct rx_connection * callp;
515 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
516 if (code) return code;
518 /* now make the get acl call */
519 fid.Volume = scp->fid.volume;
520 fid.Vnode = scp->fid.vnode;
521 fid.Unique = scp->fid.unique;
523 acl.AFSOpaque_val = ioctlp->outDatap;
524 acl.AFSOpaque_len = 0;
525 code = cm_Conn(&scp->fid, userp, &req, &connp);
528 callp = cm_GetRxConn(connp);
529 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
530 rx_PutConnection(callp);
532 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
533 code = cm_MapRPCError(code, &req);
534 cm_ReleaseSCache(scp);
536 if (code) return code;
538 /* skip over return data */
539 tlen = (int)strlen(ioctlp->outDatap) + 1;
540 ioctlp->outDatap += tlen;
542 /* and return success */
546 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
555 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
556 if (code) return code;
558 #ifdef AFS_FREELANCE_CLIENT
559 if ( cm_freelanceEnabled &&
560 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
561 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
562 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
563 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
564 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
567 #endif /* AFS_FREELANCE_CLIENT */
569 cellp = cm_FindCellByID(scp->fid.cell);
571 StringCbCopyA(ioctlp->outDatap, 999999, cellp->name);
572 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
576 code = CM_ERROR_NOSUCHCELL;
579 cm_ReleaseSCache(scp);
583 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
588 AFSFetchStatus fileStatus;
593 struct rx_connection * callp;
597 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
598 if (code) return code;
600 /* now make the get acl call */
601 fid.Volume = scp->fid.volume;
602 fid.Vnode = scp->fid.vnode;
603 fid.Unique = scp->fid.unique;
605 acl.AFSOpaque_val = ioctlp->inDatap;
606 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
607 code = cm_Conn(&scp->fid, userp, &req, &connp);
610 callp = cm_GetRxConn(connp);
611 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
612 rx_PutConnection(callp);
614 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
615 code = cm_MapRPCError(code, &req);
617 /* invalidate cache info, since we just trashed the ACL cache */
618 lock_ObtainMutex(&scp->mx);
619 cm_DiscardSCache(scp);
620 lock_ReleaseMutex(&scp->mx);
622 cm_ReleaseSCache(scp);
629 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
638 lock_ObtainWrite(&cm_scacheLock);
639 for (i=0; i<cm_data.hashTableSize; i++) {
640 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
641 cm_HoldSCacheNoLock(scp);
642 lock_ReleaseWrite(&cm_scacheLock);
644 /* now flush the file */
645 code = cm_FlushFile(scp, userp, &req);
646 lock_ObtainWrite(&cm_scacheLock);
647 cm_ReleaseSCacheNoLock(scp);
650 lock_ReleaseWrite(&cm_scacheLock);
655 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
659 unsigned long volume;
665 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
666 if (code) return code;
668 volume = scp->fid.volume;
669 cell = scp->fid.cell;
670 cm_ReleaseSCache(scp);
672 code = cm_FlushVolume(userp, &req, cell, volume);
677 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
685 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
686 if (code) return code;
688 cm_FlushFile(scp, userp, &req);
689 cm_ReleaseSCache(scp);
694 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
698 char offLineMsg[256];
702 AFSFetchVolumeStatus volStat;
703 AFSStoreVolumeStatus storeStat;
708 struct rx_connection * callp;
712 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
713 if (code) return code;
715 cellp = cm_FindCellByID(scp->fid.cell);
718 if (scp->flags & CM_SCACHEFLAG_RO) {
719 cm_ReleaseSCache(scp);
720 return CM_ERROR_READONLY;
723 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
725 cm_ReleaseSCache(scp);
729 /* Copy the junk out, using cp as a roving pointer. */
730 cp = ioctlp->inDatap;
731 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
732 cp += sizeof(AFSFetchVolumeStatus);
733 StringCbCopyA(volName, sizeof(volName), cp);
734 cp += strlen(volName)+1;
735 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
736 cp += strlen(offLineMsg)+1;
737 StringCbCopyA(motd, sizeof(motd), cp);
739 if (volStat.MinQuota != -1) {
740 storeStat.MinQuota = volStat.MinQuota;
741 storeStat.Mask |= AFS_SETMINQUOTA;
743 if (volStat.MaxQuota != -1) {
744 storeStat.MaxQuota = volStat.MaxQuota;
745 storeStat.Mask |= AFS_SETMAXQUOTA;
749 code = cm_Conn(&scp->fid, userp, &req, &tcp);
752 callp = cm_GetRxConn(tcp);
753 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
754 &storeStat, volName, offLineMsg, motd);
755 rx_PutConnection(callp);
757 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
758 code = cm_MapRPCError(code, &req);
760 /* return on failure */
761 cm_ReleaseSCache(scp);
766 /* we are sending parms back to make compat. with prev system. should
767 * change interface later to not ask for current status, just set
770 cp = ioctlp->outDatap;
771 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
772 cp += sizeof(VolumeStatus);
773 StringCbCopyA(cp, 999999, volName);
774 cp += strlen(volName)+1;
775 StringCbCopyA(cp, 999999, offLineMsg);
776 cp += strlen(offLineMsg)+1;
777 StringCbCopyA(cp, 999999, motd);
778 cp += strlen(motd)+1;
780 /* now return updated return data pointer */
781 ioctlp->outDatap = cp;
786 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
790 char offLineMsg[256];
794 AFSFetchVolumeStatus volStat;
800 struct rx_connection * callp;
804 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
805 if (code) return code;
808 OfflineMsg = offLineMsg;
811 code = cm_Conn(&scp->fid, userp, &req, &tcp);
814 callp = cm_GetRxConn(tcp);
815 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
816 &volStat, &Name, &OfflineMsg, &MOTD);
817 rx_PutConnection(callp);
819 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
820 code = cm_MapRPCError(code, &req);
822 cm_ReleaseSCache(scp);
823 if (code) return code;
825 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
826 cp = ioctlp->outDatap;
827 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
828 cp += sizeof(AFSFetchVolumeStatus);
829 StringCbCopyA(cp, 999999, volName);
830 cp += strlen(volName)+1;
831 StringCbCopyA(cp, 999999, offLineMsg);
832 cp += strlen(offLineMsg)+1;
833 StringCbCopyA(cp, 999999, motd);
834 cp += strlen(motd)+1;
836 /* return new size */
837 ioctlp->outDatap = cp;
842 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
852 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
853 if (code) return code;
855 memset(&fid, 0, sizeof(cm_fid_t));
856 fid.volume = scp->fid.volume;
857 fid.vnode = scp->fid.vnode;
858 fid.unique = scp->fid.unique;
860 cm_ReleaseSCache(scp);
862 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
863 cp = ioctlp->outDatap;
864 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
865 cp += sizeof(cm_fid_t);
867 /* return new size */
868 ioctlp->outDatap = cp;
873 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
882 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
883 if (code) return code;
885 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
886 cp = ioctlp->outDatap;
887 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
888 cp += sizeof(afs_uint32);
889 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
890 cp += sizeof(afs_uint32);
892 /* return new size */
893 ioctlp->outDatap = cp;
895 cm_ReleaseSCache(scp);
900 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
906 cm_serverRef_t **tsrpp, *current;
908 unsigned long volume;
914 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
915 if (code) return code;
917 volume = scp->fid.volume;
919 cellp = cm_FindCellByID(scp->fid.cell);
922 cm_ReleaseSCache(scp);
924 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
925 if (code) return code;
927 cp = ioctlp->outDatap;
929 lock_ObtainMutex(&tvp->mx);
930 tsrpp = cm_GetVolServers(tvp, volume);
931 lock_ObtainRead(&cm_serverLock);
932 for (current = *tsrpp; current; current = current->next) {
933 tsp = current->server;
934 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
937 lock_ReleaseRead(&cm_serverLock);
938 cm_FreeServerList(tsrpp);
939 lock_ReleaseMutex(&tvp->mx);
941 /* still room for terminating NULL, add it on */
942 volume = 0; /* reuse vbl */
943 memcpy(cp, (char *)&volume, sizeof(long));
946 ioctlp->outDatap = cp;
951 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
961 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
962 if (code) return code;
964 cp = ioctlp->inDatap;
966 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
967 cm_ReleaseSCache(dscp);
968 if (code) return code;
970 lock_ObtainMutex(&scp->mx);
972 /* now check that this is a real mount point */
973 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
974 lock_ReleaseMutex(&scp->mx);
975 cm_ReleaseSCache(scp);
976 return CM_ERROR_INVAL;
979 code = cm_ReadMountPoint(scp, userp, &req);
981 cp = ioctlp->outDatap;
982 StringCbCopyA(cp, 999999, scp->mountPointStringp);
983 cp += strlen(cp) + 1;
984 ioctlp->outDatap = cp;
986 lock_ReleaseMutex(&scp->mx);
987 cm_ReleaseSCache(scp);
992 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1002 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1003 if (code) return code;
1005 cp = ioctlp->inDatap;
1007 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1009 /* if something went wrong, bail out now */
1014 lock_ObtainMutex(&scp->mx);
1015 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1016 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1018 lock_ReleaseMutex(&scp->mx);
1019 cm_ReleaseSCache(scp);
1023 /* now check that this is a real mount point */
1024 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1025 lock_ReleaseMutex(&scp->mx);
1026 cm_ReleaseSCache(scp);
1027 code = CM_ERROR_INVAL;
1031 /* time to make the RPC, so drop the lock */
1032 lock_ReleaseMutex(&scp->mx);
1033 cm_ReleaseSCache(scp);
1035 /* easier to do it this way */
1036 code = cm_Unlink(dscp, cp, userp, &req);
1037 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1038 smb_NotifyChange(FILE_ACTION_REMOVED,
1039 FILE_NOTIFY_CHANGE_DIR_NAME,
1040 dscp, cp, NULL, TRUE);
1043 cm_ReleaseSCache(dscp);
1047 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1057 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1058 tp = ioctlp->inDatap;
1061 memcpy(&temp, tp, sizeof(temp));
1062 if (temp == 0x12345678) { /* For afs3.3 version */
1063 memcpy(&csi, tp, sizeof(csi));
1064 if (csi.tinterval >= 0) {
1065 cp = ioctlp->outDatap;
1066 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1067 ioctlp->outDatap += sizeof(long);
1068 if (csi.tinterval > 0) {
1069 if (!smb_SUser(userp))
1070 return CM_ERROR_NOACCESS;
1071 cm_daemonCheckDownInterval = csi.tinterval;
1079 } else { /* For pre afs3.3 versions */
1080 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1081 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1082 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1087 * 1: fast check, don't contact servers.
1088 * 2: local cell only.
1091 /* have cell name, too */
1092 cellp = cm_GetCell(cp, 0);
1093 if (!cellp) return CM_ERROR_NOSUCHCELL;
1095 else cellp = (cm_cell_t *) 0;
1096 if (!cellp && (temp & 2)) {
1097 /* use local cell */
1098 cellp = cm_FindCellByID(1);
1100 if (!(temp & 1)) { /* if not fast, call server checker routine */
1101 /* check down servers */
1102 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1106 /* now return the current down server list */
1107 cp = ioctlp->outDatap;
1108 lock_ObtainRead(&cm_serverLock);
1109 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1110 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1111 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1112 && tsp->type == CM_SERVER_FILE) {
1113 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1117 lock_ReleaseRead(&cm_serverLock);
1119 ioctlp->outDatap = cp;
1123 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1125 /* we don't print anything superfluous, so we don't support the gag call */
1126 return CM_ERROR_INVAL;
1129 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1135 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1140 cm_SkipIoctlPath(ioctlp);
1142 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1144 temp = cm_data.buf_nOrigBuffers;
1146 /* temp is in 1K units, convert to # of buffers */
1147 temp = temp / (cm_data.buf_blockSize / 1024);
1150 /* now adjust the cache size */
1151 code = buf_SetNBuffers(temp);
1156 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1160 cm_SkipIoctlPath(ioctlp);
1162 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1166 afsd_ForceTrace(FALSE);
1167 buf_ForceTrace(FALSE);
1171 /* set tracing value to low order bit */
1172 if ((inValue & 1) == 0) {
1173 /* disable tracing */
1174 osi_LogDisable(afsd_logp);
1175 rx_DebugOnOff(FALSE);
1178 /* enable tracing */
1179 osi_LogEnable(afsd_logp);
1180 rx_DebugOnOff(TRUE);
1184 /* see if we're supposed to do a reset, too */
1186 osi_LogReset(afsd_logp);
1189 /* and copy out tracing flag */
1190 inValue = afsd_logp->enabled; /* use as a temp vbl */
1191 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1192 ioctlp->outDatap += sizeof(long);
1196 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1198 cm_cacheParms_t parms;
1200 memset(&parms, 0, sizeof(parms));
1202 /* first we get, in 1K units, the cache size */
1203 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1205 /* and then the actual # of buffers in use (not in the free list, I guess,
1206 * will be what we do).
1208 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1210 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1211 ioctlp->outDatap += sizeof(parms);
1216 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1221 cm_serverRef_t *serverRefp;
1222 cm_server_t *serverp;
1228 cm_SkipIoctlPath(ioctlp);
1230 tp = ioctlp->inDatap;
1232 memcpy((char *)&whichCell, tp, sizeof(long));
1235 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1236 if (ioctlp->inCopied-1 > sizeof(long)) {
1237 memcpy((char *)&magic, tp, sizeof(long));
1240 lock_ObtainRead(&cm_cellLock);
1241 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1242 if (whichCell == 0) break;
1245 lock_ReleaseRead(&cm_cellLock);
1249 cp = ioctlp->outDatap;
1251 if (magic == 0x12345678) {
1252 memcpy(cp, (char *)&magic, sizeof(long));
1255 memset(cp, 0, max * sizeof(long));
1257 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1258 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1259 serverRefp = tcellp->vlServersp;
1260 for (i=0; i<max; i++) {
1261 if (!serverRefp) break;
1262 serverp = serverRefp->server;
1263 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1265 serverRefp = serverRefp->next;
1267 lock_ReleaseRead(&cm_serverLock);
1268 cp = basep + max * sizeof(afs_int32);
1269 StringCbCopyA(cp, 999999, tcellp->name);
1270 cp += strlen(tcellp->name)+1;
1271 ioctlp->outDatap = cp;
1277 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1280 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1282 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1284 /* NT cache manager will read cell information from CellServDB each time
1285 * cell is accessed. So, this call is necessary only if list of server for a cell
1286 * changes (or IP addresses of cell servers changes).
1287 * All that needs to be done is to refresh server information for all cells that
1288 * are already loaded.
1290 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1295 cm_SkipIoctlPath(ioctlp);
1296 lock_ObtainWrite(&cm_cellLock);
1298 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1301 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1302 cm_FreeServerList(&cp->vlServersp);
1303 cp->vlServersp = NULL;
1304 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1305 #ifdef AFS_AFSDB_ENV
1307 if (cm_dnsEnabled) {
1309 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1310 if ( code == 0 ) { /* got cell from DNS */
1311 cp->flags |= CM_CELLFLAG_DNS;
1312 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1313 cp->timeout = time(0) + ttl;
1318 cp->flags &= ~CM_CELLFLAG_DNS;
1320 #endif /* AFS_AFSDB_ENV */
1322 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1325 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1326 cm_RandomizeServer(&cp->vlServersp);
1330 lock_ReleaseWrite(&cm_cellLock);
1334 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1338 if (cm_freelanceEnabled) {
1339 if (cm_GetRootCellName(ioctlp->outDatap))
1340 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
1341 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1342 } else if (cm_data.rootCellp) {
1343 /* return the default cellname to the caller */
1344 StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
1345 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1347 /* if we don't know our default cell, return failure */
1348 code = CM_ERROR_NOSUCHCELL;
1354 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1356 long setSysName, foundname = 0;
1357 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1358 int t, count, num = 0;
1359 char **sysnamelist[MAXSYSNAME];
1361 cm_SkipIoctlPath(ioctlp);
1363 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1364 ioctlp->inDatap += sizeof(long);
1368 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1370 cp2 = ioctlp->inDatap;
1371 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1372 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1373 t = (int)strlen(cp);
1374 if (t >= MAXSYSNAME || t <= 0)
1376 /* check for names that can shoot us in the foot */
1377 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1383 /* inname gets first entry in case we're being a translator */
1384 /* (we are never a translator) */
1385 t = (int)strlen(ioctlp->inDatap);
1386 memcpy(inname, ioctlp->inDatap, t + 1);
1387 ioctlp->inDatap += t + 1;
1391 /* Not xlating, so local case */
1393 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1395 if (!setSysName) { /* user just wants the info */
1396 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1397 foundname = cm_sysNameCount;
1398 *sysnamelist = cm_sysNameList;
1400 /* Local guy; only root can change sysname */
1401 /* clear @sys entries from the dnlc, once afs_lookup can
1402 * do lookups of @sys entries and thinks it can trust them */
1403 /* privs ok, store the entry, ... */
1404 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1405 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1406 if (setSysName > 1) { /* ... or list */
1407 cp = ioctlp->inDatap;
1408 for (count = 1; count < setSysName; ++count) {
1409 if (!cm_sysNameList[count])
1410 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1411 __FILE__, __LINE__);
1412 t = (int)strlen(cp);
1413 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1417 cm_sysNameCount = setSysName;
1421 /* return the sysname to the caller */
1422 cp = ioctlp->outDatap;
1423 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1424 cp += sizeof(afs_int32); /* skip found flag */
1426 StringCbCopyA(cp, 999999, outname);
1427 cp += strlen(outname) + 1; /* skip name and terminating null char */
1428 for ( count=1; count < foundname ; ++count) { /* ... or list */
1429 if ( !(*sysnamelist)[count] )
1430 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1431 __FILE__, __LINE__);
1432 t = (int)strlen((*sysnamelist)[count]);
1433 if (t >= MAXSYSNAME)
1434 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1435 __FILE__, __LINE__);
1436 StringCbCopyA(cp, 999999, (*sysnamelist)[count]);
1440 ioctlp->outDatap = cp;
1447 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1452 cm_SkipIoctlPath(ioctlp);
1454 cellp = cm_GetCell(ioctlp->inDatap, 0);
1456 return CM_ERROR_NOSUCHCELL;
1459 lock_ObtainMutex(&cellp->mx);
1460 if (cellp->flags & CM_CELLFLAG_SUID)
1461 temp |= CM_SETCELLFLAG_SUID;
1462 lock_ReleaseMutex(&cellp->mx);
1464 /* now copy out parm */
1465 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1466 ioctlp->outDatap += sizeof(long);
1471 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1476 cm_SkipIoctlPath(ioctlp);
1478 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1480 return CM_ERROR_NOSUCHCELL;
1482 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1484 lock_ObtainMutex(&cellp->mx);
1485 if (temp & CM_SETCELLFLAG_SUID)
1486 cellp->flags |= CM_CELLFLAG_SUID;
1488 cellp->flags &= ~CM_CELLFLAG_SUID;
1489 lock_ReleaseMutex(&cellp->mx);
1494 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1496 cm_SSetPref_t *spin; /* input */
1497 cm_SPref_t *srvin; /* one input component */
1499 int i, vlonly, noServers, type;
1500 struct sockaddr_in tmp;
1501 unsigned short rank;
1503 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1505 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1506 noServers = spin->num_servers;
1507 vlonly = spin->flags;
1509 type = CM_SERVER_VLDB;
1511 type = CM_SERVER_FILE;
1513 for ( i=0; i < noServers; i++)
1515 srvin = &(spin->servers[i]);
1516 rank = srvin->rank + (rand() & 0x000f);
1517 tmp.sin_addr = srvin->host;
1518 tmp.sin_family = AF_INET;
1520 tsp = cm_FindServer(&tmp, type);
1521 if ( tsp ) /* an existing server - ref count increased */
1523 tsp->ipRank = rank; /* no need to protect by mutex*/
1525 if (type == CM_SERVER_FILE)
1527 /* find volumes which might have RO copy
1528 /* on server and change the ordering of
1531 cm_ChangeRankVolume(tsp);
1535 /* set preferences for an existing vlserver */
1536 cm_ChangeRankCellVLServer(tsp);
1539 else /* add a new server without a cell */
1541 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1544 lock_ObtainMutex(&tsp->mx);
1545 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1546 lock_ReleaseMutex(&tsp->mx);
1547 cm_PutServer(tsp); /* decrease refcount */
1552 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1554 cm_SPrefRequest_t *spin; /* input */
1555 cm_SPrefInfo_t *spout; /* output */
1556 cm_SPref_t *srvout; /* one output component */
1558 int i, vlonly, noServers;
1560 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1562 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1563 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1564 srvout = spout->servers;
1565 noServers = spin->num_servers;
1566 vlonly = spin->flags & CM_SPREF_VLONLY;
1567 spout->num_servers = 0;
1569 lock_ObtainRead(&cm_serverLock); /* get server lock */
1571 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1572 if (spin->offset > i) {
1573 continue; /* catch up to where we left off */
1576 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1577 continue; /* ignore fileserver for -vlserver option*/
1578 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1579 continue; /* ignore vlservers */
1581 srvout->host = tsp->addr.sin_addr;
1582 srvout->rank = tsp->ipRank;
1584 spout->num_servers++;
1587 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1589 if ( tsp ) /* we ran out of space in the output buffer */
1590 spout->next_offset = i;
1592 spout->next_offset = 0;
1593 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1594 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1598 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1600 /* we ignore default asynchrony since we only have one way
1601 * of doing this today.
1606 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1608 char leaf[LEAF_SIZE];
1622 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1623 if (code) return code;
1625 /* Translate chars for the mount point name */
1626 TranslateExtendedChars(leaf);
1629 * The fs command allows the user to specify partial cell names on NT. These must
1630 * be expanded to the full cell name for mount points so that the mount points will
1631 * work on UNIX clients.
1634 /* Extract the possibly partial cell name */
1635 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1637 if (cp = strchr(cell, ':')) {
1638 /* Extract the volume name */
1640 StringCbCopyA(volume, sizeof(volume), cp + 1);
1642 /* Get the full name for this cell */
1643 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1644 #ifdef AFS_AFSDB_ENV
1645 if (code && cm_dnsEnabled)
1646 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1649 return CM_ERROR_NOSUCHCELL;
1651 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1653 /* No cell name specified */
1654 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1657 #ifdef AFS_FREELANCE_CLIENT
1658 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1659 /* we are adding the mount point to the root dir., so call
1660 * the freelance code to do the add. */
1661 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1662 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1663 *ioctlp->inDatap == '%', NULL);
1667 /* create the symlink with mode 644. The lack of X bits tells
1668 * us that it is a mount point.
1670 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1671 tattr.unixModeBits = 0644;
1672 tattr.clientModTime = time(NULL);
1674 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1675 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1676 smb_NotifyChange(FILE_ACTION_ADDED,
1677 FILE_NOTIFY_CHANGE_DIR_NAME,
1678 dscp, leaf, NULL, TRUE);
1680 cm_ReleaseSCache(dscp);
1684 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1686 char leaf[LEAF_SIZE];
1695 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1696 if (code) return code;
1698 /* Translate chars for the link name */
1699 TranslateExtendedChars(leaf);
1701 /* Translate chars for the linked to name */
1702 TranslateExtendedChars(ioctlp->inDatap);
1704 cp = ioctlp->inDatap; /* contents of link */
1706 #ifdef AFS_FREELANCE_CLIENT
1707 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1708 /* we are adding the symlink to the root dir., so call
1709 * the freelance code to do the add. */
1710 if (cp[0] == cp[1] && cp[1] == '\\' &&
1711 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1713 /* skip \\AFS\ or \\AFS\all\ */
1715 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1716 if ( !_strnicmp("all", p, 3) )
1720 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1721 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1726 /* Create symlink with mode 0755. */
1727 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1728 tattr.unixModeBits = 0755;
1730 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1731 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1732 smb_NotifyChange(FILE_ACTION_ADDED,
1733 FILE_NOTIFY_CHANGE_FILE_NAME
1734 | FILE_NOTIFY_CHANGE_DIR_NAME,
1735 dscp, leaf, NULL, TRUE);
1737 cm_ReleaseSCache(dscp);
1743 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1750 cm_scache_t *newRootScp;
1755 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1756 if (code) return code;
1758 cp = ioctlp->inDatap;
1760 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1761 cm_ReleaseSCache(dscp);
1762 if (code) return code;
1764 /* Check that it's a real symlink */
1765 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1766 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1767 scp->fileType != CM_SCACHETYPE_INVALID) {
1768 cm_ReleaseSCache(scp);
1769 return CM_ERROR_INVAL;
1772 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1773 cm_ReleaseSCache(scp);
1775 cp = ioctlp->outDatap;
1776 if (newRootScp != NULL) {
1777 StringCbCopyA(cp, 999999, cm_mountRoot);
1778 StringCbCatA(cp, 999999, "/");
1781 StringCbCopyA(cp, 999999, spacep->data);
1782 cp += strlen(cp) + 1;
1783 ioctlp->outDatap = cp;
1784 cm_FreeSpace(spacep);
1785 if (newRootScp != NULL)
1786 cm_ReleaseSCache(newRootScp);
1788 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1789 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1790 code == CM_ERROR_NOSUCHPATH &&
1791 scp->fileType == CM_SCACHETYPE_INVALID) {
1792 cp = ioctlp->outDatap;
1793 StringCbCopyA(cp, 999999, spacep->data);
1794 cp += strlen(cp) + 1;
1795 ioctlp->outDatap = cp;
1796 cm_FreeSpace(spacep);
1797 if (newRootScp != NULL)
1798 cm_ReleaseSCache(newRootScp);
1805 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1806 {/*CHECK FOR VALID SYMLINK*/
1815 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1816 if (code) return code;
1818 cp = ioctlp->inDatap;
1819 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1821 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1822 cm_ReleaseSCache(dscp);
1823 if (code) return code;
1825 /* Check that it's a real symlink */
1826 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1827 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1828 scp->fileType != CM_SCACHETYPE_INVALID)
1829 code = CM_ERROR_INVAL;
1830 cm_ReleaseSCache(scp);
1834 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1844 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1845 if (code) return code;
1847 cp = ioctlp->inDatap;
1849 #ifdef AFS_FREELANCE_CLIENT
1850 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1851 /* we are adding the mount point to the root dir., so call
1852 * the freelance code to do the add. */
1853 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1854 code = cm_FreelanceRemoveSymlink(cp);
1859 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1861 /* if something went wrong, bail out now */
1866 lock_ObtainMutex(&scp->mx);
1867 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1868 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1870 lock_ReleaseMutex(&scp->mx);
1871 cm_ReleaseSCache(scp);
1875 /* now check that this is a real symlink */
1876 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1877 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1878 scp->fileType != CM_SCACHETYPE_INVALID) {
1879 lock_ReleaseMutex(&scp->mx);
1880 cm_ReleaseSCache(scp);
1881 code = CM_ERROR_INVAL;
1885 /* time to make the RPC, so drop the lock */
1886 lock_ReleaseMutex(&scp->mx);
1887 cm_ReleaseSCache(scp);
1889 /* easier to do it this way */
1890 code = cm_Unlink(dscp, cp, userp, &req);
1891 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1892 smb_NotifyChange(FILE_ACTION_REMOVED,
1893 FILE_NOTIFY_CHANGE_FILE_NAME
1894 | FILE_NOTIFY_CHANGE_DIR_NAME,
1895 dscp, cp, NULL, TRUE);
1898 cm_ReleaseSCache(dscp);
1902 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1909 struct ClearToken ct;
1917 int release_userp = 0;
1919 saveDataPtr = ioctlp->inDatap;
1921 cm_SkipIoctlPath(ioctlp);
1923 tp = ioctlp->inDatap;
1926 memcpy(&ticketLen, tp, sizeof(ticketLen));
1927 tp += sizeof(ticketLen);
1928 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1929 return CM_ERROR_INVAL;
1931 /* remember ticket and skip over it for now */
1935 /* clear token size */
1936 memcpy(&ctSize, tp, sizeof(ctSize));
1937 tp += sizeof(ctSize);
1938 if (ctSize != sizeof(struct ClearToken))
1939 return CM_ERROR_INVAL;
1942 memcpy(&ct, tp, ctSize);
1944 if (ct.AuthHandle == -1)
1945 ct.AuthHandle = 999; /* more rxvab compat stuff */
1947 /* more stuff, if any */
1948 if (ioctlp->inCopied > tp - saveDataPtr) {
1949 /* flags: logon flag */
1950 memcpy(&flags, tp, sizeof(int));
1954 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
1955 if (!cellp) return CM_ERROR_NOSUCHCELL;
1956 tp += strlen(tp) + 1;
1960 tp += strlen(tp) + 1;
1962 #ifndef AFSIFS /* no SMB username, so we cannot log based on this */
1963 if (flags & PIOCTL_LOGON) {
1964 /* SMB user name with which to associate tokens */
1966 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
1967 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
1968 fprintf(stderr, "SMB name = %s\n", smbname);
1969 tp += strlen(tp) + 1;
1971 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
1972 osi_LogSaveString(smb_logp,uname));
1976 #ifndef DJGPP /* for win95, session key is back in pioctl */
1978 memcpy(&uuid, tp, sizeof(uuid));
1979 if (!cm_FindTokenEvent(uuid, sessionKey))
1980 return CM_ERROR_INVAL;
1983 cellp = cm_data.rootCellp;
1984 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1987 if (flags & PIOCTL_LOGON) {
1988 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
1992 /* store the token */
1993 lock_ObtainMutex(&userp->mx);
1994 ucellp = cm_GetUCell(userp, cellp);
1995 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1996 ucellp->ticketLen = ticketLen;
1997 if (ucellp->ticketp)
1998 free(ucellp->ticketp); /* Discard old token if any */
1999 ucellp->ticketp = malloc(ticketLen);
2000 memcpy(ucellp->ticketp, ticket, ticketLen);
2003 * Get the session key from the RPC, rather than from the pioctl.
2006 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2008 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2010 /* for win95, we are getting the session key from the pioctl */
2011 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2013 ucellp->kvno = ct.AuthHandle;
2014 ucellp->expirationTime = ct.EndTimestamp;
2017 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2018 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2019 lock_ReleaseMutex(&userp->mx);
2021 if (flags & PIOCTL_LOGON) {
2022 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2025 cm_ResetACLCache(userp);
2028 cm_ReleaseUser(userp);
2033 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2039 struct ClearToken ct;
2041 cm_SkipIoctlPath(ioctlp);
2043 tp = ioctlp->inDatap;
2044 cp = ioctlp->outDatap;
2047 memcpy(&iterator, tp, sizeof(iterator));
2048 tp += sizeof(iterator);
2050 lock_ObtainMutex(&userp->mx);
2052 /* look for token */
2053 for (;;iterator++) {
2054 ucellp = cm_FindUCell(userp, iterator);
2056 lock_ReleaseMutex(&userp->mx);
2057 return CM_ERROR_NOMORETOKENS;
2059 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2064 temp = ucellp->iterator + 1;
2065 memcpy(cp, &temp, sizeof(temp));
2069 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2070 cp += sizeof(ucellp->ticketLen);
2073 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2074 cp += ucellp->ticketLen;
2076 /* clear token size */
2078 memcpy(cp, &temp, sizeof(temp));
2082 ct.AuthHandle = ucellp->kvno;
2085 * Don't give out a real session key here
2088 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2090 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2092 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2094 ct.ViceId = 37; /* XXX */
2095 ct.BeginTimestamp = 0; /* XXX */
2096 ct.EndTimestamp = ucellp->expirationTime;
2097 memcpy(cp, &ct, sizeof(ct));
2100 /* Primary flag (unused) */
2102 memcpy(cp, &temp, sizeof(temp));
2106 StringCbCopyA(cp, 999999, ucellp->cellp->name);
2107 cp += strlen(cp) + 1;
2110 StringCbCopyA(cp, 999999, ucellp->userName);
2111 cp += strlen(cp) + 1;
2113 ioctlp->outDatap = cp;
2115 lock_ReleaseMutex(&userp->mx);
2120 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2126 struct ClearToken ct;
2132 cm_SkipIoctlPath(ioctlp);
2134 tp = ioctlp->inDatap;
2136 cp = ioctlp->outDatap;
2138 /* cell name is right here */
2139 cellp = cm_GetCell(tp, 0);
2141 return CM_ERROR_NOSUCHCELL;
2142 tp += strlen(tp) + 1;
2146 memcpy(&uuid, tp, sizeof(uuid));
2149 lock_ObtainMutex(&userp->mx);
2151 ucellp = cm_GetUCell(userp, cellp);
2152 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2153 lock_ReleaseMutex(&userp->mx);
2154 return CM_ERROR_NOMORETOKENS;
2158 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2159 cp += sizeof(ucellp->ticketLen);
2162 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2163 cp += ucellp->ticketLen;
2165 /* clear token size */
2167 memcpy(cp, &temp, sizeof(temp));
2171 ct.AuthHandle = ucellp->kvno;
2174 * Don't give out a real session key here
2177 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2179 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2181 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2183 ct.ViceId = 37; /* XXX */
2184 ct.BeginTimestamp = 0; /* XXX */
2185 ct.EndTimestamp = ucellp->expirationTime;
2186 memcpy(cp, &ct, sizeof(ct));
2189 /* Primary flag (unused) */
2191 memcpy(cp, &temp, sizeof(temp));
2195 StringCbCopyA(cp, 999999, ucellp->cellp->name);
2196 cp += strlen(cp) + 1;
2199 StringCbCopyA(cp, 999999, ucellp->userName);
2200 cp += strlen(cp) + 1;
2202 ioctlp->outDatap = cp;
2204 lock_ReleaseMutex(&userp->mx);
2207 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2213 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2219 cm_SkipIoctlPath(ioctlp);
2221 cp = ioctlp->outDatap;
2223 /* cell name is right here */
2224 cellp = cm_GetCell(ioctlp->inDatap, 0);
2225 if (!cellp) return CM_ERROR_NOSUCHCELL;
2227 lock_ObtainMutex(&userp->mx);
2229 ucellp = cm_GetUCell(userp, cellp);
2231 lock_ReleaseMutex(&userp->mx);
2232 return CM_ERROR_NOMORETOKENS;
2235 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2237 if (ucellp->ticketp) {
2238 free(ucellp->ticketp);
2239 ucellp->ticketp = NULL;
2241 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2244 lock_ReleaseMutex(&userp->mx);
2246 cm_ResetACLCache(userp);
2251 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2255 lock_ObtainMutex(&userp->mx);
2257 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2258 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2259 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2263 lock_ReleaseMutex(&userp->mx);
2265 cm_ResetACLCache(userp);
2270 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2272 char afspath[MAX_PATH];
2274 int nextAutoSubmount;
2276 DWORD dwType, dwSize;
2281 cm_SkipIoctlPath(ioctlp);
2283 /* Serialize this one, to prevent simultaneous mods
2286 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2288 /* Parse the input parameters--first the required afs path,
2289 * then the requested submount name (which may be "").
2291 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2292 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2294 /* If the caller supplied a suggested submount name, see if
2295 * that submount name is in use... if so, the submount's path
2296 * has to match our path.
2299 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2300 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2303 REG_OPTION_NON_VOLATILE,
2304 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2309 if (submountreqp && *submountreqp) {
2310 char submountPathNormalized[MAX_PATH];
2311 char submountPath[MAX_PATH];
2313 dwSize = sizeof(submountPath);
2314 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2315 &dwType, submountPath, &dwSize);
2317 if (status != ERROR_SUCCESS) {
2319 /* The suggested submount name isn't in use now--
2320 * so we can safely map the requested submount name
2321 * to the supplied path. Remember not to write the
2322 * leading "/afs" when writing out the submount.
2324 RegSetValueEx( hkSubmounts, submountreqp, 0,
2326 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2327 &afspath[strlen(cm_mountRoot)]:"/",
2328 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2329 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2331 RegCloseKey( hkSubmounts );
2332 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2333 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2334 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2338 /* The suggested submount name is already in use--if the
2339 * supplied path matches the submount's path, we can still
2340 * use the suggested submount name.
2342 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2343 if (!strcmp (submountPathNormalized, afspath)) {
2344 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2345 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2346 RegCloseKey( hkSubmounts );
2347 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2352 RegQueryInfoKey( hkSubmounts,
2354 NULL, /* lpcClass */
2355 NULL, /* lpReserved */
2356 NULL, /* lpcSubKeys */
2357 NULL, /* lpcMaxSubKeyLen */
2358 NULL, /* lpcMaxClassLen */
2359 &dwSubmounts, /* lpcValues */
2360 NULL, /* lpcMaxValueNameLen */
2361 NULL, /* lpcMaxValueLen */
2362 NULL, /* lpcbSecurityDescriptor */
2363 NULL /* lpftLastWriteTime */
2367 /* Having obtained a list of all available submounts, start
2368 * searching that list for a path which matches the requested
2369 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2370 * submount, in case we need to add a new one later.
2373 nextAutoSubmount = 1;
2375 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2376 char submountPathNormalized[MAX_PATH];
2377 char submountPath[MAX_PATH] = "";
2378 DWORD submountPathLen = sizeof(submountPath);
2379 char submountName[MAX_PATH];
2380 DWORD submountNameLen = sizeof(submountName);
2383 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2384 &dwType, submountPath, &submountPathLen);
2385 if (dwType == REG_EXPAND_SZ) {
2387 StringCbCopyA(buf, MAX_PATH, submountPath);
2388 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2389 if (submountPathLen > MAX_PATH)
2393 /* If this is an Auto### submount, remember its ### value */
2394 if ((!strnicmp (submountName, "auto", 4)) &&
2395 (isdigit (submountName[strlen("auto")]))) {
2396 int thisAutoSubmount;
2397 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2398 nextAutoSubmount = max (nextAutoSubmount,
2399 thisAutoSubmount+1);
2402 if ((submountPathLen == 0) ||
2403 (submountPathLen == sizeof(submountPath) - 1)) {
2407 /* See if the path for this submount matches the path
2408 * that our caller specified. If so, we can return
2411 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2412 if (!strcmp (submountPathNormalized, afspath)) {
2413 StringCbCopyA(ioctlp->outDatap, 999999, submountName);
2414 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2415 RegCloseKey(hkSubmounts);
2416 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2422 /* We've been through the entire list of existing submounts, and
2423 * didn't find any which matched the specified path. So, we'll
2424 * just have to add one. Remember not to write the leading "/afs"
2425 * when writing out the submount.
2428 StringCbPrintfA(ioctlp->outDatap, 999999, "auto%ld", nextAutoSubmount);
2430 RegSetValueEx( hkSubmounts,
2434 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2435 &afspath[strlen(cm_mountRoot)]:"/",
2436 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2437 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2439 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2440 RegCloseKey(hkSubmounts);
2441 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2445 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2447 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2448 ioctlp->outDatap += sizeof(cryptall);
2453 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2455 cm_SkipIoctlPath(ioctlp);
2457 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2462 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2467 cm_SkipIoctlPath(ioctlp);
2469 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2470 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2473 if (flags & AFSCALL_RXSTATS_ENABLE) {
2474 rx_enableProcessRPCStats();
2476 if (flags & AFSCALL_RXSTATS_DISABLE) {
2477 rx_disableProcessRPCStats();
2479 if (flags & AFSCALL_RXSTATS_CLEAR) {
2480 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2485 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2490 cm_SkipIoctlPath(ioctlp);
2492 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2493 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2496 if (flags & AFSCALL_RXSTATS_ENABLE) {
2497 rx_enablePeerRPCStats();
2499 if (flags & AFSCALL_RXSTATS_DISABLE) {
2500 rx_disablePeerRPCStats();
2502 if (flags & AFSCALL_RXSTATS_CLEAR) {
2503 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2509 extern int afsd_shutdown(int);
2510 extern int afs_shutdown;
2512 long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
2513 afs_shutdown = 1; /* flag to shut down */
2518 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2520 smb_user_t *uidp = ioctlp->uidp;
2522 if (uidp && uidp->unp) {
2523 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2524 ioctlp->outDatap += strlen(uidp->unp->name);
2531 * functions to dump contents of various structures.
2532 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2534 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2535 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2536 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2538 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2542 char logfileName[MAX_PATH+1];
2547 static _CrtMemState memstate;
2550 cm_SkipIoctlPath(ioctlp);
2551 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2553 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2554 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2556 GetWindowsDirectory(logfileName, sizeof(logfileName));
2558 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2560 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2566 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2567 ioctlp->outDatap += sizeof(long);
2572 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2574 cookie = inValue ? "b" : "e";
2580 _CrtMemCheckpoint(&memstate);
2584 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2585 _CrtSetReportFile(_CRT_WARN, hLogFile);
2586 _CrtMemDumpAllObjectsSince(&memstate);
2590 /* dump all interesting data */
2591 cm_DumpSCache(hLogFile, cookie, 1);
2592 cm_DumpBufHashTable(hLogFile, cookie, 1);
2593 smb_DumpVCP(hLogFile, cookie, 1);
2595 CloseHandle(hLogFile);
2597 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2598 ioctlp->outDatap += sizeof(long);