2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
15 #include <afsconfig.h>
16 #include <afs/param.h>
26 #include "results_dlg.h"
27 #include "volume_inf.h"
28 #include "mount_points_dlg.h"
29 #include "symlinks_dlg.h"
30 #include "hourglass.h"
31 #include "down_servers_dlg.h"
34 #include <rx/rx_globals.h>
37 #include <afs/afsint.h>
38 #include <afs/afs_consts.h>
39 #include <afs/cellconfig.h>
40 #include <afs/vldbint.h>
41 #include <afs/volser.h>
43 #include <WINNT\afsreg.h>
48 #include <cm_scache.h>
52 #define STRSAFE_NO_DEPRECATE
56 * the NO_CALLER symbol is used to document functions
57 * that are present in this file but have no caller
62 #define PCCHAR(str) ((char *)(const char *)(str))
63 #define VL_NOENT (363524L)
66 #define MAXINSIZE 1300 /* pioctl complains if data is larger than this */
67 #define VMSGSIZE 128 /* size of msg buf in volume hdr */
69 #define MAXCELLCHARS 64
70 #define MAXHOSTCHARS 64
71 #define MAXHOSTSPERCELL 8
73 static struct ubik_client *uclient;
74 static int rxInitDone = 0;
75 static char pn[] = "fs";
77 // #define LOGGING_ON // Enable this to log certain pioctl calls
80 static char *szLogFileName = "afsguilog.txt";
84 class CStringUtf8 : public CStringA
87 CStringUtf8(const CStringW& csw) : CStringA()
92 CStringUtf8(const char * cp) : CStringA(cp) {}
94 CStringUtf8() :CStringA() {}
96 void SetString(const CStringW& csw)
101 rv = WideCharToMultiByte(CP_UTF8, 0, csw, -1,
102 buffer, sizeof(buffer),
106 CStringA::SetString(buffer);
108 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
111 cb_req = WideCharToMultiByte(CP_UTF8, 0, csw, -1, NULL, 0, NULL, FALSE);
115 WideCharToMultiByte(CP_UTF8, 0, csw, -1, CStringA::GetBuffer(cb_req), cb_req, NULL, FALSE);
116 CStringA::ReleaseBuffer();
126 static CString _Utf8ToCString(const char * ustr)
131 cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, NULL, 0);
138 cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, cs.GetBuffer(cch), cch);
146 pioctl_T(const CString& path, long opcode, struct ViceIoctl * blob, int follow)
148 CStringUtf8 upath(path);
150 return pioctl_utf8(PCCHAR(upath), opcode, blob, follow);
153 #define Utf8ToCString(cs) CStringUtf8::_Utf8ToCString(cs)
155 #define pioctl_T(path, op, vblob, follow) pioctl(PCCHAR(path), op, vblob, follow)
156 #define Utf8ToCString(cs) (cs)
160 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
164 code = ugen_ClientInit(noAuthFlag, (char *)AFSDIR_CLIENT_ETC_DIRPATH,
165 info->name, 0, &uclient,
166 NULL, pn, rxkad_clear,
167 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
168 0, 0, USER_SERVICE_ID);
174 OpenFile(char *file, char *rwp)
181 code = GetWindowsDirectoryA(wdir, sizeof(wdir));
182 if (code == 0 || code > sizeof(wdir))
185 /* add trailing backslash, if required */
187 if (wdir[tlen - 1] != '\\')
192 fp = fopen(wdir, rwp);
197 CString StripPath(CString& strPath)
199 int nIndex = strPath.ReverseFind('\\');
201 CString strFile = strPath.Mid(nIndex + 1);
202 if (strFile.IsEmpty())
209 StripPath(CStringArray& files)
211 for (int i = 0; i < files.GetSize(); i++)
212 files[i] = StripPath(files[i]);
218 Flush(const CStringArray& files)
221 struct ViceIoctl blob;
226 for (int i = 0; i < files.GetSize(); i++) {
227 blob.in_size = blob.out_size = 0;
229 code = pioctl_T(files[i], VIOCFLUSH, &blob, 0);
233 ShowMessageBox(IDS_FLUSH_FAILED, MB_ICONERROR, IDS_FLUSH_FAILED, files[i]);
235 ShowMessageBox(IDS_FLUSH_ERROR, MB_ICONERROR, IDS_FLUSH_ERROR, files[i], strerror(errno));
240 ShowMessageBox(IDS_FLUSH_OK, MB_ICONINFORMATION, IDS_FLUSH_OK);
244 FlushVolume(const CStringArray& files)
247 struct ViceIoctl blob;
252 for (int i = 0; i < files.GetSize(); i++) {
253 blob.in_size = blob.out_size = 0;
255 code = pioctl_T(files[i], VIOC_FLUSHVOLUME, &blob, 0);
258 ShowMessageBox(IDS_FLUSH_VOLUME_ERROR, MB_ICONERROR, IDS_FLUSH_VOLUME_ERROR, files[i], strerror(errno));
263 ShowMessageBox(IDS_FLUSH_VOLUME_OK, MB_ICONINFORMATION, IDS_FLUSH_VOLUME_OK);
267 WhichCell(CStringArray& files)
270 struct ViceIoctl blob;
275 CStringArray results;
281 for (int i = 0; i < files.GetSize(); i++) {
282 char space[AFS_PIOCTL_MAXSIZE];
285 blob.out_size = AFS_PIOCTL_MAXSIZE;
288 code = pioctl_T(files[i], VIOC_FILE_CELL_NAME, &blob, 1);
290 if (code == ENOENT) {
291 LoadString (str, IDS_CANT_GET_CELL);
294 results.Add(GetAfsError(errno));
296 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
297 results.Add(Utf8ToCString(space));
301 LoadString (str, IDS_SHOW_CELL);
302 LoadString (str2, IDS_SHOW_CELL_COLUMN);
303 CResultsDlg dlg(SHOW_CELL_HELP_ID);
304 dlg.SetContents(str, str2, StripPath(files), results);
311 char space[AFS_PIOCTL_MAXSIZE];
313 struct ViceIoctl blob;
318 blob.in = (char *) 0;
319 blob.out_size = AFS_PIOCTL_MAXSIZE;
322 code = pioctl((char *) 0, VIOC_GET_WS_CELL, &blob, 1);
325 * Cell name is left in 'space' as side effect.
326 * At present no callers of this function.
334 struct ViceIoctl blob;
338 code = pioctl(0, VIOCCKBACK, &blob, 1);
340 ShowMessageBox(IDS_CHECK_VOLUMES_ERROR, MB_ICONERROR, IDS_CHECK_VOLUMES_ERROR, GetAfsError(errno, CString()));
344 ShowMessageBox(IDS_CHECK_VOLUMES_OK, MB_OK|MB_ICONINFORMATION, IDS_CHECK_VOLUMES_OK);
350 SetCacheSizeCmd(LONG nNewCacheSize)
353 struct ViceIoctl blob;
357 blob.in = (char *) &nNewCacheSize;
358 blob.in_size = sizeof(LONG);
361 code = pioctl(0, VIOCSETCACHESIZE, &blob, 1);
363 /* error handling? */
367 WhereIs(CStringArray& files)
370 struct ViceIoctl blob;
371 CStringArray servers;
372 CStringArray resultFiles;
378 for (int i = 0; i < files.GetSize(); i++) {
379 char space[AFS_PIOCTL_MAXSIZE];
381 blob.out_size = AFS_PIOCTL_MAXSIZE;
384 memset(space, 0, sizeof(space));
386 code = pioctl_T(files[i], VIOCWHEREIS, &blob, 1);
388 resultFiles.Add(StripPath(files[i]));
389 servers.Add(GetAfsError(errno));
393 LONG *hosts = (LONG *)space;
397 for (int j = 0; j < AFS_MAXHOSTS; j++) {
400 char *hostName = hostutil_GetNameByINet(hosts[j]);
402 resultFiles.Add(StripPath(files[i]));
405 resultFiles.Add(" ");
406 servers.Add(hostName);
410 LoadString (str, IDS_SHOW_FS);
411 LoadString (str2, IDS_SHOW_FS_COLUMN);
412 CResultsDlg dlg(SHOW_FILE_SERVERS_HELP_ID);
413 dlg.SetContents(str, str2, resultFiles, servers);
418 CMtoUNIXerror(int cm_code)
421 case CM_ERROR_TIMEDOUT:
423 case CM_ERROR_NOACCESS:
425 case CM_ERROR_NOSUCHFILE:
431 case CM_ERROR_EXISTS:
433 case CM_ERROR_CROSSDEVLINK:
435 case CM_ERROR_NOTDIR:
439 case CM_ERROR_READONLY:
441 case CM_ERROR_WOULDBLOCK:
443 case CM_ERROR_NOSUCHCELL:
444 return ESRCH; /* hack */
445 case CM_ERROR_NOSUCHVOLUME:
446 return EPIPE; /* hack */
447 case CM_ERROR_NOMORETOKENS:
448 return EDOM; /* hack */
449 case CM_ERROR_TOOMANYBUFS:
450 return EFBIG; /* hack */
452 if (cm_code > 0 && cm_code < EILSEQ)
460 GetAfsError(int code, const TCHAR *filename)
464 code = CMtoUNIXerror(code);
466 if (code == EINVAL) {
468 strMsg.Format(_T("Invalid argument; it is possible that the file is not in AFS"));
470 strMsg.Format(_T("Invalid argument"));
471 } else if (code == ENOENT) {
473 strMsg.Format(_T("The file does not exist"));
475 strMsg.Format(_T("No such file returned"));
476 } else if (code == EROFS) {
477 strMsg.Format(_T("You can not change a backup or readonly volume"));
478 } else if (code == EACCES || code == EPERM) {
479 strMsg.Format(_T("You do not have the required rights to do this operation"));
480 } else if (code == ENODEV) {
481 strMsg.Format(_T("AFS service may not have started"));
482 } else if (code == ESRCH) {
483 strMsg.Format(_T("Cell name not recognized"));
484 } else if (code == ETIMEDOUT) {
485 strMsg.Format(_T("Connection timed out"));
486 } else if (code == EPIPE) {
487 strMsg.Format(_T("Volume name or ID not recognized"));
489 strMsg.Format(_T("Error 0x%x occurred"), code);
497 foldcmp (char *a, char *b)
503 if (t >= 'A' && t <= 'Z') t += 0x20;
504 if (u >= 'A' && u <= 'Z') u += 0x20;
505 if (t != u) return 1;
506 if (t == 0) return 0;
511 GetRightsString(LONG arights, int dfs)
516 if (arights & PRSFS_READ) str += _T("r");
517 if (arights & PRSFS_LOOKUP) str += _T("l");
518 if (arights & PRSFS_INSERT) str += _T("i");
519 if (arights & PRSFS_DELETE) str += _T("d");
520 if (arights & PRSFS_WRITE) str += _T("w");
521 if (arights & PRSFS_LOCK) str += _T("k");
522 if (arights & PRSFS_ADMINISTER) str += _T("a");
526 if (arights & DFS_READ) str += _T("r"); else str += _T("-");
527 if (arights & DFS_WRITE) str += _T("w"); else printf(_T("-"));
528 if (arights & DFS_EXECUTE) str += _T("x"); else printf(_T("-"));
529 if (arights & DFS_CONTROL) str += _T("c"); else printf(_T("-"));
530 if (arights & DFS_INSERT) str += _T("i"); else printf(_T("-"));
531 if (arights & DFS_DELETE) str += _T("d"); else printf(_T("-"));
532 if (arights & (DFS_USRALL)) str += _T("+");
540 EmptyAcl(const CString& strCellName)
543 CStringUtf8 ustrCell(strCellName);
545 tp = (struct Acl *)malloc(sizeof (struct Acl));
546 tp->nplus = tp->nminus = 0;
547 tp->pluslist = tp->minuslist = 0;
549 StringCbCopyA(tp->cell, sizeof(tp->cell), ustrCell);
555 CleanACL(CStringArray& names)
559 struct ViceIoctl blob;
562 ShowMessageBox(IDS_CLEANACL_MSG, MB_OK|MB_ICONINFORMATION, IDS_CLEANACL_MSG);
566 for (int i = 0; i < names.GetSize(); i++) {
567 char space[AFS_PIOCTL_MAXSIZE];
569 blob.out_size = AFS_PIOCTL_MAXSIZE;
573 code = pioctl_T(names[i], VIOCGETAL, &blob, 1);
575 ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno));
579 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
581 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
585 ShowMessageBox(IDS_CLEANACL_NOT_SUPPORTED, MB_ICONERROR, IDS_CLEANACL_NOT_SUPPORTED, names[i]);
589 changes = CleanAcl(ta, NULL);
593 /* now set the acl */
594 blob.in = AclToString(ta);
595 blob.in_size = strlen((char *)blob.in) + 1;
598 code = pioctl_T(names[i], VIOCSETAL, &blob, 1);
600 if (errno == EINVAL) {
601 ShowMessageBox(IDS_CLEANACL_INVALID_ARG, MB_ICONERROR, IDS_CLEANACL_INVALID_ARG, names[i]);
605 ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno));
612 // Derived from fs.c's ListAclCmd
614 GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& strNegative)
618 struct ViceIoctl blob;
620 int idf = 0; //getidf(as, parm_listacl_id);
621 char space[AFS_PIOCTL_MAXSIZE];
624 blob.out_size = AFS_PIOCTL_MAXSIZE;
626 blob.in = blob.out = space;
628 code = pioctl_T(strDir, VIOCGETAL, &blob, 1);
630 ShowMessageBox(IDS_GETRIGHTS_ERROR, MB_ICONERROR, IDS_GETRIGHTS_ERROR, strDir, GetAfsError(errno));
634 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
636 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
640 ShowMessageBox(IDS_DFSACL_ERROR, MB_ICONERROR, IDS_DFSACL_ERROR);
645 // printf(" Default cell = %s\n", ta->cell);
650 for (te = ta->pluslist; te; te = te->next) {
651 strNormal.Add(te->name);
652 strNormal.Add(GetRightsString(te->rights, ta->dfs));
656 if (ta->nminus > 0) {
657 for (te = ta->minuslist; te; te = te->next) {
658 strNegative.Add(te->name);
659 strNegative.Add(GetRightsString(te->rights, ta->dfs));
667 FindList(struct AclEntry *pCurEntry, const char *entryName)
670 if (!foldcmp(pCurEntry->name, PCCHAR(entryName)))
672 pCurEntry = pCurEntry->next;
679 ChangeList(struct Acl *pAcl, BYTE bNormalRights, const CString & entryName, LONG nEntryRights)
684 struct AclEntry *pEntry;
685 CStringUtf8 uEntryName(entryName);
689 pEntry = (bNormalRights ? pAcl->pluslist : pAcl->minuslist);
690 pEntry = FindList(pEntry, uEntryName);
692 /* Found the item already in the list. */
694 pEntry->rights = nEntryRights;
696 pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs);
698 pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs);
702 /* Otherwise we make a new item and plug in the new data. */
703 pEntry = (struct AclEntry *) malloc(sizeof (struct AclEntry));
706 strcpy(pEntry->name, uEntryName);
707 pEntry->rights = nEntryRights;
710 pEntry->next = pAcl->pluslist;
711 pAcl->pluslist = pEntry;
713 if (nEntryRights == 0 || nEntryRights == -1)
714 pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs);
717 pEntry->next = pAcl->minuslist;
718 pAcl->minuslist = pEntry;
720 if (nEntryRights == 0)
721 pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs);
726 Convert(const CString& strRights, int dfs, enum rtype *rtypep)
731 *rtypep = add; /* add rights, by default */
733 if (strRights == _T("read"))
734 return PRSFS_READ | PRSFS_LOOKUP;
735 if (strRights == _T("write"))
736 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK;
737 if (strRights == _T("mail"))
738 return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP;
739 if (strRights == _T("all"))
740 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
742 if (strRights == _T("none")) {
743 *rtypep = destroy; /* Remove entire entry */
747 len = strRights.GetLength();
750 for (i = 0; i < len; i++) {
751 TCHAR c = strRights[i];
752 if (c == _T('r')) mode |= PRSFS_READ;
753 else if (c == _T('l')) mode |= PRSFS_LOOKUP;
754 else if (c == _T('i')) mode |= PRSFS_INSERT;
755 else if (c == _T('d')) mode |= PRSFS_DELETE;
756 else if (c == _T('w')) mode |= PRSFS_WRITE;
757 else if (c == _T('k')) mode |= PRSFS_LOCK;
758 else if (c == _T('a')) mode |= PRSFS_ADMINISTER;
760 fprintf(stderr, "illegal rights character '%c'.\n", c);
768 SaveACL(const CString& strCellName, const CString& strDir, const CStringArray& normal, const CStringArray& negative)
771 struct ViceIoctl blob;
779 pAcl = EmptyAcl(strCellName);
781 // Set its normal rights
783 for (i = 0; i < normal.GetSize(); i += 2) {
784 rights = Convert(normal[i + 1], 0, &rtype);
785 ChangeList(pAcl, TRUE, normal[i], rights);
788 // Set its negative rights
789 for (i = 0; i < negative.GetSize(); i += 2) {
790 rights = Convert(negative[i + 1], 0, &rtype);
791 ChangeList(pAcl, FALSE, negative[i], rights);
795 blob.in = AclToString(pAcl);
797 blob.in_size = 1 + strlen((const char *)blob.in);
799 code = pioctl_T(strDir, VIOCSETAL, &blob, 1);
802 ShowMessageBox(IDS_SAVE_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_EINVAL_ERROR, strDir);
804 ShowMessageBox(IDS_SAVE_ACL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_ERROR, strDir, GetAfsError(errno, strDir));
813 CopyACL(const CString& strToDir, const CStringArray& normal, const CStringArray& negative, BOOL bClear)
816 struct ViceIoctl blob;
818 int idf = 0; // getidf(as, parm_copyacl_id);
819 char space[AFS_PIOCTL_MAXSIZE];
822 // Get ACL to copy to
823 blob.out_size = AFS_PIOCTL_MAXSIZE;
825 blob.in = blob.out = space;
827 code = pioctl_T(strToDir, VIOCGETAL, &blob, 1);
829 ShowMessageBox(IDS_ACL_READ_ERROR, MB_ICONERROR, IDS_ACL_READ_ERROR, strToDir, GetAfsError(errno, strToDir));
834 pToAcl = EmptyAcl(space);
836 pToAcl = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
838 if (pToAcl == NULL) {
839 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
843 CleanAcl(pToAcl, NULL);
846 ShowMessageBox(IDS_NO_DFS_COPY_ACL, MB_ICONERROR, IDS_NO_DFS_COPY_ACL, strToDir);
855 for (i = 0; i < normal.GetSize(); i += 2) {
856 LONG rights = Convert(normal[i + 1], 0, &rtype);
857 ChangeList(pToAcl, TRUE, normal[i], rights);
860 // Set negative rights
861 for (i = 0; i < negative.GetSize(); i += 2) {
862 LONG rights = Convert(negative[i + 1], 0, &rtype);
863 ChangeList(pToAcl, FALSE, normal[i], rights);
867 blob.in = AclToString(pToAcl);
869 blob.in_size = 1 + strlen((char *)blob.in);
871 code = pioctl_T(strToDir, VIOCSETAL, &blob, 1);
875 ShowMessageBox(IDS_COPY_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_COPY_ACL_EINVAL_ERROR, strToDir);
877 ShowMessageBox(IDS_COPY_ACL_ERROR, MB_ICONERROR, IDS_COPY_ACL_ERROR, strToDir, GetAfsError(errno, strToDir));
883 ShowMessageBox(IDS_COPY_ACL_OK, MB_OK|MB_ICONINFORMATION, IDS_COPY_ACL_OK);
889 ParseMountPoint(const CString strFile, CString strMountPoint)
894 CString strMountPointInfo;
896 if (strMountPoint[0] == '#')
898 else if (strMountPoint[0] == '%')
899 strType = "Read/Write";
901 int nColon = strMountPoint.Find(':');
903 strCell = strMountPoint.Mid(1, nColon - 1);
904 strVolume = strMountPoint.Mid(nColon + 1);
906 strVolume = strMountPoint.Mid(1);
908 strMountPointInfo = strFile + _T("\t") + strVolume + _T("\t") + strCell + _T("\t") + strType;
910 return strMountPointInfo;
914 ParseSymlink(const CString strFile, CString strSymlink)
916 CString strSymlinkInfo;
918 strSymlinkInfo = strFile + _T("\t") + strSymlink;
920 return strSymlinkInfo;
924 IsPathInAfs(const CString & strPath)
926 struct ViceIoctl blob;
927 cm_ioctlQueryOptions_t options;
933 memset(&options, 0, sizeof(options));
934 options.size = sizeof(options);
935 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
937 blob.in_size = options.size; /* no variable length data */
939 blob.out_size = sizeof(cm_fid_t);
940 blob.out = (char *) &fid;
942 code = pioctl_T(strPath, VIOCGETFID, &blob, 1);
944 if ((errno == EINVAL) || (errno == ENOENT))
951 IsFreelanceRoot(const CString& apath)
953 struct ViceIoctl blob;
955 char space[AFS_PIOCTL_MAXSIZE];
958 blob.out_size = AFS_PIOCTL_MAXSIZE;
961 code = pioctl_T(apath, VIOC_FILE_CELL_NAME, &blob, 1);
963 return !strcmp("Freelance.Local.Root",space);
964 return 1; /* assume it is because it is more restrictive that way */
970 static char buffer[1024] = "AFS";
976 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
977 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
978 if (code == ERROR_SUCCESS) {
979 dummyLen = sizeof(buffer);
980 code = RegQueryValueExA(parmKey, "NetbiosName", NULL, NULL,
981 (LPBYTE)buffer, &dummyLen);
982 RegCloseKey (parmKey);
984 strcpy(buffer, "AFS");
990 FixNetbiosPath(CString& path)
992 if (!IsPathInAfs(path)) {
994 const char * nbname = NetbiosName();
997 nbroot.Format(_T("\\\\%S\\"), nbname);
999 nbroot.Format(_T("\\\\%s\\"), nbname);
1002 if (nbroot.CompareNoCase(path) == 0) {
1003 path.Append(_T("all\\"));
1008 #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
1013 static BOOL fAdmin = FALSE;
1014 static BOOL fTested = FALSE;
1018 /* Obtain the SID for the AFS client admin group. If the group does
1019 * not exist, then assume we have AFS client admin privileges.
1021 PSID psidAdmin = NULL;
1022 DWORD dwSize, dwSize2;
1023 TCHAR pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
1024 TCHAR *pszRefDomain = NULL;
1025 SID_NAME_USE snu = SidTypeGroup;
1027 dwSize = sizeof(pszAdminGroup);
1029 if (!GetComputerName(pszAdminGroup, &dwSize)) {
1030 /* Can't get computer name. We return false in this case.
1031 Retain fAdmin and fTested. This shouldn't happen.*/
1038 lstrcat(pszAdminGroup, _T("\\"));
1039 lstrcat(pszAdminGroup, _T(AFSCLIENT_ADMIN_GROUPNAME));
1041 LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
1042 /* that should always fail. */
1044 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1045 /* if we can't find the group, then we allow the operation */
1050 if (dwSize == 0 || dwSize2 == 0) {
1056 psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
1057 pszRefDomain = (TCHAR *)malloc(dwSize2);
1059 if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
1060 /* We can't lookup the group now even though we looked it up earlier.
1061 Could this happen? */
1064 /* Then open our current ProcessToken */
1067 if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
1070 if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
1071 /* We'll have to allocate a chunk of memory to store the list of
1072 * groups to which this user belongs; find out how much memory
1076 PTOKEN_GROUPS pGroups;
1078 GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
1080 pGroups = (PTOKEN_GROUPS)malloc(dwSize);
1082 /* Allocate that buffer, and read in the list of groups. */
1083 if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
1085 /* Look through the list of group SIDs and see if any of them
1086 * matches the AFS Client Admin group SID.
1089 for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
1091 if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
1101 /* if do not have permission because we were not explicitly listed
1102 * in the Admin Client Group let's see if we are the SYSTEM account
1105 PTOKEN_USER pTokenUser;
1106 SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
1107 PSID pSidLocalSystem = 0;
1110 GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
1112 pTokenUser = (PTOKEN_USER)malloc(dwSize);
1114 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
1115 gle = GetLastError();
1117 if (AllocateAndInitializeSid( &SIDAuth, 1,
1118 SECURITY_LOCAL_SYSTEM_RID,
1119 0, 0, 0, 0, 0, 0, 0,
1122 if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
1126 FreeSid(pSidLocalSystem);
1145 Parent(const CString& path)
1147 int last_slash = path.ReverseFind(_T('\\'));
1149 if (last_slash != -1) {
1150 CString ret = path.Left(last_slash + 1);
1153 if (path.GetLength() >= 2 && path[1] == _T(':')) {
1154 CString ret = path.Left(2);
1155 ret.AppendChar(_T('.'));
1158 CString ret = _T(".");
1165 LastComponent(const CString& path)
1167 int last_slash = path.ReverseFind(_T('\\'));
1169 if (last_slash != -1) {
1170 CString ret = path.Mid(last_slash + 1);
1173 if (path.GetLength() >= 2 && path[1] == _T(':')) {
1174 CString ret = path.Mid(2);
1184 GetCell(const CString & path)
1186 char cellname[MAXCELLCHARS];
1188 struct ViceIoctl blob;
1191 blob.out_size = sizeof(cellname);
1192 blob.out = cellname;
1194 code = pioctl_T(path, VIOC_FILE_CELL_NAME, &blob, 1);
1201 return Utf8ToCString(cellname);
1207 ListMount(CStringArray& files)
1210 struct ViceIoctl blob;
1213 CString parent_dir; /* Parent directory of true name */
1214 CStringUtf8 last_component; /* Last component of true name */
1216 CStringArray mountPoints;
1218 HOURGLASS hourglass;
1222 for (int i = 0; i < files.GetSize(); i++) {
1223 int last_slash = files[i].ReverseFind(_T('\\'));
1224 char space[AFS_PIOCTL_MAXSIZE];
1226 if (last_slash != -1) {
1227 last_component.SetString( files[i].Mid(last_slash + 1) );
1228 parent_dir.SetString( files[i].Left(last_slash + 1) );
1229 FixNetbiosPath(parent_dir);
1231 // The path is of the form "C:foo" or just "foo". If
1232 // there is a drive, then use the current directory of
1233 // that drive. Otherwise we just use '.'.
1235 if (files[i].GetLength() >= 2 && files[i][1] == _T(':')) {
1236 parent_dir.Format(_T("%c:."), files[i][0]);
1237 last_component.SetString( files[i].Mid(2) );
1239 parent_dir.SetString( _T("."));
1240 last_component.SetString( files[i] );
1244 blob.in_size = last_component.GetLength() + 1;
1245 blob.in = last_component.GetBuffer();
1246 blob.out_size = AFS_PIOCTL_MAXSIZE;
1248 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1250 code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
1252 last_component.ReleaseBuffer();
1256 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
1257 nPos = strlen(space) - 1;
1258 if (space[nPos] == '.')
1260 mountPoints.Add(ParseMountPoint(StripPath(files[i]), Utf8ToCString(space)));
1263 if (errno == EINVAL)
1264 mountPoints.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i])));
1266 mountPoints.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i]))));
1270 CMountPointsDlg dlg;
1271 dlg.SetMountPoints(mountPoints);
1278 MakeMount(const CString& strDir,
1279 const CString& strVolName,
1280 const CString& strInCellName,
1284 struct ViceIoctl blob;
1285 HOURGLASS hourglass;
1287 ASSERT(strVolName.GetLength() < 64);
1289 CString strParent = Parent(strDir);
1291 FixNetbiosPath(strParent);
1292 if (!IsPathInAfs(strParent)) {
1293 ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR);
1297 CString strPath = strParent + LastComponent(strDir);
1299 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1300 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR,
1301 IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1307 strMount.Format(_T("%c%s%s%s."),
1308 ((bRW)?_T('%'):_T('#')),
1310 ((strInCellName.IsEmpty())?_T(""):_T(":")),
1313 CStringUtf8 ustrMount(strMount);
1316 blob.in_size = ustrMount.GetLength() + 1;
1317 blob.in = ustrMount.GetBuffer();
1320 code = pioctl_T(strPath, VIOC_AFS_CREATE_MT_PT, &blob, 0);
1322 ustrMount.ReleaseBuffer();
1325 ShowMessageBox(IDS_MOUNT_POINT_ERROR, MB_ICONERROR, IDS_MOUNT_POINT_ERROR, GetAfsError(errno, strDir));
1333 RemoveSymlink(const CString& strName)
1337 struct ViceIoctl blob;
1338 char lsbuffer[1024];
1340 HOURGLASS hourglass;
1342 CString strParent = Parent(strName);
1343 CStringUtf8 ustrLast(LastComponent(strName));
1344 FixNetbiosPath(strParent);
1346 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1347 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1351 blob.in_size = ustrLast.GetLength() + 1;
1352 blob.in = ustrLast.GetBuffer();
1353 blob.out = lsbuffer;
1354 blob.out_size = sizeof(lsbuffer);
1355 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 0);
1356 ustrLast.ReleaseBuffer();
1360 blob.in_size = ustrLast.GetLength() + 1;
1361 blob.in = ustrLast.GetBuffer();
1363 code = pioctl_T(strParent, VIOC_DELSYMLINK, &blob, 0);
1365 ustrLast.ReleaseBuffer();
1371 IsSymlink(const CString& strName)
1373 struct ViceIoctl blob;
1375 char space[AFS_PIOCTL_MAXSIZE];
1376 HOURGLASS hourglass;
1378 CStringUtf8 ustrLast(LastComponent(strName));
1379 CString strParent = Parent(strName);
1381 FixNetbiosPath(strParent);
1383 blob.in_size = ustrLast.GetLength() + 1;
1384 blob.in = ustrLast.GetBuffer();
1385 blob.out_size = AFS_PIOCTL_MAXSIZE;
1387 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1389 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1);
1391 ustrLast.ReleaseBuffer();
1398 IsMountPoint(const CString& path)
1401 struct ViceIoctl blob;
1402 char lsbuffer[1024];
1404 HOURGLASS hourglass;
1406 CString parent = Parent(path);
1407 FixNetbiosPath(parent);
1409 CStringUtf8 mountpoint(LastComponent(path));
1411 blob.in_size = mountpoint.GetLength() + 1;
1412 blob.in = mountpoint.GetBuffer();
1413 blob.out = lsbuffer;
1414 blob.out_size = sizeof(lsbuffer);
1416 code = pioctl_T(parent, VIOC_AFS_STAT_MT_PT, &blob, 0);
1418 mountpoint.ReleaseBuffer();
1425 * Delete AFS mount points. Variables are used as follows:
1426 * tbuffer: Set to point to the null-terminated directory name of the mount point
1427 * (or ``.'' if none is provided)
1428 * tp: Set to point to the actual name of the mount point to nuke.
1431 RemoveMount(CStringArray& files)
1434 struct ViceIoctl blob;
1436 CStringArray results;
1440 HOURGLASS hourglass;
1442 for (int i = 0; i < files.GetSize(); i++) {
1443 if (!IsMountPoint(files[i])) {
1445 if (errno == EINVAL)
1446 results.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i])));
1448 results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i]))));
1449 continue; // don't bother trying
1452 CString parent = Parent(files[i]);
1453 CStringUtf8 mountpoint(LastComponent(files[i]));
1454 FixNetbiosPath(parent);
1456 if ( IsFreelanceRoot(parent) && !IsAdmin() ) {
1457 results.Add(GetMessageString(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, StripPath(files[i])));
1459 continue; /* skip */
1463 blob.in_size = mountpoint.GetLength() + 1;
1464 blob.in = mountpoint.GetBuffer();
1466 code = pioctl_T(parent, VIOC_AFS_DELETE_MT_PT, &blob, 0);
1468 mountpoint.ReleaseBuffer();
1472 results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i]))));
1474 results.Add(GetMessageString(IDS_DELETED));
1477 LoadString (str, IDS_REMOVE_MP);
1478 LoadString (str2, IDS_REMOVE_MP_COLUMN);
1479 CResultsDlg dlg(REMOVE_MOUNT_POINTS_HELP_ID);
1480 dlg.SetContents(str, str2, StripPath(files), results);
1487 GetVolumeInfo(CString strFile, CVolInfo& volInfo)
1490 struct ViceIoctl blob;
1491 struct VolumeStatus *status;
1493 char space[AFS_PIOCTL_MAXSIZE];
1494 HOURGLASS hourglass;
1496 volInfo.m_strFilePath = strFile;
1497 volInfo.m_strFileName = StripPath(strFile);
1500 volInfo.m_strName = "VolumeName";
1502 volInfo.m_nQuota = 20 * 1024 * 1024;
1503 volInfo.m_nNewQuota = volInfo.m_nQuota;
1504 volInfo.m_nUsed = volInfo.m_nQuota / 2;
1505 volInfo.m_nPartSize = 50 * 1024 * 1024;
1506 volInfo.m_nPartFree = 30 * 1024 * 1024;
1507 volInfo.m_nDup = -1;
1511 blob.out_size = AFS_PIOCTL_MAXSIZE;
1515 code = pioctl_T(strFile, VIOCGETVOLSTAT, &blob, 1);
1516 if (code || blob.out_size < sizeof(*status)) {
1517 volInfo.m_strErrorMsg = GetAfsError(errno, strFile);
1521 status = (VolumeStatus *)space;
1522 name = (char *)status + sizeof(*status);
1524 volInfo.m_strName = Utf8ToCString(name);
1525 volInfo.m_nID = status->Vid;
1526 volInfo.m_nQuota = status->MaxQuota;
1527 volInfo.m_nNewQuota = status->MaxQuota;
1528 volInfo.m_nUsed = status->BlocksInUse;
1529 volInfo.m_nPartSize = status->PartMaxBlocks;
1530 volInfo.m_nPartFree = status->PartBlocksAvail;
1531 volInfo.m_nDup = -1;
1537 SetVolInfo(CVolInfo& volInfo)
1540 struct ViceIoctl blob;
1541 struct VolumeStatus *status;
1543 char space[AFS_PIOCTL_MAXSIZE];
1544 HOURGLASS hourglass;
1546 blob.out_size = AFS_PIOCTL_MAXSIZE;
1547 blob.in_size = sizeof(*status) + 3; /* for the three terminating nulls */
1551 status = (VolumeStatus *)space;
1552 status->MinQuota = -1;
1553 status->MaxQuota = volInfo.m_nNewQuota;
1555 input = (char *)status + sizeof(*status);
1556 *(input++) = '\0'; /* never set name: this call doesn't change vldb */
1557 *(input++) = '\0'; // No offmsg
1558 *(input++) = '\0'; // No motd
1561 FILE *fp = OpenFile(szLogFileName, "a");
1563 fprintf(fp, "\nSetVolInfo() pioctl parms:\n");
1564 fprintf(fp, "\tpathp = %s\n\topcode = VIOCSETVOLSTAT (%d)\n\tblobp = %ld\n", PCCHAR(volInfo.m_strFilePath), VIOCSETVOLSTAT, &blob);
1565 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);
1566 fprintf(fp, "\t\t\tstatus->MinQuota = %ld\n", status->MinQuota);
1567 fprintf(fp, "\t\t\tstatus->MaxQuota = %ld\n", status->MaxQuota);
1568 fprintf(fp, "\t\t\tOther status fields aren't set\n");
1569 fprintf(fp, "\t\t\t3 nulls follow the VolumeStatus structure.\n");
1570 fprintf(fp, "\tfollow = 1\n");
1575 code = pioctl_T(volInfo.m_strFilePath, VIOCSETVOLSTAT, &blob, 1);
1576 if (code || blob.out_size < sizeof(*status)) {
1577 ShowMessageBox(IDS_SET_QUOTA_ERROR, MB_ICONERROR, IDS_SET_QUOTA_ERROR, GetAfsError(errno, volInfo.m_strName));
1585 GetCellName(const CString& cellNamep, struct afsconf_cell *infop)
1587 CStringUtf8 uCellName(cellNamep);
1589 StringCbCopyA(infop->name, sizeof(infop->name), uCellName);
1593 CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast)
1596 struct ViceIoctl blob;
1599 struct afsconf_cell info;
1600 struct chservinfo checkserv;
1601 char space[AFS_PIOCTL_MAXSIZE];
1602 HOURGLASS hourglass;
1604 memset(&checkserv, 0, sizeof(struct chservinfo));
1605 blob.in_size = sizeof(struct chservinfo);
1606 blob.in = (caddr_t)&checkserv;
1608 blob.out_size = AFS_PIOCTL_MAXSIZE;
1610 memset(space, 0, sizeof(afs_int32)); /* so we assure zero when nothing is copied back */
1612 if (nCellsToCheck == SPECIFIC_CELL) {
1614 GetCellName(strCellName, &info);
1615 strcpy(checkserv.tbuffer,info.name);
1616 checkserv.tsize = strlen(info.name) + 1;
1618 if (nCellsToCheck != ALL_CELLS)
1620 strcpy(checkserv.tbuffer, "\0");
1621 checkserv.tsize = 0;
1624 temp |= 1; /* set fast flag */
1626 checkserv.magic = 0x12345678; /* XXX */
1627 checkserv.tflags = temp;
1628 checkserv.tinterval = -1; /* don't change current interval */
1630 code = pioctl_utf8(0, VIOCCKSERV, &blob, 1);
1632 ShowMessageBox(IDS_CHECK_SERVERS_ERROR, MB_ICONERROR, IDS_CHECK_SERVERS_ERROR, GetAfsError(errno, CString()));
1636 memcpy(&temp, space, sizeof(LONG));
1639 ShowMessageBox(IDS_ALL_SERVERS_RUNNING, MB_OK|MB_ICONINFORMATION, IDS_ALL_SERVERS_RUNNING);
1643 CStringArray servers;
1644 for (j = 0; j < AFS_MAXHOSTS; j++) {
1645 memcpy(&temp, space + j * sizeof(LONG), sizeof(LONG));
1649 char *name = hostutil_GetNameByINet(temp);
1653 CDownServersDlg dlg;
1654 dlg.SetServerNames(servers);
1661 GetTokenInfo(CStringArray& tokenInfo)
1665 time_t current_time;
1666 time_t tokenExpireTime;
1670 struct ktc_principal serviceName, clientName;
1671 struct ktc_token token;
1673 CString strTokenInfo;
1674 CString strUserName;
1675 CString strCellName;
1678 // tokenInfo.Add("");
1682 HOURGLASS hourglass;
1684 // printf("\nTokens held by the Cache Manager:\n\n");
1686 current_time = time(0);
1689 rc = ktc_ListTokens(cellNum, &cellNum, &serviceName);
1690 if (rc == KTC_NOENT) {
1692 // printf(" --End of list --\n");
1695 else if (rc == KTC_NOCM) {
1696 ShowMessageBox(IDS_GET_TOKENS_NO_AFS_SERVICE);
1697 // printf("AFS service may not have started\n");
1701 ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR, rc);
1703 // printf("Unexpected error, code %d\n", rc);
1707 rc = ktc_GetToken(&serviceName, &token, sizeof(token), &clientName);
1709 ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR2, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR2,
1710 serviceName.name, serviceName.instance, serviceName.cell, rc);
1714 tokenExpireTime = token.endTime;
1716 strcpy(userName, clientName.name);
1717 if (clientName.instance[0] != 0) {
1718 strcat(userName, ".");
1719 strcat(userName, clientName.instance);
1722 BOOL bShowName = FALSE;
1724 if (userName[0] == '\0')
1725 ; //printf("Tokens");
1726 // AFS ID is not returned at this time.
1727 // else if (strncmp(userName, "AFS ID", 6) == 0)
1728 // printf("User's (%s) tokens", userName);
1729 // sscanf(userName, "(AFS ID %s)", szAfsID);
1730 else if (strncmp(userName, "Unix UID", 8) == 0)
1731 ; //printf("Tokens");
1733 strUserName = userName;
1734 // printf("User %s's tokens", userName);
1736 // printf(" for %s%s%s@%s ", serviceName.name, serviceName.instance[0] ? "." : "", serviceName.instance, serviceName.cell);
1737 strCellName = serviceName.cell;
1739 if (tokenExpireTime <= current_time)
1740 strExpir = "[>> Expired <<]";
1741 // printf("[>> Expired <<]\n");
1743 expireString = ctime(&tokenExpireTime);
1744 expireString += 4; /* Skip day of week */
1745 expireString[12] = '\0'; /* Omit secs & year */
1746 // printf("[Expires %s]\n", expireString);
1748 strExpir.Format(_T("%S"), expireString);
1750 strExpir.Format(_T("%s"), expireString);
1754 strTokenInfo = strUserName + "\t" + strCellName + "\t" + strExpir + "\t" + strCellName;
1755 tokenInfo.Add(strTokenInfo);
1759 // printf("Press <Enter> or <Return> when finished: ");
1765 MakeSymbolicLink(const CString& strName, const CString& strTarget)
1767 struct ViceIoctl blob;
1769 HOURGLASS hourglass;
1771 CString strParent = Parent(strName);
1772 FixNetbiosPath(strParent);
1774 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1775 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1779 CStringUtf8 ustrTarget(strTarget);
1781 blob.in_size = ustrTarget.GetLength() + 1;
1782 blob.in = ustrTarget.GetBuffer();
1786 code = pioctl_T(strName, VIOC_SYMLINK, &blob, 0);
1788 ustrTarget.ReleaseBuffer();
1796 ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath)
1798 ASSERT(nlenPath<MAX_PATH);
1799 struct ViceIoctl blob;
1800 char orig_name[MAX_PATH+1]; /*Original name, may be modified*/
1801 char true_name[MAX_PATH+1]; /*``True'' dirname (e.g., symlink target)*/
1802 char parent_dir[MAX_PATH+1]; /*Parent directory of true name*/
1803 char *last_component; /*Last component of true name*/
1805 char space[AFS_PIOCTL_MAXSIZE];
1806 HOURGLASS hourglass;
1808 strcpy(orig_name, strName);
1809 strcpy(true_name, orig_name);
1811 * Find rightmost slash, if any.
1813 last_component = (char *) strrchr(true_name, '\\');
1814 if (!last_component)
1815 last_component = (char *) strrchr(true_name, '/');
1816 if (last_component) {
1818 * Found it. Designate everything before it as the parent directory,
1819 * everything after it as the final component.
1821 strncpy(parent_dir, true_name, last_component - true_name + 1);
1822 parent_dir[last_component - true_name + 1] = 0;
1823 last_component++; /*Skip the slash*/
1825 if (!IsPathInAfs(parent_dir)) {
1826 const char * nbname = NetbiosName();
1827 int len = strlen(nbname);
1829 if (parent_dir[0] == '\\' && parent_dir[1] == '\\' &&
1830 parent_dir[len+2] == '\\' &&
1831 parent_dir[len+3] == '\0' &&
1832 !strnicmp(nbname,&parent_dir[2],len))
1834 sprintf(parent_dir,"\\\\%s\\all\\", nbname);
1840 * No slash appears in the given file name. Set parent_dir to the current
1841 * directory, and the last component as the given name.
1843 fs_ExtractDriveLetter(true_name, parent_dir);
1844 strcat(parent_dir, ".");
1845 last_component = true_name;
1846 fs_StripDriveLetter(true_name, true_name, sizeof(true_name));
1848 blob.in = last_component;
1849 blob.in_size = strlen(last_component)+1;
1850 blob.out_size = AFS_PIOCTL_MAXSIZE;
1852 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1853 if ((code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1)))
1854 strcpy(space,"???");
1855 ASSERT(strlen(space)<MAX_PATH);
1856 strncpy(strPath,space,nlenPath);
1860 ListSymlink(CStringArray& files)
1863 struct ViceIoctl blob;
1865 CStringArray symlinks;
1866 char space[AFS_PIOCTL_MAXSIZE];
1867 HOURGLASS hourglass;
1871 for (int i = 0; i < files.GetSize(); i++) {
1873 CString strParent = Parent(files[i]);
1874 CStringUtf8 ustrLast(LastComponent(files[i]));
1876 FixNetbiosPath(strParent);
1878 blob.in_size = ustrLast.GetLength() + 1;
1879 blob.in = ustrLast.GetBuffer();
1880 blob.out_size = AFS_PIOCTL_MAXSIZE;
1882 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1884 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1);
1886 ustrLast.ReleaseBuffer();
1892 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
1893 syml = Utf8ToCString(space);
1894 len = syml.GetLength();
1897 if (syml[len - 1] == _T('.'))
1898 syml.Truncate(len - 1);
1901 symlinks.Add(ParseSymlink(StripPath(files[i]), syml));
1905 if (errno == EINVAL)
1906 symlinks.Add(GetMessageString(IDS_NOT_SYMLINK_ERROR, StripPath(files[i])));
1908 symlinks.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i]))));
1913 dlg.SetSymlinks(symlinks);