From: Jeffrey Altman Date: Thu, 12 Jun 2008 15:54:23 +0000 (+0000) Subject: windows-pioctl-refactoring-20080612 X-Git-Tag: openafs-devel-1_5_61~1050 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=d8c3a598184df6066c330769e49fb1e301464e52 windows-pioctl-refactoring-20080612 LICENSE MIT Refactor the pioctl handling to provide a layer of abstraction between the smb server and the actual pioctl data processing. This will permit a redirector pioctl layer to be implemented on top of the core cm_ioctl interfaces. The general approach is that there is a new cm_ioctl_t object which is embedded withing a higher level abstraction object. This object maintains all of the pioctl state processing and removes any notion of file descriptors or other communication channel parameters. The cm_ioctl module maintains just about all of the core functional processing except for SetToken which needs further abstraction. Path processing is now performed at the higher layer and cm_ioctl functions accept cm_user_t, cm_scache_t, and cm_req_t objects from the higher layer. The smb_ioctl module performs all of the path translation using smb server knowledge and passes the necessary objects to the cm_ioctl module for processing. --- diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 5c95346..fcb20b0 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -47,8 +47,8 @@ #define PIOCTL_LOGON 0x1 #define MAX_PATH 260 -static const char utf8_prefix[] = UTF8_PREFIX; -static const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char); +const char utf8_prefix[] = UTF8_PREFIX; +const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char); osi_mutex_t cm_Afsdsbmt_Lock; @@ -62,23 +62,34 @@ void cm_InitIoctl(void) lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock"); } -long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) +/* + * Utility function. (Not currently in use.) + * This function forces all dirty buffers to the file server and + * then discards the status info. + */ +afs_int32 +cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) { long code; code = buf_CleanVnode(scp, userp, reqp); - - lock_ObtainWrite(&scp->rw); - cm_DiscardSCache(scp); - lock_ReleaseWrite(&scp->rw); - + if (!code) { + lock_ObtainWrite(&scp->rw); + cm_DiscardSCache(scp); + lock_ReleaseWrite(&scp->rw); + } osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code); return code; } -long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) +/* + * Utility function. Used within this file. + * scp must be held but not locked. + */ +afs_int32 +cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) { - long code; + afs_int32 code; #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { @@ -91,16 +102,21 @@ long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) lock_ObtainWrite(&scp->rw); cm_DiscardSCache(scp); - lock_ReleaseWrite(&scp->rw); osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code); return code; } -long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) +/* + * Utility function. (Not currently in use) + * IoctlPath must be parsed or skipped prior to calling. + * scp must be held but not locked. + */ +afs_int32 +cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) { - long code = 0; + afs_int32 code = 0; cm_scache_t * pscp; pscp = cm_FindSCacheParent(scp); @@ -112,10 +128,13 @@ long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) return code; } - -long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume) +/* + * Utility function. Used within this function. + */ +afs_int32 +cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume) { - long code = 0; + afs_int32 code = 0; cm_scache_t *scp; int i; @@ -146,10 +165,11 @@ long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint3 } /* - * cm_ResetACLCache -- invalidate ACL info for a user that has just - * obtained or lost tokens + * Utility function. Used within this file. + * Invalidate ACL info for a user that has just obtained or lost tokens. */ -void cm_ResetACLCache(cm_user_t *userp) +void +cm_ResetACLCache(cm_user_t *userp) { cm_scache_t *scp; int hash; @@ -174,260 +194,33 @@ void cm_ResetACLCache(cm_user_t *userp) * * If an extended character (80 - FF) is entered into a file * or directory name in Windows, the character is translated - * into the OEM character map before being passed to us. Why - * this occurs is unknown. Our pioctl functions must match + * into the OEM character map before being passed to us. + * The pioctl functions must match * this translation for paths given via our own commands (like * fs). If we do not do this, then we will try to perform an * operation on a non-translated path, which we will fail to * find, since the path was created with the translated chars. * This function performs the required translation. + * + * OEM character code pages are used by the non-Unicode SMB + * mode. Do not use if the CM_IOCTLFLAG_USEUTF8 is set. */ -void TranslateExtendedChars(char *str) +void +TranslateExtendedChars(char *str) { if (!str || !*str) return; CharToOem(str, str); } - -/* parse the passed-in file name and do a namei on it. If we fail, - * return an error code, otherwise return the vnode located in *scpp. - */ -#define CM_PARSE_FLAG_LITERAL 1 - -long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, - cm_scache_t **scpp, afs_uint32 flags) -{ - long code; - cm_scache_t *substRootp = NULL; - cm_scache_t *iscp = NULL; - char * relativePath; - char * lastComponent = NULL; - afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW); - int free_path = FALSE; - - relativePath = ioctlp->inDatap; - /* setup the next data value for the caller to use */ - ioctlp->inDatap += (long)strlen(ioctlp->inDatap) + 1;; - - osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath)); - - /* This is usually the file name, but for StatMountPoint it is the path. */ - /* ioctlp->inDatap can be either of the form: - * \path\. - * \path\file - * \\netbios-name\submount\path\. - * \\netbios-name\submount\path\file - */ - - /* We do not perform path name translation on the ioctl path data - * because these paths were not translated by Windows through the - * file system API. Therefore, they are not OEM characters but - * whatever the display character set is. - */ - - // TranslateExtendedChars(relativePath); - - /* This is usually nothing, but for StatMountPoint it is the file name. */ - // TranslateExtendedChars(ioctlp->inDatap); - - /* If the string starts with our UTF-8 prefix (which is the - sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 - strings), we assume that the provided path is UTF-8. Otherwise - we have to convert the string to UTF-8, since that is what we - want to use everywhere else.*/ - - if (memcmp(relativePath, utf8_prefix, utf8_prefix_size) == 0) { - int len, normalized_len; - char * normalized_path; - - /* String is UTF-8 */ - relativePath += utf8_prefix_size; - ioctlp->flags |= SMB_IOCTLFLAG_USEUTF8; - - len = (ioctlp->inDatap - relativePath); - - normalized_len = cm_NormalizeUtf8String(relativePath, len, NULL, 0); - - if (normalized_len > len) { - normalized_path = malloc(normalized_len); - free_path = TRUE; - } else { - normalized_path = relativePath; - } - - cm_NormalizeUtf8String(relativePath, len, normalized_path, normalized_len); - - if (normalized_path != relativePath) - relativePath = normalized_path; - } else { - /* Not a UTF-8 string */ - /* TODO: If this is an OEM string, we should convert it to - UTF-8. */ - } - - if (relativePath[0] == relativePath[1] && - relativePath[1] == '\\' && - !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName))) - { - char shareName[256]; - char *sharePath; - int shareFound, i; - - /* We may have found a UNC path. - * If the first component is the NetbiosName, - * then throw out the second component (the submount) - * since it had better expand into the value of ioctl->tidPathp - */ - char * p; - p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */ - if ( !_strnicmp("all", p, 3) ) - p += 4; - for (i = 0; *p && *p != '\\'; i++,p++ ) { - shareName[i] = *p; - } - p++; /* skip past trailing slash */ - shareName[i] = 0; /* terminate string */ - - shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath); - if ( shareFound ) { - /* we found a sharename, therefore use the resulting path */ - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, sharePath, reqp, &substRootp); - free(sharePath); - if (code) { - osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - - lastComponent = strrchr(p, '\\'); - if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) { - *lastComponent = '\0'; - lastComponent++; - - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, &iscp); - if (code == 0) - code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, - userp, NULL, reqp, scpp); - if (iscp) - cm_ReleaseSCache(iscp); - } else { - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD, - userp, NULL, reqp, scpp); - } - cm_ReleaseSCache(substRootp); - if (code) { - osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - } else { - /* otherwise, treat the name as a cellname mounted off the afs root. - * This requires that we reconstruct the shareName string with - * leading and trailing slashes. - */ - p = relativePath + 2 + strlen(cm_NetbiosName) + 1; - if ( !_strnicmp("all", p, 3) ) - p += 4; - - shareName[0] = '/'; - for (i = 1; *p && *p != '\\'; i++,p++ ) { - shareName[i] = *p; - } - p++; /* skip past trailing slash */ - shareName[i++] = '/'; /* add trailing slash */ - shareName[i] = 0; /* terminate string */ - - - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, shareName, reqp, &substRootp); - if (code) { - osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - - lastComponent = strrchr(p, '\\'); - if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) { - *lastComponent = '\0'; - lastComponent++; - - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, &iscp); - if (code == 0) - code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, - userp, NULL, reqp, scpp); - if (iscp) - cm_ReleaseSCache(iscp); - } else { - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD, - userp, NULL, reqp, scpp); - } - - if (code) { - cm_ReleaseSCache(substRootp); - osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - } - } else { - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, ioctlp->tidPathp, reqp, &substRootp); - if (code) { - osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - - lastComponent = strrchr(relativePath, '\\'); - if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) { - *lastComponent = '\0'; - lastComponent++; - - code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, &iscp); - if (code == 0) - code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, - userp, NULL, reqp, scpp); - if (iscp) - cm_ReleaseSCache(iscp); - } else { - code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow, - userp, NULL, reqp, scpp); - } - if (code) { - cm_ReleaseSCache(substRootp); - osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code); - if (free_path) - free(relativePath); - return code; - } - } - if (substRootp) - cm_ReleaseSCache(substRootp); - - /* and return success */ - osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code); - - if (free_path) - free(relativePath); - return 0; -} - -void cm_SkipIoctlPath(smb_ioctl_t *ioctlp) +/* + * Utility function. + * If the IoctlPath is not parsed then it must be skipped. + */ +void +cm_SkipIoctlPath(cm_ioctl_t *ioctlp) { size_t temp; @@ -436,10 +229,10 @@ void cm_SkipIoctlPath(smb_ioctl_t *ioctlp) } /* - * Must be called before cm_ParseIoctlPath or cm_SkipIoctlPath + * Must be called before XXX_ParseIoctlPath or cm_SkipIoctlPath */ -static cm_ioctlQueryOptions_t * -cm_IoctlGetQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp) +cm_ioctlQueryOptions_t * +cm_IoctlGetQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp) { afs_uint32 pathlen = strlen(ioctlp->inDatap) + 1; char *p = ioctlp->inDatap + pathlen; @@ -455,12 +248,12 @@ cm_IoctlGetQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp) } /* - * Must be called after cm_ParseIoctlPath or cm_SkipIoctlPath + * Must be called after smb_ParseIoctlPath or cm_SkipIoctlPath * or any other time that ioctlp->inDatap points at the * cm_ioctlQueryOptions_t object. */ -static void -cm_IoctlSkipQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp) +void +cm_IoctlSkipQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp) { cm_ioctlQueryOptions_t * optionsp = (cm_ioctlQueryOptions_t *)ioctlp->inDatap; ioctlp->inDatap += optionsp->size; @@ -473,7 +266,8 @@ cm_IoctlSkipQueryOptions(struct smb_ioctl *ioctlp, struct cm_user *userp) * easier (because we can always jump past the initial "/afs" to find * the AFS path that should be written into afsdsbmt.ini). */ -void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp) +void +cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp) { char *cp; char bslash_mountRoot[256]; @@ -504,199 +298,24 @@ void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp) } } -#define LEAF_SIZE 256 -/* parse the passed-in file name and do a namei on its parent. If we fail, - * return an error code, otherwise return the vnode located in *scpp. - */ -long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, - cm_scache_t **scpp, char *leafp) -{ - long code; - char tbuffer[1024]; - char *tp, *jp; - cm_scache_t *substRootp = NULL; - char *inpathp; - int free_path = FALSE; - - inpathp = ioctlp->inDatap; - - /* If the string starts with our UTF-8 prefix (which is the - sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 - strings), we assume that the provided path is UTF-8. Otherwise - we have to convert the string to UTF-8, since that is what we - want to use everywhere else.*/ - - if (memcmp(inpathp, utf8_prefix, utf8_prefix_size) == 0) { - int len, normalized_len; - char * normalized_path; - - /* String is UTF-8 */ - inpathp += utf8_prefix_size; - ioctlp->flags |= SMB_IOCTLFLAG_USEUTF8; - - len = strlen(inpathp) + 1; - - normalized_len = cm_NormalizeUtf8String(inpathp, len, NULL, 0); - - if (normalized_len > len) { - normalized_path = malloc(normalized_len); - free_path = TRUE; - } else { - normalized_path = inpathp; - } - cm_NormalizeUtf8String(inpathp, len, normalized_path, normalized_len); - - if (normalized_path != inpathp) - inpathp = normalized_path; - } else { - /* Not a UTF-8 string */ - /* TODO: If this is an OEM string, we should convert it to - UTF-8. */ - } - - StringCbCopyA(tbuffer, sizeof(tbuffer), inpathp); - tp = strrchr(tbuffer, '\\'); - jp = strrchr(tbuffer, '/'); - if (!tp) - tp = jp; - else if (jp && (tp - tbuffer) < (jp - tbuffer)) - tp = jp; - if (!tp) { - StringCbCopyA(tbuffer, sizeof(tbuffer), "\\"); - if (leafp) - StringCbCopyA(leafp, LEAF_SIZE, inpathp); - } - else { - *tp = 0; - if (leafp) - StringCbCopyA(leafp, LEAF_SIZE, tp+1); - } - - if (free_path) - free(inpathp); - inpathp = NULL; /* We don't need this from this point on */ - - if (free_path) - free(inpathp); - inpathp = NULL; /* We don't need this from this point on */ - - if (tbuffer[0] == tbuffer[1] && - tbuffer[1] == '\\' && - !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName))) - { - char shareName[256]; - char *sharePath; - int shareFound, i; - - /* We may have found a UNC path. - * If the first component is the NetbiosName, - * then throw out the second component (the submount) - * since it had better expand into the value of ioctl->tidPathp - */ - char * p; - p = tbuffer + 2 + strlen(cm_NetbiosName) + 1; - if ( !_strnicmp("all", p, 3) ) - p += 4; - - for (i = 0; *p && *p != '\\'; i++,p++ ) { - shareName[i] = *p; - } - p++; /* skip past trailing slash */ - shareName[i] = 0; /* terminate string */ - - shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath); - if ( shareFound ) { - /* we found a sharename, therefore use the resulting path */ - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, sharePath, reqp, &substRootp); - free(sharePath); - if (code) return code; - - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, scpp); - cm_ReleaseSCache(substRootp); - if (code) return code; - } else { - /* otherwise, treat the name as a cellname mounted off the afs root. - * This requires that we reconstruct the shareName string with - * leading and trailing slashes. - */ - p = tbuffer + 2 + strlen(cm_NetbiosName) + 1; - if ( !_strnicmp("all", p, 3) ) - p += 4; - - shareName[0] = '/'; - for (i = 1; *p && *p != '\\'; i++,p++ ) { - shareName[i] = *p; - } - p++; /* skip past trailing slash */ - shareName[i++] = '/'; /* add trailing slash */ - shareName[i] = 0; /* terminate string */ - - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, shareName, reqp, &substRootp); - if (code) return code; - - code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, scpp); - cm_ReleaseSCache(substRootp); - if (code) return code; - } - } else { - code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, - CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, ioctlp->tidPathp, reqp, &substRootp); - if (code) return code; - - code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, - userp, NULL, reqp, scpp); - cm_ReleaseSCache(substRootp); - if (code) return code; - } - - /* # of bytes of path */ - code = (long)strlen(ioctlp->inDatap) + 1; - ioctlp->inDatap += code; - - /* and return success */ - return 0; -} - -long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) +/* + * VIOCGETAL internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp) { + afs_int32 code; cm_conn_t *connp; - cm_scache_t *scp; AFSOpaque acl; AFSFetchStatus fileStatus; AFSVolSync volSync; - long code; AFSFid afid; int tlen; - cm_req_t req; struct rx_connection * callp; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; /* now make the get acl call */ #ifdef AFS_FREELANCE_CLIENT @@ -712,18 +331,19 @@ long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) do { acl.AFSOpaque_val = ioctlp->outDatap; acl.AFSOpaque_len = 0; - code = cm_ConnFromFID(&scp->fid, userp, &req, &connp); - if (code) continue; + code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp); + if (code) + continue; callp = cm_GetRxConn(connp); code = RXAFS_FetchACL(callp, &afid, &acl, &fileStatus, &volSync); rx_PutConnection(callp); - } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); - cm_ReleaseSCache(scp); + } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code)); + code = cm_MapRPCError(code, reqp); - if (code) return code; + if (code) + return code; } /* skip over return data */ tlen = (int)strlen(ioctlp->outDatap) + 1; @@ -733,32 +353,18 @@ long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) return 0; } -long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOC_FILE_CELL_NAME internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetFileCellName(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - long code; - cm_scache_t *scp; + afs_int32 code; cm_cell_t *cellp; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; #ifdef AFS_FREELANCE_CLIENT if ( cm_freelanceEnabled && @@ -781,27 +387,27 @@ long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp) code = CM_ERROR_NOSUCHCELL; } - cm_ReleaseSCache(scp); return code; } -long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOCSETAL internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { + afs_int32 code; cm_conn_t *connp; - cm_scache_t *scp; AFSOpaque acl; AFSFetchStatus fileStatus; AFSVolSync volSync; - long code; AFSFid fid; - cm_req_t req; struct rx_connection * callp; - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0); - if (code) return code; - #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { code = CM_ERROR_NOACCESS; @@ -815,39 +421,41 @@ long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp) do { acl.AFSOpaque_val = ioctlp->inDatap; acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1; - code = cm_ConnFromFID(&scp->fid, userp, &req, &connp); - if (code) continue; + code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp); + if (code) + continue; callp = cm_GetRxConn(connp); code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync); rx_PutConnection(callp); - } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); + } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code)); + code = cm_MapRPCError(code, reqp); /* invalidate cache info, since we just trashed the ACL cache */ lock_ObtainWrite(&scp->rw); cm_DiscardSCache(scp); lock_ReleaseWrite(&scp->rw); } - cm_ReleaseSCache(scp); return code; } - - -long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_FLUSHALL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long code; + afs_int32 code; cm_scache_t *scp; int i; cm_req_t req; cm_InitReq(&req); - cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ - lock_ObtainWrite(&cm_scacheLock); for (i=0; inextp) { @@ -865,33 +473,18 @@ long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; } -long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_FLUSHVOLUME internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlFlushVolume(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - long code; - cm_scache_t *scp; - unsigned long volume; - unsigned long cell; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; + afs_int32 code; + afs_uint32 volume; + afs_uint32 cell; #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { @@ -901,38 +494,21 @@ long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp) { volume = scp->fid.volume; cell = scp->fid.cell; - cm_ReleaseSCache(scp); - - code = cm_FlushVolume(userp, &req, cell, volume); + code = cm_FlushVolume(userp, reqp, cell, volume); } return code; } -long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCFLUSH internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlFlushFile(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - long code; - cm_scache_t *scp; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; + afs_int32 code; #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { @@ -940,35 +516,34 @@ long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp) } else #endif { - cm_FlushFile(scp, userp, &req); + cm_FlushFile(scp, userp, reqp); } - cm_ReleaseSCache(scp); - return 0; } -long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOCSETVOLSTAT internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlSetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - cm_scache_t *scp; + afs_int32 code; char volName[32]; char offLineMsg[256]; char motd[256]; cm_conn_t *tcp; - long code; AFSFetchVolumeStatus volStat; AFSStoreVolumeStatus storeStat; cm_volume_t *tvp; char *cp; cm_cell_t *cellp; - cm_req_t req; struct rx_connection * callp; int len; - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, 0); - if (code) return code; - #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { code = CM_ERROR_NOACCESS; @@ -978,17 +553,14 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) cellp = cm_FindCellByID(scp->fid.cell, 0); osi_assertx(cellp, "null cm_cell_t"); - if (scp->flags & CM_SCACHEFLAG_RO) { - cm_ReleaseSCache(scp); + if (scp->flags & CM_SCACHEFLAG_RO) return CM_ERROR_READONLY; - } - code = cm_FindVolumeByID(cellp, scp->fid.volume, userp, &req, + code = cm_FindVolumeByID(cellp, scp->fid.volume, userp, reqp, CM_GETVOL_FLAG_CREATE, &tvp); - if (code) { - cm_ReleaseSCache(scp); + if (code) return code; - } + cm_PutVolume(tvp); /* Copy the junk out, using cp as a roving pointer. */ @@ -1017,23 +589,22 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) } do { - code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp); - if (code) continue; + code = cm_ConnFromFID(&scp->fid, userp, reqp, &tcp); + if (code) + continue; callp = cm_GetRxConn(tcp); code = RXAFS_SetVolumeStatus(callp, scp->fid.volume, &storeStat, volName, offLineMsg, motd); rx_PutConnection(callp); - } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); + } while (cm_Analyze(tcp, userp, reqp, &scp->fid, NULL, NULL, NULL, code)); + code = cm_MapRPCError(code, reqp); } /* return on failure */ - cm_ReleaseSCache(scp); - if (code) { + if (code) return code; - } /* we are sending parms back to make compat. with prev system. should * change interface later to not ask for current status, just set @@ -1055,41 +626,27 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOCGETVOLSTAT internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - char volName[32]; - cm_scache_t *scp; - char offLineMsg[256]; - char motd[256]; + afs_int32 code; + char volName[32]="(unknown)"; + char offLineMsg[256]="server temporarily inaccessible"; + char motd[256]="server temporarily inaccessible"; cm_conn_t *connp; - register long code; AFSFetchVolumeStatus volStat; - register char *cp; + char *cp; char *Name; char *OfflineMsg; char *MOTD; - cm_req_t req; struct rx_connection * callp; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { @@ -1109,7 +666,7 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) OfflineMsg = offLineMsg; MOTD = motd; do { - code = cm_ConnFromFID(&scp->fid, userp, &req, &connp); + code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp); if (code) continue; callp = cm_GetRxConn(connp); @@ -1117,12 +674,12 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) &volStat, &Name, &OfflineMsg, &MOTD); rx_PutConnection(callp); - } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); + } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, NULL, NULL, code)); + code = cm_MapRPCError(code, reqp); } - cm_ReleaseSCache(scp); - if (code) return code; + if (code) + return code; /* Copy all this junk into msg->im_data, keeping track of the lengths. */ cp = ioctlp->outDatap; @@ -1141,24 +698,17 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCGETFID internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetFid(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - cm_scache_t *scp; - register long code; - register char *cp; + char *cp; cm_fid_t fid; - cm_req_t req; - cm_ioctlQueryOptions_t * optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - if (code) return code; memset(&fid, 0, sizeof(cm_fid_t)); fid.cell = scp->fid.cell; @@ -1166,8 +716,6 @@ long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp) fid.vnode = scp->fid.vnode; fid.unique = scp->fid.unique; - cm_ReleaseSCache(scp); - /* Copy all this junk into msg->im_data, keeping track of the lengths. */ cp = ioctlp->outDatap; memcpy(cp, (char *)&fid, sizeof(cm_fid_t)); @@ -1179,128 +727,97 @@ long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_GETFILETYPE internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetFileType(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - cm_scache_t *scp; - register long code; - register char *cp; + afs_int32 code = 0; + char *cp; afs_uint32 fileType = 0; - cm_req_t req; - cm_ioctlQueryOptions_t * optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + if (scp->fileType == 0) { + lock_ObtainWrite(&scp->rw); + code = cm_SyncOp(scp, NULL, userp, reqp, 0, + CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + if (code == 0) + cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + lock_ReleaseWrite(&scp->rw); } - if (code) - return code; - - fileType = scp->fileType; - cm_ReleaseSCache(scp); - /* Copy all this junk into msg->im_data, keeping track of the lengths. */ - cp = ioctlp->outDatap; - memcpy(cp, (char *)&fileType, sizeof(fileType)); - cp += sizeof(fileType); + if (code == 0) { + fileType = scp->fileType; - /* return new size */ - ioctlp->outDatap = cp; + /* Copy all this junk into msg->im_data, keeping track of the lengths. */ + cp = ioctlp->outDatap; + memcpy(cp, (char *)&fileType, sizeof(fileType)); + cp += sizeof(fileType); - return 0; + /* return new size */ + ioctlp->outDatap = cp; + } + return code; } -long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCGETOWNER internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlGetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - cm_scache_t *scp; - register long code; - register char *cp; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; + afs_int32 code = 0; + char *cp; - cm_InitReq(&req); + lock_ObtainWrite(&scp->rw); + code = cm_SyncOp(scp, NULL, userp, reqp, 0, + CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + if (code == 0) + cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + lock_ReleaseWrite(&scp->rw); - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + if (code == 0) { + /* Copy all this junk into msg->im_data, keeping track of the lengths. */ + cp = ioctlp->outDatap; + memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32)); + cp += sizeof(afs_uint32); + memcpy(cp, (char *)&scp->group, sizeof(afs_uint32)); + cp += sizeof(afs_uint32); - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + /* return new size */ + ioctlp->outDatap = cp; } - if (code) - return code; - - /* Copy all this junk into msg->im_data, keeping track of the lengths. */ - cp = ioctlp->outDatap; - memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32)); - cp += sizeof(afs_uint32); - memcpy(cp, (char *)&scp->group, sizeof(afs_uint32)); - cp += sizeof(afs_uint32); - - /* return new size */ - ioctlp->outDatap = cp; - - cm_ReleaseSCache(scp); - - return 0; + return code; } -long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOCWHEREIS internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - long code; - cm_scache_t *scp; + afs_int32 code; cm_cell_t *cellp; cm_volume_t *tvp; cm_serverRef_t **tsrpp, *current; cm_server_t *tsp; - unsigned long volume; + afs_uint32 volume; char *cp; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; volume = scp->fid.volume; cellp = cm_FindCellByID(scp->fid.cell, 0); - cm_ReleaseSCache(scp); - if (!cellp) return CM_ERROR_NOSUCHCELL; @@ -1327,7 +844,7 @@ long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp) } else #endif { - code = cm_FindVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp); + code = cm_FindVolumeByID(cellp, volume, userp, reqp, CM_GETVOL_FLAG_CREATE, &tvp); if (code) return code; @@ -1354,72 +871,79 @@ long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_AFS_STAT_MT_PT internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlStatMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp) { - long code; - cm_scache_t *dscp; + afs_int32 code; cm_scache_t *scp; char *cp; - cm_req_t req; - - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); - if (code) return code; cp = ioctlp->inDatap; - code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); - cm_ReleaseSCache(dscp); - if (code) return code; - + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp); + if (code) + return code; + lock_ObtainWrite(&scp->rw); + code = cm_SyncOp(scp, NULL, userp, reqp, 0, + CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + if (code == 0) + cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + else + goto done; /* now check that this is a real mount point */ if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) { - lock_ReleaseWrite(&scp->rw); - cm_ReleaseSCache(scp); - return CM_ERROR_INVAL; + code = CM_ERROR_INVAL; + goto done; } - code = cm_ReadMountPoint(scp, userp, &req); + code = cm_ReadMountPoint(scp, userp, reqp); if (code == 0) { cp = ioctlp->outDatap; StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp); cp += strlen(cp) + 1; ioctlp->outDatap = cp; } + + done: lock_ReleaseWrite(&scp->rw); cm_ReleaseSCache(scp); return code; } -long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_AFS_DELETE_MT_PT internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp) { - long code; - cm_scache_t *dscp; + afs_int32 code; cm_scache_t *scp; char *cp; char *originalName = NULL; - cm_req_t req; cm_dirOp_t dirop; - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); - if (code) return code; - cp = ioctlp->inDatap; - code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp); /* if something went wrong, bail out now */ if (code) goto done3; lock_ObtainWrite(&scp->rw); - code = cm_SyncOp(scp, NULL, userp, &req, 0, + code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code) goto done2; @@ -1434,7 +958,7 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) lock_ReleaseWrite(&scp->rw); #ifdef USE_BPLUS - code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop); + code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, &dirop); if (code == 0) { code = cm_BPlusDirLookupOriginalName(&dirop, cp, &originalName); /* The cm_Dir* functions can't be used to lookup the @@ -1464,7 +988,7 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) #endif { /* easier to do it this way */ - code = cm_Unlink(dscp, originalName, cp, userp, &req); + code = cm_Unlink(dscp, originalName, cp, userp, reqp); } if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) smb_NotifyChange(FILE_ACTION_REMOVED, @@ -1486,11 +1010,16 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_ReleaseSCache(scp); done3: - cm_ReleaseSCache(dscp); return code; } -long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCCKSERV internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlCheckServers(struct cm_ioctl *ioctlp, struct cm_user *userp) { cm_cell_t *cellp; chservinfo_t csi; @@ -1500,7 +1029,6 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_server_t *tsp; int haveCell; - cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ tp = ioctlp->inDatap; haveCell = 0; @@ -1542,7 +1070,9 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) else cellp = (cm_cell_t *) 0; if (!cellp && (temp & 2)) { /* use local cell */ - cellp = cm_FindCellByID(1, 0); + char wscell[CELL_MAXNAMELEN+1]; + cm_GetRootCellName(wscell); + cellp = cm_GetCell(wscell, 0); } if (!(temp & 1)) { /* if not fast, call server checker routine */ /* check down servers */ @@ -1554,7 +1084,8 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) cp = ioctlp->outDatap; lock_ObtainRead(&cm_serverLock); for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) { - if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */ + if (cellp && tsp->cellp != cellp) + continue; /* cell spec'd and wrong */ if ((tsp->flags & CM_SERVERFLAG_DOWN) && tsp->type == CM_SERVER_FILE) { memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long)); @@ -1567,24 +1098,32 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp) -{ - /* we don't print anything superfluous, so we don't support the gag call */ - return CM_ERROR_INVAL; -} - -long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCCKBACK internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlCheckVolumes(cm_ioctl_t *ioctlp, cm_user_t *userp) { cm_RefreshVolumes(); return 0; } -long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCSETCACHESIZE internals. + * + * Assumes that pioctl path has been parsed or skipped. + * + * This function is no longer meaningful in the current day world + * of persistent caches. The buf_SetNBuffers() function will + * inevitably fail. + */ +afs_int32 +cm_IoctlSetCacheSize(struct cm_ioctl *ioctlp, struct cm_user *userp) { + afs_int32 code; afs_uint64 temp; - long code; - - cm_SkipIoctlPath(ioctlp); memcpy(&temp, ioctlp->inDatap, sizeof(temp)); if (temp == 0) @@ -1600,13 +1139,17 @@ long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; } -long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_TRACECTL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlTraceControl(cm_ioctl_t *ioctlp, cm_user_t *userp) { - long inValue; - - cm_SkipIoctlPath(ioctlp); - - memcpy(&inValue, ioctlp->inDatap, sizeof(long)); + afs_uint32 inValue; + + memcpy(&inValue, ioctlp->inDatap, sizeof(afs_uint32)); /* print trace */ if (inValue & 8) { @@ -1635,12 +1178,18 @@ long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp) /* and copy out tracing flag */ inValue = afsd_logp->enabled; /* use as a temp vbl */ - memcpy(ioctlp->outDatap, &inValue, sizeof(long)); - ioctlp->outDatap += sizeof(long); + memcpy(ioctlp->outDatap, &inValue, sizeof(afs_uint32)); + ioctlp->outDatap += sizeof(afs_uint32); return 0; } -long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCGETCACHEPARMS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetCacheParms(struct cm_ioctl *ioctlp, struct cm_user *userp) { cm_cacheParms_t parms; @@ -1660,7 +1209,13 @@ long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCGETCELL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetCell(struct cm_ioctl *ioctlp, struct cm_user *userp) { long whichCell; long magic = 0; @@ -1672,21 +1227,20 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) char *tp; char *basep; - cm_SkipIoctlPath(ioctlp); - tp = ioctlp->inDatap; memcpy((char *)&whichCell, tp, sizeof(long)); tp += sizeof(long); /* see if more than one long passed in, ignoring the null pathname (the -1) */ - if (ioctlp->inCopied-1 > sizeof(long)) { - memcpy((char *)&magic, tp, sizeof(long)); + if (ioctlp->inCopied-1 > sizeof(afs_uint32)) { + memcpy((char *)&magic, tp, sizeof(afs_uint32)); } lock_ObtainRead(&cm_cellLock); for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->allNextp) { - if (whichCell == 0) break; + if (whichCell == 0) + break; whichCell--; } lock_ReleaseRead(&cm_cellLock); @@ -1702,14 +1256,12 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) memset(cp, 0, max * sizeof(long)); basep = cp; lock_ObtainRead(&cm_serverLock); /* for going down server list */ - /* jaltman - do the reference counts to serverRefp contents need to be increased? */ - serverRefp = tcellp->vlServersp; - for (i=0; ivlServersp; + serverRefp && inext) { serverp = serverRefp->server; memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long)); cp += sizeof(long); - serverRefp = serverRefp->next; } lock_ReleaseRead(&cm_serverLock); cp = basep + max * sizeof(afs_int32); @@ -1724,11 +1276,16 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */ } -long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp) + +/* + * VIOCNEWCELL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlNewCell(struct cm_ioctl *ioctlp, struct cm_user *userp) { - /* NT cache manager will read cell information from CellServDB each time - * cell is accessed. So, this call is necessary only if list of server for a cell - * changes (or IP addresses of cell servers changes). + /* * All that needs to be done is to refresh server information for all cells that * are already loaded. @@ -1738,13 +1295,11 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_cell_t *cp; cm_cell_rock_t rock; - - cm_SkipIoctlPath(ioctlp); lock_ObtainWrite(&cm_cellLock); for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { - long code; + afs_int32 code; lock_ObtainMutex(&cp->mx); /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/ cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE); @@ -1782,37 +1337,47 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp) -{ - long code = 0; - - if (cm_freelanceEnabled) { - if (cm_GetRootCellName(ioctlp->outDatap)) - StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root"); - ioctlp->outDatap += strlen(ioctlp->outDatap) +1; - } else if (cm_data.rootCellp) { - /* return the default cellname to the caller */ - StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name); - ioctlp->outDatap += strlen(ioctlp->outDatap) +1; - } else { - /* if we don't know our default cell, return failure */ - code = CM_ERROR_NOSUCHCELL; - } +/* + * VIOC_GET_WS_CELL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp) +{ + afs_int32 code = 0; + + if (cm_freelanceEnabled) { + if (cm_GetRootCellName(ioctlp->outDatap)) + StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root"); + ioctlp->outDatap += strlen(ioctlp->outDatap) +1; + } else if (cm_data.rootCellp) { + /* return the default cellname to the caller */ + StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name); + ioctlp->outDatap += strlen(ioctlp->outDatap) +1; + } else { + /* if we don't know our default cell, return failure */ + code = CM_ERROR_NOSUCHCELL; + } return code; } -long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_AFS_SYSNAME internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long setSysName, foundname = 0; + afs_uint32 setSysName, foundname = 0; char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME]; int t, count, num = 0; char **sysnamelist[MAXSYSNAME]; - cm_SkipIoctlPath(ioctlp); - - memcpy(&setSysName, ioctlp->inDatap, sizeof(long)); - ioctlp->inDatap += sizeof(long); + memcpy(&setSysName, ioctlp->inDatap, sizeof(afs_uint32)); + ioctlp->inDatap += sizeof(afs_uint32); if (setSysName) { /* check my args */ @@ -1895,13 +1460,17 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_GETCELLSTATUS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetCellStatus(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long temp; + afs_uint32 temp; cm_cell_t *cellp; - cm_SkipIoctlPath(ioctlp); - cellp = cm_GetCell(ioctlp->inDatap, 0); if (!cellp) return CM_ERROR_NOSUCHCELL; @@ -1913,24 +1482,28 @@ long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) lock_ReleaseMutex(&cellp->mx); /* now copy out parm */ - memcpy(ioctlp->outDatap, &temp, sizeof(long)); - ioctlp->outDatap += sizeof(long); + memcpy(ioctlp->outDatap, &temp, sizeof(afs_uint32)); + ioctlp->outDatap += sizeof(afs_uint32); return 0; } -long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_SETCELLSTATUS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlSetCellStatus(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long temp; + afs_uint32 temp; cm_cell_t *cellp; - cm_SkipIoctlPath(ioctlp); - - cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0); + cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(afs_uint32), 0); if (!cellp) return CM_ERROR_NOSUCHCELL; - memcpy((char *)&temp, ioctlp->inDatap, sizeof(long)); + memcpy((char *)&temp, ioctlp->inDatap, sizeof(afs_uint32)); lock_ObtainMutex(&cellp->mx); if (temp & CM_SETCELLFLAG_SUID) @@ -1942,16 +1515,20 @@ long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_SETSPREFS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlSetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp) { - cm_SSetPref_t *spin; /* input */ + cm_SSetPref_t *spin; /* input */ cm_SPref_t *srvin; /* one input component */ cm_server_t *tsp; - int i, vlonly, noServers, type; - struct sockaddr_in tmp; - unsigned short rank; - - cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ + int i, vlonly, noServers, type; + struct sockaddr_in tmp; + unsigned short rank; spin = (cm_SSetPref_t *)ioctlp->inDatap; noServers = spin->num_servers; @@ -2000,7 +1577,13 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_GETSPREFS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp) { cm_SPrefRequest_t *spin; /* input */ cm_SPrefInfo_t *spout; /* output */ @@ -2008,8 +1591,6 @@ long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_server_t *tsp; int i, vlonly, noServers; - cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ - spin = (cm_SPrefRequest_t *)ioctlp->inDatap; spout = (cm_SPrefInfo_t *) ioctlp->outDatap; srvout = spout->servers; @@ -2046,40 +1627,31 @@ long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp) -{ - /* we ignore default asynchrony since we only have one way - * of doing this today. - */ - return 0; -} -long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_AFS_CREATE_MT_PT internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp, char *leaf) { - char leaf[LEAF_SIZE]; - long code; - cm_scache_t *dscp; + afs_int32 code; cm_attr_t tattr; char *cp; - cm_req_t req; char mpInfo[256]; char fullCell[256]; char volume[256]; char cell[256]; int ttl; - cm_InitReq(&req); - - code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf); - if (code) - return code; - /* Translate chars for the mount point name */ - if (!(ioctlp->flags & SMB_IOCTLFLAG_USEUTF8)) { - TranslateExtendedChars(leaf); + if (!(ioctlp->flags & CM_IOCTLFLAG_USEUTF8)) { + TranslateExtendedChars(leaf); } - /* + /* * The fs command allows the user to specify partial cell names on NT. These must * be expanded to the full cell name for mount points so that the mount points will * work on UNIX clients. @@ -2100,7 +1672,6 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0); #endif if (code) { - cm_ReleaseSCache(dscp); return CM_ERROR_NOSUCHCELL; } @@ -2127,7 +1698,7 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) tattr.unixModeBits = 0644; tattr.clientModTime = time(NULL); - code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req); + code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, reqp); } if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) @@ -2135,32 +1706,30 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) FILE_NOTIFY_CHANGE_DIR_NAME, dscp, leaf, NULL, TRUE); - cm_ReleaseSCache(dscp); return code; } -long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_SYMLINK internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlSymlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp, char *leaf) { - char leaf[LEAF_SIZE]; - long code; - cm_scache_t *dscp; + afs_int32 code; cm_attr_t tattr; char *cp; - cm_req_t req; char *symlp; int free_syml = FALSE; - cm_InitReq(&req); - - code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf); - if (code) return code; - - if (!(ioctlp->flags & SMB_IOCTLFLAG_USEUTF8)) { - /* Translate chars for the link name */ - TranslateExtendedChars(leaf); + if (!(ioctlp->flags & CM_IOCTLFLAG_USEUTF8)) { + /* Translate chars for the link name */ + TranslateExtendedChars(leaf); - /* Translate chars for the linked to name */ - TranslateExtendedChars(ioctlp->inDatap); + /* Translate chars for the linked to name */ + TranslateExtendedChars(ioctlp->inDatap); } symlp = ioctlp->inDatap; /* contents of link */ @@ -2210,7 +1779,7 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) tattr.mask = CM_ATTRMASK_UNIXMODEBITS; tattr.unixModeBits = 0755; - code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req); + code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, reqp); } if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) @@ -2219,8 +1788,6 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) | FILE_NOTIFY_CHANGE_DIR_NAME, dscp, leaf, NULL, TRUE); - cm_ReleaseSCache(dscp); - if (free_syml) free(symlp); @@ -2228,26 +1795,30 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) } -long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_LISTSYMLINK internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlListlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp) { - long code; - cm_scache_t *dscp; + afs_int32 code; cm_scache_t *scp; char *cp; cm_space_t *spacep; cm_scache_t *newRootScp; - cm_req_t req; - - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); - if (code) return code; + if (!(ioctlp->flags & CM_IOCTLFLAG_USEUTF8)) { + /* Translate chars for the link name */ + TranslateExtendedChars(ioctlp->inDatap); + } cp = ioctlp->inDatap; - code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); - cm_ReleaseSCache(dscp); - if (code) return code; + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp); + if (code) + return code; /* Check that it's a real symlink */ if (scp->fileType != CM_SCACHETYPE_SYMLINK && @@ -2257,7 +1828,7 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp) return CM_ERROR_INVAL; } - code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req); + code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, reqp); cm_ReleaseSCache(scp); if (code == 0) { cp = ioctlp->outDatap; @@ -2288,25 +1859,29 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; } -long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_ISSYMLINK internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlIslink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp) {/*CHECK FOR VALID SYMLINK*/ - long code; - cm_scache_t *dscp; + afs_int32 code; cm_scache_t *scp; char *cp; - cm_req_t req; - - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); - if (code) return code; + if (!(ioctlp->flags & CM_IOCTLFLAG_USEUTF8)) { + /* Translate chars for the link name */ + TranslateExtendedChars(ioctlp->inDatap); + } cp = ioctlp->inDatap; osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp); - code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); - cm_ReleaseSCache(dscp); - if (code) return code; + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp); + if (code) + return code; /* Check that it's a real symlink */ if (scp->fileType != CM_SCACHETYPE_SYMLINK && @@ -2317,31 +1892,35 @@ long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; } -long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_DELSYMLINK internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp, cm_req_t *reqp) { - long code; - cm_scache_t *dscp; + afs_int32 code; cm_scache_t *scp; char *cp; char * originalName = NULL; - cm_req_t req; cm_dirOp_t dirop; - cm_InitReq(&req); - - code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); - if (code) return code; - + if (!(ioctlp->flags & CM_IOCTLFLAG_USEUTF8)) { + /* Translate chars for the link name */ + TranslateExtendedChars(ioctlp->inDatap); + } cp = ioctlp->inDatap; - code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp); /* if something went wrong, bail out now */ if (code) goto done3; lock_ObtainWrite(&scp->rw); - code = cm_SyncOp(scp, NULL, userp, &req, 0, + code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code) goto done2; @@ -2358,7 +1937,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) lock_ReleaseWrite(&scp->rw); #ifdef USE_BPLUS - code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop); + code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, &dirop); if (code == 0) { code = cm_BPlusDirLookupOriginalName(&dirop, cp, &originalName); /* cm_Dir*() functions can't be used to lookup the original @@ -2389,7 +1968,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) #endif { /* easier to do it this way */ - code = cm_Unlink(dscp, originalName, cp, userp, &req); + code = cm_Unlink(dscp, originalName, cp, userp, reqp); } if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) smb_NotifyChange(FILE_ACTION_REMOVED, @@ -2412,12 +1991,16 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_ReleaseSCache(scp); done3: - cm_ReleaseSCache(dscp); return code; } #ifdef QUERY_AFSID -long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid) +/* Utility function. Not currently used. + * This function performs a PTS lookup which has traditionally + * not been performed by the cache manager. + */ +afs_int32 +cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid) { afs_int32 code; namelist lnames; @@ -2493,7 +2076,13 @@ long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid) } #endif /* QUERY_AFSID */ -long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +#if 0 +/* This has been copied to smb_IoctlSetToken in its entirety. + * An equivalent version will need to be produced for the + * redirector and some extensive refactoring might be required. + */ +afs_int32 +cm_IoctlSetToken(struct cm_ioctl *ioctlp, struct cm_user *userp) { char *saveDataPtr; char *tp; @@ -2614,7 +2203,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) lock_ReleaseMutex(&userp->mx); if (flags & PIOCTL_LOGON) { - ioctlp->flags |= SMB_IOCTLFLAG_LOGON; + ioctlp->flags |= CM_IOCTLFLAG_LOGON; } cm_ResetACLCache(userp); @@ -2624,8 +2213,15 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } +#endif -long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_GETTOK internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetTokenIter(struct cm_ioctl *ioctlp, struct cm_user *userp) { char *tp, *cp; int iterator; @@ -2633,8 +2229,6 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_ucell_t *ucellp; struct ClearToken ct; - cm_SkipIoctlPath(ioctlp); - tp = ioctlp->inDatap; cp = ioctlp->outDatap; @@ -2675,12 +2269,13 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp) /* clear token */ ct.AuthHandle = ucellp->kvno; + /* - * Don't give out a real session key here + * This field is supposed to hold the session key + * but we don't want to make it easier for someone + * to attack the cache. The user gave us the session + * key in the first place. */ - /* - memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey)); - */ memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey)); ct.ViceId = 37; /* XXX */ ct.BeginTimestamp = 0; /* XXX */ @@ -2708,7 +2303,13 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_NEWGETTOK internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetToken(struct cm_ioctl *ioctlp, struct cm_user *userp) { char *cp; int temp; @@ -2717,7 +2318,6 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) struct ClearToken ct; char *tp; afs_uuid_t uuid; - cm_SkipIoctlPath(ioctlp); tp = ioctlp->inDatap; @@ -2755,12 +2355,8 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) /* clear token */ ct.AuthHandle = ucellp->kvno; - /* - * Don't give out a real session key here - */ - /* - memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey)); - */ + + /* do not give out the session key */ memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey)); ct.ViceId = 37; /* XXX */ ct.BeginTimestamp = 0; /* XXX */ @@ -2790,14 +2386,18 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCDELTOK internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlDelToken(struct cm_ioctl *ioctlp, struct cm_user *userp) { char *cp; cm_cell_t *cellp; cm_ucell_t *ucellp; - cm_SkipIoctlPath(ioctlp); - cp = ioctlp->outDatap; /* cell name is right here */ @@ -2834,7 +2434,13 @@ long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOCDELALLTOK internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlDelAllToken(struct cm_ioctl *ioctlp, struct cm_user *userp) { cm_ucell_t *ucellp; @@ -2863,7 +2469,13 @@ long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp) +/* + * VIOC_MAKESUBMOUNT internals. (This function should be deprecated) + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlMakeSubmount(cm_ioctl_t *ioctlp, cm_user_t *userp) { char afspath[MAX_PATH]; char *submountreqp; @@ -2874,8 +2486,6 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp) DWORD dwIndex; DWORD dwSubmounts; - cm_SkipIoctlPath(ioctlp); - /* Serialize this one, to prevent simultaneous mods * to afsdsbmt.ini */ @@ -3038,7 +2648,13 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp) return 0; } -long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp) +/* + * VIOC_GETRXKCRYPT internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlGetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp) { memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall)); ioctlp->outDatap += sizeof(cryptall); @@ -3046,12 +2662,16 @@ long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp) return 0; } -long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp) +/* + * VIOC_SETRXKCRYPT internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlSetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp) { afs_int32 c = cryptall; - cm_SkipIoctlPath(ioctlp); - memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall)); if (c != cryptall) { @@ -3063,13 +2683,17 @@ long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp) return 0; } -long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_RXSTAT_PROC internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlRxStatProcess(struct cm_ioctl *ioctlp, struct cm_user *userp) { afs_int32 flags; int code = 0; - cm_SkipIoctlPath(ioctlp); - memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32)); if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) { return -1; @@ -3086,13 +2710,17 @@ long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_RXSTAT_PEER internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlRxStatPeer(struct cm_ioctl *ioctlp, struct cm_user *userp) { afs_int32 flags; int code = 0; - cm_SkipIoctlPath(ioctlp); - memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32)); if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) { return -1; @@ -3109,27 +2737,19 @@ long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } -long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp) -{ - smb_user_t *uidp = ioctlp->uidp; - - if (uidp && uidp->unp) { - memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name)); - ioctlp->outDatap += strlen(uidp->unp->name); - } - - return 0; -} - -long cm_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp) +/* + * VIOC_UNICODECTL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlUnicodeControl(struct cm_ioctl *ioctlp, struct cm_user * userp) { - long result = 0; + afs_int32 result = 0; #ifdef SMB_UNICODE - long cmd; - - cm_SkipIoctlPath(ioctlp); + afs_uint32 cmd; - memcpy(&cmd, ioctlp->inDatap, sizeof(long)); + memcpy(&cmd, ioctlp->inDatap, sizeof(afs_uint32)); if (cmd & 2) { /* Setting the Unicode flag */ @@ -3151,14 +2771,18 @@ long cm_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp) return 0; } -long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp) +/* + * VIOC_UUIDCTL internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlUUIDControl(struct cm_ioctl * ioctlp, struct cm_user *userp) { - long cmd; + afs_uint32 cmd; afsUUID uuid; - cm_SkipIoctlPath(ioctlp); - - memcpy(&cmd, ioctlp->inDatap, sizeof(long)); + memcpy(&cmd, ioctlp->inDatap, sizeof(afs_uint32)); if (cmd) { /* generate a new UUID */ UuidCreate((UUID *) &uuid); @@ -3182,9 +2806,16 @@ extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock); extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock); extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock); -long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_TRACEMEMDUMP internals. + * + * Assumes that pioctl path has been parsed or skipped. + * dscp is held but not locked. + */ +afs_int32 +cm_IoctlMemoryDump(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long inValue = 0; + afs_int32 inValue = 0; HANDLE hLogFile; char logfileName[MAX_PATH+1]; char *cookie; @@ -3194,8 +2825,7 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp) static _CrtMemState memstate; #endif - cm_SkipIoctlPath(ioctlp); - memcpy(&inValue, ioctlp->inDatap, sizeof(long)); + memcpy(&inValue, ioctlp->inDatap, sizeof(afs_int32)); dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName)); if ( dwSize == 0 || dwSize > sizeof(logfileName) ) @@ -3210,8 +2840,8 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp) { /* error */ inValue = -1; - memcpy(ioctlp->outDatap, &inValue, sizeof(long)); - ioctlp->outDatap += sizeof(long); + memcpy(ioctlp->outDatap, &inValue, sizeof(afs_int32)); + ioctlp->outDatap += sizeof(afs_int32); return 0; } @@ -3252,11 +2882,11 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp) return 0; } - -static long +/* Utility functon. Not currently used. */ +static afs_int32 cm_CheckServersStatus(cm_serverRef_t *serversp) { - long code = 0; + afs_int32 code = 0; cm_serverRef_t *tsrp; cm_server_t *tsp; int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1; @@ -3304,41 +2934,24 @@ cm_CheckServersStatus(cm_serverRef_t *serversp) return code; } - -long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_PATH_AVAILABILITY internals. + * + * Assumes that pioctl path has been parsed or skipped. + * scp is held but not locked. + */ +afs_int32 +cm_IoctlPathAvailability(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) { - long code; - cm_scache_t *scp; + afs_int32 code; cm_cell_t *cellp; cm_volume_t *tvp; cm_vol_state_t *statep; afs_uint32 volume; - cm_req_t req; - cm_ioctlQueryOptions_t *optionsp; - afs_uint32 flags = 0; - - cm_InitReq(&req); - - optionsp = cm_IoctlGetQueryOptions(ioctlp, userp); - if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) - flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); - - if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { - cm_fid_t fid; - cm_SkipIoctlPath(ioctlp); - cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, - optionsp->fid.vnode, optionsp->fid.unique); - code = cm_GetSCache(&fid, &scp, userp, &req); - } else { - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); - } - if (code) - return code; #ifdef AFS_FREELANCE_CLIENT if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) { code = 0; - cm_ReleaseSCache(scp); } else #endif { @@ -3346,12 +2959,10 @@ long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp) cellp = cm_FindCellByID(scp->fid.cell, 0); - cm_ReleaseSCache(scp); - if (!cellp) return CM_ERROR_NOSUCHCELL; - code = cm_FindVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp); + code = cm_FindVolumeByID(cellp, volume, userp, reqp, CM_GETVOL_FLAG_CREATE, &tvp); if (code) return code; @@ -3376,20 +2987,24 @@ long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; } - -long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp) +/* + * VIOC_VOLSTAT_TEST internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ +afs_int32 +cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp) { - long code; + afs_int32 code; cm_cell_t *cellp = NULL; cm_volume_t *volp; cm_vol_state_t *statep; struct VolStatTest * testp; - cm_req_t req; afs_uint32 n; + cm_req_t req; cm_InitReq(&req); - cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ testp = (struct VolStatTest *)ioctlp->inDatap; #ifdef AFS_FREELANCE_CLIENT diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index 934959a..bb188f2 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -11,7 +11,6 @@ #define __CM_IOCTL_H_ENV__ 1 #ifndef __CM_IOCTL_INTERFACES_ONLY__ -#include "smb.h" #include "cm_user.h" #else typedef struct cm_fid { @@ -52,6 +51,28 @@ typedef struct cm_cacheParms { afs_uint64 parms[CM_IOCTLCACHEPARMS]; } cm_cacheParms_t; +typedef struct cm_ioctl { + /* input side */ + char *inDatap; /* ioctl func's current position + * in input parameter block */ + char *inAllocp; /* allocated input parameter block */ + afs_uint32 inCopied; /* # of input bytes copied in so far + * by write calls */ + /* output side */ + char *outDatap; /* output results assembled so far */ + char *outAllocp; /* output results assembled so far */ + afs_uint32 outCopied; /* # of output bytes copied back so far + + /* flags */ + afs_uint32 flags; +} cm_ioctl_t; + +/* flags for smb_ioctl_t */ +#define CM_IOCTLFLAG_DATAIN 1 /* reading data from client to server */ +#define CM_IOCTLFLAG_LOGON 2 /* got tokens from integrated logon */ +#define CM_IOCTLFLAG_USEUTF8 4 /* this request is using UTF-8 strings */ + + /* * The cm_IoctlQueryOptions structure is designed to be extendible. * None of the fields are required but when specified @@ -106,6 +127,9 @@ extern char * cm_sysNameList[MAXNUMSYSNAMES]; strings. */ #define UTF8_PREFIX "\33%G" +extern const char utf8_prefix[]; +extern const int utf8_prefix_size; + /* flags for rxstats pioctl */ #define AFSCALL_RXSTATS_MASK 0x7 /* Valid flag bits */ @@ -115,121 +139,129 @@ extern char * cm_sysNameList[MAXNUMSYSNAMES]; #ifndef __CM_IOCTL_INTERFACES_ONLY__ -void cm_InitIoctl(void); +extern void cm_InitIoctl(void); + +extern void cm_ResetACLCache(cm_user_t *userp); + +extern cm_ioctlQueryOptions_t * cm_IoctlGetQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp); + +extern void cm_IoctlSkipQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp); + +extern void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp); -void cm_ResetACLCache(cm_user_t *userp); +extern void cm_SkipIoctlPath(cm_ioctl_t *ioctlp); -extern long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlGetFileCellName(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetFileCellName(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlFlushAllVolumes(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlFlushAllVolumes(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlFlushVolume(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlFlushVolume(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlFlushFile(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlFlushFile(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlSetVolumeStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetVolumeStatus(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlGetVolumeStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetVolumeStatus(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlGetFid(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetFid(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlGetOwner(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetOwner(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlWhereIs(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlWhereIs(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlStatMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlStatMountPoint(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlDeleteMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlDeleteMountPoint(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlCheckServers(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlCheckServers(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGag(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGag(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlCheckVolumes(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlCheckVolumes(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSetCacheSize(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetCacheSize(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetCacheParms(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetCacheParms(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetCell(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetCell(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlNewCell(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlNewCell(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSysName(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSysName(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetCellStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetCellStatus(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSetCellStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetCellStatus(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSetSPrefs(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetSPrefs(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetSPrefs(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetSPrefs(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlStoreBehind(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlStoreBehind(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlCreateMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlCreateMountPoint(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *dscp, cm_req_t *reqp, char *leaf); -extern long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); +extern afs_int32 cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); -extern long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); +extern afs_int32 cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); -extern long cm_FlushVolume(cm_user_t *, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume); +extern afs_int32 cm_FlushVolume(cm_user_t *, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume); -extern long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); +extern afs_int32 cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); -extern long cm_IoctlTraceControl(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlTraceControl(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSetToken(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetToken(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetTokenIter(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetTokenIter(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetToken(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetToken(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlDelToken(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlDelToken(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlDelAllToken(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlDelAllToken(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSymlink(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSymlink(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *dscp, cm_req_t *reqp, char *leaf); -extern long cm_IoctlIslink(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlIslink(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlListlink(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlListlink(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp); -extern long cm_IoctlDeletelink(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlDeletelink(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *dscp, cm_req_t *reqp); -extern long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlMakeSubmount(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlSetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlShutdown(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlFreemountAddCell(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlFreemountAddCell(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlFreemountRemoveCell(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlFreemountRemoveCell(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlMemoryDump(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlMemoryDump(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlRxStatProcess(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlRxStatProcess(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlRxStatPeer(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlRxStatPeer(cm_ioctl_t *ioctlp, cm_user_t *userp); -extern long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp); +extern afs_int32 cm_IoctlUUIDControl(struct cm_ioctl * ioctlp, struct cm_user *userp); -extern long cm_IoctlPathAvailability(struct smb_ioctl * ioctlp, struct cm_user *userp); +extern afs_int32 cm_IoctlPathAvailability(struct cm_ioctl * ioctlp, struct cm_user *userp, struct cm_scache *scp, struct cm_req *reqp); -extern long cm_IoctlGetFileType(smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 cm_IoctlGetFileType(cm_ioctl_t *ioctlp, cm_user_t *userp, struct cm_scache *scp, struct cm_req *reqp); -extern long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp); +extern afs_int32 cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp); -extern long cm_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp); +extern afs_int32 cm_IoctlUnicodeControl(struct cm_ioctl *ioctlp, struct cm_user * userp); #endif /* __CM_IOCTL_INTERFACES_ONLY__ */ diff --git a/src/WINNT/afsd/cm_user.c b/src/WINNT/afsd/cm_user.c index d901692..117d51a 100644 --- a/src/WINNT/afsd/cm_user.c +++ b/src/WINNT/afsd/cm_user.c @@ -15,6 +15,7 @@ #include #include "afsd.h" +#include "smb.h" #include #include diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 8d53361..7116555 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -21,6 +21,7 @@ #include #include "afsd.h" +#include "smb.h" #include "cm_btree.h" #ifdef DEBUG diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 9ef5047..91fff17 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1510,10 +1510,10 @@ void smb_ReleaseFID(smb_fid_t *fidp) if (ioctlp) { if (ioctlp->prefix) cm_FreeSpace(ioctlp->prefix); - if (ioctlp->inAllocp) - free(ioctlp->inAllocp); - if (ioctlp->outAllocp) - free(ioctlp->outAllocp); + if (ioctlp->ioctl.inAllocp) + free(ioctlp->ioctl.inAllocp); + if (ioctlp->ioctl.outAllocp) + free(ioctlp->ioctl.outAllocp); free(ioctlp); } lock_ReleaseMutex(&fidp->mx); diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 8718ea4..abb6f69 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -318,38 +318,9 @@ typedef struct smb_pid { struct smb_tid *tidp; /* back ptr */ } smb_pid_t; -/* ioctl parameter, while being assembled and/or processed */ -typedef struct smb_ioctl { - /* input side */ - char *inDatap; /* ioctl func's current position - * in input parameter block */ - char *inAllocp; /* allocated input parameter block */ - afs_uint32 inCopied; /* # of input bytes copied in so far - * by write calls */ - cm_space_t *prefix; /* prefix for subst drives */ - char *tidPathp; /* Pathname associated with Tree ID */ - - /* output side */ - char *outDatap; /* output results assembled so far */ - char *outAllocp; /* output results assembled so far */ - afs_uint32 outCopied; /* # of output bytes copied back so far - * by read calls */ - - /* flags */ - afs_uint32 flags; - - /* fid pointer */ - struct smb_fid *fidp; - - /* uid pointer */ - smb_user_t *uidp; - -} smb_ioctl_t; - -/* flags for smb_ioctl_t */ -#define SMB_IOCTLFLAG_DATAIN 1 /* reading data from client to server */ -#define SMB_IOCTLFLAG_LOGON 2 /* got tokens from integrated logon */ -#define SMB_IOCTLFLAG_USEUTF8 4 /* this request is using UTF-8 strings */ + +/* Defined in smb_ioctl.h */ +struct smb_ioctl; /* one per file ID; these are really file descriptors */ typedef struct smb_fid { @@ -365,7 +336,7 @@ typedef struct smb_fid { the file if session is terminated) */ osi_hyper_t offset; /* our file pointer */ - smb_ioctl_t *ioctlp; /* ptr to ioctl structure */ + struct smb_ioctl *ioctlp; /* ptr to ioctl structure */ /* Under NT, we may need to know the * parent directory and pathname used * to open the file, either to delete @@ -563,6 +534,8 @@ extern smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags); extern smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags); +extern cm_user_t *smb_FindCMUserByName(char *usern, char *machine, afs_uint32 flags); + extern smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern); extern void smb_ReleaseUsername(smb_username_t *unp); diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index 8f73dac..f44d8a2 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -21,7 +21,7 @@ typedef struct chservinfo { } chservinfo_t; struct gaginfo { - unsigned long showflags, logflags, logwritethruflag, spare[3]; + afs_uint32 showflags, logflags, logwritethruflag, spare[3]; unsigned char spare2[128]; }; @@ -97,5 +97,13 @@ struct sbstruct { #define VIOC_UNICODECTL 0x33 #define VIOC_VOLSTAT_TEST 0x3F -/* Not to exceed SMB_IOCTL_MAXPROCS from smb_ioctl.h */ + +/* magic file name for ioctl opens */ +#define CM_IOCTL_FILENAME "\\_._AFS_IOCTL_._" /* double backslashes for C compiler */ +#define CM_IOCTL_FILENAME_NOSLASH "_._AFS_IOCTL_._" + +/* max parms for ioctl, in either direction */ +#define CM_IOCTL_MAXDATA 8192*2 +#define CM_IOCTL_MAXPROCS 64 + #endif /* __SMB_IOCONS_H_ENV_ */ diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 76a9d25..7729816 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -23,70 +24,74 @@ #include "smb.h" +#include "cm_rpc.h" +#include "afs/afsrpc.h" +#include "afs/auth.h" + smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS]; -/*extern unsigned char smb_LANadapter;*/ - -void smb_InitIoctl(void) -{ - int i; - for (i=0; idata, prefix->data); + StringCbCopy(copyPrefix->data, CM_UTILS_SPACESIZE, prefix->data); fidp->ioctlp->prefix = copyPrefix; } lock_ReleaseMutex(&fidp->mx); @@ -113,22 +118,23 @@ void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix) * this is the first read call. This is the function that actually makes the * call to the ioctl code. */ -long smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp) +afs_int32 +smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp) { - long opcode; + afs_int32 opcode; smb_ioctlProc_t *procp = NULL; - long code; + afs_int32 code; - if (ioctlp->flags & SMB_IOCTLFLAG_DATAIN) { - ioctlp->flags &= ~SMB_IOCTLFLAG_DATAIN; + if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) { + ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN; /* do the call now, or fail if we didn't get an opcode, or * enough of an opcode. */ - if (ioctlp->inCopied < sizeof(long)) + if (ioctlp->ioctl.inCopied < sizeof(afs_int32)) return CM_ERROR_INVAL; - memcpy(&opcode, ioctlp->inDatap, sizeof(long)); - ioctlp->inDatap += sizeof(long); + memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32)); + ioctlp->ioctl.inDatap += sizeof(afs_int32); osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode); @@ -142,13 +148,13 @@ long smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp return CM_ERROR_BADOP; /* otherwise, make the call */ - ioctlp->outDatap += sizeof(long); /* reserve room for return code */ + ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */ code = (*procp)(ioctlp, userp); osi_Log1(afsd_logp, "Ioctl return code 0x%x", code); /* copy in return code */ - memcpy(ioctlp->outAllocp, &code, sizeof(long)); + memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32)); } return 0; } @@ -157,176 +163,183 @@ long smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp * a series of reads (or the very first call), then we start a new call. * We also ensure that things are properly initialized for the start of a call. */ -void smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp) -{ - /* make sure the buffer(s) are allocated */ - if (!ioctlp->inAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA); - if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA); - - /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */ - (void) memset(ioctlp->inAllocp, 0, SMB_IOCTL_MAXDATA); - (void) memset(ioctlp->outAllocp, 0, SMB_IOCTL_MAXDATA); - - /* and make sure that we've reset our state for the new incoming request */ - if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) { - ioctlp->inCopied = 0; - ioctlp->outCopied = 0; - ioctlp->inDatap = ioctlp->inAllocp; - ioctlp->outDatap = ioctlp->outAllocp; - ioctlp->flags |= SMB_IOCTLFLAG_DATAIN; - } -} +void +smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp) +{ + /* make sure the buffer(s) are allocated */ + if (!ioctlp->ioctl.inAllocp) + ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA); + if (!ioctlp->ioctl.outAllocp) + ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA); + + /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */ + (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA); + (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA); + + /* and make sure that we've reset our state for the new incoming request */ + if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) { + ioctlp->ioctl.inCopied = 0; + ioctlp->ioctl.outCopied = 0; + ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp; + ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp; + ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN; + } +} /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */ -long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, - smb_packet_t *outp) +afs_int32 +smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_ioctl_t *iop; - long count; - long leftToCopy; - char *op; - long code; - cm_user_t *userp; + smb_ioctl_t *iop; + long count; + afs_int32 leftToCopy; + char *op; + afs_int32 code; + cm_user_t *userp; - iop = fidp->ioctlp; - count = smb_GetSMBParm(inp, 1); - userp = smb_GetUserFromVCP(vcp, inp); + iop = fidp->ioctlp; + count = smb_GetSMBParm(inp, 1); + userp = smb_GetUserFromVCP(vcp, inp); - /* Identify tree */ + /* Identify tree */ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); if(code) { cm_ReleaseUser(userp); return CM_ERROR_NOSUCHPATH; } - /* turn the connection around, if required */ - code = smb_IoctlPrepareRead(fidp, iop, userp); + /* turn the connection around, if required */ + code = smb_IoctlPrepareRead(fidp, iop, userp); + + if (code) { + cm_ReleaseUser(userp); + return code; + } + + leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied); + if (count > leftToCopy) + count = leftToCopy; - if (code) { - cm_ReleaseUser(userp); - return code; - } + /* now set the parms for a read of count bytes */ + smb_SetSMBParm(outp, 0, count); + smb_SetSMBParm(outp, 1, 0); + smb_SetSMBParm(outp, 2, 0); + smb_SetSMBParm(outp, 3, 0); + smb_SetSMBParm(outp, 4, 0); - leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied); - if (count > leftToCopy) count = leftToCopy; - - /* now set the parms for a read of count bytes */ - smb_SetSMBParm(outp, 0, count); - smb_SetSMBParm(outp, 1, 0); - smb_SetSMBParm(outp, 2, 0); - smb_SetSMBParm(outp, 3, 0); - smb_SetSMBParm(outp, 4, 0); + smb_SetSMBDataLength(outp, count+3); - smb_SetSMBDataLength(outp, count+3); + op = smb_GetSMBData(outp, NULL); + *op++ = 1; + *op++ = (char)(count & 0xff); + *op++ = (char)((count >> 8) & 0xff); - op = smb_GetSMBData(outp, NULL); - *op++ = 1; - *op++ = (char)(count & 0xff); - *op++ = (char)((count >> 8) & 0xff); - - /* now copy the data into the response packet */ - memcpy(op, iop->outCopied + iop->outAllocp, count); + /* now copy the data into the response packet */ + memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count); - /* and adjust the counters */ - iop->outCopied += count; - - cm_ReleaseUser(userp); + /* and adjust the counters */ + iop->ioctl.outCopied += count; + + cm_ReleaseUser(userp); - return 0; + return 0; } /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL * file descriptor. */ -long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +afs_int32 +smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_ioctl_t *iop; - long count; - long code; - char *op; - int inDataBlockCount; + smb_ioctl_t *iop; + long count; + afs_int32 code; + char *op; + int inDataBlockCount; - code = 0; - count = smb_GetSMBParm(inp, 1); - iop = fidp->ioctlp; + code = 0; + count = smb_GetSMBParm(inp, 1); + iop = fidp->ioctlp; - smb_IoctlPrepareWrite(fidp, iop); + smb_IoctlPrepareWrite(fidp, iop); - op = smb_GetSMBData(inp, NULL); - op = smb_ParseDataBlock(op, NULL, &inDataBlockCount); + op = smb_GetSMBData(inp, NULL); + op = smb_ParseDataBlock(op, NULL, &inDataBlockCount); - if (count + iop->inCopied > SMB_IOCTL_MAXDATA) { - code = CM_ERROR_TOOBIG; - goto done; - } + if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) { + code = CM_ERROR_TOOBIG; + goto done; + } - /* copy data */ - memcpy(iop->inDatap + iop->inCopied, op, count); + /* copy data */ + memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count); - /* adjust counts */ - iop->inCopied += count; - -done: - /* return # of bytes written */ - if (code == 0) { - smb_SetSMBParm(outp, 0, count); - smb_SetSMBDataLength(outp, 0); - } + /* adjust counts */ + iop->ioctl.inCopied += count; - return code; -} + done: + /* return # of bytes written */ + if (code == 0) { + smb_SetSMBParm(outp, 0, count); + smb_SetSMBDataLength(outp, 0); + } + + return code; +} /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL * file descriptor. */ -long smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +afs_int32 +smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_ioctl_t *iop; - long count; - long code; - char *op; - int inDataBlockCount; + smb_ioctl_t *iop; + long count; + afs_int32 code; + char *op; + int inDataBlockCount; - code = 0; - count = smb_GetSMBParm(inp, 10); - iop = fidp->ioctlp; - - smb_IoctlPrepareWrite(fidp, iop); + code = 0; + count = smb_GetSMBParm(inp, 10); + iop = fidp->ioctlp; - op = inp->data + smb_GetSMBParm(inp, 11); - inDataBlockCount = count; - - if (count + iop->inCopied > SMB_IOCTL_MAXDATA) { - code = CM_ERROR_TOOBIG; - goto done; - } - - /* copy data */ - memcpy(iop->inDatap + iop->inCopied, op, count); + smb_IoctlPrepareWrite(fidp, iop); + + op = inp->data + smb_GetSMBParm(inp, 11); + inDataBlockCount = count; + + if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) { + code = CM_ERROR_TOOBIG; + goto done; + } - /* adjust counts */ - iop->inCopied += count; - -done: - /* return # of bytes written */ - if (code == 0) { - smb_SetSMBParm(outp, 2, count); - smb_SetSMBParm(outp, 3, 0); /* reserved */ - smb_SetSMBParm(outp, 4, 0); /* reserved */ - smb_SetSMBParm(outp, 5, 0); /* reserved */ - smb_SetSMBDataLength(outp, 0); - } + /* copy data */ + memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count); + + /* adjust counts */ + iop->ioctl.inCopied += count; + + done: + /* return # of bytes written */ + if (code == 0) { + smb_SetSMBParm(outp, 2, count); + smb_SetSMBParm(outp, 3, 0); /* reserved */ + smb_SetSMBParm(outp, 4, 0); /* reserved */ + smb_SetSMBParm(outp, 5, 0); /* reserved */ + smb_SetSMBDataLength(outp, 0); + } - return code; -} + return code; +} /* called from V3 read to handle IOCTL descriptor reads */ -long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +afs_int32 +smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_ioctl_t *iop; long count; - long code; + afs_int32 code; long leftToCopy; char *op; cm_user_t *userp; @@ -341,8 +354,8 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack iop->uidp = uidp; if (uidp && uidp->unp) { osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", - uidp->userID, userp, - osi_LogSaveString(afsd_logp, uidp->unp->name)); + uidp->userID, userp, + osi_LogSaveString(afsd_logp, uidp->unp->name)); } else { if (uidp) osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", @@ -370,8 +383,9 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack return code; } - leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied); - if (count > leftToCopy) count = leftToCopy; + leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied); + if (count > leftToCopy) + count = leftToCopy; /* 0 and 1 are reserved for request chaining, were setup by our caller, * and will be further filled in after we return. @@ -399,10 +413,10 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack smb_SetSMBDataLength(outp, count); /* now copy the data into the response packet */ - memcpy(op, iop->outCopied + iop->outAllocp, count); + memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count); /* and adjust the counters */ - iop->outCopied += count; + iop->ioctl.outCopied += count; /* and cleanup things */ cm_ReleaseUser(userp); @@ -411,53 +425,49 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack } /* called from Read Raw to handle IOCTL descriptor reads */ -long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, - smb_packet_t *outp - ) +afs_int32 +smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, + smb_packet_t *outp) { smb_ioctl_t *iop; long leftToCopy; NCB *ncbp; - long code; + afs_int32 code; cm_user_t *userp; + smb_user_t *uidp; iop = fidp->ioctlp; userp = smb_GetUserFromVCP(vcp, inp); /* Log the user */ - { - smb_user_t *uidp; - - uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); - if (uidp && uidp->unp) { - osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", - uidp->userID, userp, - osi_LogSaveString(afsd_logp, uidp->unp->name)); - } else if (uidp) { - osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", - uidp->userID, userp); - } else { - osi_Log1(afsd_logp, "Ioctl no uid user %x no name", - userp); - } - if (uidp) - smb_ReleaseUID(uidp); - } + uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); + if (uidp && uidp->unp) { + osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", + uidp->userID, userp, + osi_LogSaveString(afsd_logp, uidp->unp->name)); + } else if (uidp) { + osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", + uidp->userID, userp); + } else { + osi_Log1(afsd_logp, "Ioctl no uid user %x no name", + userp); + } + if (uidp) + smb_ReleaseUID(uidp); code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); if (code) { - cm_ReleaseUser(userp); - return CM_ERROR_NOSUCHPATH; + code = CM_ERROR_NOSUCHPATH; + goto done; } code = smb_IoctlPrepareRead(fidp, iop, userp); if (code) { - cm_ReleaseUser(userp); - return code; + goto done; } - leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied); + leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied); ncbp = outp->ncbp; memset((char *)ncbp, 0, sizeof(NCB)); @@ -468,13 +478,1317 @@ long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, /*ncbp->ncb_lana_num = smb_LANadapter;*/ ncbp->ncb_lana_num = vcp->lana; - ncbp->ncb_buffer = iop->outCopied + iop->outAllocp; + ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp; code = Netbios(ncbp); if (code != 0) osi_Log1(afsd_logp, "ReadRaw send failure code %d", code); + done: cm_ReleaseUser(userp); + return code; +} + +/* parse the passed-in file name and do a namei on it. If we fail, + * return an error code, otherwise return the vnode located in *scpp. + */ +#define CM_PARSE_FLAG_LITERAL 1 + +afs_int32 +smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, + cm_scache_t **scpp, afs_uint32 flags) +{ + afs_int32 code; + cm_scache_t *substRootp = NULL; + cm_scache_t *iscp = NULL; + char * relativePath; + char * lastComponent = NULL; + afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW); + int free_path = FALSE; + + relativePath = ioctlp->ioctl.inDatap; + /* setup the next data value for the caller to use */ + ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;; + + osi_Log1(afsd_logp, "smb_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath)); + + /* This is usually the file name, but for StatMountPoint it is the path. */ + /* ioctlp->inDatap can be either of the form: + * \path\. + * \path\file + * \\netbios-name\submount\path\. + * \\netbios-name\submount\path\file + */ + + /* We do not perform path name translation on the ioctl path data + * because these paths were not translated by Windows through the + * file system API. Therefore, they are not OEM characters but + * whatever the display character set is. + */ + + // TranslateExtendedChars(relativePath); + + /* This is usually nothing, but for StatMountPoint it is the file name. */ + // TranslateExtendedChars(ioctlp->ioctl.inDatap); + + /* If the string starts with our UTF-8 prefix (which is the + sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 + strings), we assume that the provided path is UTF-8. Otherwise + we have to convert the string to UTF-8, since that is what we + want to use everywhere else.*/ + + if (memcmp(relativePath, utf8_prefix, utf8_prefix_size) == 0) { + int len, normalized_len; + char * normalized_path; + + /* String is UTF-8 */ + relativePath += utf8_prefix_size; + ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8; + + len = (ioctlp->ioctl.inDatap - relativePath); + + normalized_len = cm_NormalizeUtf8String(relativePath, len, NULL, 0); + + if (normalized_len > len) { + normalized_path = malloc(normalized_len); + free_path = TRUE; + } else { + normalized_path = relativePath; + } + + cm_NormalizeUtf8String(relativePath, len, normalized_path, normalized_len); + + if (normalized_path != relativePath) + relativePath = normalized_path; + } else { + /* Not a UTF-8 string */ + /* TODO: If this is an OEM string, we should convert it to + UTF-8. */ + } + + if (relativePath[0] == relativePath[1] && + relativePath[1] == '\\' && + !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName))) + { + char shareName[256]; + char *sharePath; + int shareFound, i; + + /* We may have found a UNC path. + * If the first component is the NetbiosName, + * then throw out the second component (the submount) + * since it had better expand into the value of ioctl->tidPathp + */ + char * p; + p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */ + if ( !_strnicmp("all", p, 3) ) + p += 4; + + for (i = 0; *p && *p != '\\'; i++,p++ ) { + shareName[i] = *p; + } + p++; /* skip past trailing slash */ + shareName[i] = 0; /* terminate string */ + + shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath); + if ( shareFound ) { + /* we found a sharename, therefore use the resulting path */ + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, sharePath, reqp, &substRootp); + free(sharePath); + if (code) { + osi_Log1(afsd_logp,"smb_ParseIoctlPath [1] code 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + + lastComponent = strrchr(p, '\\'); + if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) { + *lastComponent = '\0'; + lastComponent++; + + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, &iscp); + if (code == 0) + code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, + userp, NULL, reqp, scpp); + if (iscp) + cm_ReleaseSCache(iscp); + } else { + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD, + userp, NULL, reqp, scpp); + } + cm_ReleaseSCache(substRootp); + if (code) { + osi_Log1(afsd_logp,"smb_ParseIoctlPath [2] code 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + } else { + /* otherwise, treat the name as a cellname mounted off the afs root. + * This requires that we reconstruct the shareName string with + * leading and trailing slashes. + */ + p = relativePath + 2 + strlen(cm_NetbiosName) + 1; + if ( !_strnicmp("all", p, 3) ) + p += 4; + + shareName[0] = '/'; + for (i = 1; *p && *p != '\\'; i++,p++ ) { + shareName[i] = *p; + } + p++; /* skip past trailing slash */ + shareName[i++] = '/'; /* add trailing slash */ + shareName[i] = 0; /* terminate string */ + + + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, shareName, reqp, &substRootp); + if (code) { + osi_Log1(afsd_logp,"smb_ParseIoctlPath [3] code 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + + lastComponent = strrchr(p, '\\'); + if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) { + *lastComponent = '\0'; + lastComponent++; + + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, &iscp); + if (code == 0) + code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, + userp, NULL, reqp, scpp); + if (iscp) + cm_ReleaseSCache(iscp); + } else { + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD, + userp, NULL, reqp, scpp); + } + + if (code) { + cm_ReleaseSCache(substRootp); + osi_Log1(afsd_logp,"smb_ParseIoctlPath code [4] 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + } + } else { + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, ioctlp->tidPathp, reqp, &substRootp); + if (code) { + osi_Log1(afsd_logp,"smb_ParseIoctlPath [6] code 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + + lastComponent = strrchr(relativePath, '\\'); + if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) { + *lastComponent = '\0'; + lastComponent++; + + code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, &iscp); + if (code == 0) + code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow, + userp, NULL, reqp, scpp); + if (iscp) + cm_ReleaseSCache(iscp); + } else { + code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow, + userp, NULL, reqp, scpp); + } + if (code) { + cm_ReleaseSCache(substRootp); + osi_Log1(afsd_logp,"smb_ParseIoctlPath [7] code 0x%x", code); + if (free_path) + free(relativePath); + return code; + } + } + + if (substRootp) + cm_ReleaseSCache(substRootp); + + /* and return success */ + osi_Log1(afsd_logp,"smb_ParseIoctlPath [8] code 0x%x", code); + + if (free_path) + free(relativePath); + return 0; +} + + + +#define LEAF_SIZE 256 +/* parse the passed-in file name and do a namei on its parent. If we fail, + * return an error code, otherwise return the vnode located in *scpp. + */ +afs_int32 +smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, + cm_scache_t **scpp, char *leafp) +{ + afs_int32 code; + char tbuffer[1024]; + char *tp, *jp; + cm_scache_t *substRootp = NULL; + char *inpathp; + int free_path = FALSE; + + inpathp = ioctlp->ioctl.inDatap; + + /* If the string starts with our UTF-8 prefix (which is the + sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 + strings), we assume that the provided path is UTF-8. Otherwise + we have to convert the string to UTF-8, since that is what we + want to use everywhere else.*/ + + if (memcmp(inpathp, utf8_prefix, utf8_prefix_size) == 0) { + int len, normalized_len; + char * normalized_path; + + /* String is UTF-8 */ + inpathp += utf8_prefix_size; + ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8; + + len = strlen(inpathp) + 1; + + normalized_len = cm_NormalizeUtf8String(inpathp, len, NULL, 0); + + if (normalized_len > len) { + normalized_path = malloc(normalized_len); + free_path = TRUE; + } else { + normalized_path = inpathp; + } + + cm_NormalizeUtf8String(inpathp, len, normalized_path, normalized_len); + + if (normalized_path != inpathp) + inpathp = normalized_path; + } else { + /* Not a UTF-8 string */ + /* TODO: If this is an OEM string, we should convert it to + UTF-8. */ + } + + StringCbCopyA(tbuffer, sizeof(tbuffer), inpathp); + tp = strrchr(tbuffer, '\\'); + jp = strrchr(tbuffer, '/'); + if (!tp) + tp = jp; + else if (jp && (tp - tbuffer) < (jp - tbuffer)) + tp = jp; + if (!tp) { + StringCbCopyA(tbuffer, sizeof(tbuffer), "\\"); + if (leafp) + StringCbCopyA(leafp, LEAF_SIZE, inpathp); + } + else { + *tp = 0; + if (leafp) + StringCbCopyA(leafp, LEAF_SIZE, tp+1); + } + + if (free_path) + free(inpathp); + inpathp = NULL; /* We don't need this from this point on */ + + if (free_path) + free(inpathp); + inpathp = NULL; /* We don't need this from this point on */ + + if (tbuffer[0] == tbuffer[1] && + tbuffer[1] == '\\' && + !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName))) + { + char shareName[256]; + char *sharePath; + int shareFound, i; + + /* We may have found a UNC path. + * If the first component is the NetbiosName, + * then throw out the second component (the submount) + * since it had better expand into the value of ioctl->tidPathp + */ + char * p; + p = tbuffer + 2 + strlen(cm_NetbiosName) + 1; + if ( !_strnicmp("all", p, 3) ) + p += 4; + + for (i = 0; *p && *p != '\\'; i++,p++ ) { + shareName[i] = *p; + } + p++; /* skip past trailing slash */ + shareName[i] = 0; /* terminate string */ + + shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath); + if ( shareFound ) { + /* we found a sharename, therefore use the resulting path */ + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, sharePath, reqp, &substRootp); + free(sharePath); + if (code) return code; + + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, scpp); + cm_ReleaseSCache(substRootp); + if (code) return code; + } else { + /* otherwise, treat the name as a cellname mounted off the afs root. + * This requires that we reconstruct the shareName string with + * leading and trailing slashes. + */ + p = tbuffer + 2 + strlen(cm_NetbiosName) + 1; + if ( !_strnicmp("all", p, 3) ) + p += 4; + + shareName[0] = '/'; + for (i = 1; *p && *p != '\\'; i++,p++ ) { + shareName[i] = *p; + } + p++; /* skip past trailing slash */ + shareName[i++] = '/'; /* add trailing slash */ + shareName[i] = 0; /* terminate string */ + + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, shareName, reqp, &substRootp); + if (code) return code; + + code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, scpp); + cm_ReleaseSCache(substRootp); + if (code) return code; + } + } else { + code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data, + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, ioctlp->tidPathp, reqp, &substRootp); + if (code) return code; + + code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, NULL, reqp, scpp); + cm_ReleaseSCache(substRootp); + if (code) return code; + } + + /* # of bytes of path */ + code = (long)strlen(ioctlp->ioctl.inDatap) + 1; + ioctlp->ioctl.inDatap += code; + + /* and return success */ + return 0; +} + +afs_int32 +smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + char *saveDataPtr; + char *tp; + int ticketLen; + char *ticket; + int ctSize; + struct ClearToken ct; + cm_cell_t *cellp; + cm_ucell_t *ucellp; + char *uname = NULL; + afs_uuid_t uuid; + int flags; + char sessionKey[8]; + char *smbname; + int release_userp = 0; + char * wdir = NULL; + + saveDataPtr = ioctlp->ioctl.inDatap; + + cm_SkipIoctlPath(&ioctlp->ioctl); + + tp = ioctlp->ioctl.inDatap; + + /* ticket length */ + memcpy(&ticketLen, tp, sizeof(ticketLen)); + tp += sizeof(ticketLen); + if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN) + return CM_ERROR_INVAL; + + /* remember ticket and skip over it for now */ + ticket = tp; + tp += ticketLen; + + /* clear token size */ + memcpy(&ctSize, tp, sizeof(ctSize)); + tp += sizeof(ctSize); + if (ctSize != sizeof(struct ClearToken)) + return CM_ERROR_INVAL; + + /* clear token */ + memcpy(&ct, tp, ctSize); + tp += ctSize; + if (ct.AuthHandle == -1) + ct.AuthHandle = 999; /* more rxvab compat stuff */ + + /* more stuff, if any */ + if (ioctlp->ioctl.inCopied > tp - saveDataPtr) { + /* flags: logon flag */ + memcpy(&flags, tp, sizeof(int)); + tp += sizeof(int); + + /* cell name */ + cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE); + if (!cellp) + return CM_ERROR_NOSUCHCELL; + tp += strlen(tp) + 1; + + /* user name */ + uname = tp; + tp += strlen(tp) + 1; + + if (flags & PIOCTL_LOGON) { + /* SMB user name with which to associate tokens */ + smbname = tp; + osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]", + osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname)); + fprintf(stderr, "SMB name = %s\n", smbname); + tp += strlen(tp) + 1; + } else { + osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]", + osi_LogSaveString(smb_logp, uname)); + } + + /* uuid */ + memcpy(&uuid, tp, sizeof(uuid)); + if (!cm_FindTokenEvent(uuid, sessionKey)) + return CM_ERROR_INVAL; + } else { + cellp = cm_data.rootCellp; + osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified"); + } + + if (flags & PIOCTL_LOGON) { + userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname, + SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON); + release_userp = 1; + } + + /* store the token */ + lock_ObtainMutex(&userp->mx); + ucellp = cm_GetUCell(userp, cellp); + osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp); + ucellp->ticketLen = ticketLen; + if (ucellp->ticketp) + free(ucellp->ticketp); /* Discard old token if any */ + ucellp->ticketp = malloc(ticketLen); + memcpy(ucellp->ticketp, ticket, ticketLen); + /* + * Get the session key from the RPC, rather than from the pioctl. + */ + /* + memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey)); + */ + memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey)); + ucellp->kvno = ct.AuthHandle; + ucellp->expirationTime = ct.EndTimestamp; + ucellp->gen++; +#ifdef QUERY_AFSID + ucellp->uid = ANONYMOUSID; +#endif + if (uname) { + StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname); +#ifdef QUERY_AFSID + cm_UsernameToId(uname, ucellp, &ucellp->uid); +#endif + } + ucellp->flags |= CM_UCELLFLAG_RXKAD; + lock_ReleaseMutex(&userp->mx); + + if (flags & PIOCTL_LOGON) { + ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON; + } + + cm_ResetACLCache(userp); + + if (release_userp) + cm_ReleaseUser(userp); + + return 0; +} + + + +afs_int32 +smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp) +{ + smb_user_t *uidp = ioctlp->uidp; + + if (uidp && uidp->unp) { + memcpy(ioctlp->ioctl.outDatap, uidp->unp->name, strlen(uidp->unp->name)); + ioctlp->ioctl.outDatap += strlen(uidp->unp->name); + } + + return 0; +} + +afs_int32 +smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) +{ + cm_scache_t *scp; + afs_int32 code; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + return code; +} + +afs_int32 +smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) +{ + cm_scache_t *scp; + afs_int32 code; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + return code; +} + +afs_int32 +smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */ + + return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + return code; +} + +afs_int32 +smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0); + if (code) return code; + + code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req); + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + cm_req_t req; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t * optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + if (code) + return code; + + code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t * optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + +afs_int32 +smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} + + +afs_int32 +smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); + if (code) + return code; + + code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req); + + cm_ReleaseSCache(dscp); + + return code; +} + +afs_int32 +smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); + if (code) + return code; + + code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req); + + cm_ReleaseSCache(dscp); + + return code; +} + +afs_int32 +smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */ + + return cm_IoctlCheckServers(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + /* we don't print anything superfluous, so we don't support the gag call */ + return CM_ERROR_INVAL; +} + +afs_int32 +smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp); +} + +afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlTraceControl(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetCell(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlNewCell(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetWsCell(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlSysName(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + /* we ignore default asynchrony since we only have one way + * of doing this today. + */ return 0; +} + +afs_int32 +smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + char leaf[LEAF_SIZE]; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf); + if (code) + return code; + + code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf); + + cm_ReleaseSCache(dscp); + return code; +} + +afs_int32 +smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + char leaf[LEAF_SIZE]; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf); + if (code) return code; + + code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf); + + cm_ReleaseSCache(dscp); + + return code; +} + +afs_int32 +smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); + if (code) return code; + + code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req); + + cm_ReleaseSCache(dscp); + return code; +} + +afs_int32 +smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp) +{/*CHECK FOR VALID SYMLINK*/ + afs_int32 code; + cm_scache_t *dscp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); + if (code) return code; + + code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req); + + cm_ReleaseSCache(dscp); + + return code; +} + +afs_int32 +smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *dscp; + cm_req_t req; + + cm_InitReq(&req); + + code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0); + if (code) return code; + + code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req); + + cm_ReleaseSCache(dscp); + + return code; +} + +afs_int32 +smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetToken(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlDelToken(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlDelAllToken(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlUUIDControl(&ioctlp->ioctl, userp); +} + + +afs_int32 +smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlMemoryDump(&ioctlp->ioctl, userp); +} + +afs_int32 +smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t *optionsp; + afs_uint32 flags = 0; + + cm_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req); + cm_ReleaseSCache(scp); + return code; +} + +afs_int32 +smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + cm_SkipIoctlPath(&ioctlp->ioctl); + + return cm_IoctlVolStatTest(&ioctlp->ioctl, userp); } diff --git a/src/WINNT/afsd/smb_ioctl.h b/src/WINNT/afsd/smb_ioctl.h index ce7f3b1..a9f0c82 100644 --- a/src/WINNT/afsd/smb_ioctl.h +++ b/src/WINNT/afsd/smb_ioctl.h @@ -10,33 +10,179 @@ #ifndef __SMB_IOCTL_H_ENV__ #define __SMB_IOCTL_H_ENV__ 1 +#include + /* magic file name for ioctl opens */ -#define SMB_IOCTL_FILENAME "\\_._AFS_IOCTL_._" /* double backslashes for C compiler */ -#define SMB_IOCTL_FILENAME_NOSLASH "_._AFS_IOCTL_._" +#define SMB_IOCTL_FILENAME CM_IOCTL_FILENAME +#define SMB_IOCTL_FILENAME_NOSLASH CM_IOCTL_FILENAME_NOSLASH /* max parms for ioctl, in either direction */ -#define SMB_IOCTL_MAXDATA 8192*2 +#define SMB_IOCTL_MAXDATA CM_IOCTL_MAXDATA +#define SMB_IOCTL_MAXPROCS CM_IOCTL_MAXPROCS + +struct smb_fid; +struct smb_user; +struct smb_vc; + +/* ioctl parameter, while being assembled and/or processed */ +typedef struct smb_ioctl { + /* fid pointer */ + struct smb_fid *fidp; + + /* uid pointer */ + struct smb_user *uidp; + + /* pathname associated with the Tree ID */ + char *tidPathp; -#define SMB_IOCTL_MAXPROCS 64 /* max # of calls */ + /* prefix for subst drives */ + cm_space_t *prefix; + + cm_ioctl_t ioctl; +} smb_ioctl_t; /* procedure implementing an ioctl */ typedef long (smb_ioctlProc_t)(smb_ioctl_t *, struct cm_user *userp); extern void smb_InitIoctl(void); -extern void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix); +extern void smb_SetupIoctlFid(struct smb_fid *fidp, cm_space_t *prefix); + +extern afs_int32 smb_IoctlRead(struct smb_fid *fidp, struct smb_vc *vcp, struct smb_packet *inp, struct smb_packet *outp); + +extern afs_int32 smb_IoctlWrite(struct smb_fid *fidp, struct smb_vc *vcp, struct smb_packet *inp, struct smb_packet *outp); + +extern afs_int32 smb_IoctlV3Write(struct smb_fid *fidp, struct smb_vc *vcp, struct smb_packet *inp, struct smb_packet *outp); + +extern afs_int32 smb_IoctlV3Read(struct smb_fid *fidp, struct smb_vc *vcp, struct smb_packet *inp, struct smb_packet *outp); + +extern afs_int32 smb_IoctlReadRaw(struct smb_fid *fidp, struct smb_vc *vcp, struct smb_packet *inp, + struct smb_packet *outp); + +extern long smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 +smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, cm_scache_t **scpp, afs_uint32 flags); + +extern afs_int32 +smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, cm_scache_t **scpp, char *leafp); + +extern afs_int32 +smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp); + +extern afs_int32 +smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetFileCellName(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlFlushAllVolumes(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlFlushVolume(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlFlushFile(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetVolumeStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetVolumeStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetFid(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetOwner(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlWhereIs(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlStatMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlDeleteMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlCheckServers(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGag(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlCheckVolumes(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetCacheSize(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetCacheParms(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetCell(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlNewCell(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSysName(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetCellStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetCellStatus(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetSPrefs(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetSPrefs(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlStoreBehind(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlCreateMountPoint(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); + +extern afs_int32 cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); + +extern afs_int32 cm_FlushVolume(cm_user_t *, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume); + +extern afs_int32 cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); + +extern afs_int32 smb_IoctlTraceControl(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetToken(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetTokenIter(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetToken(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlDelToken(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlDelAllToken(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSymlink(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlIslink(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlListlink(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlDeletelink(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlFreemountAddCell(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlFreemountRemoveCell(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlMemoryDump(smb_ioctl_t *ioctlp, cm_user_t *userp); + +extern afs_int32 smb_IoctlRxStatProcess(smb_ioctl_t *ioctlp, cm_user_t *userp); -extern long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); +extern afs_int32 smb_IoctlRxStatPeer(smb_ioctl_t *ioctlp, cm_user_t *userp); -extern long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); +extern afs_int32 smb_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp); -extern long smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); +extern afs_int32 smb_IoctlPathAvailability(struct smb_ioctl * ioctlp, struct cm_user *userp); -extern long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); +extern afs_int32 smb_IoctlGetFileType(smb_ioctl_t *ioctlp, cm_user_t *userp); -extern long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, - smb_packet_t *outp); +extern afs_int32 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp); -extern long smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp); +extern afs_int32 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp); #endif /* __SMB_IOCTL_H_ENV__ */