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 lock_ObtainWrite(&scp->bufCreateLock);
66 code = buf_CleanVnode(scp, userp, reqp);
68 lock_ObtainMutex(&scp->mx);
69 cm_DiscardSCache(scp);
70 lock_ReleaseMutex(&scp->mx);
72 lock_ReleaseWrite(&scp->bufCreateLock);
73 osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
77 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
81 #ifdef AFS_FREELANCE_CLIENT
82 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
83 cm_noteLocalMountPointChange();
88 lock_ObtainWrite(&scp->bufCreateLock);
89 code = buf_FlushCleanPages(scp, userp, reqp);
91 lock_ObtainMutex(&scp->mx);
92 cm_DiscardSCache(scp);
94 lock_ReleaseMutex(&scp->mx);
96 lock_ReleaseWrite(&scp->bufCreateLock);
97 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
101 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
106 pscp = cm_FindSCacheParent(scp);
108 /* now flush the file */
109 code = cm_FlushFile(pscp, userp, reqp);
110 cm_ReleaseSCache(pscp);
116 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
122 #ifdef AFS_FREELANCE_CLIENT
123 if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
124 cm_noteLocalMountPointChange();
129 lock_ObtainWrite(&cm_scacheLock);
130 for (i=0; i<cm_data.scacheHashTableSize; i++) {
131 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
132 if (scp->fid.volume == volume && scp->fid.cell == cell) {
133 cm_HoldSCacheNoLock(scp);
134 lock_ReleaseWrite(&cm_scacheLock);
136 /* now flush the file */
137 code = cm_FlushFile(scp, userp, reqp);
138 lock_ObtainWrite(&cm_scacheLock);
139 cm_ReleaseSCacheNoLock(scp);
143 lock_ReleaseWrite(&cm_scacheLock);
149 * cm_ResetACLCache -- invalidate ACL info for a user that has just
150 * obtained or lost tokens
152 void cm_ResetACLCache(cm_user_t *userp)
157 lock_ObtainWrite(&cm_scacheLock);
158 for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
159 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
160 cm_HoldSCacheNoLock(scp);
161 lock_ReleaseWrite(&cm_scacheLock);
162 lock_ObtainMutex(&scp->mx);
163 cm_InvalidateACLUser(scp, userp);
164 lock_ReleaseMutex(&scp->mx);
165 lock_ObtainWrite(&cm_scacheLock);
166 cm_ReleaseSCacheNoLock(scp);
169 lock_ReleaseWrite(&cm_scacheLock);
173 * TranslateExtendedChars - This is a fix for TR 54482.
175 * If an extended character (80 - FF) is entered into a file
176 * or directory name in Windows, the character is translated
177 * into the OEM character map before being passed to us. Why
178 * this occurs is unknown. Our pioctl functions must match
179 * this translation for paths given via our own commands (like
180 * fs). If we do not do this, then we will try to perform an
181 * operation on a non-translated path, which we will fail to
182 * find, since the path was created with the translated chars.
183 * This function performs the required translation.
185 void TranslateExtendedChars(char *str)
193 /* parse the passed-in file name and do a namei on it. If we fail,
194 * return an error code, otherwise return the vnode located in *scpp.
196 #define CM_PARSE_FLAG_LITERAL 1
198 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
199 cm_scache_t **scpp, afs_uint32 flags)
203 cm_scache_t *substRootp = NULL;
204 cm_scache_t *iscp = NULL;
207 char * lastComponent = NULL;
208 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
210 relativePath = ioctlp->inDatap;
211 /* setup the next data value for the caller to use */
212 ioctlp->inDatap += (long)strlen(ioctlp->inDatap) + 1;;
214 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
216 /* This is usually the file name, but for StatMountPoint it is the path. */
217 /* ioctlp->inDatap can be either of the form:
220 * \\netbios-name\submount\path\.
221 * \\netbios-name\submount\path\file
224 /* We do not perform path name translation on the ioctl path data
225 * because these paths were not translated by Windows through the
226 * file system API. Therefore, they are not OEM characters but
227 * whatever the display character set is.
229 // TranslateExtendedChars(relativePath);
231 /* This is usually nothing, but for StatMountPoint it is the file name. */
232 // TranslateExtendedChars(ioctlp->inDatap);
235 /* we have passed the whole path, including the afs prefix.
236 when the pioctl call is made, we perform an ioctl to afsrdr
237 and it returns the correct (full) path. therefore, there is
238 no drive letter, and the path is absolute. */
239 code = cm_NameI(cm_data.rootSCachep, relativePath,
241 userp, "", reqp, scpp);
244 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
249 if (relativePath[0] == relativePath[1] &&
250 relativePath[1] == '\\' &&
251 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
257 /* We may have found a UNC path.
258 * If the first component is the NetbiosName,
259 * then throw out the second component (the submount)
260 * since it had better expand into the value of ioctl->tidPathp
263 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
264 if ( !_strnicmp("all", p, 3) )
267 for (i = 0; *p && *p != '\\'; i++,p++ ) {
270 p++; /* skip past trailing slash */
271 shareName[i] = 0; /* terminate string */
273 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
275 /* we found a sharename, therefore use the resulting path */
276 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
277 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
278 userp, sharePath, reqp, &substRootp);
281 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
285 lastComponent = strrchr(p, '\\');
286 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
287 *lastComponent = '\0';
290 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
291 userp, NULL, reqp, &iscp);
293 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
294 userp, NULL, reqp, scpp);
296 cm_ReleaseSCache(iscp);
298 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
299 userp, NULL, reqp, scpp);
301 cm_ReleaseSCache(substRootp);
303 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
307 /* otherwise, treat the name as a cellname mounted off the afs root.
308 * This requires that we reconstruct the shareName string with
309 * leading and trailing slashes.
311 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
312 if ( !_strnicmp("all", p, 3) )
316 for (i = 1; *p && *p != '\\'; i++,p++ ) {
319 p++; /* skip past trailing slash */
320 shareName[i++] = '/'; /* add trailing slash */
321 shareName[i] = 0; /* terminate string */
324 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
325 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
326 userp, shareName, reqp, &substRootp);
328 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
332 lastComponent = strrchr(p, '\\');
333 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
334 *lastComponent = '\0';
337 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
338 userp, NULL, reqp, &iscp);
340 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
341 userp, NULL, reqp, scpp);
343 cm_ReleaseSCache(iscp);
345 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
346 userp, NULL, reqp, scpp);
350 cm_ReleaseSCache(substRootp);
351 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
356 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
357 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
358 userp, ioctlp->tidPathp, reqp, &substRootp);
360 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
364 lastComponent = strrchr(relativePath, '\\');
365 if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) {
366 *lastComponent = '\0';
369 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
370 userp, NULL, reqp, &iscp);
372 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
373 userp, NULL, reqp, scpp);
375 cm_ReleaseSCache(iscp);
377 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
378 userp, NULL, reqp, scpp);
381 cm_ReleaseSCache(substRootp);
382 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
389 cm_ReleaseSCache(substRootp);
391 /* and return success */
392 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
396 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
400 temp = strlen(ioctlp->inDatap) + 1;
401 ioctlp->inDatap += temp;
405 * Must be called before cm_ParseIoctlPath or cm_SkipIoctlPath
407 static cm_ioctlQueryOptions_t *
408 cm_IoctlGetQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp)
410 afs_uint32 pathlen = strlen(ioctlp->inDatap) + 1;
411 char *p = ioctlp->inDatap + pathlen;
412 cm_ioctlQueryOptions_t * optionsp = NULL;
414 if (ioctlp->inCopied > p - ioctlp->inAllocp) {
415 optionsp = (cm_ioctlQueryOptions_t *)p;
416 if (optionsp->size < 12 /* minimum size of struct */)
424 * Must be called after cm_ParseIoctlPath or cm_SkipIoctlPath
425 * or any other time that ioctlp->inDatap points at the
426 * cm_ioctlQueryOptions_t object.
429 cm_IoctlSkipQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp)
431 cm_ioctlQueryOptions_t * optionsp = (cm_ioctlQueryOptions_t *)ioctlp->inDatap;
432 ioctlp->inDatap += optionsp->size;
435 /* format the specified path to look like "/afs/<cellname>/usr", by
436 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
437 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
438 * intentionally returned as "/afs/"--this makes submount manipulation
439 * easier (because we can always jump past the initial "/afs" to find
440 * the AFS path that should be written into afsdsbmt.ini).
442 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
445 char bslash_mountRoot[256];
447 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
448 bslash_mountRoot[0] = '\\';
450 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
451 StringCbCopy(outpathp, outlen, inpathp);
452 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
453 StringCbCopy(outpathp, outlen, inpathp);
454 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
455 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
456 else // inpathp looks like "<cell>/usr"
457 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
459 for (cp = outpathp; *cp != 0; ++cp) {
464 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
465 outpathp[strlen(outpathp)-1] = 0;
468 if (!strcmpi (outpathp, cm_mountRoot)) {
469 StringCbCopy(outpathp, outlen, cm_mountRoot);
473 #define LEAF_SIZE 256
474 /* parse the passed-in file name and do a namei on its parent. If we fail,
475 * return an error code, otherwise return the vnode located in *scpp.
477 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
478 cm_scache_t **scpp, char *leafp)
483 cm_scache_t *substRootp = NULL;
485 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
486 tp = strrchr(tbuffer, '\\');
487 jp = strrchr(tbuffer, '/');
490 else if (jp && (tp - tbuffer) < (jp - tbuffer))
493 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
495 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
500 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
503 if (tbuffer[0] == tbuffer[1] &&
504 tbuffer[1] == '\\' &&
505 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
511 /* We may have found a UNC path.
512 * If the first component is the NetbiosName,
513 * then throw out the second component (the submount)
514 * since it had better expand into the value of ioctl->tidPathp
517 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
518 if ( !_strnicmp("all", p, 3) )
521 for (i = 0; *p && *p != '\\'; i++,p++ ) {
524 p++; /* skip past trailing slash */
525 shareName[i] = 0; /* terminate string */
527 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
529 /* we found a sharename, therefore use the resulting path */
530 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
531 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
532 userp, sharePath, reqp, &substRootp);
534 if (code) return code;
536 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
537 userp, NULL, reqp, scpp);
538 cm_ReleaseSCache(substRootp);
539 if (code) return code;
541 /* otherwise, treat the name as a cellname mounted off the afs root.
542 * This requires that we reconstruct the shareName string with
543 * leading and trailing slashes.
545 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
546 if ( !_strnicmp("all", p, 3) )
550 for (i = 1; *p && *p != '\\'; i++,p++ ) {
553 p++; /* skip past trailing slash */
554 shareName[i++] = '/'; /* add trailing slash */
555 shareName[i] = 0; /* terminate string */
557 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
558 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
559 userp, shareName, reqp, &substRootp);
560 if (code) return code;
562 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
563 userp, NULL, reqp, scpp);
564 cm_ReleaseSCache(substRootp);
565 if (code) return code;
568 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
569 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
570 userp, ioctlp->tidPathp, reqp, &substRootp);
571 if (code) return code;
573 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
574 userp, NULL, reqp, scpp);
575 cm_ReleaseSCache(substRootp);
576 if (code) return code;
579 /* # of bytes of path */
580 code = (long)strlen(ioctlp->inDatap) + 1;
581 ioctlp->inDatap += code;
583 /* and return success */
587 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
592 AFSFetchStatus fileStatus;
598 struct rx_connection * callp;
599 cm_ioctlQueryOptions_t *optionsp;
600 afs_uint32 flags = 0;
604 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
605 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
606 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
608 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
609 cm_SkipIoctlPath(ioctlp);
611 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
613 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
618 /* now make the get acl call */
619 #ifdef AFS_FREELANCE_CLIENT
620 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
622 ioctlp->outDatap[0] ='\0';
626 fid.Volume = scp->fid.volume;
627 fid.Vnode = scp->fid.vnode;
628 fid.Unique = scp->fid.unique;
630 acl.AFSOpaque_val = ioctlp->outDatap;
631 acl.AFSOpaque_len = 0;
632 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
635 callp = cm_GetRxConn(connp);
636 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
637 rx_PutConnection(callp);
639 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
640 code = cm_MapRPCError(code, &req);
641 cm_ReleaseSCache(scp);
643 if (code) return code;
645 /* skip over return data */
646 tlen = (int)strlen(ioctlp->outDatap) + 1;
647 ioctlp->outDatap += tlen;
649 /* and return success */
653 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
659 cm_ioctlQueryOptions_t *optionsp;
660 afs_uint32 flags = 0;
664 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
665 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
666 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
668 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
669 cm_SkipIoctlPath(ioctlp);
670 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
672 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
677 #ifdef AFS_FREELANCE_CLIENT
678 if ( cm_freelanceEnabled &&
679 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
680 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
681 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
682 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
683 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
686 #endif /* AFS_FREELANCE_CLIENT */
688 cellp = cm_FindCellByID(scp->fid.cell, CM_FLAG_NOPROBE);
690 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
691 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
695 code = CM_ERROR_NOSUCHCELL;
698 cm_ReleaseSCache(scp);
702 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
707 AFSFetchStatus fileStatus;
712 struct rx_connection * callp;
716 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
717 if (code) return code;
719 #ifdef AFS_FREELANCE_CLIENT
720 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
721 code = CM_ERROR_NOACCESS;
725 /* now make the get acl call */
726 fid.Volume = scp->fid.volume;
727 fid.Vnode = scp->fid.vnode;
728 fid.Unique = scp->fid.unique;
730 acl.AFSOpaque_val = ioctlp->inDatap;
731 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
732 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
735 callp = cm_GetRxConn(connp);
736 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
737 rx_PutConnection(callp);
739 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
740 code = cm_MapRPCError(code, &req);
742 /* invalidate cache info, since we just trashed the ACL cache */
743 lock_ObtainMutex(&scp->mx);
744 cm_DiscardSCache(scp);
745 lock_ReleaseMutex(&scp->mx);
747 cm_ReleaseSCache(scp);
754 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
763 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
765 lock_ObtainWrite(&cm_scacheLock);
766 for (i=0; i<cm_data.scacheHashTableSize; i++) {
767 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
768 cm_HoldSCacheNoLock(scp);
769 lock_ReleaseWrite(&cm_scacheLock);
771 /* now flush the file */
772 code = cm_FlushFile(scp, userp, &req);
773 lock_ObtainWrite(&cm_scacheLock);
774 cm_ReleaseSCacheNoLock(scp);
777 lock_ReleaseWrite(&cm_scacheLock);
782 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
786 unsigned long volume;
789 cm_ioctlQueryOptions_t *optionsp;
790 afs_uint32 flags = 0;
794 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
795 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
796 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
798 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
799 cm_SkipIoctlPath(ioctlp);
800 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
802 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
807 #ifdef AFS_FREELANCE_CLIENT
808 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
809 code = CM_ERROR_NOACCESS;
813 volume = scp->fid.volume;
814 cell = scp->fid.cell;
815 cm_ReleaseSCache(scp);
817 code = cm_FlushVolume(userp, &req, cell, volume);
822 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
827 cm_ioctlQueryOptions_t *optionsp;
828 afs_uint32 flags = 0;
832 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
833 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
834 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
836 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
837 cm_SkipIoctlPath(ioctlp);
838 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
840 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
845 #ifdef AFS_FREELANCE_CLIENT
846 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
847 code = CM_ERROR_NOACCESS;
851 cm_FlushFile(scp, userp, &req);
853 cm_ReleaseSCache(scp);
858 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
862 char offLineMsg[256];
866 AFSFetchVolumeStatus volStat;
867 AFSStoreVolumeStatus storeStat;
872 struct rx_connection * callp;
876 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
877 if (code) return code;
879 #ifdef AFS_FREELANCE_CLIENT
880 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
881 code = CM_ERROR_NOACCESS;
885 cellp = cm_FindCellByID(scp->fid.cell, 0);
886 osi_assertx(cellp, "null cm_cell_t");
888 if (scp->flags & CM_SCACHEFLAG_RO) {
889 cm_ReleaseSCache(scp);
890 return CM_ERROR_READONLY;
893 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
894 CM_GETVOL_FLAG_CREATE, &tvp);
896 cm_ReleaseSCache(scp);
901 /* Copy the junk out, using cp as a roving pointer. */
902 cp = ioctlp->inDatap;
903 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
904 cp += sizeof(AFSFetchVolumeStatus);
905 StringCbCopyA(volName, sizeof(volName), cp);
906 cp += strlen(volName)+1;
907 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
908 cp += strlen(offLineMsg)+1;
909 StringCbCopyA(motd, sizeof(motd), cp);
911 if (volStat.MinQuota != -1) {
912 storeStat.MinQuota = volStat.MinQuota;
913 storeStat.Mask |= AFS_SETMINQUOTA;
915 if (volStat.MaxQuota != -1) {
916 storeStat.MaxQuota = volStat.MaxQuota;
917 storeStat.Mask |= AFS_SETMAXQUOTA;
921 code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
924 callp = cm_GetRxConn(tcp);
925 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
926 &storeStat, volName, offLineMsg, motd);
927 rx_PutConnection(callp);
929 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
930 code = cm_MapRPCError(code, &req);
933 /* return on failure */
934 cm_ReleaseSCache(scp);
939 /* we are sending parms back to make compat. with prev system. should
940 * change interface later to not ask for current status, just set
943 cp = ioctlp->outDatap;
944 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
945 cp += sizeof(VolumeStatus);
946 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
947 cp += strlen(volName)+1;
948 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
949 cp += strlen(offLineMsg)+1;
950 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
951 cp += strlen(motd)+1;
953 /* now return updated return data pointer */
954 ioctlp->outDatap = cp;
959 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
963 char offLineMsg[256];
967 AFSFetchVolumeStatus volStat;
973 struct rx_connection * callp;
974 cm_ioctlQueryOptions_t *optionsp;
975 afs_uint32 flags = 0;
979 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
980 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
981 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
983 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
984 cm_SkipIoctlPath(ioctlp);
985 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
987 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
992 #ifdef AFS_FREELANCE_CLIENT
993 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
995 strncpy(volName, "Freelance.Local.Root", sizeof(volName));
996 offLineMsg[0] = '\0';
997 strncpy(motd, "Freelance mode in use.", sizeof(motd));
998 volStat.Vid = scp->fid.volume;
999 volStat.MaxQuota = 0;
1000 volStat.BlocksInUse = 100;
1001 volStat.PartBlocksAvail = 0;
1002 volStat.PartMaxBlocks = 100;
1007 OfflineMsg = offLineMsg;
1010 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
1013 callp = cm_GetRxConn(connp);
1014 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
1015 &volStat, &Name, &OfflineMsg, &MOTD);
1016 rx_PutConnection(callp);
1018 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
1019 code = cm_MapRPCError(code, &req);
1022 cm_ReleaseSCache(scp);
1023 if (code) return code;
1025 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1026 cp = ioctlp->outDatap;
1027 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
1028 cp += sizeof(AFSFetchVolumeStatus);
1029 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
1030 cp += strlen(volName)+1;
1031 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
1032 cp += strlen(offLineMsg)+1;
1033 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
1034 cp += strlen(motd)+1;
1036 /* return new size */
1037 ioctlp->outDatap = cp;
1042 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
1049 cm_ioctlQueryOptions_t * optionsp;
1050 afs_uint32 flags = 0;
1054 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1055 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1056 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1058 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1059 if (code) return code;
1061 memset(&fid, 0, sizeof(cm_fid_t));
1062 fid.cell = scp->fid.cell;
1063 fid.volume = scp->fid.volume;
1064 fid.vnode = scp->fid.vnode;
1065 fid.unique = scp->fid.unique;
1067 cm_ReleaseSCache(scp);
1069 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1070 cp = ioctlp->outDatap;
1071 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
1072 cp += sizeof(cm_fid_t);
1074 /* return new size */
1075 ioctlp->outDatap = cp;
1080 long cm_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp)
1085 afs_uint32 fileType = 0;
1087 cm_ioctlQueryOptions_t * optionsp;
1088 afs_uint32 flags = 0;
1092 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1093 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1094 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1096 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1097 cm_SkipIoctlPath(ioctlp);
1098 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1100 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1105 fileType = scp->fileType;
1106 cm_ReleaseSCache(scp);
1108 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1109 cp = ioctlp->outDatap;
1110 memcpy(cp, (char *)&fileType, sizeof(fileType));
1111 cp += sizeof(fileType);
1113 /* return new size */
1114 ioctlp->outDatap = cp;
1119 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1125 cm_ioctlQueryOptions_t *optionsp;
1126 afs_uint32 flags = 0;
1130 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1131 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1132 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1134 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1135 cm_SkipIoctlPath(ioctlp);
1136 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1138 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1143 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1144 cp = ioctlp->outDatap;
1145 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
1146 cp += sizeof(afs_uint32);
1147 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
1148 cp += sizeof(afs_uint32);
1150 /* return new size */
1151 ioctlp->outDatap = cp;
1153 cm_ReleaseSCache(scp);
1158 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1164 cm_serverRef_t **tsrpp, *current;
1166 unsigned long volume;
1169 cm_ioctlQueryOptions_t *optionsp;
1170 afs_uint32 flags = 0;
1174 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
1175 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1176 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1178 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1179 cm_SkipIoctlPath(ioctlp);
1180 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
1182 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1187 volume = scp->fid.volume;
1189 cellp = cm_FindCellByID(scp->fid.cell, 0);
1191 cm_ReleaseSCache(scp);
1194 return CM_ERROR_NOSUCHCELL;
1196 #ifdef AFS_FREELANCE_CLIENT
1197 if ( cellp->cellID == AFS_FAKE_ROOT_CELL_ID) {
1198 struct in_addr addr;
1205 cp = ioctlp->outDatap;
1207 memcpy(cp, (char *)&addr, sizeof(addr));
1210 /* still room for terminating NULL, add it on */
1212 memcpy(cp, (char *)&addr, sizeof(addr));
1215 ioctlp->outDatap = cp;
1219 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
1223 cp = ioctlp->outDatap;
1225 lock_ObtainMutex(&tvp->mx);
1226 tsrpp = cm_GetVolServers(tvp, volume);
1227 lock_ObtainRead(&cm_serverLock);
1228 for (current = *tsrpp; current; current = current->next) {
1229 tsp = current->server;
1230 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1233 lock_ReleaseRead(&cm_serverLock);
1234 cm_FreeServerList(tsrpp, 0);
1235 lock_ReleaseMutex(&tvp->mx);
1237 /* still room for terminating NULL, add it on */
1238 volume = 0; /* reuse vbl */
1239 memcpy(cp, (char *)&volume, sizeof(long));
1242 ioctlp->outDatap = cp;
1248 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1258 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1259 if (code) return code;
1261 cp = ioctlp->inDatap;
1263 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1264 cm_ReleaseSCache(dscp);
1265 if (code) return code;
1267 lock_ObtainMutex(&scp->mx);
1269 /* now check that this is a real mount point */
1270 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1271 lock_ReleaseMutex(&scp->mx);
1272 cm_ReleaseSCache(scp);
1273 return CM_ERROR_INVAL;
1276 code = cm_ReadMountPoint(scp, userp, &req);
1278 cp = ioctlp->outDatap;
1279 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
1280 cp += strlen(cp) + 1;
1281 ioctlp->outDatap = cp;
1283 lock_ReleaseMutex(&scp->mx);
1284 cm_ReleaseSCache(scp);
1289 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1299 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1300 if (code) return code;
1302 cp = ioctlp->inDatap;
1304 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1306 /* if something went wrong, bail out now */
1311 lock_ObtainMutex(&scp->mx);
1312 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1313 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1315 lock_ReleaseMutex(&scp->mx);
1316 cm_ReleaseSCache(scp);
1320 /* now check that this is a real mount point */
1321 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1322 lock_ReleaseMutex(&scp->mx);
1323 cm_ReleaseSCache(scp);
1324 code = CM_ERROR_INVAL;
1328 /* time to make the RPC, so drop the lock */
1329 lock_ReleaseMutex(&scp->mx);
1330 cm_ReleaseSCache(scp);
1332 /* easier to do it this way */
1333 code = cm_Unlink(dscp, cp, userp, &req);
1334 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1335 smb_NotifyChange(FILE_ACTION_REMOVED,
1336 FILE_NOTIFY_CHANGE_DIR_NAME,
1337 dscp, cp, NULL, TRUE);
1340 lock_ObtainMutex(&scp->mx);
1341 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1342 lock_ReleaseMutex(&scp->mx);
1345 cm_ReleaseSCache(dscp);
1349 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1359 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1360 tp = ioctlp->inDatap;
1363 memcpy(&temp, tp, sizeof(temp));
1364 if (temp == 0x12345678) { /* For afs3.3 version */
1365 memcpy(&csi, tp, sizeof(csi));
1366 if (csi.tinterval >= 0) {
1367 cp = ioctlp->outDatap;
1368 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1369 ioctlp->outDatap += sizeof(long);
1370 if (csi.tinterval > 0) {
1371 if (!smb_SUser(userp))
1372 return CM_ERROR_NOACCESS;
1373 cm_daemonCheckDownInterval = csi.tinterval;
1381 } else { /* For pre afs3.3 versions */
1382 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1383 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1384 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1389 * 1: fast check, don't contact servers.
1390 * 2: local cell only.
1393 /* have cell name, too */
1394 cellp = cm_GetCell(cp, (temp & 1) ? CM_FLAG_NOPROBE : 0);
1396 return CM_ERROR_NOSUCHCELL;
1398 else cellp = (cm_cell_t *) 0;
1399 if (!cellp && (temp & 2)) {
1400 /* use local cell */
1401 cellp = cm_FindCellByID(1, 0);
1403 if (!(temp & 1)) { /* if not fast, call server checker routine */
1404 /* check down servers */
1405 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1409 /* now return the current down server list */
1410 cp = ioctlp->outDatap;
1411 lock_ObtainRead(&cm_serverLock);
1412 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1413 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1414 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1415 && tsp->type == CM_SERVER_FILE) {
1416 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1420 lock_ReleaseRead(&cm_serverLock);
1422 ioctlp->outDatap = cp;
1426 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1428 /* we don't print anything superfluous, so we don't support the gag call */
1429 return CM_ERROR_INVAL;
1432 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1434 cm_RefreshVolumes();
1438 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1443 cm_SkipIoctlPath(ioctlp);
1445 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1447 temp = cm_data.buf_nOrigBuffers;
1449 /* temp is in 1K units, convert to # of buffers */
1450 temp = temp / (cm_data.buf_blockSize / 1024);
1453 /* now adjust the cache size */
1454 code = buf_SetNBuffers(temp);
1459 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1463 cm_SkipIoctlPath(ioctlp);
1465 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1469 afsd_ForceTrace(FALSE);
1470 buf_ForceTrace(FALSE);
1474 /* set tracing value to low order bit */
1475 if ((inValue & 1) == 0) {
1476 /* disable tracing */
1477 osi_LogDisable(afsd_logp);
1478 rx_DebugOnOff(FALSE);
1481 /* enable tracing */
1482 osi_LogEnable(afsd_logp);
1483 rx_DebugOnOff(TRUE);
1487 /* see if we're supposed to do a reset, too */
1489 osi_LogReset(afsd_logp);
1492 /* and copy out tracing flag */
1493 inValue = afsd_logp->enabled; /* use as a temp vbl */
1494 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1495 ioctlp->outDatap += sizeof(long);
1499 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1501 cm_cacheParms_t parms;
1503 memset(&parms, 0, sizeof(parms));
1505 /* first we get, in 1K units, the cache size */
1506 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1508 /* and then the actual # of buffers in use (not in the free list, I guess,
1509 * will be what we do).
1511 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1513 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1514 ioctlp->outDatap += sizeof(parms);
1519 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1524 cm_serverRef_t *serverRefp;
1525 cm_server_t *serverp;
1531 cm_SkipIoctlPath(ioctlp);
1533 tp = ioctlp->inDatap;
1535 memcpy((char *)&whichCell, tp, sizeof(long));
1538 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1539 if (ioctlp->inCopied-1 > sizeof(long)) {
1540 memcpy((char *)&magic, tp, sizeof(long));
1543 lock_ObtainRead(&cm_cellLock);
1544 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->allNextp) {
1545 if (whichCell == 0) break;
1548 lock_ReleaseRead(&cm_cellLock);
1552 cp = ioctlp->outDatap;
1554 if (magic == 0x12345678) {
1555 memcpy(cp, (char *)&magic, sizeof(long));
1558 memset(cp, 0, max * sizeof(long));
1560 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1561 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1562 serverRefp = tcellp->vlServersp;
1563 for (i=0; i<max; i++) {
1564 if (!serverRefp) break;
1565 serverp = serverRefp->server;
1566 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1568 serverRefp = serverRefp->next;
1570 lock_ReleaseRead(&cm_serverLock);
1571 cp = basep + max * sizeof(afs_int32);
1572 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1573 cp += strlen(tcellp->name)+1;
1574 ioctlp->outDatap = cp;
1580 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1583 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1585 /* NT cache manager will read cell information from CellServDB each time
1586 * cell is accessed. So, this call is necessary only if list of server for a cell
1587 * changes (or IP addresses of cell servers changes).
1588 * All that needs to be done is to refresh server information for all cells that
1589 * are already loaded.
1591 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1595 cm_cell_rock_t rock;
1598 cm_SkipIoctlPath(ioctlp);
1599 lock_ObtainWrite(&cm_cellLock);
1601 for (cp = cm_data.allCellsp; cp; cp=cp->allNextp)
1604 lock_ObtainMutex(&cp->mx);
1605 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1606 cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
1607 cp->vlServersp = NULL;
1610 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
1611 #ifdef AFS_AFSDB_ENV
1613 if (cm_dnsEnabled) {
1615 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
1616 if ( code == 0 ) { /* got cell from DNS */
1617 cp->flags |= CM_CELLFLAG_DNS;
1618 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1619 cp->timeout = time(0) + ttl;
1624 cp->flags &= ~CM_CELLFLAG_DNS;
1626 #endif /* AFS_AFSDB_ENV */
1628 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1631 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1632 cm_RandomizeServer(&cp->vlServersp);
1634 lock_ReleaseMutex(&cp->mx);
1637 lock_ReleaseWrite(&cm_cellLock);
1641 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1645 if (cm_freelanceEnabled) {
1646 if (cm_GetRootCellName(ioctlp->outDatap))
1647 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1648 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1649 } else if (cm_data.rootCellp) {
1650 /* return the default cellname to the caller */
1651 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1652 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1654 /* if we don't know our default cell, return failure */
1655 code = CM_ERROR_NOSUCHCELL;
1661 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1663 long setSysName, foundname = 0;
1664 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1665 int t, count, num = 0;
1666 char **sysnamelist[MAXSYSNAME];
1668 cm_SkipIoctlPath(ioctlp);
1670 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1671 ioctlp->inDatap += sizeof(long);
1675 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1677 cp2 = ioctlp->inDatap;
1678 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1679 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1680 t = (int)strlen(cp);
1681 if (t >= MAXSYSNAME || t <= 0)
1683 /* check for names that can shoot us in the foot */
1684 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1690 /* inname gets first entry in case we're being a translator */
1691 /* (we are never a translator) */
1692 t = (int)strlen(ioctlp->inDatap);
1693 memcpy(inname, ioctlp->inDatap, t + 1);
1694 ioctlp->inDatap += t + 1;
1698 /* Not xlating, so local case */
1700 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1702 if (!setSysName) { /* user just wants the info */
1703 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1704 foundname = cm_sysNameCount;
1705 *sysnamelist = cm_sysNameList;
1707 /* Local guy; only root can change sysname */
1708 /* clear @sys entries from the dnlc, once afs_lookup can
1709 * do lookups of @sys entries and thinks it can trust them */
1710 /* privs ok, store the entry, ... */
1711 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1712 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1713 if (setSysName > 1) { /* ... or list */
1714 cp = ioctlp->inDatap;
1715 for (count = 1; count < setSysName; ++count) {
1716 if (!cm_sysNameList[count])
1717 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1718 __FILE__, __LINE__);
1719 t = (int)strlen(cp);
1720 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1724 cm_sysNameCount = setSysName;
1728 /* return the sysname to the caller */
1729 cp = ioctlp->outDatap;
1730 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1731 cp += sizeof(afs_int32); /* skip found flag */
1733 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1734 cp += strlen(outname) + 1; /* skip name and terminating null char */
1735 for ( count=1; count < foundname ; ++count) { /* ... or list */
1736 if ( !(*sysnamelist)[count] )
1737 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1738 __FILE__, __LINE__);
1739 t = (int)strlen((*sysnamelist)[count]);
1740 if (t >= MAXSYSNAME)
1741 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1742 __FILE__, __LINE__);
1743 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1747 ioctlp->outDatap = cp;
1754 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1759 cm_SkipIoctlPath(ioctlp);
1761 cellp = cm_GetCell(ioctlp->inDatap, 0);
1763 return CM_ERROR_NOSUCHCELL;
1766 lock_ObtainMutex(&cellp->mx);
1767 if (cellp->flags & CM_CELLFLAG_SUID)
1768 temp |= CM_SETCELLFLAG_SUID;
1769 lock_ReleaseMutex(&cellp->mx);
1771 /* now copy out parm */
1772 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1773 ioctlp->outDatap += sizeof(long);
1778 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1783 cm_SkipIoctlPath(ioctlp);
1785 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1787 return CM_ERROR_NOSUCHCELL;
1789 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1791 lock_ObtainMutex(&cellp->mx);
1792 if (temp & CM_SETCELLFLAG_SUID)
1793 cellp->flags |= CM_CELLFLAG_SUID;
1795 cellp->flags &= ~CM_CELLFLAG_SUID;
1796 lock_ReleaseMutex(&cellp->mx);
1801 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1803 cm_SSetPref_t *spin; /* input */
1804 cm_SPref_t *srvin; /* one input component */
1806 int i, vlonly, noServers, type;
1807 struct sockaddr_in tmp;
1808 unsigned short rank;
1810 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1812 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1813 noServers = spin->num_servers;
1814 vlonly = spin->flags;
1816 type = CM_SERVER_VLDB;
1818 type = CM_SERVER_FILE;
1820 for ( i=0; i < noServers; i++)
1822 srvin = &(spin->servers[i]);
1823 rank = srvin->rank + (rand() & 0x000f);
1824 tmp.sin_addr = srvin->host;
1825 tmp.sin_family = AF_INET;
1827 tsp = cm_FindServer(&tmp, type);
1828 if ( tsp ) /* an existing server - ref count increased */
1830 tsp->ipRank = rank; /* no need to protect by mutex*/
1832 if (type == CM_SERVER_FILE)
1834 /* find volumes which might have RO copy
1835 /* on server and change the ordering of
1838 cm_ChangeRankVolume(tsp);
1842 /* set preferences for an existing vlserver */
1843 cm_ChangeRankCellVLServer(tsp);
1846 else /* add a new server without a cell */
1848 tsp = cm_NewServer(&tmp, type, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
1851 lock_ObtainMutex(&tsp->mx);
1852 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1853 lock_ReleaseMutex(&tsp->mx);
1854 cm_PutServer(tsp); /* decrease refcount */
1859 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1861 cm_SPrefRequest_t *spin; /* input */
1862 cm_SPrefInfo_t *spout; /* output */
1863 cm_SPref_t *srvout; /* one output component */
1865 int i, vlonly, noServers;
1867 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1869 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1870 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1871 srvout = spout->servers;
1872 noServers = spin->num_servers;
1873 vlonly = spin->flags & CM_SPREF_VLONLY;
1874 spout->num_servers = 0;
1876 lock_ObtainRead(&cm_serverLock); /* get server lock */
1878 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1879 if (spin->offset > i) {
1880 continue; /* catch up to where we left off */
1883 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1884 continue; /* ignore fileserver for -vlserver option*/
1885 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1886 continue; /* ignore vlservers */
1888 srvout->host = tsp->addr.sin_addr;
1889 srvout->rank = tsp->ipRank;
1891 spout->num_servers++;
1894 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1896 if ( tsp ) /* we ran out of space in the output buffer */
1897 spout->next_offset = i;
1899 spout->next_offset = 0;
1900 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1901 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1905 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1907 /* we ignore default asynchrony since we only have one way
1908 * of doing this today.
1913 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1915 char leaf[LEAF_SIZE];
1929 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1933 /* Translate chars for the mount point name */
1934 TranslateExtendedChars(leaf);
1937 * The fs command allows the user to specify partial cell names on NT. These must
1938 * be expanded to the full cell name for mount points so that the mount points will
1939 * work on UNIX clients.
1942 /* Extract the possibly partial cell name */
1943 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1945 if (cp = strchr(cell, ':')) {
1946 /* Extract the volume name */
1948 StringCbCopyA(volume, sizeof(volume), cp + 1);
1950 /* Get the full name for this cell */
1951 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1952 #ifdef AFS_AFSDB_ENV
1953 if (code && cm_dnsEnabled)
1954 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1957 cm_ReleaseSCache(dscp);
1958 return CM_ERROR_NOSUCHCELL;
1961 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1963 /* No cell name specified */
1964 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1967 #ifdef AFS_FREELANCE_CLIENT
1968 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1969 /* we are adding the mount point to the root dir., so call
1970 * the freelance code to do the add. */
1971 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1972 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1973 *ioctlp->inDatap == '%', NULL);
1974 cm_ReleaseSCache(dscp);
1978 /* create the symlink with mode 644. The lack of X bits tells
1979 * us that it is a mount point.
1981 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1982 tattr.unixModeBits = 0644;
1983 tattr.clientModTime = time(NULL);
1985 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1986 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1987 smb_NotifyChange(FILE_ACTION_ADDED,
1988 FILE_NOTIFY_CHANGE_DIR_NAME,
1989 dscp, leaf, NULL, TRUE);
1991 cm_ReleaseSCache(dscp);
1995 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1997 char leaf[LEAF_SIZE];
2006 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
2007 if (code) return code;
2009 /* Translate chars for the link name */
2010 TranslateExtendedChars(leaf);
2012 /* Translate chars for the linked to name */
2013 TranslateExtendedChars(ioctlp->inDatap);
2015 cp = ioctlp->inDatap; /* contents of link */
2017 #ifdef AFS_FREELANCE_CLIENT
2018 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
2019 /* we are adding the symlink to the root dir., so call
2020 * the freelance code to do the add. */
2021 if (cp[0] == cp[1] && cp[1] == '\\' &&
2022 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
2024 /* skip \\AFS\ or \\AFS\all\ */
2026 p = cp + 2 + strlen(cm_NetbiosName) + 1;
2027 if ( !_strnicmp("all", p, 3) )
2031 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
2032 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
2033 cm_ReleaseSCache(dscp);
2038 /* Create symlink with mode 0755. */
2039 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
2040 tattr.unixModeBits = 0755;
2042 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
2043 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
2044 smb_NotifyChange(FILE_ACTION_ADDED,
2045 FILE_NOTIFY_CHANGE_FILE_NAME
2046 | FILE_NOTIFY_CHANGE_DIR_NAME,
2047 dscp, leaf, NULL, TRUE);
2049 cm_ReleaseSCache(dscp);
2055 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2062 cm_scache_t *newRootScp;
2067 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2068 if (code) return code;
2070 cp = ioctlp->inDatap;
2072 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2073 cm_ReleaseSCache(dscp);
2074 if (code) return code;
2076 /* Check that it's a real symlink */
2077 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2078 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2079 scp->fileType != CM_SCACHETYPE_INVALID) {
2080 cm_ReleaseSCache(scp);
2081 return CM_ERROR_INVAL;
2084 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
2085 cm_ReleaseSCache(scp);
2087 cp = ioctlp->outDatap;
2088 if (newRootScp != NULL) {
2089 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
2090 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
2093 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
2094 cp += strlen(cp) + 1;
2095 ioctlp->outDatap = cp;
2096 cm_FreeSpace(spacep);
2097 if (newRootScp != NULL)
2098 cm_ReleaseSCache(newRootScp);
2100 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
2101 scp->fileType == CM_SCACHETYPE_DFSLINK ||
2102 code == CM_ERROR_NOSUCHPATH &&
2103 scp->fileType == CM_SCACHETYPE_INVALID) {
2105 cp = ioctlp->outDatap;
2106 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
2107 cp += strlen(cp) + 1;
2108 ioctlp->outDatap = cp;
2115 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2116 {/*CHECK FOR VALID SYMLINK*/
2125 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2126 if (code) return code;
2128 cp = ioctlp->inDatap;
2129 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
2131 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2132 cm_ReleaseSCache(dscp);
2133 if (code) return code;
2135 /* Check that it's a real symlink */
2136 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2137 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2138 scp->fileType != CM_SCACHETYPE_INVALID)
2139 code = CM_ERROR_INVAL;
2140 cm_ReleaseSCache(scp);
2144 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
2154 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
2155 if (code) return code;
2157 cp = ioctlp->inDatap;
2159 #ifdef AFS_FREELANCE_CLIENT
2160 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
2161 /* we are adding the mount point to the root dir., so call
2162 * the freelance code to do the add. */
2163 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
2164 code = cm_FreelanceRemoveSymlink(cp);
2165 cm_ReleaseSCache(dscp);
2170 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
2172 /* if something went wrong, bail out now */
2176 lock_ObtainMutex(&scp->mx);
2177 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2178 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2182 /* now check that this is a real symlink */
2183 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
2184 scp->fileType != CM_SCACHETYPE_DFSLINK &&
2185 scp->fileType != CM_SCACHETYPE_INVALID) {
2186 code = CM_ERROR_INVAL;
2190 /* time to make the RPC, so drop the lock */
2191 lock_ReleaseMutex(&scp->mx);
2193 /* easier to do it this way */
2194 code = cm_Unlink(dscp, cp, userp, &req);
2195 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
2196 smb_NotifyChange(FILE_ACTION_REMOVED,
2197 FILE_NOTIFY_CHANGE_FILE_NAME
2198 | FILE_NOTIFY_CHANGE_DIR_NAME,
2199 dscp, cp, NULL, TRUE);
2201 lock_ObtainMutex(&scp->mx);
2203 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2206 lock_ReleaseMutex(&scp->mx);
2207 cm_ReleaseSCache(scp);
2210 cm_ReleaseSCache(dscp);
2215 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
2220 static struct afsconf_cell info;
2221 struct rx_connection *serverconns[MAXSERVERS];
2222 struct rx_securityClass *sc[3];
2223 afs_int32 scIndex = 2; /* authenticated - we have a token */
2224 struct ubik_client *pruclient = NULL;
2225 struct afsconf_dir *tdir;
2229 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
2230 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
2231 afsconf_Close(tdir);
2237 /* we have the token that was given to us in the settoken
2238 * call. we just have to use it.
2240 scIndex = 2; /* kerberos ticket */
2241 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
2242 ucellp->kvno, ucellp->ticketLen,
2245 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
2246 for (i = 0; i < info.numServers; i++)
2248 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
2249 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
2252 code = ubik_ClientInit(serverconns, &pruclient);
2257 code = rxs_Release(sc[scIndex]);
2259 lids.idlist_len = 0;
2260 lids.idlist_val = 0;
2261 lnames.namelist_len = 1;
2262 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
2263 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
2264 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
2265 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
2271 if (r && !stricmp(r+1,ucellp->cellp->name))
2274 code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
2275 if (lids.idlist_val) {
2276 *uid = *lids.idlist_val;
2277 free(lids.idlist_val);
2279 if (lnames.namelist_val)
2280 free(lnames.namelist_val);
2283 ubik_ClientDestroy(pruclient);
2289 #endif /* QUERY_AFSID */
2291 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2298 struct ClearToken ct;
2308 int release_userp = 0;
2311 saveDataPtr = ioctlp->inDatap;
2313 cm_SkipIoctlPath(ioctlp);
2315 tp = ioctlp->inDatap;
2318 memcpy(&ticketLen, tp, sizeof(ticketLen));
2319 tp += sizeof(ticketLen);
2320 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2321 return CM_ERROR_INVAL;
2323 /* remember ticket and skip over it for now */
2327 /* clear token size */
2328 memcpy(&ctSize, tp, sizeof(ctSize));
2329 tp += sizeof(ctSize);
2330 if (ctSize != sizeof(struct ClearToken))
2331 return CM_ERROR_INVAL;
2334 memcpy(&ct, tp, ctSize);
2336 if (ct.AuthHandle == -1)
2337 ct.AuthHandle = 999; /* more rxvab compat stuff */
2339 /* more stuff, if any */
2340 if (ioctlp->inCopied > tp - saveDataPtr) {
2341 /* flags: logon flag */
2342 memcpy(&flags, tp, sizeof(int));
2346 cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
2348 return CM_ERROR_NOSUCHCELL;
2349 tp += strlen(tp) + 1;
2353 tp += strlen(tp) + 1;
2355 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2356 if (flags & PIOCTL_LOGON) {
2357 /* SMB user name with which to associate tokens */
2359 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2360 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2361 fprintf(stderr, "SMB name = %s\n", smbname);
2362 tp += strlen(tp) + 1;
2364 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2365 osi_LogSaveString(smb_logp, uname));
2370 memcpy(&uuid, tp, sizeof(uuid));
2371 if (!cm_FindTokenEvent(uuid, sessionKey))
2372 return CM_ERROR_INVAL;
2374 cellp = cm_data.rootCellp;
2375 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2379 if (flags & PIOCTL_LOGON) {
2380 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2381 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2386 /* store the token */
2387 lock_ObtainMutex(&userp->mx);
2388 ucellp = cm_GetUCell(userp, cellp);
2389 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2390 ucellp->ticketLen = ticketLen;
2391 if (ucellp->ticketp)
2392 free(ucellp->ticketp); /* Discard old token if any */
2393 ucellp->ticketp = malloc(ticketLen);
2394 memcpy(ucellp->ticketp, ticket, ticketLen);
2396 * Get the session key from the RPC, rather than from the pioctl.
2399 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2401 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2402 ucellp->kvno = ct.AuthHandle;
2403 ucellp->expirationTime = ct.EndTimestamp;
2406 ucellp->uid = ANONYMOUSID;
2409 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2411 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2414 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2415 lock_ReleaseMutex(&userp->mx);
2417 if (flags & PIOCTL_LOGON) {
2418 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2421 cm_ResetACLCache(userp);
2424 cm_ReleaseUser(userp);
2429 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2435 struct ClearToken ct;
2437 cm_SkipIoctlPath(ioctlp);
2439 tp = ioctlp->inDatap;
2440 cp = ioctlp->outDatap;
2443 memcpy(&iterator, tp, sizeof(iterator));
2444 tp += sizeof(iterator);
2446 lock_ObtainMutex(&userp->mx);
2448 /* look for token */
2449 for (;;iterator++) {
2450 ucellp = cm_FindUCell(userp, iterator);
2452 lock_ReleaseMutex(&userp->mx);
2453 return CM_ERROR_NOMORETOKENS;
2455 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2460 temp = ucellp->iterator + 1;
2461 memcpy(cp, &temp, sizeof(temp));
2465 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2466 cp += sizeof(ucellp->ticketLen);
2469 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2470 cp += ucellp->ticketLen;
2472 /* clear token size */
2474 memcpy(cp, &temp, sizeof(temp));
2478 ct.AuthHandle = ucellp->kvno;
2480 * Don't give out a real session key here
2483 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2485 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2486 ct.ViceId = 37; /* XXX */
2487 ct.BeginTimestamp = 0; /* XXX */
2488 ct.EndTimestamp = ucellp->expirationTime;
2489 memcpy(cp, &ct, sizeof(ct));
2492 /* Primary flag (unused) */
2494 memcpy(cp, &temp, sizeof(temp));
2498 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2499 cp += strlen(cp) + 1;
2502 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2503 cp += strlen(cp) + 1;
2505 ioctlp->outDatap = cp;
2507 lock_ReleaseMutex(&userp->mx);
2512 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2518 struct ClearToken ct;
2521 cm_SkipIoctlPath(ioctlp);
2523 tp = ioctlp->inDatap;
2525 cp = ioctlp->outDatap;
2527 /* cell name is right here */
2528 cellp = cm_GetCell(tp, 0);
2530 return CM_ERROR_NOSUCHCELL;
2531 tp += strlen(tp) + 1;
2534 memcpy(&uuid, tp, sizeof(uuid));
2536 lock_ObtainMutex(&userp->mx);
2538 ucellp = cm_GetUCell(userp, cellp);
2539 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2540 lock_ReleaseMutex(&userp->mx);
2541 return CM_ERROR_NOMORETOKENS;
2545 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2546 cp += sizeof(ucellp->ticketLen);
2549 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2550 cp += ucellp->ticketLen;
2552 /* clear token size */
2554 memcpy(cp, &temp, sizeof(temp));
2558 ct.AuthHandle = ucellp->kvno;
2560 * Don't give out a real session key here
2563 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2565 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2566 ct.ViceId = 37; /* XXX */
2567 ct.BeginTimestamp = 0; /* XXX */
2568 ct.EndTimestamp = ucellp->expirationTime;
2569 memcpy(cp, &ct, sizeof(ct));
2572 /* Primary flag (unused) */
2574 memcpy(cp, &temp, sizeof(temp));
2578 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2579 cp += strlen(cp) + 1;
2582 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2583 cp += strlen(cp) + 1;
2585 ioctlp->outDatap = cp;
2587 lock_ReleaseMutex(&userp->mx);
2589 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2594 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2600 cm_SkipIoctlPath(ioctlp);
2602 cp = ioctlp->outDatap;
2604 /* cell name is right here */
2605 cellp = cm_GetCell(ioctlp->inDatap, 0);
2607 return CM_ERROR_NOSUCHCELL;
2609 lock_ObtainMutex(&userp->mx);
2611 ucellp = cm_GetUCell(userp, cellp);
2613 lock_ReleaseMutex(&userp->mx);
2614 return CM_ERROR_NOMORETOKENS;
2617 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2619 if (ucellp->ticketp) {
2620 free(ucellp->ticketp);
2621 ucellp->ticketp = NULL;
2623 ucellp->ticketLen = 0;
2624 memset(ucellp->sessionKey.data, 0, 8);
2626 ucellp->expirationTime = 0;
2627 ucellp->userName[0] = '\0';
2628 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2631 lock_ReleaseMutex(&userp->mx);
2633 cm_ResetACLCache(userp);
2638 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2642 lock_ObtainMutex(&userp->mx);
2644 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2645 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2647 if (ucellp->ticketp) {
2648 free(ucellp->ticketp);
2649 ucellp->ticketp = NULL;
2651 ucellp->ticketLen = 0;
2652 memset(ucellp->sessionKey.data, 0, 8);
2654 ucellp->expirationTime = 0;
2655 ucellp->userName[0] = '\0';
2656 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2660 lock_ReleaseMutex(&userp->mx);
2662 cm_ResetACLCache(userp);
2667 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2669 char afspath[MAX_PATH];
2671 int nextAutoSubmount;
2673 DWORD dwType, dwSize;
2678 cm_SkipIoctlPath(ioctlp);
2680 /* Serialize this one, to prevent simultaneous mods
2683 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2685 /* Parse the input parameters--first the required afs path,
2686 * then the requested submount name (which may be "").
2688 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2689 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2691 /* If the caller supplied a suggested submount name, see if
2692 * that submount name is in use... if so, the submount's path
2693 * has to match our path.
2696 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2697 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2700 REG_OPTION_NON_VOLATILE,
2701 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2706 if (submountreqp && *submountreqp) {
2707 char submountPathNormalized[MAX_PATH];
2708 char submountPath[MAX_PATH];
2710 dwSize = sizeof(submountPath);
2711 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2712 &dwType, submountPath, &dwSize);
2714 if (status != ERROR_SUCCESS) {
2716 /* The suggested submount name isn't in use now--
2717 * so we can safely map the requested submount name
2718 * to the supplied path. Remember not to write the
2719 * leading "/afs" when writing out the submount.
2721 RegSetValueEx( hkSubmounts, submountreqp, 0,
2723 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2724 &afspath[strlen(cm_mountRoot)]:"/",
2725 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2726 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2728 RegCloseKey( hkSubmounts );
2729 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2730 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2731 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2735 /* The suggested submount name is already in use--if the
2736 * supplied path matches the submount's path, we can still
2737 * use the suggested submount name.
2739 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2740 if (!strcmp (submountPathNormalized, afspath)) {
2741 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2742 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2743 RegCloseKey( hkSubmounts );
2744 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2749 RegQueryInfoKey( hkSubmounts,
2751 NULL, /* lpcClass */
2752 NULL, /* lpReserved */
2753 NULL, /* lpcSubKeys */
2754 NULL, /* lpcMaxSubKeyLen */
2755 NULL, /* lpcMaxClassLen */
2756 &dwSubmounts, /* lpcValues */
2757 NULL, /* lpcMaxValueNameLen */
2758 NULL, /* lpcMaxValueLen */
2759 NULL, /* lpcbSecurityDescriptor */
2760 NULL /* lpftLastWriteTime */
2764 /* Having obtained a list of all available submounts, start
2765 * searching that list for a path which matches the requested
2766 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2767 * submount, in case we need to add a new one later.
2770 nextAutoSubmount = 1;
2772 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2773 char submountPathNormalized[MAX_PATH];
2774 char submountPath[MAX_PATH] = "";
2775 DWORD submountPathLen = sizeof(submountPath);
2776 char submountName[MAX_PATH];
2777 DWORD submountNameLen = sizeof(submountName);
2780 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2781 &dwType, submountPath, &submountPathLen);
2782 if (dwType == REG_EXPAND_SZ) {
2784 StringCbCopyA(buf, MAX_PATH, submountPath);
2785 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2786 if (submountPathLen > MAX_PATH)
2790 /* If this is an Auto### submount, remember its ### value */
2791 if ((!strnicmp (submountName, "auto", 4)) &&
2792 (isdigit (submountName[strlen("auto")]))) {
2793 int thisAutoSubmount;
2794 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2795 nextAutoSubmount = max (nextAutoSubmount,
2796 thisAutoSubmount+1);
2799 if ((submountPathLen == 0) ||
2800 (submountPathLen == sizeof(submountPath) - 1)) {
2804 /* See if the path for this submount matches the path
2805 * that our caller specified. If so, we can return
2808 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2809 if (!strcmp (submountPathNormalized, afspath)) {
2810 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2811 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2812 RegCloseKey(hkSubmounts);
2813 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2819 /* We've been through the entire list of existing submounts, and
2820 * didn't find any which matched the specified path. So, we'll
2821 * just have to add one. Remember not to write the leading "/afs"
2822 * when writing out the submount.
2825 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2827 RegSetValueEx( hkSubmounts,
2831 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2832 &afspath[strlen(cm_mountRoot)]:"/",
2833 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2834 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2836 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2837 RegCloseKey(hkSubmounts);
2838 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2842 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2844 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2845 ioctlp->outDatap += sizeof(cryptall);
2850 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2852 afs_int32 c = cryptall;
2854 cm_SkipIoctlPath(ioctlp);
2856 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2858 if (c != cryptall) {
2860 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2862 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2867 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2872 cm_SkipIoctlPath(ioctlp);
2874 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2875 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2878 if (flags & AFSCALL_RXSTATS_ENABLE) {
2879 rx_enableProcessRPCStats();
2881 if (flags & AFSCALL_RXSTATS_DISABLE) {
2882 rx_disableProcessRPCStats();
2884 if (flags & AFSCALL_RXSTATS_CLEAR) {
2885 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2890 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2895 cm_SkipIoctlPath(ioctlp);
2897 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2898 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2901 if (flags & AFSCALL_RXSTATS_ENABLE) {
2902 rx_enablePeerRPCStats();
2904 if (flags & AFSCALL_RXSTATS_DISABLE) {
2905 rx_disablePeerRPCStats();
2907 if (flags & AFSCALL_RXSTATS_CLEAR) {
2908 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2913 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2915 smb_user_t *uidp = ioctlp->uidp;
2917 if (uidp && uidp->unp) {
2918 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2919 ioctlp->outDatap += strlen(uidp->unp->name);
2925 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2930 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2932 if (cmd) { /* generate a new UUID */
2933 UuidCreate((UUID *) &uuid);
2934 cm_data.Uuid = uuid;
2935 cm_ForceNewConnectionsAllServers();
2938 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2939 ioctlp->outDatap += sizeof(cm_data.Uuid);
2945 * functions to dump contents of various structures.
2946 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2948 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2949 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2950 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2952 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2956 char logfileName[MAX_PATH+1];
2961 static _CrtMemState memstate;
2964 cm_SkipIoctlPath(ioctlp);
2965 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2967 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2968 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2970 GetWindowsDirectory(logfileName, sizeof(logfileName));
2972 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2974 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2980 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2981 ioctlp->outDatap += sizeof(long);
2986 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2988 cookie = inValue ? "b" : "e";
2994 _CrtMemCheckpoint(&memstate);
2998 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2999 _CrtSetReportFile(_CRT_WARN, hLogFile);
3000 _CrtMemDumpAllObjectsSince(&memstate);
3004 /* dump all interesting data */
3005 cm_MemDumpDirStats(hLogFile, cookie, 1);
3006 cm_MemDumpBPlusStats(hLogFile, cookie, 1);
3007 cm_DumpCells(hLogFile, cookie, 1);
3008 cm_DumpVolumes(hLogFile, cookie, 1);
3009 cm_DumpSCache(hLogFile, cookie, 1);
3010 cm_DumpBufHashTable(hLogFile, cookie, 1);
3011 smb_DumpVCP(hLogFile, cookie, 1);
3013 CloseHandle(hLogFile);
3015 inValue = 0; /* success */
3016 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
3017 ioctlp->outDatap += sizeof(long);
3024 cm_CheckServersStatus(cm_serverRef_t *serversp)
3027 cm_serverRef_t *tsrp;
3029 int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
3031 if (serversp == NULL) {
3032 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
3033 return CM_ERROR_ALLDOWN;
3036 lock_ObtainRead(&cm_serverLock);
3037 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
3038 if (tsp = tsrp->server) {
3039 cm_GetServerNoLock(tsp);
3040 lock_ReleaseRead(&cm_serverLock);
3041 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
3043 if (tsrp->status == srv_busy) {
3046 } else if (tsrp->status == srv_offline) {
3056 lock_ObtainRead(&cm_serverLock);
3057 cm_PutServerNoLock(tsp);
3060 lock_ReleaseRead(&cm_serverLock);
3063 code = CM_ERROR_ALLDOWN;
3065 code = CM_ERROR_ALLBUSY;
3066 else if (allOffline || (someBusy && someOffline))
3067 code = CM_ERROR_ALLOFFLINE;
3070 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
3075 long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
3081 cm_vol_state_t *statep;
3084 cm_ioctlQueryOptions_t *optionsp;
3085 afs_uint32 flags = 0;
3089 optionsp = cm_IoctlGetQueryOptions(ioctlp, userp);
3090 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
3091 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
3093 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
3094 cm_SkipIoctlPath(ioctlp);
3095 code = cm_GetSCache(&optionsp->fid, &scp, userp, &req);
3097 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
3102 #ifdef AFS_FREELANCE_CLIENT
3103 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
3105 cm_ReleaseSCache(scp);
3109 volume = scp->fid.volume;
3111 cellp = cm_FindCellByID(scp->fid.cell, 0);
3113 cm_ReleaseSCache(scp);
3116 return CM_ERROR_NOSUCHCELL;
3118 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
3122 if (volume == tvp->rw.ID)
3124 else if (volume == tvp->ro.ID)
3129 switch (statep->state) {
3135 code = CM_ERROR_ALLBUSY;
3138 code = CM_ERROR_ALLOFFLINE;
3141 code = CM_ERROR_ALLDOWN;
3150 long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
3153 cm_cell_t *cellp = NULL;
3155 cm_vol_state_t *statep;
3156 struct VolStatTest * testp;
3163 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
3164 testp = (struct VolStatTest *)ioctlp->inDatap;
3166 #ifdef AFS_FREELANCE_CLIENT
3167 if (testp->fid.cell == -1)
3168 return CM_ERROR_NOACCESS;
3171 if (testp->flags & VOLSTAT_TEST_CHECK_VOLUME) {
3172 cm_CheckOfflineVolumes();
3176 if (testp->flags & VOLSTAT_TEST_NETWORK_UP) {
3177 cm_VolStatus_Network_Started(cm_NetbiosName
3185 if (testp->flags & VOLSTAT_TEST_NETWORK_DOWN) {
3186 cm_VolStatus_Network_Stopped(cm_NetbiosName
3194 if (testp->cellname[0]) {
3195 n = atoi(testp->cellname);
3197 testp->fid.cell = n;
3199 cellp = cm_GetCell(testp->cellname, 0);
3202 if (testp->fid.cell > 0) {
3203 cellp = cm_FindCellByID(testp->fid.cell, 0);
3207 return CM_ERROR_NOSUCHCELL;
3209 if (testp->volname[0]) {
3210 n = atoi(testp->volname);
3212 testp->fid.volume = n;
3214 code = cm_GetVolumeByName(cellp, testp->volname, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3217 if (testp->fid.volume > 0)
3218 code = cm_GetVolumeByID(cellp, testp->fid.volume, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3223 if (testp->fid.volume) {
3224 if (testp->fid.volume == volp->rw.ID)
3226 else if (testp->fid.volume == volp->ro.ID)
3231 len = strlen(testp->volname);
3233 if (stricmp(".readonly", &testp->volname[len-9]) == 0)
3235 else if (stricmp(".backup", &testp->volname[len-7]) == 0)
3242 statep->state = testp->state;
3243 code = cm_VolStatus_Change_Notification(cellp->cellID, statep->ID, testp->state);