/* * 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 */ extern "C" { #include #include } #include "stdafx.h" #include #include #include "gui2fs.h" #include "msgs.h" #include "results_dlg.h" #include "volume_inf.h" #include "mount_points_dlg.h" #include "hourglass.h" #include "down_servers_dlg.h" extern "C" { #include #include #include "fs.h" #include "fs_utils.h" #include #include } #define PCCHAR(str) ((char *)(const char *)(str)) #define MAXHOSTS 13 #define OMAXHOSTS 8 #define MAXNAME 100 #define MAXSIZE 2048 #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 struct afsconf_cell { char name[MAXCELLCHARS]; short numServers; short flags; struct sockaddr_in hostAddr[MAXHOSTSPERCELL]; char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS]; char *linkedCell; }; static char space[MAXSIZE]; static char tspace[1024]; // #define LOGGING_ON // Enable this to log certain pioctl calls #ifdef LOGGING_ON static char *szLogFileName = "afsguilog.txt"; #endif FILE *OpenFile(char *file, char *rwp) { char wdir[256]; long code; long tlen; FILE *fp; code = GetWindowsDirectory(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(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) { register 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(PCCHAR(files[i]), VIOCFLUSH, &blob, 0); if (code) { error = 1; if (errno == EMFILE) ShowMessageBox(IDS_FLUSH_FAILED, MB_ICONEXCLAMATION, IDS_FLUSH_FAILED, files[i]); else ShowMessageBox(IDS_FLUSH_ERROR, MB_ICONEXCLAMATION, IDS_FLUSH_ERROR, files[i], strerror(errno)); } } if (!error) ShowMessageBox(IDS_FLUSH_OK, MB_ICONEXCLAMATION, IDS_FLUSH_OK); } void FlushVolume(const CStringArray& files) { register 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(PCCHAR(files[i]), VIOC_FLUSHVOLUME, &blob, 0); if (code) { error = 1; ShowMessageBox(IDS_FLUSH_VOLUME_ERROR, MB_ICONEXCLAMATION, IDS_FLUSH_VOLUME_ERROR, files[i], strerror(errno)); } } if (!code) ShowMessageBox(IDS_FLUSH_VOLUME_OK, MB_ICONEXCLAMATION, IDS_FLUSH_VOLUME_OK); } void WhichCell(CStringArray& files) { register 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++) { blob.in_size = 0; blob.out_size = MAXSIZE; blob.out = space; code = pioctl(PCCHAR(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 results.Add(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 WSCellCmd() { register LONG code; struct ViceIoctl blob; HOURGLASS hourglass; blob.in_size = 0; blob.in = (char *) 0; blob.out_size = MAXSIZE; blob.out = space; code = pioctl((char *) 0, VIOC_GET_WS_CELL, &blob, 1); if (code) { //Die(errno, (char *) 0); } //else //printf("This workstation belongs to cell '%s'\n", space); } BOOL CheckVolumes() { register 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_ICONEXCLAMATION, IDS_CHECK_VOLUMES_ERROR, GetAfsError(errno, CString())); return FALSE; } ShowMessageBox(IDS_CHECK_VOLUMES_OK, MB_OK, IDS_CHECK_VOLUMES_OK); return TRUE; } void SetCacheSizeCmd(LONG nNewCacheSize) { register 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); //if (code) // Die(errno, (char *) 0); //else // printf("New cache size set.\n"); } void WhereIs(CStringArray& files) { register LONG code; struct ViceIoctl blob; CStringArray servers; CStringArray resultFiles; CString str; CString str2; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; memset(space, 0, sizeof(space)); code = pioctl(PCCHAR(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 < 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(); } CString GetAfsError(int code, const char *filename) { CString strMsg; if (code == EINVAL) { if (filename) strMsg.Format("Invalid argument; it is possible that the file is not in AFS"); else strMsg.Format("Invalid argument"); } else if (code == ENOENT) { if (filename) strMsg.Format("The file does not exist"); else strMsg.Format("No such file returned"); } else if (code == EROFS) { strMsg.Format("You can not change a backup or readonly volume"); } else if (code == EACCES || code == EPERM) { strMsg.Format("You do not have the required rights to do this operation"); } else if (code == ENODEV) { strMsg.Format("AFS service may not have started"); } else if (code == ESRCH) { strMsg.Format("Cell name not recognized"); } else if (code == ETIMEDOUT) { strMsg.Format("Connection timed out"); } else if (code == EPIPE) { strMsg.Format("Volume name or ID not recognized"); } else { strMsg.Format("Error 0x%x occurred", code); } return strMsg; } /************************************************************************ ************************** ACL Code ************************************* ************************************************************************/ typedef char sec_rgy_name_t[1025]; /* A DCE definition */ struct AclEntry { struct AclEntry *next; char name[MAXNAME]; LONG rights; }; struct Acl { int dfs; // Originally true if a dfs acl; now also the type // of the acl (1, 2, or 3, corresponding to object, // initial dir, or initial object). sec_rgy_name_t cell; // DFS cell name int nplus; int nminus; struct AclEntry *pluslist; struct AclEntry *minuslist; }; int foldcmp (register char *a, register char *b) { register 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; } } extern "C" void ZapList(struct AclEntry *alist) { register struct AclEntry *tp, *np; for (tp = alist; tp; tp = np) { np = tp->next; free(tp); } } extern "C" void ZapAcl (struct Acl *acl) { ZapList(acl->pluslist); ZapList(acl->minuslist); free(acl); } extern "C" int PruneList (struct AclEntry **ae, int dfs) { struct AclEntry **lp = ae; struct AclEntry *te, *ne; LONG ctr = 0; for (te = *ae; te; te = ne) { if ((!dfs && te->rights == 0) || te->rights == -1) { *lp = te->next; ne = te->next; free(te); ctr++; } else { ne = te->next; lp = &te->next; } } return ctr; } char *SkipLine (register char *astr) { while (*astr != '\n') astr++; astr++; return astr; } /* tell if a name is 23 or -45 (digits or minus digits), which are bad names we must prune */ static BadName(register char *aname) { register int tc; /* all must be '-' or digit to be bad */ while (tc = *aname++) { if ((tc != '-') && (tc < '0' || tc > '9')) return 0; } return 1; } CString GetRightsString(register LONG arights, int dfs) { CString str; if (!dfs) { if (arights & PRSFS_READ) str += "r"; if (arights & PRSFS_LOOKUP) str += "l"; if (arights & PRSFS_INSERT) str += "i"; if (arights & PRSFS_DELETE) str += "d"; if (arights & PRSFS_WRITE) str += "w"; if (arights & PRSFS_LOCK) str += "k"; if (arights & PRSFS_ADMINISTER) str += "a"; } else { ASSERT(FALSE); /* if (arights & DFS_READ) str += "r"; else str += "-"; if (arights & DFS_WRITE) str += "w"; else printf("-"); if (arights & DFS_EXECUTE) str += "x"; else printf("-"); if (arights & DFS_CONTROL) str += "c"; else printf("-"); if (arights & DFS_INSERT) str += "i"; else printf("-"); if (arights & DFS_DELETE) str += "d"; else printf("-"); if (arights & (DFS_USRALL)) str += "+"; */ } return str; } char *AclToString(struct Acl *acl) { static char mydata[MAXSIZE]; char tstring[MAXSIZE]; char dfsstring[30]; struct AclEntry *tp; if (acl->dfs) sprintf(dfsstring, " dfs:%d %s", acl->dfs, acl->cell); else dfsstring[0] = '\0'; sprintf(mydata, "%d%s\n%d\n", acl->nplus, dfsstring, acl->nminus); for(tp = acl->pluslist; tp; tp = tp->next) { sprintf(tstring, "%s %d\n", tp->name, tp->rights); strcat(mydata, tstring); } for(tp = acl->minuslist; tp; tp = tp->next) { sprintf(tstring, "%s %d\n", tp->name, tp->rights); strcat(mydata, tstring); } return mydata; } struct Acl *EmptyAcl(const CString& strCellName) { register struct Acl *tp; tp = (struct Acl *)malloc(sizeof (struct Acl)); tp->nplus = tp->nminus = 0; tp->pluslist = tp->minuslist = 0; tp->dfs = 0; strcpy(tp->cell, strCellName); return tp; } struct Acl *ParseAcl(char *astr) { int nplus, nminus, i, trights; char tname[MAXNAME]; struct AclEntry *first, *last, *tl; struct Acl *ta; ta = (struct Acl *) malloc (sizeof (struct Acl)); ta->dfs = 0; sscanf(astr, "%d dfs:%d %s", &ta->nplus, &ta->dfs, ta->cell); astr = SkipLine(astr); sscanf(astr, "%d", &ta->nminus); astr = SkipLine(astr); nplus = ta->nplus; nminus = ta->nminus; last = 0; first = 0; for(i = 0; i < nplus; i++) { sscanf(astr, "%100s %d", tname, &trights); astr = SkipLine(astr); tl = (struct AclEntry *) malloc(sizeof (struct AclEntry)); if (!first) first = tl; strcpy(tl->name, tname); tl->rights = trights; tl->next = 0; if (last) last->next = tl; last = tl; } ta->pluslist = first; last = 0; first = 0; for(i=0; i < nminus; i++) { sscanf(astr, "%100s %d", tname, &trights); astr = SkipLine(astr); tl = (struct AclEntry *) malloc(sizeof (struct AclEntry)); if (!first) first = tl; strcpy(tl->name, tname); tl->rights = trights; tl->next = 0; if (last) last->next = tl; last = tl; } ta->minuslist = first; return ta; } /* clean up an access control list of its bad entries; return 1 if we made any changes to the list, and 0 otherwise */ extern "C" int CleanAcl(struct Acl *aa) { register struct AclEntry *te, **le, *ne; int changes; HOURGLASS hourglass; /* Don't correct DFS ACL's for now */ if (aa->dfs) return 0; /* prune out bad entries */ changes = 0; /* count deleted entries */ le = &aa->pluslist; for(te = aa->pluslist; te; te = ne) { ne = te->next; if (BadName(te->name)) { /* zap this dude */ *le = te->next; aa->nplus--; free(te); changes++; } else le = &te->next; } le = &aa->minuslist; for(te = aa->minuslist; te; te = ne) { ne = te->next; if (BadName(te->name)) { /* zap this dude */ *le = te->next; aa->nminus--; free(te); changes++; } else le = &te->next; } return changes; } void CleanACL(CStringArray& names) { register LONG code; register struct Acl *ta; struct ViceIoctl blob; int changes; ShowMessageBox(IDS_CLEANACL_MSG, MB_OK, IDS_CLEANACL_MSG); HOURGLASS hourglass; for (int i = 0; i < names.GetSize(); i++) { blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; code = pioctl(PCCHAR(names[i]), VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONEXCLAMATION, 0, names[i], GetAfsError(errno)); continue; } ta = ParseAcl(space); if (ta->dfs) { ShowMessageBox(IDS_CLEANACL_NOT_SUPPORTED, MB_ICONEXCLAMATION, IDS_CLEANACL_NOT_SUPPORTED, names[i]); continue; } changes = CleanAcl(ta); 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(PCCHAR(names[i]), VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { ShowMessageBox(IDS_CLEANACL_INVALID_ARG, MB_ICONEXCLAMATION, IDS_CLEANACL_INVALID_ARG, names[i]); continue; } else { ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONEXCLAMATION, 0, names[i], GetAfsError(errno)); continue; } } } } // Derived from fs.c's ListAclCmd BOOL GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& strNegative) { register LONG code; register struct Acl *ta; struct ViceIoctl blob; struct AclEntry *te; int idf = 0; //getidf(as, parm_listacl_id); HOURGLASS hourglass; blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; code = pioctl(PCCHAR(strDir), VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_GETRIGHTS_ERROR, MB_ICONEXCLAMATION, IDS_GETRIGHTS_ERROR, strDir, GetAfsError(errno)); return FALSE; } ta = ParseAcl(space); if (ta->dfs) { ShowMessageBox(IDS_DFSACL_ERROR, MB_ICONEXCLAMATION, 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(register 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 char *entryName, LONG nEntryRights) { ASSERT(pAcl); ASSERT(entryName); struct AclEntry *pEntry; HOURGLASS hourglass; pEntry = (bNormalRights ? pAcl->pluslist : pAcl->minuslist); pEntry = FindList(pEntry, entryName); /* 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, entryName); 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); } } enum rtype {add, destroy, deny}; LONG Convert(const register char *arights, int dfs, enum rtype *rtypep) { register int i, len; LONG mode; register char tc; *rtypep = add; /* add rights, by default */ if (!strcmp(arights,"read")) return PRSFS_READ | PRSFS_LOOKUP; if (!strcmp(arights, "write")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK; if (!strcmp(arights, "mail")) return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP; if (!strcmp(arights, "all")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER; if (!strcmp(arights, "none")) { *rtypep = destroy; /* Remove entire entry */ return 0; } len = strlen(arights); mode = 0; for (i = 0; i < len; i++) { tc = *arights++; if (tc == 'r') mode |= PRSFS_READ; else if (tc == 'l') mode |= PRSFS_LOOKUP; else if (tc == 'i') mode |= PRSFS_INSERT; else if (tc == 'd') mode |= PRSFS_DELETE; else if (tc == 'w') mode |= PRSFS_WRITE; else if (tc == 'k') mode |= PRSFS_LOCK; else if (tc == 'a') mode |= PRSFS_ADMINISTER; else { fprintf(stderr, "illegal rights character '%c'.\n", tc); exit(1); } } return mode; } BOOL SaveACL(const CString& strCellName, const CString& strDir, const CStringArray& normal, const CStringArray& negative) { register 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 for (int 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(PCCHAR(strDir), VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) ShowMessageBox(IDS_SAVE_ACL_EINVAL_ERROR, MB_ICONEXCLAMATION, IDS_SAVE_ACL_EINVAL_ERROR, strDir); else ShowMessageBox(IDS_SAVE_ACL_ERROR, MB_ICONEXCLAMATION, 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) { register LONG code; struct ViceIoctl blob; struct Acl *pToAcl; int idf = 0; // getidf(as, parm_copyacl_id); HOURGLASS hourglass; // Get ACL to copy to blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; code = pioctl(PCCHAR(strToDir), VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_ACL_READ_ERROR, MB_ICONEXCLAMATION, IDS_ACL_READ_ERROR, strToDir, GetAfsError(errno, strToDir)); return FALSE; } if (bClear) pToAcl = EmptyAcl(space); else pToAcl = ParseAcl(space); CleanAcl(pToAcl); if (pToAcl->dfs) { ShowMessageBox(IDS_NO_DFS_COPY_ACL, MB_ICONEXCLAMATION, IDS_NO_DFS_COPY_ACL, strToDir); ZapAcl(pToAcl); return FALSE; } enum rtype rtype; // Set normal rights for (int 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(PCCHAR(strToDir), VIOCSETAL, &blob, 1); if (code) { ZapAcl(pToAcl); if (errno == EINVAL) ShowMessageBox(IDS_COPY_ACL_EINVAL_ERROR, MB_ICONEXCLAMATION, IDS_COPY_ACL_EINVAL_ERROR, strToDir); else ShowMessageBox(IDS_COPY_ACL_ERROR, MB_ICONEXCLAMATION, IDS_COPY_ACL_ERROR, strToDir, GetAfsError(errno, strToDir)); return FALSE; } ZapAcl(pToAcl); ShowMessageBox(IDS_COPY_ACL_OK, MB_OK, 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); strMountPointInfo = strFile + "\t" + strVolume + "\t" + strCell + "\t" + strType; return strMountPointInfo; } BOOL ListMount(CStringArray& files) { register LONG code; struct ViceIoctl blob; int error; char orig_name[1024]; /* Original name, may be modified */ char true_name[1024]; /* ``True'' dirname (e.g., symlink target) */ char parent_dir[1024]; /* Parent directory of true name */ register char *last_component; /* Last component of true name */ CStringArray mountPoints; HOURGLASS hourglass; error = 0; for (int i = 0; i < files.GetSize(); i++) { strcpy(orig_name, files[i]); strcpy(true_name, orig_name); /* * Find rightmost slash, if any. */ last_component = (char *)strrchr(true_name, '\\'); if (last_component) { /* * Found it. Designate everything before it as the parent directory, * everything after it as the final component. */ strncpy(parent_dir, true_name, last_component - true_name + 1); parent_dir[last_component - true_name + 1] = 0; last_component++; /* Skip the slash */ } else { /* * No slash appears in the given file name. Set parent_dir to the current * directory, and the last component as the given name. */ fs_ExtractDriveLetter(true_name, parent_dir); strcat(parent_dir, "."); last_component = true_name; fs_StripDriveLetter(true_name, true_name, sizeof(true_name)); } blob.in = last_component; blob.in_size = strlen(last_component) + 1; blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, MAXSIZE); code = pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); if (code == 0) { int nPos = strlen(space) - 1; if (space[nPos] == '.') space[nPos] = 0; mountPoints.Add(ParseMountPoint(StripPath(files[i]), 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 IsPathInAfs(const CHAR *strPath) { struct ViceIoctl blob; int code; HOURGLASS hourglass; blob.in_size = 0; blob.out_size = MAXSIZE; blob.out = space; code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1); if (code) return FALSE; return TRUE; } /* return a static pointer to a buffer */ static char *Parent(char *apath) { register char *tp; strcpy(tspace, apath); tp = strrchr(tspace, '\\'); if (tp) { *(tp+1) = 0; /* lv trailing slash so Parent("k:\foo") is "k:\" not "k:" */ } else { fs_ExtractDriveLetter(apath, tspace); strcat(tspace, "."); } return tspace; } BOOL MakeMount(const CString& strDir, const CString& strVolName, const CString& strCellName, BOOL bRW) { register LONG code; register char *cellName; char localCellName[1000]; struct ViceIoctl blob; HOURGLASS hourglass; ASSERT(strVolName.GetLength() < 64); /* defect #3069 if (as->parms[5].items && !as->parms[2].items) { fprintf(stderr,"fs: must provide cell when creating cellular mount point.\n"); return FALSE; } */ if (strCellName.GetLength() > 0) /* cell name specified */ cellName = PCCHAR(strCellName); else cellName = (char *) 0; if (!IsPathInAfs(Parent(PCCHAR(strDir)))) { ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONEXCLAMATION, IDS_MAKE_MP_NOT_AFS_ERROR); return FALSE; } if (cellName) { blob.in_size = 0; blob.out_size = MAXSIZE; blob.out = space; code = pioctl(Parent(PCCHAR(strDir)), VIOC_FILE_CELL_NAME, &blob, 1); } strcpy(localCellName, (cellName? cellName : space)); if (bRW) /* if -rw specified */ strcpy(space, "%"); else strcpy(space, "#"); /* If cellular mount point, prepend cell prefix */ if (cellName) { strcat(space, localCellName); strcat(space, ":"); } strcat(space, strVolName); /* append volume name */ strcat(space, "."); /* stupid convention; these end with a period */ /* create symlink with a special pioctl for Windows NT, since it doesn't * have a symlink system call. */ blob.out_size = 0; blob.in_size = 1 + strlen(space); blob.in = space; blob.out = NULL; code = pioctl(PCCHAR(strDir), VIOC_AFS_CREATE_MT_PT, &blob, 0); if (code) { ShowMessageBox(IDS_MOUNT_POINT_ERROR, MB_ICONEXCLAMATION, IDS_MOUNT_POINT_ERROR, GetAfsError(errno, strDir)); return FALSE; } return TRUE; } /* */ long fs_ExtractDriveLetter(const char *inPathp, char *outPathp) { if (inPathp[0] != 0 && inPathp[1] == ':') { /* there is a drive letter */ *outPathp++ = *inPathp++; *outPathp++ = *inPathp++; *outPathp++ = 0; } else *outPathp = 0; return 0; } /* strip the drive letter from a component */ long fs_StripDriveLetter(const char *inPathp, char *outPathp, long outSize) { char tempBuffer[1000]; strcpy(tempBuffer, inPathp); if (tempBuffer[0] != 0 && tempBuffer[1] == ':') { /* drive letter present */ strcpy(outPathp, tempBuffer+2); } else { /* no drive letter present */ strcpy(outPathp, tempBuffer); } return 0; } BOOL RemoveSymlink(const char * linkName) { BOOL error = FALSE; INT code=0; struct ViceIoctl blob; char tbuffer[1024]; char lsbuffer[1024]; char tpbuffer[1024]; char *tp; HOURGLASS hourglass; tp = (char *) strrchr(linkName, '\\'); if (!tp) tp = (char *) strrchr(linkName, '/'); if (tp) { strncpy(tbuffer, linkName, code=tp-linkName+1); /* the dir name */ tbuffer[code] = 0; tp++; /* skip the slash */ } else { fs_ExtractDriveLetter(linkName, tbuffer); strcat(tbuffer, "."); fs_StripDriveLetter(tp, tpbuffer, 0); tp=tpbuffer; } blob.in = tp; blob.in_size = strlen(tp)+1; blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); code = pioctl(tbuffer, VIOC_LISTSYMLINK, &blob, 0); if (code) return FALSE; blob.out_size = 0; blob.in = tp; blob.in_size = strlen(tp)+1; return (pioctl(tbuffer, VIOC_DELSYMLINK, &blob, 0)==0); } BOOL IsSymlink(const char * true_name) { char parent_dir[MAXSIZE]; /*Parent directory of true name*/ char strip_name[MAXSIZE]; struct ViceIoctl blob; char *last_component; int code; HOURGLASS hourglass; last_component = (char *) strrchr(true_name, '\\'); if (!last_component) last_component = (char *) strrchr(true_name, '/'); if (last_component) { /* * Found it. Designate everything before it as the parent directory, * everything after it as the final component. */ strncpy(parent_dir, true_name, last_component - true_name + 1); parent_dir[last_component - true_name + 1] = 0; last_component++; /*Skip the slash*/ } else { /* * No slash appears in the given file name. Set parent_dir to the current * directory, and the last component as the given name. */ fs_ExtractDriveLetter(true_name, parent_dir); strcat(parent_dir, "."); last_component = strip_name; fs_StripDriveLetter(true_name, strip_name, sizeof(strip_name)); } blob.in = last_component; blob.in_size = strlen(last_component)+1; blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, MAXSIZE); code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1); 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) { register LONG code = 0; struct ViceIoctl blob; char tbuffer[1024]; char lsbuffer[1024]; register char *tp; BOOL error = FALSE; CStringArray results; CString str; CString str2; HOURGLASS hourglass; for (int i = 0; i < files.GetSize(); i++) { char szCurItem[1024]; strcpy(szCurItem, files[i]); tp = (char *)strrchr(szCurItem, '\\'); if (tp) { strncpy(tbuffer, szCurItem, code = tp - szCurItem + 1); /* the dir name */ tbuffer[code] = 0; tp++; /* skip the slash */ } else { fs_ExtractDriveLetter(szCurItem, tbuffer); strcat(tbuffer, "."); tp = szCurItem; fs_StripDriveLetter(tp, tp, 0); } blob.in = tp; blob.in_size = strlen(tp)+1; blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); code = pioctl(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0); if (code) { 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 } blob.out_size = 0; blob.in = tp; blob.in_size = strlen(tp)+1; code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0); 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) { register LONG code; struct ViceIoctl blob; struct VolumeStatus *status; char *name; HOURGLASS hourglass; volInfo.m_strFilePath = strFile; volInfo.m_strFileName = StripPath(strFile); /* 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 = MAXSIZE; blob.in_size = 0; blob.out = space; code = pioctl(PCCHAR(strFile), VIOCGETVOLSTAT, &blob, 1); if (code) { volInfo.m_strErrorMsg = GetAfsError(errno, strFile); return FALSE; } status = (VolumeStatus *)space; name = (char *)status + sizeof(*status); volInfo.m_strName = 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; return TRUE; } BOOL SetVolInfo(CVolInfo& volInfo) { register LONG code; struct ViceIoctl blob; struct VolumeStatus *status; char *input; HOURGLASS hourglass; blob.out_size = 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(PCCHAR(volInfo.m_strFilePath), VIOCSETVOLSTAT, &blob, 1); if (code) { ShowMessageBox(IDS_SET_QUOTA_ERROR, MB_ICONEXCLAMATION, IDS_SET_QUOTA_ERROR, GetAfsError(errno, volInfo.m_strName)); return FALSE; } return TRUE; } int GetCellName(char *cellNamep, struct afsconf_cell *infop) { strcpy(infop->name, cellNamep); return 0; } BOOL CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast) { register LONG code; struct ViceIoctl blob; register LONG j; LONG temp = 0; struct afsconf_cell info; struct chservinfo checkserv; HOURGLASS hourglass; memset(&checkserv, 0, sizeof(struct chservinfo)); blob.in_size = sizeof(struct chservinfo); blob.in = (caddr_t)&checkserv; blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, sizeof(LONG)); /* so we assure zero when nothing is copied back */ /* prepare flags for checkservers command */ if (nCellsToCheck == LOCAL_CELL) temp = 2; /* default to checking local cell only */ else if (nCellsToCheck == ALL_CELLS) temp &= ~2; /* turn off local cell check */ if (bFast) temp |= 1; /* set fast flag */ checkserv.magic = 0x12345678; /* XXX */ checkserv.tflags = temp; /* now copy in optional cell name, if specified */ if (nCellsToCheck == SPECIFIC_CELL) { GetCellName(PCCHAR(strCellName), &info); strcpy(checkserv.tbuffer,info.name); checkserv.tsize = strlen(info.name) + 1; } else { strcpy(checkserv.tbuffer, "\0"); checkserv.tsize = 0; } checkserv.tinterval = -1; /* don't change current interval */ code = pioctl(0, VIOCCKSERV, &blob, 1); if (code) { ShowMessageBox(IDS_CHECK_SERVERS_ERROR, MB_ICONEXCLAMATION, IDS_CHECK_SERVERS_ERROR, GetAfsError(errno, CString())); return FALSE; } memcpy(&temp, space, sizeof(LONG)); if (temp == 0) { ShowMessageBox(IDS_ALL_SERVERS_RUNNING, MB_OK, IDS_ALL_SERVERS_RUNNING); return TRUE; } CStringArray servers; for (j = 0; j < 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; int 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_ICONEXCLAMATION, 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_ICONEXCLAMATION, 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); strExpir.Format("%s", expireString); } strTokenInfo = strUserName + "\t" + strCellName + "\t" + strExpir + "\t" + strCellName; tokenInfo.Add(strTokenInfo); } } // printf("Press or when finished: "); // gets(s); return TRUE; } UINT MakeSymbolicLink(const char *strName ,const char *strDir) { struct ViceIoctl blob; char space[MAXSIZE]; UINT code; HOURGLASS hourglass; /*lets confirm its a good symlink*/ if (!IsPathInAfs(strDir)) return 1; LPTSTR lpsz = new TCHAR[strlen(strDir)+1]; _tcscpy(lpsz, strName); strcpy(space, strDir); blob.out_size = 0; blob.in_size = 1 + strlen(space); blob.in = space; blob.out = NULL; if ((code=pioctl(lpsz, VIOC_SYMLINK, &blob, 0))!=0) return code; return 0; } void ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath) { ASSERT(nlenPath