/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include "stdafx.h" #include #include extern "C" { #include #include #include #include } #include #include #include "gui2fs.h" #include "msgs.h" #include "results_dlg.h" #include "volume_inf.h" #include "mount_points_dlg.h" #include "symlinks_dlg.h" #include "hourglass.h" #include "down_servers_dlg.h" extern "C" { #include #include "fs_utils.h" #include "fs_acl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include } #define STRSAFE_NO_DEPRECATE #include /* * the NO_CALLER symbol is used to document functions * that are present in this file but have no caller */ #define NO_CALLER #define PCCHAR(str) ((char *)(const char *)(str)) #define VL_NOENT (363524L) #define MAXNAME 100 #define MAXINSIZE 1300 /* pioctl complains if data is larger than this */ #define VMSGSIZE 128 /* size of msg buf in volume hdr */ #define MAXCELLCHARS 64 #define MAXHOSTCHARS 64 #define MAXHOSTSPERCELL 8 static struct ubik_client *uclient; static int rxInitDone = 0; static char pn[] = "fs"; // #define LOGGING_ON // Enable this to log certain pioctl calls #ifdef LOGGING_ON static char *szLogFileName = "afsguilog.txt"; #endif #ifdef UNICODE class CStringUtf8 : public CStringA { public: CStringUtf8(const CStringW& csw) : CStringA() { SetString(csw); } CStringUtf8(const char * cp) : CStringA(cp) {} CStringUtf8() :CStringA() {} void SetString(const CStringW& csw) { char buffer[1024]; int rv; rv = WideCharToMultiByte(CP_UTF8, 0, csw, -1, buffer, sizeof(buffer), NULL, FALSE); if (rv != 0) { CStringA::SetString(buffer); } else { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { int cb_req; cb_req = WideCharToMultiByte(CP_UTF8, 0, csw, -1, NULL, 0, NULL, FALSE); if (cb_req != 0) { cb_req ++; WideCharToMultiByte(CP_UTF8, 0, csw, -1, CStringA::GetBuffer(cb_req), cb_req, NULL, FALSE); CStringA::ReleaseBuffer(); } } else { #ifdef DEBUG DebugBreak(); #endif } } } static CString _Utf8ToCString(const char * ustr) { CString cs; int cch; cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, NULL, 0); if (cch == 0) { cs.Empty(); return cs; } cch++; cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, cs.GetBuffer(cch), cch); cs.ReleaseBuffer(); return cs; } }; long pioctl_T(const CString& path, long opcode, struct ViceIoctl * blob, int follow) { CStringUtf8 upath(path); return pioctl_utf8(PCCHAR(upath), opcode, blob, follow); } #define Utf8ToCString(cs) CStringUtf8::_Utf8ToCString(cs) #else #define pioctl_T(path, op, vblob, follow) pioctl(PCCHAR(path), op, vblob, follow) #define Utf8ToCString(cs) (cs) #endif static int NO_CALLER VLDBInit(int noAuthFlag, struct afsconf_cell *info) { afs_int32 code; code = ugen_ClientInit(noAuthFlag, (char *)AFSDIR_CLIENT_ETC_DIRPATH, info->name, 0, &uclient, NULL, pn, rxkad_clear, VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50, 0, 0, USER_SERVICE_ID); rxInitDone = 1; return code; } static FILE * OpenFile(char *file, char *rwp) { char wdir[256]; long code; long tlen; FILE *fp; code = GetWindowsDirectoryA(wdir, sizeof(wdir)); if (code == 0 || code > sizeof(wdir)) return FALSE; /* add trailing backslash, if required */ tlen = strlen(wdir); if (wdir[tlen - 1] != '\\') strcat(wdir, "\\"); strcat(wdir, file); fp = fopen(wdir, rwp); return fp; } CString StripPath(const CString& strPath) { int nIndex = strPath.ReverseFind('\\'); CString strFile = strPath.Mid(nIndex + 1); if (strFile.IsEmpty()) return strPath; return strFile; } CStringArray& StripPath(CStringArray& files) { for (int i = 0; i < files.GetSize(); i++) files[i] = StripPath(files[i]); return files; } void Flush(const CStringArray& files) { LONG code; struct ViceIoctl blob; int error = 0; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { blob.in_size = blob.out_size = 0; code = pioctl_T(files[i], VIOCFLUSH, &blob, 0); if (code) { error = 1; if (errno == EMFILE) ShowMessageBox(IDS_FLUSH_FAILED, MB_ICONERROR, IDS_FLUSH_FAILED, files[i]); else ShowMessageBox(IDS_FLUSH_ERROR, MB_ICONERROR, IDS_FLUSH_ERROR, files[i], strerror(errno)); } } if (!error) ShowMessageBox(IDS_FLUSH_OK, MB_ICONINFORMATION, IDS_FLUSH_OK); } void FlushVolume(const CStringArray& files) { LONG code; struct ViceIoctl blob; int error = 0; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { blob.in_size = blob.out_size = 0; code = pioctl_T(files[i], VIOC_FLUSHVOLUME, &blob, 0); if (code) { error = 1; ShowMessageBox(IDS_FLUSH_VOLUME_ERROR, MB_ICONERROR, IDS_FLUSH_VOLUME_ERROR, files[i], strerror(errno)); } } if (!code) ShowMessageBox(IDS_FLUSH_VOLUME_OK, MB_ICONINFORMATION, IDS_FLUSH_VOLUME_OK); } void NO_CALLER WhichCell(CStringArray& files) { LONG code; struct ViceIoctl blob; int error; CString str; CString str2; CStringArray results; error = 0; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { char space[AFS_PIOCTL_MAXSIZE]; blob.in_size = 0; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; code = pioctl_T(files[i], VIOC_FILE_CELL_NAME, &blob, 1); if (code) { if (code == ENOENT) { LoadString (str, IDS_CANT_GET_CELL); results.Add(str); } else results.Add(GetAfsError(errno)); } else { space[AFS_PIOCTL_MAXSIZE - 1] = '\0'; results.Add(Utf8ToCString(space)); } } LoadString (str, IDS_SHOW_CELL); LoadString (str2, IDS_SHOW_CELL_COLUMN); CResultsDlg dlg(SHOW_CELL_HELP_ID); dlg.SetContents(str, str2, StripPath(files), results); dlg.DoModal(); } void NO_CALLER WSCellCmd(void) { char space[AFS_PIOCTL_MAXSIZE]; LONG code; struct ViceIoctl blob; HOURGLASS hourglass; blob.in_size = 0; blob.in = (char *) 0; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; code = pioctl((char *) 0, VIOC_GET_WS_CELL, &blob, 1); /* * Cell name is left in 'space' as side effect. * At present no callers of this function. */ } BOOL NO_CALLER CheckVolumes(void) { LONG code; struct ViceIoctl blob; blob.in_size = 0; blob.out_size = 0; code = pioctl(0, VIOCCKBACK, &blob, 1); if (code) { ShowMessageBox(IDS_CHECK_VOLUMES_ERROR, MB_ICONERROR, IDS_CHECK_VOLUMES_ERROR, GetAfsError(errno, CString())); return FALSE; } ShowMessageBox(IDS_CHECK_VOLUMES_OK, MB_OK|MB_ICONINFORMATION, IDS_CHECK_VOLUMES_OK); return TRUE; } void NO_CALLER SetCacheSizeCmd(LONG nNewCacheSize) { LONG code; struct ViceIoctl blob; HOURGLASS hourglass; blob.in = (char *) &nNewCacheSize; blob.in_size = sizeof(LONG); blob.out_size = 0; code = pioctl(0, VIOCSETCACHESIZE, &blob, 1); /* error handling? */ } void NO_CALLER WhereIs(CStringArray& files) { LONG code; struct ViceIoctl blob; CStringArray servers; CStringArray resultFiles; CString str; CString str2; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { char space[AFS_PIOCTL_MAXSIZE]; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; memset(space, 0, sizeof(space)); code = pioctl_T(files[i], VIOCWHEREIS, &blob, 1); if (code) { resultFiles.Add(StripPath(files[i])); servers.Add(GetAfsError(errno)); continue; } LONG *hosts = (LONG *)space; BOOL bFirst = TRUE; str = ""; for (int j = 0; j < AFS_MAXHOSTS; j++) { if (hosts[j] == 0) break; char *hostName = hostutil_GetNameByINet(hosts[j]); if (bFirst) { resultFiles.Add(StripPath(files[i])); bFirst = FALSE; } else resultFiles.Add(" "); servers.Add(hostName); } } LoadString (str, IDS_SHOW_FS); LoadString (str2, IDS_SHOW_FS_COLUMN); CResultsDlg dlg(SHOW_FILE_SERVERS_HELP_ID); dlg.SetContents(str, str2, resultFiles, servers); dlg.DoModal(); } static int CMtoUNIXerror(int cm_code) { switch (cm_code) { case CM_ERROR_TIMEDOUT: return ETIMEDOUT; case CM_ERROR_NOACCESS: return EACCES; case CM_ERROR_NOSUCHFILE: return ENOENT; case CM_ERROR_INVAL: return EINVAL; case CM_ERROR_BADFD: return EBADF; case CM_ERROR_EXISTS: return EEXIST; case CM_ERROR_CROSSDEVLINK: return EXDEV; case CM_ERROR_NOTDIR: return ENOTDIR; case CM_ERROR_ISDIR: return EISDIR; case CM_ERROR_READONLY: return EROFS; case CM_ERROR_WOULDBLOCK: return EWOULDBLOCK; case CM_ERROR_NOSUCHCELL: return ESRCH; /* hack */ case CM_ERROR_NOSUCHVOLUME: return EPIPE; /* hack */ case CM_ERROR_NOMORETOKENS: return EDOM; /* hack */ case CM_ERROR_TOOMANYBUFS: return EFBIG; /* hack */ default: if (cm_code > 0 && cm_code < EILSEQ) return cm_code; else return ENOTTY; } } CString GetAfsError(int code, const TCHAR *filename) { CString strMsg; code = CMtoUNIXerror(code); if (code == EINVAL) { if (filename) strMsg.Format(_T("Invalid argument; it is possible that the file is not in AFS")); else strMsg.Format(_T("Invalid argument")); } else if (code == ENOENT) { if (filename) strMsg.Format(_T("The file does not exist")); else strMsg.Format(_T("No such file returned")); } else if (code == EROFS) { strMsg.Format(_T("You can not change a backup or readonly volume")); } else if (code == EACCES || code == EPERM) { strMsg.Format(_T("You do not have the required rights to do this operation")); } else if (code == ENODEV) { strMsg.Format(_T("AFS service may not have started")); } else if (code == ESRCH) { strMsg.Format(_T("Cell name not recognized")); } else if (code == ETIMEDOUT) { strMsg.Format(_T("Connection timed out")); } else if (code == EPIPE) { strMsg.Format(_T("Volume name or ID not recognized")); } else { strMsg.Format(_T("Error 0x%x occurred"), code); } return strMsg; } static int foldcmp (char *a, char *b) { char t, u; while (1) { t = *a++; u = *b++; if (t >= 'A' && t <= 'Z') t += 0x20; if (u >= 'A' && u <= 'Z') u += 0x20; if (t != u) return 1; if (t == 0) return 0; } } CString GetRightsString(LONG arights, int dfs) { CString str; if (!dfs) { if (arights & PRSFS_READ) str += _T("r"); if (arights & PRSFS_LOOKUP) str += _T("l"); if (arights & PRSFS_INSERT) str += _T("i"); if (arights & PRSFS_DELETE) str += _T("d"); if (arights & PRSFS_WRITE) str += _T("w"); if (arights & PRSFS_LOCK) str += _T("k"); if (arights & PRSFS_ADMINISTER) str += _T("a"); } else { ASSERT(FALSE); /* if (arights & DFS_READ) str += _T("r"); else str += _T("-"); if (arights & DFS_WRITE) str += _T("w"); else printf(_T("-")); if (arights & DFS_EXECUTE) str += _T("x"); else printf(_T("-")); if (arights & DFS_CONTROL) str += _T("c"); else printf(_T("-")); if (arights & DFS_INSERT) str += _T("i"); else printf(_T("-")); if (arights & DFS_DELETE) str += _T("d"); else printf(_T("-")); if (arights & (DFS_USRALL)) str += _T("+"); */ } return str; } struct Acl * EmptyAcl(const CString& strCellName) { struct Acl *tp; CStringUtf8 ustrCell(strCellName); tp = (struct Acl *)malloc(sizeof (struct Acl)); tp->nplus = tp->nminus = 0; tp->pluslist = tp->minuslist = 0; tp->dfs = 0; StringCbCopyA(tp->cell, sizeof(tp->cell), ustrCell); return tp; } void CleanACL(CStringArray& names) { LONG code; struct Acl *ta; struct ViceIoctl blob; int changes; ShowMessageBox(IDS_CLEANACL_MSG, MB_OK|MB_ICONINFORMATION, IDS_CLEANACL_MSG); HOURGLASS hourglass; for (int i = 0; i < names.GetSize(); i++) { char space[AFS_PIOCTL_MAXSIZE]; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; code = pioctl_T(names[i], VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno)); continue; } ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE); if (ta == NULL) { ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA); continue; } if (ta->dfs) { ShowMessageBox(IDS_CLEANACL_NOT_SUPPORTED, MB_ICONERROR, IDS_CLEANACL_NOT_SUPPORTED, names[i]); continue; } changes = CleanAcl(ta, NULL); if (!changes) continue; /* now set the acl */ blob.in = AclToString(ta); blob.in_size = strlen((char *)blob.in) + 1; blob.out_size = 0; code = pioctl_T(names[i], VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { ShowMessageBox(IDS_CLEANACL_INVALID_ARG, MB_ICONERROR, IDS_CLEANACL_INVALID_ARG, names[i]); continue; } else { ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno)); continue; } } } } // Derived from fs.c's ListAclCmd BOOL GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& strNegative) { LONG code; struct Acl *ta; struct ViceIoctl blob; struct AclEntry *te; int idf = 0; //getidf(as, parm_listacl_id); char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; code = pioctl_T(strDir, VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_GETRIGHTS_ERROR, MB_ICONERROR, IDS_GETRIGHTS_ERROR, strDir, GetAfsError(errno)); return FALSE; } ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE); if (ta == NULL) { ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA); return FALSE; } if (ta->dfs) { ShowMessageBox(IDS_DFSACL_ERROR, MB_ICONERROR, IDS_DFSACL_ERROR); return FALSE; } // if (ta->dfs) // printf(" Default cell = %s\n", ta->cell); CString strRight; if (ta->nplus > 0) { for (te = ta->pluslist; te; te = te->next) { strNormal.Add(te->name); strNormal.Add(GetRightsString(te->rights, ta->dfs)); } } if (ta->nminus > 0) { for (te = ta->minuslist; te; te = te->next) { strNegative.Add(te->name); strNegative.Add(GetRightsString(te->rights, ta->dfs)); } } return TRUE; } struct AclEntry * FindList(struct AclEntry *pCurEntry, const char *entryName) { while (pCurEntry) { if (!foldcmp(pCurEntry->name, PCCHAR(entryName))) return pCurEntry; pCurEntry = pCurEntry->next; } return 0; } void ChangeList(struct Acl *pAcl, BYTE bNormalRights, const CString & entryName, LONG nEntryRights) { ASSERT(pAcl); ASSERT(entryName); struct AclEntry *pEntry; CStringUtf8 uEntryName(entryName); HOURGLASS hourglass; pEntry = (bNormalRights ? pAcl->pluslist : pAcl->minuslist); pEntry = FindList(pEntry, uEntryName); /* Found the item already in the list. */ if (pEntry) { pEntry->rights = nEntryRights; if (bNormalRights) pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs); else pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs); return; } /* Otherwise we make a new item and plug in the new data. */ pEntry = (struct AclEntry *) malloc(sizeof (struct AclEntry)); ASSERT(pEntry); strcpy(pEntry->name, uEntryName); pEntry->rights = nEntryRights; if (bNormalRights) { pEntry->next = pAcl->pluslist; pAcl->pluslist = pEntry; pAcl->nplus++; if (nEntryRights == 0 || nEntryRights == -1) pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs); } else { pEntry->next = pAcl->minuslist; pAcl->minuslist = pEntry; pAcl->nminus++; if (nEntryRights == 0) pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs); } } static LONG Convert(const CString& strRights, int dfs, enum rtype *rtypep) { int i, len; LONG mode; *rtypep = add; /* add rights, by default */ if (strRights == _T("read")) return PRSFS_READ | PRSFS_LOOKUP; if (strRights == _T("write")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK; if (strRights == _T("mail")) return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP; if (strRights == _T("all")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER; if (strRights == _T("none")) { *rtypep = destroy; /* Remove entire entry */ return 0; } len = strRights.GetLength(); mode = 0; for (i = 0; i < len; i++) { TCHAR c = strRights[i]; if (c == _T('r')) mode |= PRSFS_READ; else if (c == _T('l')) mode |= PRSFS_LOOKUP; else if (c == _T('i')) mode |= PRSFS_INSERT; else if (c == _T('d')) mode |= PRSFS_DELETE; else if (c == _T('w')) mode |= PRSFS_WRITE; else if (c == _T('k')) mode |= PRSFS_LOCK; else if (c == _T('a')) mode |= PRSFS_ADMINISTER; else { fprintf(stderr, "illegal rights character '%c'.\n", c); exit(1); } } return mode; } BOOL SaveACL(const CString& strCellName, const CString& strDir, const CStringArray& normal, const CStringArray& negative) { LONG code; struct ViceIoctl blob; struct Acl *pAcl; LONG rights; enum rtype rtype; HOURGLASS hourglass; // Create a new ACL pAcl = EmptyAcl(strCellName); // Set its normal rights int i; for (i = 0; i < normal.GetSize(); i += 2) { rights = Convert(normal[i + 1], 0, &rtype); ChangeList(pAcl, TRUE, normal[i], rights); } // Set its negative rights for (i = 0; i < negative.GetSize(); i += 2) { rights = Convert(negative[i + 1], 0, &rtype); ChangeList(pAcl, FALSE, negative[i], rights); } // Write the ACL blob.in = AclToString(pAcl); blob.out_size = 0; blob.in_size = 1 + strlen((const char *)blob.in); code = pioctl_T(strDir, VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) ShowMessageBox(IDS_SAVE_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_EINVAL_ERROR, strDir); else ShowMessageBox(IDS_SAVE_ACL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_ERROR, strDir, GetAfsError(errno, strDir)); } ZapAcl(pAcl); return (code == 0); } BOOL CopyACL(const CString& strToDir, const CStringArray& normal, const CStringArray& negative, BOOL bClear) { LONG code; struct ViceIoctl blob; struct Acl *pToAcl; int idf = 0; // getidf(as, parm_copyacl_id); char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; // Get ACL to copy to blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; code = pioctl_T(strToDir, VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_ACL_READ_ERROR, MB_ICONERROR, IDS_ACL_READ_ERROR, strToDir, GetAfsError(errno, strToDir)); return FALSE; } if (bClear) pToAcl = EmptyAcl(space); else pToAcl = ParseAcl(space, AFS_PIOCTL_MAXSIZE); if (pToAcl == NULL) { ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA); return FALSE; } CleanAcl(pToAcl, NULL); if (pToAcl->dfs) { ShowMessageBox(IDS_NO_DFS_COPY_ACL, MB_ICONERROR, IDS_NO_DFS_COPY_ACL, strToDir); ZapAcl(pToAcl); return FALSE; } enum rtype rtype; // Set normal rights int i; for (i = 0; i < normal.GetSize(); i += 2) { LONG rights = Convert(normal[i + 1], 0, &rtype); ChangeList(pToAcl, TRUE, normal[i], rights); } // Set negative rights for (i = 0; i < negative.GetSize(); i += 2) { LONG rights = Convert(negative[i + 1], 0, &rtype); ChangeList(pToAcl, FALSE, normal[i], rights); } // Save modified ACL blob.in = AclToString(pToAcl); blob.out_size = 0; blob.in_size = 1 + strlen((char *)blob.in); code = pioctl_T(strToDir, VIOCSETAL, &blob, 1); if (code) { ZapAcl(pToAcl); if (errno == EINVAL) ShowMessageBox(IDS_COPY_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_COPY_ACL_EINVAL_ERROR, strToDir); else ShowMessageBox(IDS_COPY_ACL_ERROR, MB_ICONERROR, IDS_COPY_ACL_ERROR, strToDir, GetAfsError(errno, strToDir)); return FALSE; } ZapAcl(pToAcl); ShowMessageBox(IDS_COPY_ACL_OK, MB_OK|MB_ICONINFORMATION, IDS_COPY_ACL_OK); return TRUE; } CString ParseMountPoint(const CString strFile, CString strMountPoint) { CString strType; CString strVolume; CString strCell; CString strMountPointInfo; if (strMountPoint[0] == '#') strType = "Regular"; else if (strMountPoint[0] == '%') strType = "Read/Write"; int nColon = strMountPoint.Find(':'); if (nColon >= 0) { strCell = strMountPoint.Mid(1, nColon - 1); strVolume = strMountPoint.Mid(nColon + 1); } else { strVolume = strMountPoint.Mid(1); strCell = _T("(local)"); } strMountPointInfo = _T("=> ") + strVolume + _T(" : ") + strCell + _T(" cell [") + strType + _T("]"); return strMountPointInfo; } CString ParseSymlink(const CString strFile, CString strSymlink) { CString strSymlinkInfo; strSymlinkInfo = _T("-> ") + strSymlink; return strSymlinkInfo; } BOOL GetFID(const CString& path, CString& fidstring, BOOL bLiteral) { struct ViceIoctl blob; cm_ioctlQueryOptions_t options; cm_fid_t fid; int code; memset(&options, 0, sizeof(options)); options.size = sizeof(options); options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL; options.literal = bLiteral ? 1 : 0; blob.in_size = options.size; /* no variable length data */ blob.in = &options; blob.out_size = sizeof(cm_fid_t); blob.out = (char *) &fid; code = pioctl_T(path, VIOCGETFID, &blob, 1); fidstring.Empty(); if (code == 0) { fidstring.Format( TEXT("%lu.%lu.%lu"), fid.volume, fid.vnode, fid.unique); return TRUE; } return FALSE; } BOOL IsPathInAfs(const CString & strPath) { struct ViceIoctl blob; cm_ioctlQueryOptions_t options; cm_fid_t fid; int code; HOURGLASS hourglass; memset(&options, 0, sizeof(options)); options.size = sizeof(options); options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL; options.literal = 1; blob.in_size = options.size; /* no variable length data */ blob.in = &options; blob.out_size = sizeof(cm_fid_t); blob.out = (char *) &fid; code = pioctl_T(strPath, VIOCGETFID, &blob, 1); if (code) { if ((errno == EINVAL) || (errno == ENOENT)) return FALSE; } return TRUE; } static int IsFreelanceRoot(const CString& apath) { struct ViceIoctl blob; afs_int32 code; char space[AFS_PIOCTL_MAXSIZE]; blob.in_size = 0; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; code = pioctl_T(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code == 0) return !strcmp("Freelance.Local.Root",space); return 1; /* assume it is because it is more restrictive that way */ } static const char * NetbiosName(void) { static char buffer[1024] = "AFS"; HKEY parmKey; DWORD code; DWORD dummyLen; DWORD enabled = 0; code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey); if (code == ERROR_SUCCESS) { dummyLen = sizeof(buffer); code = RegQueryValueExA(parmKey, "NetbiosName", NULL, NULL, (LPBYTE)buffer, &dummyLen); RegCloseKey (parmKey); } else { strcpy(buffer, "AFS"); } return buffer; } static void FixNetbiosPath(CString& path) { if (!IsPathInAfs(path)) { CString nbroot; const char * nbname = NetbiosName(); nbroot.Format(_T("\\\\%s\\"), nbname); if (nbroot.CompareNoCase(path) == 0) { path.Append(_T("all\\")); } } } #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins" static BOOL IsAdmin (void) { static BOOL fAdmin = FALSE; static BOOL fTested = FALSE; if (!fTested) { /* Obtain the SID for the AFS client admin group. If the group does * not exist, then assume we have AFS client admin privileges. */ PSID psidAdmin = NULL; DWORD dwSize, dwSize2; TCHAR pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ]; TCHAR *pszRefDomain = NULL; SID_NAME_USE snu = SidTypeGroup; dwSize = sizeof(pszAdminGroup); if (!GetComputerName(pszAdminGroup, &dwSize)) { /* Can't get computer name. We return false in this case. Retain fAdmin and fTested. This shouldn't happen.*/ return FALSE; } dwSize = 0; dwSize2 = 0; lstrcat(pszAdminGroup, _T("\\")); lstrcat(pszAdminGroup, _T(AFSCLIENT_ADMIN_GROUPNAME)); LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu); /* that should always fail. */ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { /* if we can't find the group, then we allow the operation */ fAdmin = TRUE; return TRUE; } if (dwSize == 0 || dwSize2 == 0) { /* Paranoia */ fAdmin = TRUE; return TRUE; } psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize); pszRefDomain = (TCHAR *)malloc(dwSize2); if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) { /* We can't lookup the group now even though we looked it up earlier. Could this happen? */ fAdmin = TRUE; } else { /* Then open our current ProcessToken */ HANDLE hToken; if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken)) { if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) { /* We'll have to allocate a chunk of memory to store the list of * groups to which this user belongs; find out how much memory * we'll need. */ DWORD dwSize = 0; PTOKEN_GROUPS pGroups; GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize); pGroups = (PTOKEN_GROUPS)malloc(dwSize); /* Allocate that buffer, and read in the list of groups. */ if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize)) { /* Look through the list of group SIDs and see if any of them * matches the AFS Client Admin group SID. */ size_t iGroup = 0; for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup) { if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) { fAdmin = TRUE; } } } if (pGroups) free(pGroups); } /* if do not have permission because we were not explicitly listed * in the Admin Client Group let's see if we are the SYSTEM account */ if (!fAdmin) { PTOKEN_USER pTokenUser; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; PSID pSidLocalSystem = 0; DWORD gle; GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); pTokenUser = (PTOKEN_USER)malloc(dwSize); if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) gle = GetLastError(); if (AllocateAndInitializeSid( &SIDAuth, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidLocalSystem)) { if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) { fAdmin = TRUE; } FreeSid(pSidLocalSystem); } if ( pTokenUser ) free(pTokenUser); } } } free(psidAdmin); free(pszRefDomain); fTested = TRUE; } return fAdmin; } CString Parent(const CString& path) { int last_slash = path.ReverseFind(_T('\\')); if (last_slash != -1) { CString ret = path.Left(last_slash + 1); return ret; } else { if (path.GetLength() >= 2 && path[1] == _T(':')) { CString ret = path.Left(2); ret.AppendChar(_T('.')); return ret; } else { CString ret = _T("."); return ret; } } } CString LastComponent(const CString& path) { int last_slash = path.ReverseFind(_T('\\')); if (last_slash != -1) { CString ret = path.Mid(last_slash + 1); return ret; } else { if (path.GetLength() >= 2 && path[1] == _T(':')) { CString ret = path.Mid(2); return ret; } else { CString ret = path; return ret; } } } static CString GetCell(const CString & path, BOOL bFollow = TRUE); static CString GetCell(const CString & path, BOOL bFollow) { char cellname[MAXCELLCHARS]; afs_int32 code; struct ViceIoctl blob; blob.in_size = 0; blob.out_size = sizeof(cellname); blob.out = cellname; code = pioctl_T(path, VIOC_FILE_CELL_NAME, &blob, 1); if (code) { CString s; s.Empty(); return s; } else { return Utf8ToCString(cellname); } } BOOL ListMount(CStringArray& files) { LONG code; struct ViceIoctl blob; int error; CString parent_dir; /* Parent directory of true name */ CStringUtf8 last_component; /* Last component of true name */ CStringArray mountPoints; HOURGLASS hourglass; error = 0; for (int i = 0; i < files.GetSize(); i++) { int last_slash = files[i].ReverseFind(_T('\\')); char space[AFS_PIOCTL_MAXSIZE]; if (last_slash != -1) { last_component.SetString( files[i].Mid(last_slash + 1) ); parent_dir.SetString( files[i].Left(last_slash + 1) ); FixNetbiosPath(parent_dir); } else { // The path is of the form "C:foo" or just "foo". If // there is a drive, then use the current directory of // that drive. Otherwise we just use '.'. if (files[i].GetLength() >= 2 && files[i][1] == _T(':')) { parent_dir.Format(_T("%c:."), files[i][0]); last_component.SetString( files[i].Mid(2) ); } else { parent_dir.SetString( _T(".")); last_component.SetString( files[i] ); } } blob.in_size = last_component.GetLength() + 1; blob.in = last_component.GetBuffer(); blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; memset(space, 0, AFS_PIOCTL_MAXSIZE); code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); last_component.ReleaseBuffer(); if (code == 0) { int nPos; space[AFS_PIOCTL_MAXSIZE - 1] = '\0'; nPos = strlen(space) - 1; if (space[nPos] == '.') space[nPos] = 0; mountPoints.Add(ParseMountPoint(StripPath(files[i]), Utf8ToCString(space))); } else { error = 1; if (errno == EINVAL) mountPoints.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i]))); else mountPoints.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i])))); } } CMountPointsDlg dlg; dlg.SetMountPoints(mountPoints); dlg.DoModal(); return !error; } BOOL MakeMount(const CString& strDir, const CString& strVolName, const CString& strInCellName, BOOL bRW) { LONG code; struct ViceIoctl blob; HOURGLASS hourglass; ASSERT(strVolName.GetLength() < 64); CString strParent = Parent(strDir); FixNetbiosPath(strParent); if (!IsPathInAfs(strParent)) { ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR); return FALSE; } CString strPath = strParent + LastComponent(strDir); if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } CString strMount; strMount.Format(_T("%c%s%s%s."), ((bRW)?_T('%'):_T('#')), strInCellName, ((strInCellName.IsEmpty())?_T(""):_T(":")), strVolName); CStringUtf8 ustrMount(strMount); blob.out_size = 0; blob.in_size = ustrMount.GetLength() + 1; blob.in = ustrMount.GetBuffer(); blob.out = NULL; code = pioctl_T(strPath, VIOC_AFS_CREATE_MT_PT, &blob, 0); ustrMount.ReleaseBuffer(); if (code) { ShowMessageBox(IDS_MOUNT_POINT_ERROR, MB_ICONERROR, IDS_MOUNT_POINT_ERROR, GetAfsError(errno, strDir)); return FALSE; } return TRUE; } BOOL RemoveSymlink(const CString& strName) { BOOL error = FALSE; INT code=0; struct ViceIoctl blob; char lsbuffer[1024]; HOURGLASS hourglass; CString strParent = Parent(strName); CStringUtf8 ustrLast(LastComponent(strName)); FixNetbiosPath(strParent); if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } blob.in_size = ustrLast.GetLength() + 1; blob.in = ustrLast.GetBuffer(); blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 0); ustrLast.ReleaseBuffer(); if (code) return FALSE; blob.out_size = 0; blob.in_size = ustrLast.GetLength() + 1; blob.in = ustrLast.GetBuffer(); code = pioctl_T(strParent, VIOC_DELSYMLINK, &blob, 0); ustrLast.ReleaseBuffer(); return (code == 0); } BOOL IsSymlink(const CString& strName) { struct ViceIoctl blob; int code; char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; CStringUtf8 ustrLast(LastComponent(strName)); CString strParent = Parent(strName); FixNetbiosPath(strParent); blob.in_size = ustrLast.GetLength() + 1; blob.in = ustrLast.GetBuffer(); blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; memset(space, 0, AFS_PIOCTL_MAXSIZE); code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1); ustrLast.ReleaseBuffer(); return (code==0); } BOOL IsMountPoint(const CString& path) { LONG code = 0; struct ViceIoctl blob; char lsbuffer[1024]; HOURGLASS hourglass; CString parent = Parent(path); FixNetbiosPath(parent); CStringUtf8 mountpoint(LastComponent(path)); blob.in_size = mountpoint.GetLength() + 1; blob.in = mountpoint.GetBuffer(); blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); code = pioctl_T(parent, VIOC_AFS_STAT_MT_PT, &blob, 0); mountpoint.ReleaseBuffer(); return (code==0); } /* * Delete AFS mount points. Variables are used as follows: * tbuffer: Set to point to the null-terminated directory name of the mount point * (or ``.'' if none is provided) * tp: Set to point to the actual name of the mount point to nuke. */ BOOL RemoveMount(CStringArray& files) { LONG code = 0; struct ViceIoctl blob; BOOL error = FALSE; CStringArray results; CString str; CString str2; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { if (!IsMountPoint(files[i])) { error = TRUE; if (errno == EINVAL) results.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i]))); else results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i])))); continue; // don't bother trying } CString parent = Parent(files[i]); CStringUtf8 mountpoint(LastComponent(files[i])); FixNetbiosPath(parent); if ( IsFreelanceRoot(parent) && !IsAdmin() ) { results.Add(GetMessageString(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, StripPath(files[i]))); error = TRUE; continue; /* skip */ } blob.out_size = 0; blob.in_size = mountpoint.GetLength() + 1; blob.in = mountpoint.GetBuffer(); code = pioctl_T(parent, VIOC_AFS_DELETE_MT_PT, &blob, 0); mountpoint.ReleaseBuffer(); if (code) { error = TRUE; results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i])))); } else results.Add(GetMessageString(IDS_DELETED)); } LoadString (str, IDS_REMOVE_MP); LoadString (str2, IDS_REMOVE_MP_COLUMN); CResultsDlg dlg(REMOVE_MOUNT_POINTS_HELP_ID); dlg.SetContents(str, str2, StripPath(files), results); dlg.DoModal(); return !error; } BOOL GetVolumeInfo(CString strFile, CVolInfo& volInfo, BOOL bFollow) { LONG code; struct ViceIoctl blob; struct VolumeStatus *status; char *name; char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; CString strTarget = bFollow ? strFile : Parent(strFile); volInfo.m_strFilePath = strTarget; volInfo.m_strFileName = StripPath(strTarget); /* volInfo.m_strName = "VolumeName"; volInfo.m_nID = 10; volInfo.m_nQuota = 20 * 1024 * 1024; volInfo.m_nNewQuota = volInfo.m_nQuota; volInfo.m_nUsed = volInfo.m_nQuota / 2; volInfo.m_nPartSize = 50 * 1024 * 1024; volInfo.m_nPartFree = 30 * 1024 * 1024; volInfo.m_nDup = -1; return TRUE; */ blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; code = pioctl_T(strTarget, VIOCGETVOLSTAT, &blob, 1); if (code || blob.out_size < sizeof(*status)) { volInfo.m_strErrorMsg = GetAfsError(errno, strTarget); return FALSE; } status = (VolumeStatus *)space; name = (char *)status + sizeof(*status); volInfo.m_strName = Utf8ToCString(name); volInfo.m_nID = status->Vid; volInfo.m_nQuota = status->MaxQuota; volInfo.m_nNewQuota = status->MaxQuota; volInfo.m_nUsed = status->BlocksInUse; volInfo.m_nPartSize = status->PartMaxBlocks; volInfo.m_nPartFree = status->PartBlocksAvail; volInfo.m_nDup = -1; errno = 0; code = pioctl_T(strTarget, VIOC_PATH_AVAILABILITY, &blob, 1); switch (errno) { case 0: volInfo.m_strAvail =_T("Online"); break; case ENXIO: volInfo.m_strAvail = _T("Offline"); break; case ENOSYS: volInfo.m_strAvail = _T("Unreachable"); break; case EBUSY: volInfo.m_strAvail = _T("Busy"); break; default: volInfo.m_strAvail = _T("Unknown"); } return TRUE; } BOOL SetVolInfo(CVolInfo& volInfo) { LONG code; struct ViceIoctl blob; struct VolumeStatus *status; char *input; char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = sizeof(*status) + 3; /* for the three terminating nulls */ blob.out = space; blob.in = space; status = (VolumeStatus *)space; status->MinQuota = -1; status->MaxQuota = volInfo.m_nNewQuota; input = (char *)status + sizeof(*status); *(input++) = '\0'; /* never set name: this call doesn't change vldb */ *(input++) = '\0'; // No offmsg *(input++) = '\0'; // No motd #ifdef LOGGING_ON FILE *fp = OpenFile(szLogFileName, "a"); if (fp) { fprintf(fp, "\nSetVolInfo() pioctl parms:\n"); fprintf(fp, "\tpathp = %s\n\topcode = VIOCSETVOLSTAT (%d)\n\tblobp = %ld\n", PCCHAR(volInfo.m_strFilePath), VIOCSETVOLSTAT, &blob); fprintf(fp, "\t\tblobp.in = %ld (VolumeStatus *status)\n\t\tblobp.in_size = %ld\n\t\tblobp.out = %ld ((VolumeStatus *status))\n\t\tblobp.out_size = %ld\n", blob.in, blob.in_size, blob.out, blob.out_size); fprintf(fp, "\t\t\tstatus->MinQuota = %ld\n", status->MinQuota); fprintf(fp, "\t\t\tstatus->MaxQuota = %ld\n", status->MaxQuota); fprintf(fp, "\t\t\tOther status fields aren't set\n"); fprintf(fp, "\t\t\t3 nulls follow the VolumeStatus structure.\n"); fprintf(fp, "\tfollow = 1\n"); fclose(fp); } #endif code = pioctl_T(volInfo.m_strFilePath, VIOCSETVOLSTAT, &blob, 1); if (code || blob.out_size < sizeof(*status)) { ShowMessageBox(IDS_SET_QUOTA_ERROR, MB_ICONERROR, IDS_SET_QUOTA_ERROR, GetAfsError(errno, volInfo.m_strName)); return FALSE; } return TRUE; } void GetCellName(const CString& cellNamep, struct afsconf_cell *infop) { CStringUtf8 uCellName(cellNamep); StringCbCopyA(infop->name, sizeof(infop->name), uCellName); } BOOL NO_CALLER CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast) { LONG code; struct ViceIoctl blob; LONG j; LONG temp = 0; struct afsconf_cell info; struct chservinfo checkserv; char space[AFS_PIOCTL_MAXSIZE]; HOURGLASS hourglass; memset(&checkserv, 0, sizeof(struct chservinfo)); blob.in_size = sizeof(struct chservinfo); blob.in = (caddr_t)&checkserv; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; memset(space, 0, sizeof(afs_int32)); /* so we assure zero when nothing is copied back */ if (nCellsToCheck == SPECIFIC_CELL) { temp = 2; GetCellName(strCellName, &info); strcpy(checkserv.tbuffer,info.name); checkserv.tsize = strlen(info.name) + 1; } else { if (nCellsToCheck != ALL_CELLS) temp = 2; strcpy(checkserv.tbuffer, "\0"); checkserv.tsize = 0; } if (bFast) temp |= 1; /* set fast flag */ checkserv.magic = 0x12345678; /* XXX */ checkserv.tflags = temp; checkserv.tinterval = -1; /* don't change current interval */ code = pioctl_utf8(0, VIOCCKSERV, &blob, 1); if (code) { ShowMessageBox(IDS_CHECK_SERVERS_ERROR, MB_ICONERROR, IDS_CHECK_SERVERS_ERROR, GetAfsError(errno, CString())); return FALSE; } memcpy(&temp, space, sizeof(LONG)); if (temp == 0) { ShowMessageBox(IDS_ALL_SERVERS_RUNNING, MB_OK|MB_ICONINFORMATION, IDS_ALL_SERVERS_RUNNING); return TRUE; } CStringArray servers; for (j = 0; j < AFS_MAXHOSTS; j++) { memcpy(&temp, space + j * sizeof(LONG), sizeof(LONG)); if (temp == 0) break; char *name = hostutil_GetNameByINet(temp); servers.Add(name); } CDownServersDlg dlg; dlg.SetServerNames(servers); dlg.DoModal(); return TRUE; } BOOL GetTokenInfo(CStringArray& tokenInfo) { int cellNum; int rc; time_t current_time; time_t tokenExpireTime; char *expireString; char userName[100]; // char s[100]; struct ktc_principal serviceName, clientName; struct ktc_token token; CString strTokenInfo; CString strUserName; CString strCellName; CString strExpir; // tokenInfo.Add(""); // return TRUE; HOURGLASS hourglass; // printf("\nTokens held by the Cache Manager:\n\n"); cellNum = 0; current_time = time(0); while (1) { rc = ktc_ListTokens(cellNum, &cellNum, &serviceName); if (rc == KTC_NOENT) { /* end of list */ // printf(" --End of list --\n"); break; } else if (rc == KTC_NOCM) { ShowMessageBox(IDS_GET_TOKENS_NO_AFS_SERVICE); // printf("AFS service may not have started\n"); break; } else if (rc) { ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR, rc); return FALSE; // printf("Unexpected error, code %d\n", rc); // exit(1); } else { rc = ktc_GetToken(&serviceName, &token, sizeof(token), &clientName); if (rc) { ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR2, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR2, serviceName.name, serviceName.instance, serviceName.cell, rc); continue; } tokenExpireTime = token.endTime; strcpy(userName, clientName.name); if (clientName.instance[0] != 0) { strcat(userName, "."); strcat(userName, clientName.instance); } BOOL bShowName = FALSE; if (userName[0] == '\0') ; //printf("Tokens"); // AFS ID is not returned at this time. // else if (strncmp(userName, "AFS ID", 6) == 0) // printf("User's (%s) tokens", userName); // sscanf(userName, "(AFS ID %s)", szAfsID); else if (strncmp(userName, "Unix UID", 8) == 0) ; //printf("Tokens"); else strUserName = userName; // printf("User %s's tokens", userName); // printf(" for %s%s%s@%s ", serviceName.name, serviceName.instance[0] ? "." : "", serviceName.instance, serviceName.cell); strCellName = serviceName.cell; if (tokenExpireTime <= current_time) strExpir = "[>> Expired <<]"; // printf("[>> Expired <<]\n"); else { expireString = ctime(&tokenExpireTime); expireString += 4; /* Skip day of week */ expireString[12] = '\0'; /* Omit secs & year */ // printf("[Expires %s]\n", expireString); #ifdef UNICODE strExpir.Format(_T("%S"), expireString); #else strExpir.Format(_T("%s"), expireString); #endif } strTokenInfo = strUserName + "\t" + strCellName + "\t" + strExpir + "\t" + strCellName; tokenInfo.Add(strTokenInfo); } } // printf("Press or when finished: "); // gets(s); return TRUE; } UINT MakeSymbolicLink(const CString& strName, const CString& strTarget) { struct ViceIoctl blob; UINT code; HOURGLASS hourglass; CString strParent = Parent(strName); FixNetbiosPath(strParent); if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } CStringUtf8 ustrTarget(strTarget); blob.in_size = ustrTarget.GetLength() + 1; blob.in = ustrTarget.GetBuffer(); blob.out_size = 0; blob.out = NULL; code = pioctl_T(strName, VIOC_SYMLINK, &blob, 0); ustrTarget.ReleaseBuffer(); if (code != 0) return code; return 0; } void NO_CALLER ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath) { ASSERT(nlenPath 0) { if (syml[len - 1] == _T('.')) syml.Truncate(len - 1); } symlinks.Add(ParseSymlink(StripPath(files[i]), syml)); } else { error = 1; if (errno == EINVAL) symlinks.Add(GetMessageString(IDS_NOT_SYMLINK_ERROR, StripPath(files[i]))); else symlinks.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i])))); } } CSymlinksDlg dlg; dlg.SetSymlinks(symlinks); dlg.DoModal(); return !error; } CString GetCellName( const CString& strPath, BOOL bFollow ) { return GetCell(bFollow ? strPath : Parent(strPath)); } CString GetServer( const CString& strPath, BOOL bFollow ) { LONG code; struct ViceIoctl blob; CString server; char space[AFS_PIOCTL_MAXSIZE]; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; memset(space, 0, sizeof(space)); code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCWHEREIS, &blob, 1); if (code) { server=GetAfsError(errno); } else { LONG *hosts = (LONG *)space; for (int j = 0; j < AFS_MAXHOSTS; j++) { if (hosts[j] == 0) break; char *hostName = hostutil_GetNameByINet(hosts[j]); server=hostName; } } return server; } void GetServers( const CString& strPath, CStringArray& servers, BOOL bFollow ) { LONG code; struct ViceIoctl blob; char space[AFS_PIOCTL_MAXSIZE]; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; memset(space, 0, sizeof(space)); code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCWHEREIS, &blob, 1); if (code) { servers.Add(GetAfsError(errno)); } else { LONG *hosts = (LONG *)space; for (int j = 0; j < AFS_MAXHOSTS; j++) { if (hosts[j] == 0) break; char *hostName = hostutil_GetNameByINet(hosts[j]); servers.Add(hostName); } } } CString GetOwner( const CString& strPath, BOOL bFollow ) { LONG code; struct ViceIoctl blob; afs_int32 owner[2]; CString ret = TEXT("(unknown)"); blob.in_size = 0; blob.out_size = 2 * sizeof(afs_int32); blob.out = (char *) &owner; code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCGETOWNER, &blob, 1); if (code == 0 && blob.out_size == 2 * sizeof(afs_int32)) { char oname[PR_MAXNAMELEN] = "(unknown)"; char confDir[257]; CStringUtf8 cell; cell = GetCell(strPath, bFollow); /* Go to the PRDB and see if this all number username is valid */ cm_GetConfigDir(confDir, sizeof(confDir)); pr_Initialize(1, confDir, PCCHAR(cell)); pr_SIdToName(owner[0], oname); ret.Empty(); ret.Format(TEXT("%s [%d]"), (LPCTSTR)CString(oname), owner[0]); } return ret; } CString GetGroup( const CString& strPath, BOOL bFollow ) { LONG code; struct ViceIoctl blob; afs_int32 owner[2]; CString ret = TEXT("(unknown)"); blob.in_size = 0; blob.out_size = 2 * sizeof(afs_int32); blob.out = (char *) &owner; code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCGETOWNER, &blob, 1); if (code == 0 && blob.out_size == 2 * sizeof(afs_int32)) { char gname[PR_MAXNAMELEN] = "(unknown)"; char confDir[257]; CStringUtf8 cell; cell = GetCell(strPath, bFollow); /* Go to the PRDB and see if this all number username is valid */ cm_GetConfigDir(confDir, sizeof(confDir)); pr_Initialize(1, confDir, PCCHAR(cell)); pr_SIdToName(owner[1], gname); ret.Empty(); ret.Format(TEXT("%s [%d]"), (LPCTSTR)CString(gname), owner[1]); } return ret; } BOOL GetUnixModeBits( const CString& strPath, CString& user, CString& group, CString& other, CString& suid ) { // the strings must match the unix ls command output: "rwx" means read/write/execute permissions LONG code; struct ViceIoctl blob; afs_uint32 unixModeBits; CString ret = TEXT("(unknown)"); user.Empty(); group.Empty(); other.Empty(); suid.Empty(); blob.in_size = 0; blob.out_size = sizeof(afs_int32); blob.out = (char *) &unixModeBits; code = pioctl_T(strPath, VIOC_GETUNIXMODE, &blob, 1); if (code == 0 && blob.out_size == sizeof(afs_uint32)) { if (unixModeBits & S_IRUSR) user += _T("r"); if (unixModeBits & S_IWUSR) user += _T("w"); if (unixModeBits & S_IXUSR) user += _T("x"); if (unixModeBits & S_IRGRP) group += _T("r"); if (unixModeBits & S_IWGRP) group += _T("w"); if (unixModeBits & S_IXGRP) group += _T("x"); if (unixModeBits & S_IROTH) other += _T("r"); if (unixModeBits & S_IWOTH) other += _T("w"); if (unixModeBits & S_IXOTH) other += _T("x"); if (unixModeBits & S_ISUID) suid += _T("s"); if (unixModeBits & S_ISGID) suid += _T("g"); if (unixModeBits & S_ISVTX) suid += _T("v"); return TRUE; } return FALSE; } void SetUnixModeBits( const CStringArray& files, const CString& user, const CString& group, const CString& other, const CString& suid ) { // set the unix file attributes for all paths in 'files'. LONG code; struct ViceIoctl blob; struct { cm_ioctlQueryOptions_t options; afs_uint32 unixModeBits; } inData; memset(&inData, 0, sizeof(inData)); inData.options.size = sizeof(inData.options); inData.options.field_flags = 0; inData.options.literal = 0; /* always applying to target */ blob.in_size = inData.options.size; /* no variable length data */ blob.in = &inData; blob.out = NULL; blob.out_size = 0; inData.unixModeBits = 0; if (user.Find(_T("r")) != -1) inData.unixModeBits |= S_IRUSR; if (user.Find(_T("w")) != -1) inData.unixModeBits |= S_IWUSR; if (user.Find(_T("x")) != -1) inData.unixModeBits |= S_IXUSR; if (group.Find(_T("r")) != -1) inData.unixModeBits |= S_IRGRP; if (group.Find(_T("w")) != -1) inData.unixModeBits |= S_IWGRP; if (group.Find(_T("x")) != -1) inData.unixModeBits |= S_IXGRP; if (other.Find(_T("r")) != -1) inData.unixModeBits |= S_IROTH; if (other.Find(_T("w")) != -1) inData.unixModeBits |= S_IWOTH; if (other.Find(_T("x")) != -1) inData.unixModeBits |= S_IXOTH; if (suid.Find(_T("s")) != -1) inData.unixModeBits |= S_ISUID; if (suid.Find(_T("g")) != -1) inData.unixModeBits |= S_ISGID; if (suid.Find(_T("v")) != -1) inData.unixModeBits |= S_ISVTX; for (int i = 0; i < files.GetSize(); i++) code = pioctl_T(files[i], VIOC_SETUNIXMODE, &blob, 1); } CString GetMountpoint( const CString& strPath ) { LONG code; struct ViceIoctl blob; char space[AFS_PIOCTL_MAXSIZE]; CString parent_dir; /* Parent directory of true name */ CStringUtf8 last_component; /* Last component of true name */ CString mountPoint; int last_slash = strPath.ReverseFind(_T('\\')); if (last_slash != -1) { last_component.SetString( strPath.Mid(last_slash + 1) ); parent_dir.SetString( strPath.Left(last_slash + 1) ); FixNetbiosPath(parent_dir); } else { // The path is of the form "C:foo" or just "foo". If // there is a drive, then use the current directory of // that drive. Otherwise we just use '.'. if (strPath.GetLength() >= 2 && strPath[1] == _T(':')) { parent_dir.Format(_T("%c:."), strPath[0]); last_component.SetString( strPath.Mid(2) ); } else { parent_dir.SetString( _T(".")); last_component.SetString( strPath ); } } blob.in_size = last_component.GetLength() + 1; blob.in = last_component.GetBuffer(); blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; memset(space, 0, AFS_PIOCTL_MAXSIZE); code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); last_component.ReleaseBuffer(); if (code == 0) { int nPos; space[AFS_PIOCTL_MAXSIZE - 1] = '\0'; nPos = strlen(space) - 1; if (space[nPos] == '.') space[nPos] = 0; mountPoint = ParseMountPoint(StripPath(strPath), Utf8ToCString(space)); } else { if (errno == EINVAL) mountPoint = GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(strPath)); else mountPoint = GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(strPath))); } return mountPoint; } CString GetSymlink( const CString& strPath ) { LONG code; struct ViceIoctl blob; CString symlink; char space[AFS_PIOCTL_MAXSIZE]; CString strParent = Parent(strPath); CStringUtf8 ustrLast(LastComponent(strPath)); FixNetbiosPath(strParent); blob.in_size = ustrLast.GetLength() + 1; blob.in = ustrLast.GetBuffer(); blob.out_size = AFS_PIOCTL_MAXSIZE; blob.out = space; memset(space, 0, AFS_PIOCTL_MAXSIZE); code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1); ustrLast.ReleaseBuffer(); if (code == 0) { CString syml; int len; space[AFS_PIOCTL_MAXSIZE - 1] = '\0'; syml = Utf8ToCString(space); len = syml.GetLength(); if (len > 0) { if (syml[len - 1] == _T('.')) syml.Truncate(len - 1); } symlink = ParseSymlink(StripPath(strPath), syml); } else { if (errno == EINVAL) symlink = GetMessageString(IDS_NOT_SYMLINK_ERROR, StripPath(strPath)); else symlink = GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(strPath))); } return symlink; }