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>
12 #include <afs/cellconfig.h>
13 #include <afs/ptserver.h>
27 #include "afsd_init.h"
28 #include <WINNT\afsreg.h>
38 #include <..\afsrdr\kif.h>
45 /* Copied from afs_tokens.h */
46 #define PIOCTL_LOGON 0x1
49 osi_mutex_t cm_Afsdsbmt_Lock;
51 extern afs_int32 cryptall;
52 extern char cm_NetbiosName[];
54 extern void afsi_log(char *pattern, ...);
56 void cm_InitIoctl(void)
58 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
61 long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
65 code = buf_CleanVnode(scp, userp, reqp);
67 lock_ObtainMutex(&scp->mx);
68 cm_DiscardSCache(scp);
69 lock_ReleaseMutex(&scp->mx);
71 osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
75 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
79 #ifdef AFS_FREELANCE_CLIENT
80 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
81 cm_noteLocalMountPointChange();
86 code = buf_FlushCleanPages(scp, userp, reqp);
88 lock_ObtainMutex(&scp->mx);
89 cm_DiscardSCache(scp);
91 lock_ReleaseMutex(&scp->mx);
93 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
97 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
102 pscp = cm_FindSCacheParent(scp);
104 /* now flush the file */
105 code = cm_FlushFile(pscp, userp, reqp);
106 cm_ReleaseSCache(pscp);
112 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
118 #ifdef AFS_FREELANCE_CLIENT
119 if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
120 cm_noteLocalMountPointChange();
125 lock_ObtainWrite(&cm_scacheLock);
126 for (i=0; i<cm_data.scacheHashTableSize; i++) {
127 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
128 if (scp->fid.volume == volume && scp->fid.cell == cell) {
129 cm_HoldSCacheNoLock(scp);
130 lock_ReleaseWrite(&cm_scacheLock);
132 /* now flush the file */
133 code = cm_FlushFile(scp, userp, reqp);
134 lock_ObtainWrite(&cm_scacheLock);
135 cm_ReleaseSCacheNoLock(scp);
139 lock_ReleaseWrite(&cm_scacheLock);
145 * cm_ResetACLCache -- invalidate ACL info for a user that has just
146 * obtained or lost tokens
148 void cm_ResetACLCache(cm_user_t *userp)
153 lock_ObtainWrite(&cm_scacheLock);
154 for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
155 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
156 cm_HoldSCacheNoLock(scp);
157 lock_ReleaseWrite(&cm_scacheLock);
158 lock_ObtainMutex(&scp->mx);
159 cm_InvalidateACLUser(scp, userp);
160 lock_ReleaseMutex(&scp->mx);
161 lock_ObtainWrite(&cm_scacheLock);
162 cm_ReleaseSCacheNoLock(scp);
165 lock_ReleaseWrite(&cm_scacheLock);
169 * TranslateExtendedChars - This is a fix for TR 54482.
171 * If an extended character (80 - FF) is entered into a file
172 * or directory name in Windows, the character is translated
173 * into the OEM character map before being passed to us. Why
174 * this occurs is unknown. Our pioctl functions must match
175 * this translation for paths given via our own commands (like
176 * fs). If we do not do this, then we will try to perform an
177 * operation on a non-translated path, which we will fail to
178 * find, since the path was created with the translated chars.
179 * This function performs the required translation.
181 void TranslateExtendedChars(char *str)
189 /* parse the passed-in file name and do a namei on it. If we fail,
190 * return an error code, otherwise return the vnode located in *scpp.
192 #define CM_PARSE_FLAG_LITERAL 1
194 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
195 cm_scache_t **scpp, afs_uint32 flags)
199 cm_scache_t *substRootp = NULL;
200 cm_scache_t *iscp = NULL;
203 char * lastComponent = NULL;
204 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
206 relativePath = ioctlp->inDatap;
207 /* setup the next data value for the caller to use */
208 ioctlp->inDatap += (long)strlen(ioctlp->inDatap) + 1;;
210 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
212 /* This is usually the file name, but for StatMountPoint it is the path. */
213 /* ioctlp->inDatap can be either of the form:
216 * \\netbios-name\submount\path\.
217 * \\netbios-name\submount\path\file
220 /* We do not perform path name translation on the ioctl path data
221 * because these paths were not translated by Windows through the
222 * file system API. Therefore, they are not OEM characters but
223 * whatever the display character set is.
225 // TranslateExtendedChars(relativePath);
227 /* This is usually nothing, but for StatMountPoint it is the file name. */
228 // TranslateExtendedChars(ioctlp->inDatap);
231 /* we have passed the whole path, including the afs prefix.
232 when the pioctl call is made, we perform an ioctl to afsrdr
233 and it returns the correct (full) path. therefore, there is
234 no drive letter, and the path is absolute. */
235 code = cm_NameI(cm_data.rootSCachep, relativePath,
237 userp, "", reqp, scpp);
240 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
245 if (relativePath[0] == relativePath[1] &&
246 relativePath[1] == '\\' &&
247 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
253 /* We may have found a UNC path.
254 * If the first component is the NetbiosName,
255 * then throw out the second component (the submount)
256 * since it had better expand into the value of ioctl->tidPathp
259 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
260 if ( !_strnicmp("all", p, 3) )
263 for (i = 0; *p && *p != '\\'; i++,p++ ) {
266 p++; /* skip past trailing slash */
267 shareName[i] = 0; /* terminate string */
269 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
271 /* we found a sharename, therefore use the resulting path */
272 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
273 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
274 userp, sharePath, reqp, &substRootp);
277 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
281 lastComponent = strrchr(p, '\\');
282 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
283 *lastComponent = '\0';
286 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
287 userp, NULL, reqp, &iscp);
289 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
290 userp, NULL, reqp, scpp);
292 cm_ReleaseSCache(iscp);
294 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
295 userp, NULL, reqp, scpp);
297 cm_ReleaseSCache(substRootp);
299 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
303 /* otherwise, treat the name as a cellname mounted off the afs root.
304 * This requires that we reconstruct the shareName string with
305 * leading and trailing slashes.
307 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
308 if ( !_strnicmp("all", p, 3) )
312 for (i = 1; *p && *p != '\\'; i++,p++ ) {
315 p++; /* skip past trailing slash */
316 shareName[i++] = '/'; /* add trailing slash */
317 shareName[i] = 0; /* terminate string */
320 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
321 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
322 userp, shareName, reqp, &substRootp);
324 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
328 lastComponent = strrchr(p, '\\');
329 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
330 *lastComponent = '\0';
333 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
334 userp, NULL, reqp, &iscp);
336 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
337 userp, NULL, reqp, scpp);
339 cm_ReleaseSCache(iscp);
341 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
342 userp, NULL, reqp, scpp);
346 cm_ReleaseSCache(substRootp);
347 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
352 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
353 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
354 userp, ioctlp->tidPathp, reqp, &substRootp);
356 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
360 lastComponent = strrchr(relativePath, '\\');
361 if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) {
362 *lastComponent = '\0';
365 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
366 userp, NULL, reqp, &iscp);
368 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
369 userp, NULL, reqp, scpp);
371 cm_ReleaseSCache(iscp);
373 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
374 userp, NULL, reqp, scpp);
377 cm_ReleaseSCache(substRootp);
378 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
385 cm_ReleaseSCache(substRootp);
387 /* and return success */
388 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
392 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
396 temp = strlen(ioctlp->inDatap) + 1;
397 ioctlp->inDatap += temp;
401 * Must be called before cm_ParseIoctlPath or cm_SkipIoctlPath
403 static cm_ioctlQueryOptions_t *
404 cm_IoctlGetQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp)
406 afs_uint32 pathlen = strlen(ioctlp->inDatap) + 1;
407 char *p = ioctlp->inDatap + pathlen;
408 cm_ioctlQueryOptions_t * optionsp = NULL;
410 if (ioctlp->inCopied > p - ioctlp->inAllocp) {
411 optionsp = (cm_ioctlQueryOptions_t *)p;
412 if (optionsp->size < 12 /* minimum size of struct */)
420 * Must be called after cm_ParseIoctlPath or cm_SkipIoctlPath
421 * or any other time that ioctlp->inDatap points at the
422 * cm_ioctlQueryOptions_t object.
425 cm_IoctlSkipQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp)
427 cm_ioctlQueryOptions_t * optionsp = (cm_ioctlQueryOptions_t *)ioctlp->inDatap;
428 ioctlp->inDatap += optionsp->size;
431 /* format the specified path to look like "/afs/<cellname>/usr", by
432 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
433 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
434 * intentionally returned as "/afs/"--this makes submount manipulation
435 * easier (because we can always jump past the initial "/afs" to find
436 * the AFS path that should be written into afsdsbmt.ini).
438 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
441 char bslash_mountRoot[256];
443 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
444 bslash_mountRoot[0] = '\\';
446 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
447 StringCbCopy(outpathp, outlen, inpathp);
448 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
449 StringCbCopy(outpathp, outlen, inpathp);
450 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
451 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
452 else // inpathp looks like "<cell>/usr"
453 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
455 for (cp = outpathp; *cp != 0; ++cp) {
460 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
461 outpathp[strlen(outpathp)-1] = 0;
464 if (!strcmpi (outpathp, cm_mountRoot)) {
465 StringCbCopy(outpathp, outlen, cm_mountRoot);
469 #define LEAF_SIZE 256
470 /* parse the passed-in file name and do a namei on its parent. If we fail,
471 * return an error code, otherwise return the vnode located in *scpp.
473 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
474 cm_scache_t **scpp, char *leafp)
479 cm_scache_t *substRootp = NULL;
481 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
482 tp = strrchr(tbuffer, '\\');
483 jp = strrchr(tbuffer, '/');
486 else if (jp && (tp - tbuffer) < (jp - tbuffer))
489 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
491 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
496 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
499 if (tbuffer[0] == tbuffer[1] &&
500 tbuffer[1] == '\\' &&
501 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
507 /* We may have found a UNC path.
508 * If the first component is the NetbiosName,
509 * then throw out the second component (the submount)
510 * since it had better expand into the value of ioctl->tidPathp
513 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
514 if ( !_strnicmp("all", p, 3) )
517 for (i = 0; *p && *p != '\\'; i++,p++ ) {
520 p++; /* skip past trailing slash */
521 shareName[i] = 0; /* terminate string */
523 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
525 /* we found a sharename, therefore use the resulting path */
526 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
527 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
528 userp, sharePath, reqp, &substRootp);
530 if (code) return code;
532 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
533 userp, NULL, reqp, scpp);
534 cm_ReleaseSCache(substRootp);
535 if (code) return code;
537 /* otherwise, treat the name as a cellname mounted off the afs root.
538 * This requires that we reconstruct the shareName string with
539 * leading and trailing slashes.
541 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
542 if ( !_strnicmp("all", p, 3) )
546 for (i = 1; *p && *p != '\\'; i++,p++ ) {
549 p++; /* skip past trailing slash */
550 shareName[i++] = '/'; /* add trailing slash */
551 shareName[i] = 0; /* terminate string */
553 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
554 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
555 userp, shareName, reqp, &substRootp);
556 if (code) return code;
558 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
559 userp, NULL, reqp, scpp);
560 cm_ReleaseSCache(substRootp);
561 if (code) return code;
564 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
565 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
566 userp, ioctlp->tidPathp, reqp, &substRootp);
567 if (code) return code;
569 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
570 userp, NULL, reqp, scpp);
571 cm_ReleaseSCache(substRootp);
572 if (code) return code;
575 /* # of bytes of path */
576 code = (long)strlen(ioctlp->inDatap) + 1;
577 ioctlp->inDatap += code;
579 /* and return success */
583 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
588 AFSFetchStatus fileStatus;
594 struct rx_connection * callp;
595 cm_ioctlQueryOptions_t *optionsp;
596 afs_uint32 flags = 0;
600 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
601 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
602 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
604 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
605 cm_SkipIoctlPath(ioctlp);
607 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
609 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
614 /* now make the get acl call */
615 #ifdef AFS_FREELANCE_CLIENT
616 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
618 ioctlp->outDatap[0] ='\0';
622 fid.Volume = scp->fid.volume;
623 fid.Vnode = scp->fid.vnode;
624 fid.Unique = scp->fid.unique;
626 acl.AFSOpaque_val = ioctlp->outDatap;
627 acl.AFSOpaque_len = 0;
628 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
631 callp = cm_GetRxConn(connp);
632 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
633 rx_PutConnection(callp);
635 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
636 code = cm_MapRPCError(code, &req);
637 cm_ReleaseSCache(scp);
639 if (code) return code;
641 /* skip over return data */
642 tlen = (int)strlen(ioctlp->outDatap) + 1;
643 ioctlp->outDatap += tlen;
645 /* and return success */
649 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
655 cm_ioctlQueryOptions_t *optionsp;
656 afs_uint32 flags = 0;
660 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
661 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
662 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
664 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
665 cm_SkipIoctlPath(ioctlp);
666 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
668 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
673 #ifdef AFS_FREELANCE_CLIENT
674 if ( cm_freelanceEnabled &&
675 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
676 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
677 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
678 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
679 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
682 #endif /* AFS_FREELANCE_CLIENT */
684 cellp = cm_FindCellByID(scp->fid.cell, CM_FLAG_NOPROBE);
686 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
687 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
691 code = CM_ERROR_NOSUCHCELL;
694 cm_ReleaseSCache(scp);
698 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
703 AFSFetchStatus fileStatus;
708 struct rx_connection * callp;
712 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
713 if (code) return code;
715 #ifdef AFS_FREELANCE_CLIENT
716 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
717 code = CM_ERROR_NOACCESS;
721 /* now make the get acl call */
722 fid.Volume = scp->fid.volume;
723 fid.Vnode = scp->fid.vnode;
724 fid.Unique = scp->fid.unique;
726 acl.AFSOpaque_val = ioctlp->inDatap;
727 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
728 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
731 callp = cm_GetRxConn(connp);
732 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
733 rx_PutConnection(callp);
735 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
736 code = cm_MapRPCError(code, &req);
738 /* invalidate cache info, since we just trashed the ACL cache */
739 lock_ObtainMutex(&scp->mx);
740 cm_DiscardSCache(scp);
741 lock_ReleaseMutex(&scp->mx);
743 cm_ReleaseSCache(scp);
750 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
759 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
761 lock_ObtainWrite(&cm_scacheLock);
762 for (i=0; i<cm_data.scacheHashTableSize; i++) {
763 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
764 cm_HoldSCacheNoLock(scp);
765 lock_ReleaseWrite(&cm_scacheLock);
767 /* now flush the file */
768 code = cm_FlushFile(scp, userp, &req);
769 lock_ObtainWrite(&cm_scacheLock);
770 cm_ReleaseSCacheNoLock(scp);
773 lock_ReleaseWrite(&cm_scacheLock);
778 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
782 unsigned long volume;
785 cm_ioctlQueryOptions_t *optionsp;
786 afs_uint32 flags = 0;
790 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
791 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
792 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
794 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
795 cm_SkipIoctlPath(ioctlp);
796 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
798 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
803 #ifdef AFS_FREELANCE_CLIENT
804 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
805 code = CM_ERROR_NOACCESS;
809 volume = scp->fid.volume;
810 cell = scp->fid.cell;
811 cm_ReleaseSCache(scp);
813 code = cm_FlushVolume(userp, &req, cell, volume);
818 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
823 cm_ioctlQueryOptions_t *optionsp;
824 afs_uint32 flags = 0;
828 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
829 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
830 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
832 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
833 cm_SkipIoctlPath(ioctlp);
834 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
836 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
841 #ifdef AFS_FREELANCE_CLIENT
842 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
843 code = CM_ERROR_NOACCESS;
847 cm_FlushFile(scp, userp, &req);
849 cm_ReleaseSCache(scp);
854 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
858 char offLineMsg[256];
862 AFSFetchVolumeStatus volStat;
863 AFSStoreVolumeStatus storeStat;
868 struct rx_connection * callp;
872 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
873 if (code) return code;
875 #ifdef AFS_FREELANCE_CLIENT
876 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
877 code = CM_ERROR_NOACCESS;
881 cellp = cm_FindCellByID(scp->fid.cell, 0);
882 osi_assertx(cellp, "null cm_cell_t");
884 if (scp->flags & CM_SCACHEFLAG_RO) {
885 cm_ReleaseSCache(scp);
886 return CM_ERROR_READONLY;
889 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
890 CM_GETVOL_FLAG_CREATE, &tvp);
892 cm_ReleaseSCache(scp);
897 /* Copy the junk out, using cp as a roving pointer. */
898 cp = ioctlp->inDatap;
899 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
900 cp += sizeof(AFSFetchVolumeStatus);
901 StringCbCopyA(volName, sizeof(volName), cp);
902 cp += strlen(volName)+1;
903 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
904 cp += strlen(offLineMsg)+1;
905 StringCbCopyA(motd, sizeof(motd), cp);
907 if (volStat.MinQuota != -1) {
908 storeStat.MinQuota = volStat.MinQuota;
909 storeStat.Mask |= AFS_SETMINQUOTA;
911 if (volStat.MaxQuota != -1) {
912 storeStat.MaxQuota = volStat.MaxQuota;
913 storeStat.Mask |= AFS_SETMAXQUOTA;
917 code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
920 callp = cm_GetRxConn(tcp);
921 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
922 &storeStat, volName, offLineMsg, motd);
923 rx_PutConnection(callp);
925 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
926 code = cm_MapRPCError(code, &req);
929 /* return on failure */
930 cm_ReleaseSCache(scp);
935 /* we are sending parms back to make compat. with prev system. should
936 * change interface later to not ask for current status, just set
939 cp = ioctlp->outDatap;
940 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
941 cp += sizeof(VolumeStatus);
942 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
943 cp += strlen(volName)+1;
944 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
945 cp += strlen(offLineMsg)+1;
946 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
947 cp += strlen(motd)+1;
949 /* now return updated return data pointer */
950 ioctlp->outDatap = cp;
955 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
959 char offLineMsg[256];
963 AFSFetchVolumeStatus volStat;
969 struct rx_connection * callp;
970 cm_ioctlQueryOptions_t *optionsp;
971 afs_uint32 flags = 0;
975 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
976 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
977 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
979 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
980 cm_SkipIoctlPath(ioctlp);
981 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
983 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
988 #ifdef AFS_FREELANCE_CLIENT
989 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
991 strncpy(volName, "Freelance.Local.Root", sizeof(volName));
992 offLineMsg[0] = '\0';
993 strncpy(motd, "Freelance mode in use.", sizeof(motd));
994 volStat.Vid = scp->fid.volume;
995 volStat.MaxQuota = 0;
996 volStat.BlocksInUse = 100;
997 volStat.PartBlocksAvail = 0;
998 volStat.PartMaxBlocks = 100;
1003 OfflineMsg = offLineMsg;
1006 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
1009 callp = cm_GetRxConn(connp);
1010 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
1011 &volStat, &Name, &OfflineMsg, &MOTD);
1012 rx_PutConnection(callp);
1014 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
1015 code = cm_MapRPCError(code, &req);
1018 cm_ReleaseSCache(scp);
1019 if (code) return code;
1021 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1022 cp = ioctlp->outDatap;
1023 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
1024 cp += sizeof(AFSFetchVolumeStatus);
1025 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
1026 cp += strlen(volName)+1;
1027 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
1028 cp += strlen(offLineMsg)+1;
1029 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
1030 cp += strlen(motd)+1;
1032 /* return new size */
1033 ioctlp->outDatap = cp;
1038 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
1045 cm_ioctlQueryOptions_t * optionsp;
1046 afs_uint32 flags = 0;
1050 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1051 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1052 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1054 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1055 if (code) return code;
1057 memset(&fid, 0, sizeof(cm_fid_t));
1058 fid.cell = scp->fid.cell;
1059 fid.volume = scp->fid.volume;
1060 fid.vnode = scp->fid.vnode;
1061 fid.unique = scp->fid.unique;
1063 cm_ReleaseSCache(scp);
1065 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1066 cp = ioctlp->outDatap;
1067 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
1068 cp += sizeof(cm_fid_t);
1070 /* return new size */
1071 ioctlp->outDatap = cp;
1076 long cm_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp)
1081 afs_uint32 fileType = 0;
1083 cm_ioctlQueryOptions_t * optionsp;
1084 afs_uint32 flags = 0;
1088 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1089 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1090 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1092 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1093 cm_SkipIoctlPath(ioctlp);
1094 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1096 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1101 fileType = scp->fileType;
1102 cm_ReleaseSCache(scp);
1104 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1105 cp = ioctlp->outDatap;
1106 memcpy(cp, (char *)&fileType, sizeof(fileType));
1107 cp += sizeof(fileType);
1109 /* return new size */
1110 ioctlp->outDatap = cp;
1115 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1121 cm_ioctlQueryOptions_t *optionsp;
1122 afs_uint32 flags = 0;
1126 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1127 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1128 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1130 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1131 cm_SkipIoctlPath(ioctlp);
1132 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1134 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1139 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1140 cp = ioctlp->outDatap;
1141 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
1142 cp += sizeof(afs_uint32);
1143 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
1144 cp += sizeof(afs_uint32);
1146 /* return new size */
1147 ioctlp->outDatap = cp;
1149 cm_ReleaseSCache(scp);
1154 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1160 cm_serverRef_t **tsrpp, *current;
1162 unsigned long volume;
1165 cm_ioctlQueryOptions_t *optionsp;
1166 afs_uint32 flags = 0;
1170 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1171 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1172 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1174 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1175 cm_SkipIoctlPath(ioctlp);
1176 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1178 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1183 volume = scp->fid.volume;
1185 cellp = cm_FindCellByID(scp->fid.cell, 0);
1187 cm_ReleaseSCache(scp);
1190 return CM_ERROR_NOSUCHCELL;
1192 #ifdef AFS_FREELANCE_CLIENT
1193 if ( cellp->cellID == AFS_FAKE_ROOT_CELL_ID) {
1194 struct in_addr addr;
1201 cp = ioctlp->outDatap;
1203 memcpy(cp, (char *)&addr, sizeof(addr));
1206 /* still room for terminating NULL, add it on */
1208 memcpy(cp, (char *)&addr, sizeof(addr));
1211 ioctlp->outDatap = cp;
1215 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
1219 cp = ioctlp->outDatap;
1221 lock_ObtainMutex(&tvp->mx);
1222 tsrpp = cm_GetVolServers(tvp, volume);
1223 lock_ObtainRead(&cm_serverLock);
1224 for (current = *tsrpp; current; current = current->next) {
1225 tsp = current->server;
1226 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1229 lock_ReleaseRead(&cm_serverLock);
1230 cm_FreeServerList(tsrpp, 0);
1231 lock_ReleaseMutex(&tvp->mx);
1233 /* still room for terminating NULL, add it on */
1234 volume = 0; /* reuse vbl */
1235 memcpy(cp, (char *)&volume, sizeof(long));
1238 ioctlp->outDatap = cp;
1244 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1254 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1255 if (code) return code;
1257 cp = ioctlp->inDatap;
1259 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1260 cm_ReleaseSCache(dscp);
1261 if (code) return code;
1263 lock_ObtainMutex(&scp->mx);
1265 /* now check that this is a real mount point */
1266 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1267 lock_ReleaseMutex(&scp->mx);
1268 cm_ReleaseSCache(scp);
1269 return CM_ERROR_INVAL;
1272 code = cm_ReadMountPoint(scp, userp, &req);
1274 cp = ioctlp->outDatap;
1275 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
1276 cp += strlen(cp) + 1;
1277 ioctlp->outDatap = cp;
1279 lock_ReleaseMutex(&scp->mx);
1280 cm_ReleaseSCache(scp);
1285 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1295 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1296 if (code) return code;
1298 cp = ioctlp->inDatap;
1300 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1302 /* if something went wrong, bail out now */
1307 lock_ObtainMutex(&scp->mx);
1308 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1309 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1311 lock_ReleaseMutex(&scp->mx);
1312 cm_ReleaseSCache(scp);
1316 /* now check that this is a real mount point */
1317 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1318 lock_ReleaseMutex(&scp->mx);
1319 cm_ReleaseSCache(scp);
1320 code = CM_ERROR_INVAL;
1324 /* time to make the RPC, so drop the lock */
1325 lock_ReleaseMutex(&scp->mx);
1326 cm_ReleaseSCache(scp);
1328 /* easier to do it this way */
1329 code = cm_Unlink(dscp, cp, userp, &req);
1330 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1331 smb_NotifyChange(FILE_ACTION_REMOVED,
1332 FILE_NOTIFY_CHANGE_DIR_NAME,
1333 dscp, cp, NULL, TRUE);
1336 lock_ObtainMutex(&scp->mx);
1337 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1338 lock_ReleaseMutex(&scp->mx);
1341 cm_ReleaseSCache(dscp);
1345 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1355 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1356 tp = ioctlp->inDatap;
1359 memcpy(&temp, tp, sizeof(temp));
1360 if (temp == 0x12345678) { /* For afs3.3 version */
1361 memcpy(&csi, tp, sizeof(csi));
1362 if (csi.tinterval >= 0) {
1363 cp = ioctlp->outDatap;
1364 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1365 ioctlp->outDatap += sizeof(long);
1366 if (csi.tinterval > 0) {
1367 if (!smb_SUser(userp))
1368 return CM_ERROR_NOACCESS;
1369 cm_daemonCheckDownInterval = csi.tinterval;
1377 } else { /* For pre afs3.3 versions */
1378 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1379 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1380 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1385 * 1: fast check, don't contact servers.
1386 * 2: local cell only.
1389 /* have cell name, too */
1390 cellp = cm_GetCell(cp, (temp & 1) ? CM_FLAG_NOPROBE : 0);
1392 return CM_ERROR_NOSUCHCELL;
1394 else cellp = (cm_cell_t *) 0;
1395 if (!cellp && (temp & 2)) {
1396 /* use local cell */
1397 cellp = cm_FindCellByID(1, 0);
1399 if (!(temp & 1)) { /* if not fast, call server checker routine */
1400 /* check down servers */
1401 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1405 /* now return the current down server list */
1406 cp = ioctlp->outDatap;
1407 lock_ObtainRead(&cm_serverLock);
1408 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1409 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1410 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1411 && tsp->type == CM_SERVER_FILE) {
1412 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1416 lock_ReleaseRead(&cm_serverLock);
1418 ioctlp->outDatap = cp;
1422 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1424 /* we don't print anything superfluous, so we don't support the gag call */
1425 return CM_ERROR_INVAL;
1428 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1430 cm_RefreshVolumes();
1434 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1439 cm_SkipIoctlPath(ioctlp);
1441 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1443 temp = cm_data.buf_nOrigBuffers;
1445 /* temp is in 1K units, convert to # of buffers */
1446 temp = temp / (cm_data.buf_blockSize / 1024);
1449 /* now adjust the cache size */
1450 code = buf_SetNBuffers(temp);
1455 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1459 cm_SkipIoctlPath(ioctlp);
1461 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1465 afsd_ForceTrace(FALSE);
1466 buf_ForceTrace(FALSE);
1470 /* set tracing value to low order bit */
1471 if ((inValue & 1) == 0) {
1472 /* disable tracing */
1473 osi_LogDisable(afsd_logp);
1474 rx_DebugOnOff(FALSE);
1477 /* enable tracing */
1478 osi_LogEnable(afsd_logp);
1479 rx_DebugOnOff(TRUE);
1483 /* see if we're supposed to do a reset, too */
1485 osi_LogReset(afsd_logp);
1488 /* and copy out tracing flag */
1489 inValue = afsd_logp->enabled; /* use as a temp vbl */
1490 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1491 ioctlp->outDatap += sizeof(long);
1495 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1497 cm_cacheParms_t parms;
1499 memset(&parms, 0, sizeof(parms));
1501 /* first we get, in 1K units, the cache size */
1502 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1504 /* and then the actual # of buffers in use (not in the free list, I guess,
1505 * will be what we do).
1507 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1509 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1510 ioctlp->outDatap += sizeof(parms);
1515 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1520 cm_serverRef_t *serverRefp;
1521 cm_server_t *serverp;
1527 cm_SkipIoctlPath(ioctlp);
1529 tp = ioctlp->inDatap;
1531 memcpy((char *)&whichCell, tp, sizeof(long));
1534 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1535 if (ioctlp->inCopied-1 > sizeof(long)) {
1536 memcpy((char *)&magic, tp, sizeof(long));
1539 lock_ObtainRead(&cm_cellLock);
1540 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->allNextp) {
1541 if (whichCell == 0) break;
1544 lock_ReleaseRead(&cm_cellLock);
1548 cp = ioctlp->outDatap;
1550 if (magic == 0x12345678) {
1551 memcpy(cp, (char *)&magic, sizeof(long));
1554 memset(cp, 0, max * sizeof(long));
1556 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1557 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1558 serverRefp = tcellp->vlServersp;
1559 for (i=0; i<max; i++) {
1560 if (!serverRefp) break;
1561 serverp = serverRefp->server;
1562 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1564 serverRefp = serverRefp->next;
1566 lock_ReleaseRead(&cm_serverLock);
1567 cp = basep + max * sizeof(afs_int32);
1568 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1569 cp += strlen(tcellp->name)+1;
1570 ioctlp->outDatap = cp;
1576 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1579 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1581 /* NT cache manager will read cell information from CellServDB each time
1582 * cell is accessed. So, this call is necessary only if list of server for a cell
1583 * changes (or IP addresses of cell servers changes).
1584 * All that needs to be done is to refresh server information for all cells that
1585 * are already loaded.
1587 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1591 cm_cell_rock_t rock;
1594 cm_SkipIoctlPath(ioctlp);
1595 lock_ObtainWrite(&cm_cellLock);
1597 for (cp = cm_data.allCellsp; cp; cp=cp->allNextp)
1600 lock_ObtainMutex(&cp->mx);
1601 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1602 cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
1603 cp->vlServersp = NULL;
1606 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
1607 #ifdef AFS_AFSDB_ENV
1609 if (cm_dnsEnabled) {
1611 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
1612 if ( code == 0 ) { /* got cell from DNS */
1613 cp->flags |= CM_CELLFLAG_DNS;
1614 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1615 cp->timeout = time(0) + ttl;
1620 cp->flags &= ~CM_CELLFLAG_DNS;
1622 #endif /* AFS_AFSDB_ENV */
1624 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1627 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1628 cm_RandomizeServer(&cp->vlServersp);
1630 lock_ReleaseMutex(&cp->mx);
1633 lock_ReleaseWrite(&cm_cellLock);
1637 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1641 if (cm_freelanceEnabled) {
1642 if (cm_GetRootCellName(ioctlp->outDatap))
1643 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1644 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1645 } else if (cm_data.rootCellp) {
1646 /* return the default cellname to the caller */
1647 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1648 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1650 /* if we don't know our default cell, return failure */
1651 code = CM_ERROR_NOSUCHCELL;
1657 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1659 long setSysName, foundname = 0;
1660 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1661 int t, count, num = 0;
1662 char **sysnamelist[MAXSYSNAME];
1664 cm_SkipIoctlPath(ioctlp);
1666 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1667 ioctlp->inDatap += sizeof(long);
1671 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1673 cp2 = ioctlp->inDatap;
1674 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1675 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1676 t = (int)strlen(cp);
1677 if (t >= MAXSYSNAME || t <= 0)
1679 /* check for names that can shoot us in the foot */
1680 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1686 /* inname gets first entry in case we're being a translator */
1687 /* (we are never a translator) */
1688 t = (int)strlen(ioctlp->inDatap);
1689 memcpy(inname, ioctlp->inDatap, t + 1);
1690 ioctlp->inDatap += t + 1;
1694 /* Not xlating, so local case */
1696 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1698 if (!setSysName) { /* user just wants the info */
1699 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1700 foundname = cm_sysNameCount;
1701 *sysnamelist = cm_sysNameList;
1703 /* Local guy; only root can change sysname */
1704 /* clear @sys entries from the dnlc, once afs_lookup can
1705 * do lookups of @sys entries and thinks it can trust them */
1706 /* privs ok, store the entry, ... */
1707 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1708 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1709 if (setSysName > 1) { /* ... or list */
1710 cp = ioctlp->inDatap;
1711 for (count = 1; count < setSysName; ++count) {
1712 if (!cm_sysNameList[count])
1713 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1714 __FILE__, __LINE__);
1715 t = (int)strlen(cp);
1716 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1720 cm_sysNameCount = setSysName;
1724 /* return the sysname to the caller */
1725 cp = ioctlp->outDatap;
1726 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1727 cp += sizeof(afs_int32); /* skip found flag */
1729 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1730 cp += strlen(outname) + 1; /* skip name and terminating null char */
1731 for ( count=1; count < foundname ; ++count) { /* ... or list */
1732 if ( !(*sysnamelist)[count] )
1733 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1734 __FILE__, __LINE__);
1735 t = (int)strlen((*sysnamelist)[count]);
1736 if (t >= MAXSYSNAME)
1737 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1738 __FILE__, __LINE__);
1739 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1743 ioctlp->outDatap = cp;
1750 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1755 cm_SkipIoctlPath(ioctlp);
1757 cellp = cm_GetCell(ioctlp->inDatap, 0);
1759 return CM_ERROR_NOSUCHCELL;
1762 lock_ObtainMutex(&cellp->mx);
1763 if (cellp->flags & CM_CELLFLAG_SUID)
1764 temp |= CM_SETCELLFLAG_SUID;
1765 lock_ReleaseMutex(&cellp->mx);
1767 /* now copy out parm */
1768 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1769 ioctlp->outDatap += sizeof(long);
1774 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1779 cm_SkipIoctlPath(ioctlp);
1781 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1783 return CM_ERROR_NOSUCHCELL;
1785 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1787 lock_ObtainMutex(&cellp->mx);
1788 if (temp & CM_SETCELLFLAG_SUID)
1789 cellp->flags |= CM_CELLFLAG_SUID;
1791 cellp->flags &= ~CM_CELLFLAG_SUID;
1792 lock_ReleaseMutex(&cellp->mx);
1797 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1799 cm_SSetPref_t *spin; /* input */
1800 cm_SPref_t *srvin; /* one input component */
1802 int i, vlonly, noServers, type;
1803 struct sockaddr_in tmp;
1804 unsigned short rank;
1806 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1808 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1809 noServers = spin->num_servers;
1810 vlonly = spin->flags;
1812 type = CM_SERVER_VLDB;
1814 type = CM_SERVER_FILE;
1816 for ( i=0; i < noServers; i++)
1818 srvin = &(spin->servers[i]);
1819 rank = srvin->rank + (rand() & 0x000f);
1820 tmp.sin_addr = srvin->host;
1821 tmp.sin_family = AF_INET;
1823 tsp = cm_FindServer(&tmp, type);
1824 if ( tsp ) /* an existing server - ref count increased */
1826 tsp->ipRank = rank; /* no need to protect by mutex*/
1828 if (type == CM_SERVER_FILE)
1830 /* find volumes which might have RO copy
1831 /* on server and change the ordering of
1834 cm_ChangeRankVolume(tsp);
1838 /* set preferences for an existing vlserver */
1839 cm_ChangeRankCellVLServer(tsp);
1842 else /* add a new server without a cell */
1844 tsp = cm_NewServer(&tmp, type, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
1847 lock_ObtainMutex(&tsp->mx);
1848 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1849 lock_ReleaseMutex(&tsp->mx);
1850 cm_PutServer(tsp); /* decrease refcount */
1855 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1857 cm_SPrefRequest_t *spin; /* input */
1858 cm_SPrefInfo_t *spout; /* output */
1859 cm_SPref_t *srvout; /* one output component */
1861 int i, vlonly, noServers;
1863 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1865 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1866 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1867 srvout = spout->servers;
1868 noServers = spin->num_servers;
1869 vlonly = spin->flags & CM_SPREF_VLONLY;
1870 spout->num_servers = 0;
1872 lock_ObtainRead(&cm_serverLock); /* get server lock */
1874 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1875 if (spin->offset > i) {
1876 continue; /* catch up to where we left off */
1879 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1880 continue; /* ignore fileserver for -vlserver option*/
1881 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1882 continue; /* ignore vlservers */
1884 srvout->host = tsp->addr.sin_addr;
1885 srvout->rank = tsp->ipRank;
1887 spout->num_servers++;
1890 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1892 if ( tsp ) /* we ran out of space in the output buffer */
1893 spout->next_offset = i;
1895 spout->next_offset = 0;
1896 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1897 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1901 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1903 /* we ignore default asynchrony since we only have one way
1904 * of doing this today.
1909 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1911 char leaf[LEAF_SIZE];
1925 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1929 /* Translate chars for the mount point name */
1930 TranslateExtendedChars(leaf);
1933 * The fs command allows the user to specify partial cell names on NT. These must
1934 * be expanded to the full cell name for mount points so that the mount points will
1935 * work on UNIX clients.
1938 /* Extract the possibly partial cell name */
1939 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1941 if (cp = strchr(cell, ':')) {
1942 /* Extract the volume name */
1944 StringCbCopyA(volume, sizeof(volume), cp + 1);
1946 /* Get the full name for this cell */
1947 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1948 #ifdef AFS_AFSDB_ENV
1949 if (code && cm_dnsEnabled)
1950 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1953 cm_ReleaseSCache(dscp);
1954 return CM_ERROR_NOSUCHCELL;
1957 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1959 /* No cell name specified */
1960 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1963 #ifdef AFS_FREELANCE_CLIENT
1964 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1965 /* we are adding the mount point to the root dir., so call
1966 * the freelance code to do the add. */
1967 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1968 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1969 *ioctlp->inDatap == '%', NULL);
1970 cm_ReleaseSCache(dscp);
1974 /* create the symlink with mode 644. The lack of X bits tells
1975 * us that it is a mount point.
1977 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1978 tattr.unixModeBits = 0644;
1979 tattr.clientModTime = time(NULL);
1981 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1982 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1983 smb_NotifyChange(FILE_ACTION_ADDED,
1984 FILE_NOTIFY_CHANGE_DIR_NAME,
1985 dscp, leaf, NULL, TRUE);
1987 cm_ReleaseSCache(dscp);
1991 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1993 char leaf[LEAF_SIZE];
2002 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
2003 if (code) return code;
2005 /* Translate chars for the link name */
2006 TranslateExtendedChars(leaf);
2008 /* Translate chars for the linked to name */
2009 TranslateExtendedChars(ioctlp->inDatap);
2011 cp = ioctlp->inDatap; /* contents of link */
2013 #ifdef AFS_FREELANCE_CLIENT
2014 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
2015 /* we are adding the symlink to the root dir., so call
2016 * the freelance code to do the add. */
2017 if (cp[0] == cp[1] && cp[1] == '\\' &&
2018 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
2020 /* skip \\AFS\ or \\AFS\all\ */
2022 p = cp + 2 + strlen(cm_NetbiosName) + 1;
2023 if ( !_strnicmp("all", p, 3) )
2027 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
2028 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
2029 cm_ReleaseSCache(dscp);
2034 /* Create symlink with mode 0755. */
2035 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
2036 tattr.unixModeBits = 0755;
2038 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
2039 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
2040 smb_NotifyChange(FILE_ACTION_ADDED,
2041 FILE_NOTIFY_CHANGE_FILE_NAME
2042 | FILE_NOTIFY_CHANGE_DIR_NAME,
2043 dscp, leaf, NULL, TRUE);
2045 cm_ReleaseSCache(dscp);
2051 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2058 cm_scache_t *newRootScp;
2063 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2064 if (code) return code;
2066 cp = ioctlp->inDatap;
2068 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2069 cm_ReleaseSCache(dscp);
2070 if (code) return code;
2072 /* Check that it's a real symlink */
2073 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2074 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2075 scp->fileType != CM_SCACHETYPE_INVALID) {
2076 cm_ReleaseSCache(scp);
2077 return CM_ERROR_INVAL;
2080 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
2081 cm_ReleaseSCache(scp);
2083 cp = ioctlp->outDatap;
2084 if (newRootScp != NULL) {
2085 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
2086 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
2089 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
2090 cp += strlen(cp) + 1;
2091 ioctlp->outDatap = cp;
2092 cm_FreeSpace(spacep);
2093 if (newRootScp != NULL)
2094 cm_ReleaseSCache(newRootScp);
2096 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
2097 scp->fileType == CM_SCACHETYPE_DFSLINK ||
2098 code == CM_ERROR_NOSUCHPATH &&
2099 scp->fileType == CM_SCACHETYPE_INVALID) {
2101 cp = ioctlp->outDatap;
2102 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
2103 cp += strlen(cp) + 1;
2104 ioctlp->outDatap = cp;
2111 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2112 {/*CHECK FOR VALID SYMLINK*/
2121 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2122 if (code) return code;
2124 cp = ioctlp->inDatap;
2125 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
2127 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2128 cm_ReleaseSCache(dscp);
2129 if (code) return code;
2131 /* Check that it's a real symlink */
2132 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2133 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2134 scp->fileType != CM_SCACHETYPE_INVALID)
2135 code = CM_ERROR_INVAL;
2136 cm_ReleaseSCache(scp);
2140 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2150 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2151 if (code) return code;
2153 cp = ioctlp->inDatap;
2155 #ifdef AFS_FREELANCE_CLIENT
2156 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
2157 /* we are adding the mount point to the root dir., so call
2158 * the freelance code to do the add. */
2159 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
2160 code = cm_FreelanceRemoveSymlink(cp);
2161 cm_ReleaseSCache(dscp);
2166 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2168 /* if something went wrong, bail out now */
2172 lock_ObtainMutex(&scp->mx);
2173 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2174 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2178 /* now check that this is a real symlink */
2179 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2180 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2181 scp->fileType != CM_SCACHETYPE_INVALID) {
2182 code = CM_ERROR_INVAL;
2186 /* time to make the RPC, so drop the lock */
2187 lock_ReleaseMutex(&scp->mx);
2189 /* easier to do it this way */
2190 code = cm_Unlink(dscp, cp, userp, &req);
2191 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
2192 smb_NotifyChange(FILE_ACTION_REMOVED,
2193 FILE_NOTIFY_CHANGE_FILE_NAME
2194 | FILE_NOTIFY_CHANGE_DIR_NAME,
2195 dscp, cp, NULL, TRUE);
2197 lock_ObtainMutex(&scp->mx);
2199 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2202 lock_ReleaseMutex(&scp->mx);
2203 cm_ReleaseSCache(scp);
2206 cm_ReleaseSCache(dscp);
2211 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
2216 static struct afsconf_cell info;
2217 struct rx_connection *serverconns[MAXSERVERS];
2218 struct rx_securityClass *sc[3];
2219 afs_int32 scIndex = 2; /* authenticated - we have a token */
2220 struct ubik_client *pruclient = NULL;
2221 struct afsconf_dir *tdir;
2225 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
2226 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
2227 afsconf_Close(tdir);
2233 /* we have the token that was given to us in the settoken
2234 * call. we just have to use it.
2236 scIndex = 2; /* kerberos ticket */
2237 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
2238 ucellp->kvno, ucellp->ticketLen,
2241 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
2242 for (i = 0; i < info.numServers; i++)
2244 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
2245 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
2248 code = ubik_ClientInit(serverconns, &pruclient);
2253 code = rxs_Release(sc[scIndex]);
2255 lids.idlist_len = 0;
2256 lids.idlist_val = 0;
2257 lnames.namelist_len = 1;
2258 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
2259 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
2260 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
2261 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
2267 if (r && !stricmp(r+1,ucellp->cellp->name))
2270 code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
2271 if (lids.idlist_val) {
2272 *uid = *lids.idlist_val;
2273 free(lids.idlist_val);
2275 if (lnames.namelist_val)
2276 free(lnames.namelist_val);
2279 ubik_ClientDestroy(pruclient);
2285 #endif /* QUERY_AFSID */
2287 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2294 struct ClearToken ct;
2304 int release_userp = 0;
2307 saveDataPtr = ioctlp->inDatap;
2309 cm_SkipIoctlPath(ioctlp);
2311 tp = ioctlp->inDatap;
2314 memcpy(&ticketLen, tp, sizeof(ticketLen));
2315 tp += sizeof(ticketLen);
2316 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2317 return CM_ERROR_INVAL;
2319 /* remember ticket and skip over it for now */
2323 /* clear token size */
2324 memcpy(&ctSize, tp, sizeof(ctSize));
2325 tp += sizeof(ctSize);
2326 if (ctSize != sizeof(struct ClearToken))
2327 return CM_ERROR_INVAL;
2330 memcpy(&ct, tp, ctSize);
2332 if (ct.AuthHandle == -1)
2333 ct.AuthHandle = 999; /* more rxvab compat stuff */
2335 /* more stuff, if any */
2336 if (ioctlp->inCopied > tp - saveDataPtr) {
2337 /* flags: logon flag */
2338 memcpy(&flags, tp, sizeof(int));
2342 cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
2344 return CM_ERROR_NOSUCHCELL;
2345 tp += strlen(tp) + 1;
2349 tp += strlen(tp) + 1;
2351 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2352 if (flags & PIOCTL_LOGON) {
2353 /* SMB user name with which to associate tokens */
2355 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2356 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2357 fprintf(stderr, "SMB name = %s\n", smbname);
2358 tp += strlen(tp) + 1;
2360 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2361 osi_LogSaveString(smb_logp, uname));
2366 memcpy(&uuid, tp, sizeof(uuid));
2367 if (!cm_FindTokenEvent(uuid, sessionKey))
2368 return CM_ERROR_INVAL;
2370 cellp = cm_data.rootCellp;
2371 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2375 if (flags & PIOCTL_LOGON) {
2376 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2377 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2382 /* store the token */
2383 lock_ObtainMutex(&userp->mx);
2384 ucellp = cm_GetUCell(userp, cellp);
2385 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2386 ucellp->ticketLen = ticketLen;
2387 if (ucellp->ticketp)
2388 free(ucellp->ticketp); /* Discard old token if any */
2389 ucellp->ticketp = malloc(ticketLen);
2390 memcpy(ucellp->ticketp, ticket, ticketLen);
2392 * Get the session key from the RPC, rather than from the pioctl.
2395 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2397 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2398 ucellp->kvno = ct.AuthHandle;
2399 ucellp->expirationTime = ct.EndTimestamp;
2402 ucellp->uid = ANONYMOUSID;
2405 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2407 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2410 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2411 lock_ReleaseMutex(&userp->mx);
2413 if (flags & PIOCTL_LOGON) {
2414 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2417 cm_ResetACLCache(userp);
2420 cm_ReleaseUser(userp);
2425 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2431 struct ClearToken ct;
2433 cm_SkipIoctlPath(ioctlp);
2435 tp = ioctlp->inDatap;
2436 cp = ioctlp->outDatap;
2439 memcpy(&iterator, tp, sizeof(iterator));
2440 tp += sizeof(iterator);
2442 lock_ObtainMutex(&userp->mx);
2444 /* look for token */
2445 for (;;iterator++) {
2446 ucellp = cm_FindUCell(userp, iterator);
2448 lock_ReleaseMutex(&userp->mx);
2449 return CM_ERROR_NOMORETOKENS;
2451 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2456 temp = ucellp->iterator + 1;
2457 memcpy(cp, &temp, sizeof(temp));
2461 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2462 cp += sizeof(ucellp->ticketLen);
2465 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2466 cp += ucellp->ticketLen;
2468 /* clear token size */
2470 memcpy(cp, &temp, sizeof(temp));
2474 ct.AuthHandle = ucellp->kvno;
2476 * Don't give out a real session key here
2479 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2481 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2482 ct.ViceId = 37; /* XXX */
2483 ct.BeginTimestamp = 0; /* XXX */
2484 ct.EndTimestamp = ucellp->expirationTime;
2485 memcpy(cp, &ct, sizeof(ct));
2488 /* Primary flag (unused) */
2490 memcpy(cp, &temp, sizeof(temp));
2494 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2495 cp += strlen(cp) + 1;
2498 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2499 cp += strlen(cp) + 1;
2501 ioctlp->outDatap = cp;
2503 lock_ReleaseMutex(&userp->mx);
2508 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2514 struct ClearToken ct;
2517 cm_SkipIoctlPath(ioctlp);
2519 tp = ioctlp->inDatap;
2521 cp = ioctlp->outDatap;
2523 /* cell name is right here */
2524 cellp = cm_GetCell(tp, 0);
2526 return CM_ERROR_NOSUCHCELL;
2527 tp += strlen(tp) + 1;
2530 memcpy(&uuid, tp, sizeof(uuid));
2532 lock_ObtainMutex(&userp->mx);
2534 ucellp = cm_GetUCell(userp, cellp);
2535 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2536 lock_ReleaseMutex(&userp->mx);
2537 return CM_ERROR_NOMORETOKENS;
2541 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2542 cp += sizeof(ucellp->ticketLen);
2545 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2546 cp += ucellp->ticketLen;
2548 /* clear token size */
2550 memcpy(cp, &temp, sizeof(temp));
2554 ct.AuthHandle = ucellp->kvno;
2556 * Don't give out a real session key here
2559 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2561 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2562 ct.ViceId = 37; /* XXX */
2563 ct.BeginTimestamp = 0; /* XXX */
2564 ct.EndTimestamp = ucellp->expirationTime;
2565 memcpy(cp, &ct, sizeof(ct));
2568 /* Primary flag (unused) */
2570 memcpy(cp, &temp, sizeof(temp));
2574 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2575 cp += strlen(cp) + 1;
2578 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2579 cp += strlen(cp) + 1;
2581 ioctlp->outDatap = cp;
2583 lock_ReleaseMutex(&userp->mx);
2585 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2590 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2596 cm_SkipIoctlPath(ioctlp);
2598 cp = ioctlp->outDatap;
2600 /* cell name is right here */
2601 cellp = cm_GetCell(ioctlp->inDatap, 0);
2603 return CM_ERROR_NOSUCHCELL;
2605 lock_ObtainMutex(&userp->mx);
2607 ucellp = cm_GetUCell(userp, cellp);
2609 lock_ReleaseMutex(&userp->mx);
2610 return CM_ERROR_NOMORETOKENS;
2613 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2615 if (ucellp->ticketp) {
2616 free(ucellp->ticketp);
2617 ucellp->ticketp = NULL;
2619 ucellp->ticketLen = 0;
2620 memset(ucellp->sessionKey.data, 0, 8);
2622 ucellp->expirationTime = 0;
2623 ucellp->userName[0] = '\0';
2624 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2627 lock_ReleaseMutex(&userp->mx);
2629 cm_ResetACLCache(userp);
2634 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2638 lock_ObtainMutex(&userp->mx);
2640 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2641 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2643 if (ucellp->ticketp) {
2644 free(ucellp->ticketp);
2645 ucellp->ticketp = NULL;
2647 ucellp->ticketLen = 0;
2648 memset(ucellp->sessionKey.data, 0, 8);
2650 ucellp->expirationTime = 0;
2651 ucellp->userName[0] = '\0';
2652 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2656 lock_ReleaseMutex(&userp->mx);
2658 cm_ResetACLCache(userp);
2663 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2665 char afspath[MAX_PATH];
2667 int nextAutoSubmount;
2669 DWORD dwType, dwSize;
2674 cm_SkipIoctlPath(ioctlp);
2676 /* Serialize this one, to prevent simultaneous mods
2679 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2681 /* Parse the input parameters--first the required afs path,
2682 * then the requested submount name (which may be "").
2684 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2685 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2687 /* If the caller supplied a suggested submount name, see if
2688 * that submount name is in use... if so, the submount's path
2689 * has to match our path.
2692 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2693 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2696 REG_OPTION_NON_VOLATILE,
2697 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2702 if (submountreqp && *submountreqp) {
2703 char submountPathNormalized[MAX_PATH];
2704 char submountPath[MAX_PATH];
2706 dwSize = sizeof(submountPath);
2707 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2708 &dwType, submountPath, &dwSize);
2710 if (status != ERROR_SUCCESS) {
2712 /* The suggested submount name isn't in use now--
2713 * so we can safely map the requested submount name
2714 * to the supplied path. Remember not to write the
2715 * leading "/afs" when writing out the submount.
2717 RegSetValueEx( hkSubmounts, submountreqp, 0,
2719 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2720 &afspath[strlen(cm_mountRoot)]:"/",
2721 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2722 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2724 RegCloseKey( hkSubmounts );
2725 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2726 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2727 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2731 /* The suggested submount name is already in use--if the
2732 * supplied path matches the submount's path, we can still
2733 * use the suggested submount name.
2735 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2736 if (!strcmp (submountPathNormalized, afspath)) {
2737 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2738 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2739 RegCloseKey( hkSubmounts );
2740 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2745 RegQueryInfoKey( hkSubmounts,
2747 NULL, /* lpcClass */
2748 NULL, /* lpReserved */
2749 NULL, /* lpcSubKeys */
2750 NULL, /* lpcMaxSubKeyLen */
2751 NULL, /* lpcMaxClassLen */
2752 &dwSubmounts, /* lpcValues */
2753 NULL, /* lpcMaxValueNameLen */
2754 NULL, /* lpcMaxValueLen */
2755 NULL, /* lpcbSecurityDescriptor */
2756 NULL /* lpftLastWriteTime */
2760 /* Having obtained a list of all available submounts, start
2761 * searching that list for a path which matches the requested
2762 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2763 * submount, in case we need to add a new one later.
2766 nextAutoSubmount = 1;
2768 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2769 char submountPathNormalized[MAX_PATH];
2770 char submountPath[MAX_PATH] = "";
2771 DWORD submountPathLen = sizeof(submountPath);
2772 char submountName[MAX_PATH];
2773 DWORD submountNameLen = sizeof(submountName);
2776 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2777 &dwType, submountPath, &submountPathLen);
2778 if (dwType == REG_EXPAND_SZ) {
2780 StringCbCopyA(buf, MAX_PATH, submountPath);
2781 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2782 if (submountPathLen > MAX_PATH)
2786 /* If this is an Auto### submount, remember its ### value */
2787 if ((!strnicmp (submountName, "auto", 4)) &&
2788 (isdigit (submountName[strlen("auto")]))) {
2789 int thisAutoSubmount;
2790 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2791 nextAutoSubmount = max (nextAutoSubmount,
2792 thisAutoSubmount+1);
2795 if ((submountPathLen == 0) ||
2796 (submountPathLen == sizeof(submountPath) - 1)) {
2800 /* See if the path for this submount matches the path
2801 * that our caller specified. If so, we can return
2804 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2805 if (!strcmp (submountPathNormalized, afspath)) {
2806 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2807 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2808 RegCloseKey(hkSubmounts);
2809 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2815 /* We've been through the entire list of existing submounts, and
2816 * didn't find any which matched the specified path. So, we'll
2817 * just have to add one. Remember not to write the leading "/afs"
2818 * when writing out the submount.
2821 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2823 RegSetValueEx( hkSubmounts,
2827 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2828 &afspath[strlen(cm_mountRoot)]:"/",
2829 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2830 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2832 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2833 RegCloseKey(hkSubmounts);
2834 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2838 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2840 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2841 ioctlp->outDatap += sizeof(cryptall);
2846 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2848 afs_int32 c = cryptall;
2850 cm_SkipIoctlPath(ioctlp);
2852 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2854 if (c != cryptall) {
2856 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2858 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2863 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2868 cm_SkipIoctlPath(ioctlp);
2870 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2871 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2874 if (flags & AFSCALL_RXSTATS_ENABLE) {
2875 rx_enableProcessRPCStats();
2877 if (flags & AFSCALL_RXSTATS_DISABLE) {
2878 rx_disableProcessRPCStats();
2880 if (flags & AFSCALL_RXSTATS_CLEAR) {
2881 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2886 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2891 cm_SkipIoctlPath(ioctlp);
2893 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2894 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2897 if (flags & AFSCALL_RXSTATS_ENABLE) {
2898 rx_enablePeerRPCStats();
2900 if (flags & AFSCALL_RXSTATS_DISABLE) {
2901 rx_disablePeerRPCStats();
2903 if (flags & AFSCALL_RXSTATS_CLEAR) {
2904 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2909 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2911 smb_user_t *uidp = ioctlp->uidp;
2913 if (uidp && uidp->unp) {
2914 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2915 ioctlp->outDatap += strlen(uidp->unp->name);
2921 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2926 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2928 if (cmd) { /* generate a new UUID */
2929 UuidCreate((UUID *) &uuid);
2930 cm_data.Uuid = uuid;
2931 cm_ForceNewConnectionsAllServers();
2934 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2935 ioctlp->outDatap += sizeof(cm_data.Uuid);
2941 * functions to dump contents of various structures.
2942 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2944 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2945 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2946 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2948 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2952 char logfileName[MAX_PATH+1];
2957 static _CrtMemState memstate;
2960 cm_SkipIoctlPath(ioctlp);
2961 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2963 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2964 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2966 GetWindowsDirectory(logfileName, sizeof(logfileName));
2968 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2970 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2976 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2977 ioctlp->outDatap += sizeof(long);
2982 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2984 cookie = inValue ? "b" : "e";
2990 _CrtMemCheckpoint(&memstate);
2994 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2995 _CrtSetReportFile(_CRT_WARN, hLogFile);
2996 _CrtMemDumpAllObjectsSince(&memstate);
3000 /* dump all interesting data */
3001 cm_MemDumpDirStats(hLogFile, cookie, 1);
3002 cm_MemDumpBPlusStats(hLogFile, cookie, 1);
3003 cm_DumpCells(hLogFile, cookie, 1);
3004 cm_DumpVolumes(hLogFile, cookie, 1);
3005 cm_DumpSCache(hLogFile, cookie, 1);
3006 cm_DumpBufHashTable(hLogFile, cookie, 1);
3007 smb_DumpVCP(hLogFile, cookie, 1);
3009 CloseHandle(hLogFile);
3011 inValue = 0; /* success */
3012 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
3013 ioctlp->outDatap += sizeof(long);
3020 cm_CheckServersStatus(cm_serverRef_t *serversp)
3023 cm_serverRef_t *tsrp;
3025 int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
3027 if (serversp == NULL) {
3028 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
3029 return CM_ERROR_ALLDOWN;
3032 lock_ObtainRead(&cm_serverLock);
3033 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
3034 if (tsp = tsrp->server) {
3035 cm_GetServerNoLock(tsp);
3036 lock_ReleaseRead(&cm_serverLock);
3037 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
3039 if (tsrp->status == srv_busy) {
3042 } else if (tsrp->status == srv_offline) {
3052 lock_ObtainRead(&cm_serverLock);
3053 cm_PutServerNoLock(tsp);
3056 lock_ReleaseRead(&cm_serverLock);
3059 code = CM_ERROR_ALLDOWN;
3061 code = CM_ERROR_ALLBUSY;
3062 else if (allOffline || (someBusy && someOffline))
3063 code = CM_ERROR_ALLOFFLINE;
3066 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
3071 long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
3077 cm_vol_state_t *statep;
3080 cm_ioctlQueryOptions_t *optionsp;
3081 afs_uint32 flags = 0;
3085 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
3086 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
3087 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
3089 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
3090 cm_SkipIoctlPath(ioctlp);
3091 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
3093 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
3098 #ifdef AFS_FREELANCE_CLIENT
3099 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
3101 cm_ReleaseSCache(scp);
3105 volume = scp->fid.volume;
3107 cellp = cm_FindCellByID(scp->fid.cell, 0);
3109 cm_ReleaseSCache(scp);
3112 return CM_ERROR_NOSUCHCELL;
3114 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
3118 if (volume == tvp->rw.ID)
3120 else if (volume == tvp->ro.ID)
3125 switch (statep->state) {
3131 code = CM_ERROR_ALLBUSY;
3134 code = CM_ERROR_ALLOFFLINE;
3137 code = CM_ERROR_ALLDOWN;
3146 long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
3149 cm_cell_t *cellp = NULL;
3151 cm_vol_state_t *statep;
3152 struct VolStatTest * testp;
3159 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
3160 testp = (struct VolStatTest *)ioctlp->inDatap;
3162 #ifdef AFS_FREELANCE_CLIENT
3163 if (testp->fid.cell == -1)
3164 return CM_ERROR_NOACCESS;
3167 if (testp->flags & VOLSTAT_TEST_CHECK_VOLUME) {
3168 cm_CheckOfflineVolumes();
3172 if (testp->flags & VOLSTAT_TEST_NETWORK_UP) {
3173 cm_VolStatus_Network_Started(cm_NetbiosName
3181 if (testp->flags & VOLSTAT_TEST_NETWORK_DOWN) {
3182 cm_VolStatus_Network_Stopped(cm_NetbiosName
3190 if (testp->cellname[0]) {
3191 n = atoi(testp->cellname);
3193 testp->fid.cell = n;
3195 cellp = cm_GetCell(testp->cellname, 0);
3198 if (testp->fid.cell > 0) {
3199 cellp = cm_FindCellByID(testp->fid.cell, 0);
3203 return CM_ERROR_NOSUCHCELL;
3205 if (testp->volname[0]) {
3206 n = atoi(testp->volname);
3208 testp->fid.volume = n;
3210 code = cm_GetVolumeByName(cellp, testp->volname, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3213 if (testp->fid.volume > 0)
3214 code = cm_GetVolumeByID(cellp, testp->fid.volume, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3219 if (testp->fid.volume) {
3220 if (testp->fid.volume == volp->rw.ID)
3222 else if (testp->fid.volume == volp->ro.ID)
3227 len = strlen(testp->volname);
3229 if (stricmp(".readonly", &testp->volname[len-9]) == 0)
3231 else if (stricmp(".backup", &testp->volname[len-7]) == 0)
3238 statep->state = testp->state;
3239 code = cm_VolStatus_Change_Notification(cellp->cellID, statep->ID, testp->state);