LINUX: afs_create infinite fetchStatus loop
[pkg-k5-afs_openafs.git] / src / WINNT / client_exp / gui2fs.cpp
blob769594aaa7a3c764459d41c0c04870796ab35b29
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
10 #include "stdafx.h"
11 #include <winsock2.h>
12 #include <ws2tcpip.h>
14 extern "C" {
15 #include <afsconfig.h>
16 #include <afs/param.h>
17 #include <roken.h>
18 #include <afs/stds.h>
21 #include <errno.h>
22 #include <time.h>
24 #include "gui2fs.h"
25 #include "msgs.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"
33 extern "C" {
34 #include <rx/rx_globals.h>
35 #include "fs_utils.h"
36 #include "fs_acl.h"
37 #include <afs/afsint.h>
38 #include <afs/afs_consts.h>
39 #include <afs/cellconfig.h>
40 #include <afs/ptserver.h>
41 #include <afs/ptuser.h>
42 #include <afs/vldbint.h>
43 #include <afs/volser.h>
44 #include <afs/auth.h>
45 #include <WINNT\afsreg.h>
46 #include <cm.h>
47 #include <cm_nls.h>
48 #include <osi.h>
49 #include <cm_user.h>
50 #include <cm_scache.h>
51 #include <cm_ioctl.h>
52 #include <cm_config.h>
55 #define STRSAFE_NO_DEPRECATE
56 #include <strsafe.h>
59 * the NO_CALLER symbol is used to document functions
60 * that are present in this file but have no caller
62 #define NO_CALLER
65 #define PCCHAR(str) ((char *)(const char *)(str))
66 #define VL_NOENT (363524L)
68 #define MAXNAME 100
69 #define MAXINSIZE 1300 /* pioctl complains if data is larger than this */
70 #define VMSGSIZE 128 /* size of msg buf in volume hdr */
72 #define MAXCELLCHARS 64
73 #define MAXHOSTCHARS 64
74 #define MAXHOSTSPERCELL 8
76 static struct ubik_client *uclient;
77 static int rxInitDone = 0;
78 static char pn[] = "fs";
80 // #define LOGGING_ON // Enable this to log certain pioctl calls
82 #ifdef LOGGING_ON
83 static char *szLogFileName = "afsguilog.txt";
84 #endif
86 #ifdef UNICODE
87 class CStringUtf8 : public CStringA
89 public:
90 CStringUtf8(const CStringW& csw) : CStringA()
92 SetString(csw);
95 CStringUtf8(const char * cp) : CStringA(cp) {}
97 CStringUtf8() :CStringA() {}
99 void SetString(const CStringW& csw)
101 char buffer[1024];
102 int rv;
104 rv = WideCharToMultiByte(CP_UTF8, 0, csw, -1,
105 buffer, sizeof(buffer),
106 NULL, FALSE);
108 if (rv != 0) {
109 CStringA::SetString(buffer);
110 } else {
111 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
112 int cb_req;
114 cb_req = WideCharToMultiByte(CP_UTF8, 0, csw, -1, NULL, 0, NULL, FALSE);
115 if (cb_req != 0) {
116 cb_req ++;
118 WideCharToMultiByte(CP_UTF8, 0, csw, -1, CStringA::GetBuffer(cb_req), cb_req, NULL, FALSE);
119 CStringA::ReleaseBuffer();
121 } else {
122 #ifdef DEBUG
123 DebugBreak();
124 #endif
129 static CString _Utf8ToCString(const char * ustr)
131 CString cs;
132 int cch;
134 cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, NULL, 0);
135 if (cch == 0) {
136 cs.Empty();
137 return cs;
140 cch++;
141 cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, cs.GetBuffer(cch), cch);
142 cs.ReleaseBuffer();
144 return cs;
148 long
149 pioctl_T(const CString& path, long opcode, struct ViceIoctl * blob, int follow)
151 CStringUtf8 upath(path);
153 return pioctl_utf8(PCCHAR(upath), opcode, blob, follow);
156 #define Utf8ToCString(cs) CStringUtf8::_Utf8ToCString(cs)
157 #else
158 #define pioctl_T(path, op, vblob, follow) pioctl(PCCHAR(path), op, vblob, follow)
159 #define Utf8ToCString(cs) (cs)
160 #endif
162 static int NO_CALLER
163 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
165 afs_int32 code;
167 code = ugen_ClientInit(noAuthFlag, (char *)AFSDIR_CLIENT_ETC_DIRPATH,
168 info->name, 0, &uclient,
169 NULL, pn, rxkad_clear,
170 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
171 0, 0, USER_SERVICE_ID);
172 rxInitDone = 1;
173 return code;
176 static FILE *
177 OpenFile(char *file, char *rwp)
179 char wdir[256];
180 long code;
181 long tlen;
182 FILE *fp;
184 code = GetWindowsDirectoryA(wdir, sizeof(wdir));
185 if (code == 0 || code > sizeof(wdir))
186 return FALSE;
188 /* add trailing backslash, if required */
189 tlen = strlen(wdir);
190 if (wdir[tlen - 1] != '\\')
191 strcat(wdir, "\\");
193 strcat(wdir, file);
195 fp = fopen(wdir, rwp);
197 return fp;
200 CString StripPath(const CString& strPath)
202 int nIndex = strPath.ReverseFind('\\');
204 CString strFile = strPath.Mid(nIndex + 1);
205 if (strFile.IsEmpty())
206 return strPath;
208 return strFile;
211 CStringArray&
212 StripPath(CStringArray& files)
214 for (int i = 0; i < files.GetSize(); i++)
215 files[i] = StripPath(files[i]);
217 return files;
220 void
221 Flush(const CStringArray& files)
223 LONG code;
224 struct ViceIoctl blob;
225 int error = 0;
227 HOURGLASS hourglass;
229 for (int i = 0; i < files.GetSize(); i++) {
230 blob.in_size = blob.out_size = 0;
232 code = pioctl_T(files[i], VIOCFLUSH, &blob, 0);
233 if (code) {
234 error = 1;
235 if (errno == EMFILE)
236 ShowMessageBox(IDS_FLUSH_FAILED, MB_ICONERROR, IDS_FLUSH_FAILED, files[i]);
237 else
238 ShowMessageBox(IDS_FLUSH_ERROR, MB_ICONERROR, IDS_FLUSH_ERROR, files[i], strerror(errno));
242 if (!error)
243 ShowMessageBox(IDS_FLUSH_OK, MB_ICONINFORMATION, IDS_FLUSH_OK);
246 void
247 FlushVolume(const CStringArray& files)
249 LONG code;
250 struct ViceIoctl blob;
251 int error = 0;
253 HOURGLASS hourglass;
255 for (int i = 0; i < files.GetSize(); i++) {
256 blob.in_size = blob.out_size = 0;
258 code = pioctl_T(files[i], VIOC_FLUSHVOLUME, &blob, 0);
259 if (code) {
260 error = 1;
261 ShowMessageBox(IDS_FLUSH_VOLUME_ERROR, MB_ICONERROR, IDS_FLUSH_VOLUME_ERROR, files[i], strerror(errno));
265 if (!code)
266 ShowMessageBox(IDS_FLUSH_VOLUME_OK, MB_ICONINFORMATION, IDS_FLUSH_VOLUME_OK);
269 void NO_CALLER
270 WhichCell(CStringArray& files)
272 LONG code;
273 struct ViceIoctl blob;
274 int error;
275 CString str;
276 CString str2;
278 CStringArray results;
280 error = 0;
282 HOURGLASS hourglass;
284 for (int i = 0; i < files.GetSize(); i++) {
285 char space[AFS_PIOCTL_MAXSIZE];
287 blob.in_size = 0;
288 blob.out_size = AFS_PIOCTL_MAXSIZE;
289 blob.out = space;
291 code = pioctl_T(files[i], VIOC_FILE_CELL_NAME, &blob, 1);
292 if (code) {
293 if (code == ENOENT) {
294 LoadString (str, IDS_CANT_GET_CELL);
295 results.Add(str);
296 } else
297 results.Add(GetAfsError(errno));
298 } else {
299 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
300 results.Add(Utf8ToCString(space));
304 LoadString (str, IDS_SHOW_CELL);
305 LoadString (str2, IDS_SHOW_CELL_COLUMN);
306 CResultsDlg dlg(SHOW_CELL_HELP_ID);
307 dlg.SetContents(str, str2, StripPath(files), results);
308 dlg.DoModal();
311 void NO_CALLER
312 WSCellCmd(void)
314 char space[AFS_PIOCTL_MAXSIZE];
315 LONG code;
316 struct ViceIoctl blob;
318 HOURGLASS hourglass;
320 blob.in_size = 0;
321 blob.in = (char *) 0;
322 blob.out_size = AFS_PIOCTL_MAXSIZE;
323 blob.out = space;
325 code = pioctl((char *) 0, VIOC_GET_WS_CELL, &blob, 1);
328 * Cell name is left in 'space' as side effect.
329 * At present no callers of this function.
333 BOOL NO_CALLER
334 CheckVolumes(void)
336 LONG code;
337 struct ViceIoctl blob;
339 blob.in_size = 0;
340 blob.out_size = 0;
341 code = pioctl(0, VIOCCKBACK, &blob, 1);
342 if (code) {
343 ShowMessageBox(IDS_CHECK_VOLUMES_ERROR, MB_ICONERROR, IDS_CHECK_VOLUMES_ERROR, GetAfsError(errno, CString()));
344 return FALSE;
347 ShowMessageBox(IDS_CHECK_VOLUMES_OK, MB_OK|MB_ICONINFORMATION, IDS_CHECK_VOLUMES_OK);
349 return TRUE;
352 void NO_CALLER
353 SetCacheSizeCmd(LONG nNewCacheSize)
355 LONG code;
356 struct ViceIoctl blob;
358 HOURGLASS hourglass;
360 blob.in = (char *) &nNewCacheSize;
361 blob.in_size = sizeof(LONG);
362 blob.out_size = 0;
364 code = pioctl(0, VIOCSETCACHESIZE, &blob, 1);
366 /* error handling? */
369 void NO_CALLER
370 WhereIs(CStringArray& files)
372 LONG code;
373 struct ViceIoctl blob;
374 CStringArray servers;
375 CStringArray resultFiles;
376 CString str;
377 CString str2;
379 HOURGLASS hourglass;
381 for (int i = 0; i < files.GetSize(); i++) {
382 char space[AFS_PIOCTL_MAXSIZE];
384 blob.out_size = AFS_PIOCTL_MAXSIZE;
385 blob.in_size = 0;
386 blob.out = space;
387 memset(space, 0, sizeof(space));
389 code = pioctl_T(files[i], VIOCWHEREIS, &blob, 1);
390 if (code) {
391 resultFiles.Add(StripPath(files[i]));
392 servers.Add(GetAfsError(errno));
393 continue;
396 LONG *hosts = (LONG *)space;
397 BOOL bFirst = TRUE;
398 str = "";
400 for (int j = 0; j < AFS_MAXHOSTS; j++) {
401 if (hosts[j] == 0)
402 break;
403 char *hostName = hostutil_GetNameByINet(hosts[j]);
404 if (bFirst) {
405 resultFiles.Add(StripPath(files[i]));
406 bFirst = FALSE;
407 } else
408 resultFiles.Add(" ");
409 servers.Add(hostName);
413 LoadString (str, IDS_SHOW_FS);
414 LoadString (str2, IDS_SHOW_FS_COLUMN);
415 CResultsDlg dlg(SHOW_FILE_SERVERS_HELP_ID);
416 dlg.SetContents(str, str2, resultFiles, servers);
417 dlg.DoModal();
420 static int
421 CMtoUNIXerror(int cm_code)
423 switch (cm_code) {
424 case CM_ERROR_TIMEDOUT:
425 return ETIMEDOUT;
426 case CM_ERROR_NOACCESS:
427 return EACCES;
428 case CM_ERROR_NOSUCHFILE:
429 return ENOENT;
430 case CM_ERROR_INVAL:
431 return EINVAL;
432 case CM_ERROR_BADFD:
433 return EBADF;
434 case CM_ERROR_EXISTS:
435 return EEXIST;
436 case CM_ERROR_CROSSDEVLINK:
437 return EXDEV;
438 case CM_ERROR_NOTDIR:
439 return ENOTDIR;
440 case CM_ERROR_ISDIR:
441 return EISDIR;
442 case CM_ERROR_READONLY:
443 return EROFS;
444 case CM_ERROR_WOULDBLOCK:
445 return EWOULDBLOCK;
446 case CM_ERROR_NOSUCHCELL:
447 return ESRCH; /* hack */
448 case CM_ERROR_NOSUCHVOLUME:
449 return EPIPE; /* hack */
450 case CM_ERROR_NOMORETOKENS:
451 return EDOM; /* hack */
452 case CM_ERROR_TOOMANYBUFS:
453 return EFBIG; /* hack */
454 default:
455 if (cm_code > 0 && cm_code < EILSEQ)
456 return cm_code;
457 else
458 return ENOTTY;
462 CString
463 GetAfsError(int code, const TCHAR *filename)
465 CString strMsg;
467 code = CMtoUNIXerror(code);
469 if (code == EINVAL) {
470 if (filename)
471 strMsg.Format(_T("Invalid argument; it is possible that the file is not in AFS"));
472 else
473 strMsg.Format(_T("Invalid argument"));
474 } else if (code == ENOENT) {
475 if (filename)
476 strMsg.Format(_T("The file does not exist"));
477 else
478 strMsg.Format(_T("No such file returned"));
479 } else if (code == EROFS) {
480 strMsg.Format(_T("You can not change a backup or readonly volume"));
481 } else if (code == EACCES || code == EPERM) {
482 strMsg.Format(_T("You do not have the required rights to do this operation"));
483 } else if (code == ENODEV) {
484 strMsg.Format(_T("AFS service may not have started"));
485 } else if (code == ESRCH) {
486 strMsg.Format(_T("Cell name not recognized"));
487 } else if (code == ETIMEDOUT) {
488 strMsg.Format(_T("Connection timed out"));
489 } else if (code == EPIPE) {
490 strMsg.Format(_T("Volume name or ID not recognized"));
491 } else {
492 strMsg.Format(_T("Error 0x%x occurred"), code);
495 return strMsg;
499 static int
500 foldcmp (char *a, char *b)
502 char t, u;
503 while (1) {
504 t = *a++;
505 u = *b++;
506 if (t >= 'A' && t <= 'Z') t += 0x20;
507 if (u >= 'A' && u <= 'Z') u += 0x20;
508 if (t != u) return 1;
509 if (t == 0) return 0;
513 CString
514 GetRightsString(LONG arights, int dfs)
516 CString str;
518 if (!dfs) {
519 if (arights & PRSFS_READ) str += _T("r");
520 if (arights & PRSFS_LOOKUP) str += _T("l");
521 if (arights & PRSFS_INSERT) str += _T("i");
522 if (arights & PRSFS_DELETE) str += _T("d");
523 if (arights & PRSFS_WRITE) str += _T("w");
524 if (arights & PRSFS_LOCK) str += _T("k");
525 if (arights & PRSFS_ADMINISTER) str += _T("a");
526 } else {
527 ASSERT(FALSE);
529 if (arights & DFS_READ) str += _T("r"); else str += _T("-");
530 if (arights & DFS_WRITE) str += _T("w"); else printf(_T("-"));
531 if (arights & DFS_EXECUTE) str += _T("x"); else printf(_T("-"));
532 if (arights & DFS_CONTROL) str += _T("c"); else printf(_T("-"));
533 if (arights & DFS_INSERT) str += _T("i"); else printf(_T("-"));
534 if (arights & DFS_DELETE) str += _T("d"); else printf(_T("-"));
535 if (arights & (DFS_USRALL)) str += _T("+");
539 return str;
542 struct Acl *
543 EmptyAcl(const CString& strCellName)
545 struct Acl *tp;
546 CStringUtf8 ustrCell(strCellName);
548 tp = (struct Acl *)malloc(sizeof (struct Acl));
549 tp->nplus = tp->nminus = 0;
550 tp->pluslist = tp->minuslist = 0;
551 tp->dfs = 0;
552 StringCbCopyA(tp->cell, sizeof(tp->cell), ustrCell);
554 return tp;
557 void
558 CleanACL(CStringArray& names)
560 LONG code;
561 struct Acl *ta;
562 struct ViceIoctl blob;
563 int changes;
565 ShowMessageBox(IDS_CLEANACL_MSG, MB_OK|MB_ICONINFORMATION, IDS_CLEANACL_MSG);
567 HOURGLASS hourglass;
569 for (int i = 0; i < names.GetSize(); i++) {
570 char space[AFS_PIOCTL_MAXSIZE];
572 blob.out_size = AFS_PIOCTL_MAXSIZE;
573 blob.in_size = 0;
574 blob.out = space;
576 code = pioctl_T(names[i], VIOCGETAL, &blob, 1);
577 if (code) {
578 ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno));
579 continue;
582 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
583 if (ta == NULL) {
584 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
585 continue;
587 if (ta->dfs) {
588 ShowMessageBox(IDS_CLEANACL_NOT_SUPPORTED, MB_ICONERROR, IDS_CLEANACL_NOT_SUPPORTED, names[i]);
589 continue;
592 changes = CleanAcl(ta, NULL);
593 if (!changes)
594 continue;
596 /* now set the acl */
597 blob.in = AclToString(ta);
598 blob.in_size = strlen((char *)blob.in) + 1;
599 blob.out_size = 0;
601 code = pioctl_T(names[i], VIOCSETAL, &blob, 1);
602 if (code) {
603 if (errno == EINVAL) {
604 ShowMessageBox(IDS_CLEANACL_INVALID_ARG, MB_ICONERROR, IDS_CLEANACL_INVALID_ARG, names[i]);
605 continue;
607 else {
608 ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno));
609 continue;
615 // Derived from fs.c's ListAclCmd
616 BOOL
617 GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& strNegative)
619 LONG code;
620 struct Acl *ta;
621 struct ViceIoctl blob;
622 struct AclEntry *te;
623 int idf = 0; //getidf(as, parm_listacl_id);
624 char space[AFS_PIOCTL_MAXSIZE];
625 HOURGLASS hourglass;
627 blob.out_size = AFS_PIOCTL_MAXSIZE;
628 blob.in_size = idf;
629 blob.in = blob.out = space;
631 code = pioctl_T(strDir, VIOCGETAL, &blob, 1);
632 if (code) {
633 ShowMessageBox(IDS_GETRIGHTS_ERROR, MB_ICONERROR, IDS_GETRIGHTS_ERROR, strDir, GetAfsError(errno));
634 return FALSE;
637 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
638 if (ta == NULL) {
639 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
640 return FALSE;
642 if (ta->dfs) {
643 ShowMessageBox(IDS_DFSACL_ERROR, MB_ICONERROR, IDS_DFSACL_ERROR);
644 return FALSE;
647 // if (ta->dfs)
648 // printf(" Default cell = %s\n", ta->cell);
650 CString strRight;
652 if (ta->nplus > 0) {
653 for (te = ta->pluslist; te; te = te->next) {
654 strNormal.Add(te->name);
655 strNormal.Add(GetRightsString(te->rights, ta->dfs));
659 if (ta->nminus > 0) {
660 for (te = ta->minuslist; te; te = te->next) {
661 strNegative.Add(te->name);
662 strNegative.Add(GetRightsString(te->rights, ta->dfs));
666 return TRUE;
669 struct AclEntry *
670 FindList(struct AclEntry *pCurEntry, const char *entryName)
672 while (pCurEntry) {
673 if (!foldcmp(pCurEntry->name, PCCHAR(entryName)))
674 return pCurEntry;
675 pCurEntry = pCurEntry->next;
678 return 0;
681 void
682 ChangeList(struct Acl *pAcl, BYTE bNormalRights, const CString & entryName, LONG nEntryRights)
684 ASSERT(pAcl);
685 ASSERT(entryName);
687 struct AclEntry *pEntry;
688 CStringUtf8 uEntryName(entryName);
690 HOURGLASS hourglass;
692 pEntry = (bNormalRights ? pAcl->pluslist : pAcl->minuslist);
693 pEntry = FindList(pEntry, uEntryName);
695 /* Found the item already in the list. */
696 if (pEntry) {
697 pEntry->rights = nEntryRights;
698 if (bNormalRights)
699 pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs);
700 else
701 pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs);
702 return;
705 /* Otherwise we make a new item and plug in the new data. */
706 pEntry = (struct AclEntry *) malloc(sizeof (struct AclEntry));
707 ASSERT(pEntry);
709 strcpy(pEntry->name, uEntryName);
710 pEntry->rights = nEntryRights;
712 if (bNormalRights) {
713 pEntry->next = pAcl->pluslist;
714 pAcl->pluslist = pEntry;
715 pAcl->nplus++;
716 if (nEntryRights == 0 || nEntryRights == -1)
717 pAcl->nplus -= PruneList(&pAcl->pluslist, pAcl->dfs);
719 else {
720 pEntry->next = pAcl->minuslist;
721 pAcl->minuslist = pEntry;
722 pAcl->nminus++;
723 if (nEntryRights == 0)
724 pAcl->nminus -= PruneList(&pAcl->minuslist, pAcl->dfs);
728 static LONG
729 Convert(const CString& strRights, int dfs, enum rtype *rtypep)
731 int i, len;
732 LONG mode;
734 *rtypep = add; /* add rights, by default */
736 if (strRights == _T("read"))
737 return PRSFS_READ | PRSFS_LOOKUP;
738 if (strRights == _T("write"))
739 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK;
740 if (strRights == _T("mail"))
741 return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP;
742 if (strRights == _T("all"))
743 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
745 if (strRights == _T("none")) {
746 *rtypep = destroy; /* Remove entire entry */
747 return 0;
750 len = strRights.GetLength();
751 mode = 0;
753 for (i = 0; i < len; i++) {
754 TCHAR c = strRights[i];
755 if (c == _T('r')) mode |= PRSFS_READ;
756 else if (c == _T('l')) mode |= PRSFS_LOOKUP;
757 else if (c == _T('i')) mode |= PRSFS_INSERT;
758 else if (c == _T('d')) mode |= PRSFS_DELETE;
759 else if (c == _T('w')) mode |= PRSFS_WRITE;
760 else if (c == _T('k')) mode |= PRSFS_LOCK;
761 else if (c == _T('a')) mode |= PRSFS_ADMINISTER;
762 else {
763 fprintf(stderr, "illegal rights character '%c'.\n", c);
764 exit(1);
767 return mode;
770 BOOL
771 SaveACL(const CString& strCellName, const CString& strDir, const CStringArray& normal, const CStringArray& negative)
773 LONG code;
774 struct ViceIoctl blob;
775 struct Acl *pAcl;
776 LONG rights;
777 enum rtype rtype;
779 HOURGLASS hourglass;
781 // Create a new ACL
782 pAcl = EmptyAcl(strCellName);
784 // Set its normal rights
785 int i;
786 for (i = 0; i < normal.GetSize(); i += 2) {
787 rights = Convert(normal[i + 1], 0, &rtype);
788 ChangeList(pAcl, TRUE, normal[i], rights);
791 // Set its negative rights
792 for (i = 0; i < negative.GetSize(); i += 2) {
793 rights = Convert(negative[i + 1], 0, &rtype);
794 ChangeList(pAcl, FALSE, negative[i], rights);
797 // Write the ACL
798 blob.in = AclToString(pAcl);
799 blob.out_size = 0;
800 blob.in_size = 1 + strlen((const char *)blob.in);
802 code = pioctl_T(strDir, VIOCSETAL, &blob, 1);
803 if (code) {
804 if (errno == EINVAL)
805 ShowMessageBox(IDS_SAVE_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_EINVAL_ERROR, strDir);
806 else
807 ShowMessageBox(IDS_SAVE_ACL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_ERROR, strDir, GetAfsError(errno, strDir));
810 ZapAcl(pAcl);
812 return (code == 0);
815 BOOL
816 CopyACL(const CString& strToDir, const CStringArray& normal, const CStringArray& negative, BOOL bClear)
818 LONG code;
819 struct ViceIoctl blob;
820 struct Acl *pToAcl;
821 int idf = 0; // getidf(as, parm_copyacl_id);
822 char space[AFS_PIOCTL_MAXSIZE];
823 HOURGLASS hourglass;
825 // Get ACL to copy to
826 blob.out_size = AFS_PIOCTL_MAXSIZE;
827 blob.in_size = idf;
828 blob.in = blob.out = space;
830 code = pioctl_T(strToDir, VIOCGETAL, &blob, 1);
831 if (code) {
832 ShowMessageBox(IDS_ACL_READ_ERROR, MB_ICONERROR, IDS_ACL_READ_ERROR, strToDir, GetAfsError(errno, strToDir));
833 return FALSE;
836 if (bClear)
837 pToAcl = EmptyAcl(space);
838 else
839 pToAcl = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
841 if (pToAcl == NULL) {
842 ShowMessageBox(IDS_INVALID_ACL_DATA, MB_ICONERROR, IDS_INVALID_ACL_DATA);
843 return FALSE;
846 CleanAcl(pToAcl, NULL);
848 if (pToAcl->dfs) {
849 ShowMessageBox(IDS_NO_DFS_COPY_ACL, MB_ICONERROR, IDS_NO_DFS_COPY_ACL, strToDir);
850 ZapAcl(pToAcl);
851 return FALSE;
854 enum rtype rtype;
856 // Set normal rights
857 int i;
858 for (i = 0; i < normal.GetSize(); i += 2) {
859 LONG rights = Convert(normal[i + 1], 0, &rtype);
860 ChangeList(pToAcl, TRUE, normal[i], rights);
863 // Set negative rights
864 for (i = 0; i < negative.GetSize(); i += 2) {
865 LONG rights = Convert(negative[i + 1], 0, &rtype);
866 ChangeList(pToAcl, FALSE, normal[i], rights);
869 // Save modified ACL
870 blob.in = AclToString(pToAcl);
871 blob.out_size = 0;
872 blob.in_size = 1 + strlen((char *)blob.in);
874 code = pioctl_T(strToDir, VIOCSETAL, &blob, 1);
875 if (code) {
876 ZapAcl(pToAcl);
877 if (errno == EINVAL)
878 ShowMessageBox(IDS_COPY_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_COPY_ACL_EINVAL_ERROR, strToDir);
879 else
880 ShowMessageBox(IDS_COPY_ACL_ERROR, MB_ICONERROR, IDS_COPY_ACL_ERROR, strToDir, GetAfsError(errno, strToDir));
881 return FALSE;
884 ZapAcl(pToAcl);
886 ShowMessageBox(IDS_COPY_ACL_OK, MB_OK|MB_ICONINFORMATION, IDS_COPY_ACL_OK);
888 return TRUE;
891 CString
892 ParseMountPoint(const CString strFile, CString strMountPoint)
894 CString strType;
895 CString strVolume;
896 CString strCell;
897 CString strMountPointInfo;
899 if (strMountPoint[0] == '#')
900 strType = "Regular";
901 else if (strMountPoint[0] == '%')
902 strType = "Read/Write";
904 int nColon = strMountPoint.Find(':');
905 if (nColon >= 0) {
906 strCell = strMountPoint.Mid(1, nColon - 1);
907 strVolume = strMountPoint.Mid(nColon + 1);
908 } else {
909 strVolume = strMountPoint.Mid(1);
910 strCell = _T("(local)");
913 strMountPointInfo = _T("=> ") + strVolume + _T(" : ") + strCell + _T(" cell [") + strType + _T("]");
915 return strMountPointInfo;
918 CString
919 ParseSymlink(const CString strFile, CString strSymlink)
921 CString strSymlinkInfo;
923 strSymlinkInfo = _T("-> ") + strSymlink;
925 return strSymlinkInfo;
928 BOOL
929 GetFID(const CString& path, CString& fidstring, BOOL bLiteral)
931 struct ViceIoctl blob;
932 cm_ioctlQueryOptions_t options;
933 cm_fid_t fid;
934 int code;
936 memset(&options, 0, sizeof(options));
937 options.size = sizeof(options);
938 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
939 options.literal = bLiteral ? 1 : 0;
940 blob.in_size = options.size; /* no variable length data */
941 blob.in = &options;
942 blob.out_size = sizeof(cm_fid_t);
943 blob.out = (char *) &fid;
945 code = pioctl_T(path, VIOCGETFID, &blob, 1);
946 fidstring.Empty();
947 if (code == 0) {
948 fidstring.Format( TEXT("%lu.%lu.%lu"),
949 fid.volume,
950 fid.vnode,
951 fid.unique);
952 return TRUE;
954 return FALSE;
957 BOOL
958 IsPathInAfs(const CString & strPath)
960 struct ViceIoctl blob;
961 cm_ioctlQueryOptions_t options;
962 cm_fid_t fid;
963 int code;
965 HOURGLASS hourglass;
967 memset(&options, 0, sizeof(options));
968 options.size = sizeof(options);
969 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
970 options.literal = 1;
971 blob.in_size = options.size; /* no variable length data */
972 blob.in = &options;
973 blob.out_size = sizeof(cm_fid_t);
974 blob.out = (char *) &fid;
976 code = pioctl_T(strPath, VIOCGETFID, &blob, 1);
977 if (code) {
978 if ((errno == EINVAL) || (errno == ENOENT))
979 return FALSE;
981 return TRUE;
984 static int
985 IsFreelanceRoot(const CString& apath)
987 struct ViceIoctl blob;
988 afs_int32 code;
989 char space[AFS_PIOCTL_MAXSIZE];
991 blob.in_size = 0;
992 blob.out_size = AFS_PIOCTL_MAXSIZE;
993 blob.out = space;
995 code = pioctl_T(apath, VIOC_FILE_CELL_NAME, &blob, 1);
996 if (code == 0)
997 return !strcmp("Freelance.Local.Root",space);
998 return 1; /* assume it is because it is more restrictive that way */
1001 static const char *
1002 NetbiosName(void)
1004 static char buffer[1024] = "AFS";
1005 HKEY parmKey;
1006 DWORD code;
1007 DWORD dummyLen;
1008 DWORD enabled = 0;
1010 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1011 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
1012 if (code == ERROR_SUCCESS) {
1013 dummyLen = sizeof(buffer);
1014 code = RegQueryValueExA(parmKey, "NetbiosName", NULL, NULL,
1015 (LPBYTE)buffer, &dummyLen);
1016 RegCloseKey (parmKey);
1017 } else {
1018 strcpy(buffer, "AFS");
1020 return buffer;
1023 static void
1024 FixNetbiosPath(CString& path)
1026 if (!IsPathInAfs(path)) {
1027 CString nbroot;
1028 const char * nbname = NetbiosName();
1030 nbroot.Format(_T("\\\\%s\\"), nbname);
1032 if (nbroot.CompareNoCase(path) == 0) {
1033 path.Append(_T("all\\"));
1038 #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
1040 static BOOL
1041 IsAdmin (void)
1043 static BOOL fAdmin = FALSE;
1044 static BOOL fTested = FALSE;
1046 if (!fTested)
1048 /* Obtain the SID for the AFS client admin group. If the group does
1049 * not exist, then assume we have AFS client admin privileges.
1051 PSID psidAdmin = NULL;
1052 DWORD dwSize, dwSize2;
1053 TCHAR pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
1054 TCHAR *pszRefDomain = NULL;
1055 SID_NAME_USE snu = SidTypeGroup;
1057 dwSize = sizeof(pszAdminGroup);
1059 if (!GetComputerName(pszAdminGroup, &dwSize)) {
1060 /* Can't get computer name. We return false in this case.
1061 Retain fAdmin and fTested. This shouldn't happen.*/
1062 return FALSE;
1065 dwSize = 0;
1066 dwSize2 = 0;
1068 lstrcat(pszAdminGroup, _T("\\"));
1069 lstrcat(pszAdminGroup, _T(AFSCLIENT_ADMIN_GROUPNAME));
1071 LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
1072 /* that should always fail. */
1074 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1075 /* if we can't find the group, then we allow the operation */
1076 fAdmin = TRUE;
1077 return TRUE;
1080 if (dwSize == 0 || dwSize2 == 0) {
1081 /* Paranoia */
1082 fAdmin = TRUE;
1083 return TRUE;
1086 psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
1087 pszRefDomain = (TCHAR *)malloc(dwSize2);
1089 if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
1090 /* We can't lookup the group now even though we looked it up earlier.
1091 Could this happen? */
1092 fAdmin = TRUE;
1093 } else {
1094 /* Then open our current ProcessToken */
1095 HANDLE hToken;
1097 if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
1100 if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
1101 /* We'll have to allocate a chunk of memory to store the list of
1102 * groups to which this user belongs; find out how much memory
1103 * we'll need.
1105 DWORD dwSize = 0;
1106 PTOKEN_GROUPS pGroups;
1108 GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
1110 pGroups = (PTOKEN_GROUPS)malloc(dwSize);
1112 /* Allocate that buffer, and read in the list of groups. */
1113 if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
1115 /* Look through the list of group SIDs and see if any of them
1116 * matches the AFS Client Admin group SID.
1118 size_t iGroup = 0;
1119 for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
1121 if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
1122 fAdmin = TRUE;
1127 if (pGroups)
1128 free(pGroups);
1131 /* if do not have permission because we were not explicitly listed
1132 * in the Admin Client Group let's see if we are the SYSTEM account
1134 if (!fAdmin) {
1135 PTOKEN_USER pTokenUser;
1136 SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
1137 PSID pSidLocalSystem = 0;
1138 DWORD gle;
1140 GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
1142 pTokenUser = (PTOKEN_USER)malloc(dwSize);
1144 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
1145 gle = GetLastError();
1147 if (AllocateAndInitializeSid( &SIDAuth, 1,
1148 SECURITY_LOCAL_SYSTEM_RID,
1149 0, 0, 0, 0, 0, 0, 0,
1150 &pSidLocalSystem))
1152 if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
1153 fAdmin = TRUE;
1156 FreeSid(pSidLocalSystem);
1159 if ( pTokenUser )
1160 free(pTokenUser);
1165 free(psidAdmin);
1166 free(pszRefDomain);
1168 fTested = TRUE;
1171 return fAdmin;
1174 CString
1175 Parent(const CString& path)
1177 int last_slash = path.ReverseFind(_T('\\'));
1179 if (last_slash != -1) {
1180 CString ret = path.Left(last_slash + 1);
1181 return ret;
1182 } else {
1183 if (path.GetLength() >= 2 && path[1] == _T(':')) {
1184 CString ret = path.Left(2);
1185 ret.AppendChar(_T('.'));
1186 return ret;
1187 } else {
1188 CString ret = _T(".");
1189 return ret;
1194 CString
1195 LastComponent(const CString& path)
1197 int last_slash = path.ReverseFind(_T('\\'));
1199 if (last_slash != -1) {
1200 CString ret = path.Mid(last_slash + 1);
1201 return ret;
1202 } else {
1203 if (path.GetLength() >= 2 && path[1] == _T(':')) {
1204 CString ret = path.Mid(2);
1205 return ret;
1206 } else {
1207 CString ret = path;
1208 return ret;
1213 static CString
1214 GetCell(const CString & path, BOOL bFollow = TRUE);
1216 static CString
1217 GetCell(const CString & path, BOOL bFollow)
1219 char cellname[MAXCELLCHARS];
1220 afs_int32 code;
1221 struct ViceIoctl blob;
1223 blob.in_size = 0;
1224 blob.out_size = sizeof(cellname);
1225 blob.out = cellname;
1227 code = pioctl_T(path, VIOC_FILE_CELL_NAME, &blob, 1);
1228 if (code) {
1229 CString s;
1230 s.Empty();
1232 return s;
1233 } else {
1234 return Utf8ToCString(cellname);
1239 BOOL
1240 ListMount(CStringArray& files)
1242 LONG code;
1243 struct ViceIoctl blob;
1244 int error;
1246 CString parent_dir; /* Parent directory of true name */
1247 CStringUtf8 last_component; /* Last component of true name */
1249 CStringArray mountPoints;
1251 HOURGLASS hourglass;
1253 error = 0;
1255 for (int i = 0; i < files.GetSize(); i++) {
1256 int last_slash = files[i].ReverseFind(_T('\\'));
1257 char space[AFS_PIOCTL_MAXSIZE];
1259 if (last_slash != -1) {
1260 last_component.SetString( files[i].Mid(last_slash + 1) );
1261 parent_dir.SetString( files[i].Left(last_slash + 1) );
1262 FixNetbiosPath(parent_dir);
1263 } else {
1264 // The path is of the form "C:foo" or just "foo". If
1265 // there is a drive, then use the current directory of
1266 // that drive. Otherwise we just use '.'.
1268 if (files[i].GetLength() >= 2 && files[i][1] == _T(':')) {
1269 parent_dir.Format(_T("%c:."), files[i][0]);
1270 last_component.SetString( files[i].Mid(2) );
1271 } else {
1272 parent_dir.SetString( _T("."));
1273 last_component.SetString( files[i] );
1277 blob.in_size = last_component.GetLength() + 1;
1278 blob.in = last_component.GetBuffer();
1279 blob.out_size = AFS_PIOCTL_MAXSIZE;
1280 blob.out = space;
1281 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1283 code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
1285 last_component.ReleaseBuffer();
1287 if (code == 0) {
1288 int nPos;
1289 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
1290 nPos = strlen(space) - 1;
1291 if (space[nPos] == '.')
1292 space[nPos] = 0;
1293 mountPoints.Add(ParseMountPoint(StripPath(files[i]), Utf8ToCString(space)));
1294 } else {
1295 error = 1;
1296 if (errno == EINVAL)
1297 mountPoints.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i])));
1298 else
1299 mountPoints.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i]))));
1303 CMountPointsDlg dlg;
1304 dlg.SetMountPoints(mountPoints);
1305 dlg.DoModal();
1307 return !error;
1310 BOOL
1311 MakeMount(const CString& strDir,
1312 const CString& strVolName,
1313 const CString& strInCellName,
1314 BOOL bRW)
1316 LONG code;
1317 struct ViceIoctl blob;
1318 HOURGLASS hourglass;
1320 ASSERT(strVolName.GetLength() < 64);
1322 CString strParent = Parent(strDir);
1324 FixNetbiosPath(strParent);
1325 if (!IsPathInAfs(strParent)) {
1326 ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR);
1327 return FALSE;
1330 CString strPath = strParent + LastComponent(strDir);
1332 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1333 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR,
1334 IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1335 return FALSE;
1338 CString strMount;
1340 strMount.Format(_T("%c%s%s%s."),
1341 ((bRW)?_T('%'):_T('#')),
1342 strInCellName,
1343 ((strInCellName.IsEmpty())?_T(""):_T(":")),
1344 strVolName);
1346 CStringUtf8 ustrMount(strMount);
1348 blob.out_size = 0;
1349 blob.in_size = ustrMount.GetLength() + 1;
1350 blob.in = ustrMount.GetBuffer();
1351 blob.out = NULL;
1353 code = pioctl_T(strPath, VIOC_AFS_CREATE_MT_PT, &blob, 0);
1355 ustrMount.ReleaseBuffer();
1357 if (code) {
1358 ShowMessageBox(IDS_MOUNT_POINT_ERROR, MB_ICONERROR, IDS_MOUNT_POINT_ERROR, GetAfsError(errno, strDir));
1359 return FALSE;
1362 return TRUE;
1365 BOOL
1366 RemoveSymlink(const CString& strName)
1368 BOOL error = FALSE;
1369 INT code=0;
1370 struct ViceIoctl blob;
1371 char lsbuffer[1024];
1373 HOURGLASS hourglass;
1375 CString strParent = Parent(strName);
1376 CStringUtf8 ustrLast(LastComponent(strName));
1377 FixNetbiosPath(strParent);
1379 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1380 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1381 return FALSE;
1384 blob.in_size = ustrLast.GetLength() + 1;
1385 blob.in = ustrLast.GetBuffer();
1386 blob.out = lsbuffer;
1387 blob.out_size = sizeof(lsbuffer);
1388 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 0);
1389 ustrLast.ReleaseBuffer();
1390 if (code)
1391 return FALSE;
1392 blob.out_size = 0;
1393 blob.in_size = ustrLast.GetLength() + 1;
1394 blob.in = ustrLast.GetBuffer();
1396 code = pioctl_T(strParent, VIOC_DELSYMLINK, &blob, 0);
1398 ustrLast.ReleaseBuffer();
1400 return (code == 0);
1403 BOOL
1404 IsSymlink(const CString& strName)
1406 struct ViceIoctl blob;
1407 int code;
1408 char space[AFS_PIOCTL_MAXSIZE];
1409 HOURGLASS hourglass;
1411 CStringUtf8 ustrLast(LastComponent(strName));
1412 CString strParent = Parent(strName);
1414 FixNetbiosPath(strParent);
1416 blob.in_size = ustrLast.GetLength() + 1;
1417 blob.in = ustrLast.GetBuffer();
1418 blob.out_size = AFS_PIOCTL_MAXSIZE;
1419 blob.out = space;
1420 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1422 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1);
1424 ustrLast.ReleaseBuffer();
1426 return (code==0);
1430 BOOL
1431 IsMountPoint(const CString& path)
1433 LONG code = 0;
1434 struct ViceIoctl blob;
1435 char lsbuffer[1024];
1437 HOURGLASS hourglass;
1439 CString parent = Parent(path);
1440 FixNetbiosPath(parent);
1442 CStringUtf8 mountpoint(LastComponent(path));
1444 blob.in_size = mountpoint.GetLength() + 1;
1445 blob.in = mountpoint.GetBuffer();
1446 blob.out = lsbuffer;
1447 blob.out_size = sizeof(lsbuffer);
1449 code = pioctl_T(parent, VIOC_AFS_STAT_MT_PT, &blob, 0);
1451 mountpoint.ReleaseBuffer();
1453 return (code==0);
1458 * Delete AFS mount points. Variables are used as follows:
1459 * tbuffer: Set to point to the null-terminated directory name of the mount point
1460 * (or ``.'' if none is provided)
1461 * tp: Set to point to the actual name of the mount point to nuke.
1463 BOOL
1464 RemoveMount(CStringArray& files)
1466 LONG code = 0;
1467 struct ViceIoctl blob;
1468 BOOL error = FALSE;
1469 CStringArray results;
1470 CString str;
1471 CString str2;
1473 HOURGLASS hourglass;
1475 for (int i = 0; i < files.GetSize(); i++) {
1476 if (!IsMountPoint(files[i])) {
1477 error = TRUE;
1478 if (errno == EINVAL)
1479 results.Add(GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(files[i])));
1480 else
1481 results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i]))));
1482 continue; // don't bother trying
1485 CString parent = Parent(files[i]);
1486 CStringUtf8 mountpoint(LastComponent(files[i]));
1487 FixNetbiosPath(parent);
1489 if ( IsFreelanceRoot(parent) && !IsAdmin() ) {
1490 results.Add(GetMessageString(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, StripPath(files[i])));
1491 error = TRUE;
1492 continue; /* skip */
1495 blob.out_size = 0;
1496 blob.in_size = mountpoint.GetLength() + 1;
1497 blob.in = mountpoint.GetBuffer();
1499 code = pioctl_T(parent, VIOC_AFS_DELETE_MT_PT, &blob, 0);
1501 mountpoint.ReleaseBuffer();
1503 if (code) {
1504 error = TRUE;
1505 results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i]))));
1506 } else
1507 results.Add(GetMessageString(IDS_DELETED));
1510 LoadString (str, IDS_REMOVE_MP);
1511 LoadString (str2, IDS_REMOVE_MP_COLUMN);
1512 CResultsDlg dlg(REMOVE_MOUNT_POINTS_HELP_ID);
1513 dlg.SetContents(str, str2, StripPath(files), results);
1514 dlg.DoModal();
1516 return !error;
1519 BOOL
1520 GetVolumeInfo(CString strFile, CVolInfo& volInfo, BOOL bFollow)
1522 LONG code;
1523 struct ViceIoctl blob;
1524 struct VolumeStatus *status;
1525 char *name;
1526 char space[AFS_PIOCTL_MAXSIZE];
1527 HOURGLASS hourglass;
1528 CString strTarget = bFollow ? strFile : Parent(strFile);
1530 volInfo.m_strFilePath = strTarget;
1531 volInfo.m_strFileName = StripPath(strTarget);
1534 volInfo.m_strName = "VolumeName";
1535 volInfo.m_nID = 10;
1536 volInfo.m_nQuota = 20 * 1024 * 1024;
1537 volInfo.m_nNewQuota = volInfo.m_nQuota;
1538 volInfo.m_nUsed = volInfo.m_nQuota / 2;
1539 volInfo.m_nPartSize = 50 * 1024 * 1024;
1540 volInfo.m_nPartFree = 30 * 1024 * 1024;
1541 volInfo.m_nDup = -1;
1542 return TRUE;
1545 blob.out_size = AFS_PIOCTL_MAXSIZE;
1546 blob.in_size = 0;
1547 blob.out = space;
1549 code = pioctl_T(strTarget, VIOCGETVOLSTAT, &blob, 1);
1550 if (code || blob.out_size < sizeof(*status)) {
1551 volInfo.m_strErrorMsg = GetAfsError(errno, strTarget);
1552 return FALSE;
1555 status = (VolumeStatus *)space;
1556 name = (char *)status + sizeof(*status);
1558 volInfo.m_strName = Utf8ToCString(name);
1559 volInfo.m_nID = status->Vid;
1560 volInfo.m_nQuota = status->MaxQuota;
1561 volInfo.m_nNewQuota = status->MaxQuota;
1562 volInfo.m_nUsed = status->BlocksInUse;
1563 volInfo.m_nPartSize = status->PartMaxBlocks;
1564 volInfo.m_nPartFree = status->PartBlocksAvail;
1565 volInfo.m_nDup = -1;
1567 errno = 0;
1568 code = pioctl_T(strTarget, VIOC_PATH_AVAILABILITY, &blob, 1);
1569 switch (errno) {
1570 case 0:
1571 volInfo.m_strAvail =_T("Online");
1572 break;
1573 case ENXIO:
1574 volInfo.m_strAvail = _T("Offline");
1575 break;
1576 case ENOSYS:
1577 volInfo.m_strAvail = _T("Unreachable");
1578 break;
1579 case EBUSY:
1580 volInfo.m_strAvail = _T("Busy");
1581 break;
1582 default:
1583 volInfo.m_strAvail = _T("Unknown");
1586 return TRUE;
1589 BOOL
1590 SetVolInfo(CVolInfo& volInfo)
1592 LONG code;
1593 struct ViceIoctl blob;
1594 struct VolumeStatus *status;
1595 char *input;
1596 char space[AFS_PIOCTL_MAXSIZE];
1597 HOURGLASS hourglass;
1599 blob.out_size = AFS_PIOCTL_MAXSIZE;
1600 blob.in_size = sizeof(*status) + 3; /* for the three terminating nulls */
1601 blob.out = space;
1602 blob.in = space;
1604 status = (VolumeStatus *)space;
1605 status->MinQuota = -1;
1606 status->MaxQuota = volInfo.m_nNewQuota;
1608 input = (char *)status + sizeof(*status);
1609 *(input++) = '\0'; /* never set name: this call doesn't change vldb */
1610 *(input++) = '\0'; // No offmsg
1611 *(input++) = '\0'; // No motd
1613 #ifdef LOGGING_ON
1614 FILE *fp = OpenFile(szLogFileName, "a");
1615 if (fp) {
1616 fprintf(fp, "\nSetVolInfo() pioctl parms:\n");
1617 fprintf(fp, "\tpathp = %s\n\topcode = VIOCSETVOLSTAT (%d)\n\tblobp = %ld\n", PCCHAR(volInfo.m_strFilePath), VIOCSETVOLSTAT, &blob);
1618 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);
1619 fprintf(fp, "\t\t\tstatus->MinQuota = %ld\n", status->MinQuota);
1620 fprintf(fp, "\t\t\tstatus->MaxQuota = %ld\n", status->MaxQuota);
1621 fprintf(fp, "\t\t\tOther status fields aren't set\n");
1622 fprintf(fp, "\t\t\t3 nulls follow the VolumeStatus structure.\n");
1623 fprintf(fp, "\tfollow = 1\n");
1624 fclose(fp);
1626 #endif
1628 code = pioctl_T(volInfo.m_strFilePath, VIOCSETVOLSTAT, &blob, 1);
1629 if (code || blob.out_size < sizeof(*status)) {
1630 ShowMessageBox(IDS_SET_QUOTA_ERROR, MB_ICONERROR, IDS_SET_QUOTA_ERROR, GetAfsError(errno, volInfo.m_strName));
1631 return FALSE;
1634 return TRUE;
1637 void
1638 GetCellName(const CString& cellNamep, struct afsconf_cell *infop)
1640 CStringUtf8 uCellName(cellNamep);
1642 StringCbCopyA(infop->name, sizeof(infop->name), uCellName);
1645 BOOL NO_CALLER
1646 CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast)
1648 LONG code;
1649 struct ViceIoctl blob;
1650 LONG j;
1651 LONG temp = 0;
1652 struct afsconf_cell info;
1653 struct chservinfo checkserv;
1654 char space[AFS_PIOCTL_MAXSIZE];
1655 HOURGLASS hourglass;
1657 memset(&checkserv, 0, sizeof(struct chservinfo));
1658 blob.in_size = sizeof(struct chservinfo);
1659 blob.in = (caddr_t)&checkserv;
1661 blob.out_size = AFS_PIOCTL_MAXSIZE;
1662 blob.out = space;
1663 memset(space, 0, sizeof(afs_int32)); /* so we assure zero when nothing is copied back */
1665 if (nCellsToCheck == SPECIFIC_CELL) {
1666 temp = 2;
1667 GetCellName(strCellName, &info);
1668 strcpy(checkserv.tbuffer,info.name);
1669 checkserv.tsize = strlen(info.name) + 1;
1670 } else {
1671 if (nCellsToCheck != ALL_CELLS)
1672 temp = 2;
1673 strcpy(checkserv.tbuffer, "\0");
1674 checkserv.tsize = 0;
1676 if (bFast)
1677 temp |= 1; /* set fast flag */
1679 checkserv.magic = 0x12345678; /* XXX */
1680 checkserv.tflags = temp;
1681 checkserv.tinterval = -1; /* don't change current interval */
1683 code = pioctl_utf8(0, VIOCCKSERV, &blob, 1);
1684 if (code) {
1685 ShowMessageBox(IDS_CHECK_SERVERS_ERROR, MB_ICONERROR, IDS_CHECK_SERVERS_ERROR, GetAfsError(errno, CString()));
1686 return FALSE;
1689 memcpy(&temp, space, sizeof(LONG));
1691 if (temp == 0) {
1692 ShowMessageBox(IDS_ALL_SERVERS_RUNNING, MB_OK|MB_ICONINFORMATION, IDS_ALL_SERVERS_RUNNING);
1693 return TRUE;
1696 CStringArray servers;
1697 for (j = 0; j < AFS_MAXHOSTS; j++) {
1698 memcpy(&temp, space + j * sizeof(LONG), sizeof(LONG));
1699 if (temp == 0)
1700 break;
1702 char *name = hostutil_GetNameByINet(temp);
1703 servers.Add(name);
1706 CDownServersDlg dlg;
1707 dlg.SetServerNames(servers);
1708 dlg.DoModal();
1710 return TRUE;
1713 BOOL
1714 GetTokenInfo(CStringArray& tokenInfo)
1716 int cellNum;
1717 int rc;
1718 time_t current_time;
1719 time_t tokenExpireTime;
1720 char *expireString;
1721 char userName[100];
1722 // char s[100];
1723 struct ktc_principal serviceName, clientName;
1724 struct ktc_token token;
1726 CString strTokenInfo;
1727 CString strUserName;
1728 CString strCellName;
1729 CString strExpir;
1731 // tokenInfo.Add("");
1732 // return TRUE;
1735 HOURGLASS hourglass;
1737 // printf("\nTokens held by the Cache Manager:\n\n");
1738 cellNum = 0;
1739 current_time = time(0);
1741 while (1) {
1742 rc = ktc_ListTokens(cellNum, &cellNum, &serviceName);
1743 if (rc == KTC_NOENT) {
1744 /* end of list */
1745 // printf(" --End of list --\n");
1746 break;
1748 else if (rc == KTC_NOCM) {
1749 ShowMessageBox(IDS_GET_TOKENS_NO_AFS_SERVICE);
1750 // printf("AFS service may not have started\n");
1751 break;
1753 else if (rc) {
1754 ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR, rc);
1755 return FALSE;
1756 // printf("Unexpected error, code %d\n", rc);
1757 // exit(1);
1759 else {
1760 rc = ktc_GetToken(&serviceName, &token, sizeof(token), &clientName);
1761 if (rc) {
1762 ShowMessageBox(IDS_GET_TOKENS_UNEXPECTED_ERROR2, MB_ICONERROR, IDS_GET_TOKENS_UNEXPECTED_ERROR2,
1763 serviceName.name, serviceName.instance, serviceName.cell, rc);
1764 continue;
1767 tokenExpireTime = token.endTime;
1769 strcpy(userName, clientName.name);
1770 if (clientName.instance[0] != 0) {
1771 strcat(userName, ".");
1772 strcat(userName, clientName.instance);
1775 BOOL bShowName = FALSE;
1777 if (userName[0] == '\0')
1778 ; //printf("Tokens");
1779 // AFS ID is not returned at this time.
1780 // else if (strncmp(userName, "AFS ID", 6) == 0)
1781 // printf("User's (%s) tokens", userName);
1782 // sscanf(userName, "(AFS ID %s)", szAfsID);
1783 else if (strncmp(userName, "Unix UID", 8) == 0)
1784 ; //printf("Tokens");
1785 else
1786 strUserName = userName;
1787 // printf("User %s's tokens", userName);
1789 // printf(" for %s%s%s@%s ", serviceName.name, serviceName.instance[0] ? "." : "", serviceName.instance, serviceName.cell);
1790 strCellName = serviceName.cell;
1792 if (tokenExpireTime <= current_time)
1793 strExpir = "[>> Expired <<]";
1794 // printf("[>> Expired <<]\n");
1795 else {
1796 expireString = ctime(&tokenExpireTime);
1797 expireString += 4; /* Skip day of week */
1798 expireString[12] = '\0'; /* Omit secs & year */
1799 // printf("[Expires %s]\n", expireString);
1800 #ifdef UNICODE
1801 strExpir.Format(_T("%S"), expireString);
1802 #else
1803 strExpir.Format(_T("%s"), expireString);
1804 #endif
1807 strTokenInfo = strUserName + "\t" + strCellName + "\t" + strExpir + "\t" + strCellName;
1808 tokenInfo.Add(strTokenInfo);
1812 // printf("Press <Enter> or <Return> when finished: ");
1813 // gets(s);
1814 return TRUE;
1817 UINT
1818 MakeSymbolicLink(const CString& strName, const CString& strTarget)
1820 struct ViceIoctl blob;
1821 UINT code;
1822 HOURGLASS hourglass;
1824 CString strParent = Parent(strName);
1825 FixNetbiosPath(strParent);
1827 if (!IsPathInAfs(strParent)) {
1828 ShowMessageBox(IDS_MAKE_LNK_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR);
1829 return FALSE;
1832 if ( IsFreelanceRoot(strParent) && !IsAdmin() ) {
1833 ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR);
1834 return FALSE;
1837 CStringUtf8 ustrTarget(strTarget);
1839 blob.in_size = ustrTarget.GetLength() + 1;
1840 blob.in = ustrTarget.GetBuffer();
1841 blob.out_size = 0;
1842 blob.out = NULL;
1844 code = pioctl_T(strName, VIOC_SYMLINK, &blob, 0);
1846 ustrTarget.ReleaseBuffer();
1848 if (code != 0)
1849 return code;
1850 return 0;
1853 void NO_CALLER
1854 ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath)
1856 ASSERT(nlenPath<MAX_PATH);
1857 struct ViceIoctl blob;
1858 char orig_name[MAX_PATH+1]; /*Original name, may be modified*/
1859 char true_name[MAX_PATH+1]; /*``True'' dirname (e.g., symlink target)*/
1860 char parent_dir[MAX_PATH+1]; /*Parent directory of true name*/
1861 char *last_component; /*Last component of true name*/
1862 UINT code;
1863 char space[AFS_PIOCTL_MAXSIZE];
1864 HOURGLASS hourglass;
1866 strcpy(orig_name, strName);
1867 strcpy(true_name, orig_name);
1869 * Find rightmost slash, if any.
1871 last_component = (char *) strrchr(true_name, '\\');
1872 if (!last_component)
1873 last_component = (char *) strrchr(true_name, '/');
1874 if (last_component) {
1876 * Found it. Designate everything before it as the parent directory,
1877 * everything after it as the final component.
1879 strncpy(parent_dir, true_name, last_component - true_name + 1);
1880 parent_dir[last_component - true_name + 1] = 0;
1881 last_component++; /*Skip the slash*/
1883 if (!IsPathInAfs(parent_dir)) {
1884 const char * nbname = NetbiosName();
1885 int len = strlen(nbname);
1887 if (parent_dir[0] == '\\' && parent_dir[1] == '\\' &&
1888 parent_dir[len+2] == '\\' &&
1889 parent_dir[len+3] == '\0' &&
1890 !strnicmp(nbname,&parent_dir[2],len))
1892 sprintf(parent_dir,"\\\\%s\\all\\", nbname);
1896 else {
1898 * No slash appears in the given file name. Set parent_dir to the current
1899 * directory, and the last component as the given name.
1901 fs_ExtractDriveLetter(true_name, parent_dir);
1902 strcat(parent_dir, ".");
1903 last_component = true_name;
1904 fs_StripDriveLetter(true_name, true_name, sizeof(true_name));
1906 blob.in = last_component;
1907 blob.in_size = strlen(last_component)+1;
1908 blob.out_size = AFS_PIOCTL_MAXSIZE;
1909 blob.out = space;
1910 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1911 if ((code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1)))
1912 strcpy(space,"???");
1913 ASSERT(strlen(space)<MAX_PATH);
1914 strncpy(strPath,space,nlenPath);
1917 BOOL NO_CALLER
1918 ListSymlink(CStringArray& files)
1920 LONG code;
1921 struct ViceIoctl blob;
1922 int error;
1923 CStringArray symlinks;
1924 char space[AFS_PIOCTL_MAXSIZE];
1925 HOURGLASS hourglass;
1927 error = 0;
1929 for (int i = 0; i < files.GetSize(); i++) {
1931 CString strParent = Parent(files[i]);
1932 CStringUtf8 ustrLast(LastComponent(files[i]));
1934 FixNetbiosPath(strParent);
1936 blob.in_size = ustrLast.GetLength() + 1;
1937 blob.in = ustrLast.GetBuffer();
1938 blob.out_size = AFS_PIOCTL_MAXSIZE;
1939 blob.out = space;
1940 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1942 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1);
1944 ustrLast.ReleaseBuffer();
1946 if (code == 0) {
1947 CString syml;
1948 int len;
1950 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
1951 syml = Utf8ToCString(space);
1952 len = syml.GetLength();
1954 if (len > 0) {
1955 if (syml[len - 1] == _T('.'))
1956 syml.Truncate(len - 1);
1959 symlinks.Add(ParseSymlink(StripPath(files[i]), syml));
1961 } else {
1962 error = 1;
1963 if (errno == EINVAL)
1964 symlinks.Add(GetMessageString(IDS_NOT_SYMLINK_ERROR, StripPath(files[i])));
1965 else
1966 symlinks.Add(GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(files[i]))));
1970 CSymlinksDlg dlg;
1971 dlg.SetSymlinks(symlinks);
1972 dlg.DoModal();
1974 return !error;
1977 CString
1978 GetCellName( const CString& strPath, BOOL bFollow )
1980 return GetCell(bFollow ? strPath : Parent(strPath));
1983 CString
1984 GetServer( const CString& strPath, BOOL bFollow )
1986 LONG code;
1987 struct ViceIoctl blob;
1988 CString server;
1989 char space[AFS_PIOCTL_MAXSIZE];
1991 blob.out_size = AFS_PIOCTL_MAXSIZE;
1992 blob.in_size = 0;
1993 blob.out = space;
1994 memset(space, 0, sizeof(space));
1996 code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCWHEREIS, &blob, 1);
1997 if (code) {
1998 server=GetAfsError(errno);
1999 } else {
2000 LONG *hosts = (LONG *)space;
2002 for (int j = 0; j < AFS_MAXHOSTS; j++) {
2003 if (hosts[j] == 0)
2004 break;
2005 char *hostName = hostutil_GetNameByINet(hosts[j]);
2006 server=hostName;
2010 return server;
2013 void
2014 GetServers( const CString& strPath, CStringArray& servers, BOOL bFollow )
2016 LONG code;
2017 struct ViceIoctl blob;
2018 char space[AFS_PIOCTL_MAXSIZE];
2020 blob.out_size = AFS_PIOCTL_MAXSIZE;
2021 blob.in_size = 0;
2022 blob.out = space;
2023 memset(space, 0, sizeof(space));
2025 code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCWHEREIS, &blob, 1);
2026 if (code) {
2027 servers.Add(GetAfsError(errno));
2028 } else {
2029 LONG *hosts = (LONG *)space;
2031 for (int j = 0; j < AFS_MAXHOSTS; j++) {
2032 if (hosts[j] == 0)
2033 break;
2034 char *hostName = hostutil_GetNameByINet(hosts[j]);
2035 servers.Add(hostName);
2040 CString
2041 GetOwner( const CString& strPath, BOOL bFollow )
2043 LONG code;
2044 struct ViceIoctl blob;
2045 afs_int32 owner[2];
2046 CString ret = TEXT("(unknown)");
2048 blob.in_size = 0;
2049 blob.out_size = 2 * sizeof(afs_int32);
2050 blob.out = (char *) &owner;
2052 code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCGETOWNER, &blob, 1);
2053 if (code == 0 && blob.out_size == 2 * sizeof(afs_int32)) {
2054 char oname[PR_MAXNAMELEN] = "(unknown)";
2055 char confDir[257];
2056 CStringUtf8 cell;
2058 cell = GetCell(strPath, bFollow);
2060 /* Go to the PRDB and see if this all number username is valid */
2061 cm_GetConfigDir(confDir, sizeof(confDir));
2063 pr_Initialize(1, confDir, PCCHAR(cell));
2064 pr_SIdToName(owner[0], oname);
2066 ret.Empty();
2067 ret.Format(TEXT("%s [%d]"), (LPCTSTR)CString(oname), owner[0]);
2070 return ret;
2073 CString
2074 GetGroup( const CString& strPath, BOOL bFollow )
2076 LONG code;
2077 struct ViceIoctl blob;
2078 afs_int32 owner[2];
2079 CString ret = TEXT("(unknown)");
2081 blob.in_size = 0;
2082 blob.out_size = 2 * sizeof(afs_int32);
2083 blob.out = (char *) &owner;
2085 code = pioctl_T(bFollow ? strPath : Parent(strPath), VIOCGETOWNER, &blob, 1);
2086 if (code == 0 && blob.out_size == 2 * sizeof(afs_int32)) {
2087 char gname[PR_MAXNAMELEN] = "(unknown)";
2088 char confDir[257];
2089 CStringUtf8 cell;
2091 cell = GetCell(strPath, bFollow);
2093 /* Go to the PRDB and see if this all number username is valid */
2094 cm_GetConfigDir(confDir, sizeof(confDir));
2096 pr_Initialize(1, confDir, PCCHAR(cell));
2097 pr_SIdToName(owner[1], gname);
2099 ret.Empty();
2100 ret.Format(TEXT("%s [%d]"), (LPCTSTR)CString(gname), owner[1]);
2103 return ret;
2106 BOOL
2107 GetUnixModeBits( const CString& strPath, CString& user, CString& group, CString& other, CString& suid )
2109 // the strings must match the unix ls command output: "rwx" means read/write/execute permissions
2111 LONG code;
2112 struct ViceIoctl blob;
2113 afs_uint32 unixModeBits;
2114 CString ret = TEXT("(unknown)");
2116 user.Empty();
2117 group.Empty();
2118 other.Empty();
2119 suid.Empty();
2121 blob.in_size = 0;
2122 blob.out_size = sizeof(afs_int32);
2123 blob.out = (char *) &unixModeBits;
2125 code = pioctl_T(strPath, VIOC_GETUNIXMODE, &blob, 1);
2126 if (code == 0 && blob.out_size == sizeof(afs_uint32)) {
2127 if (unixModeBits & S_IRUSR)
2128 user += _T("r");
2129 if (unixModeBits & S_IWUSR)
2130 user += _T("w");
2131 if (unixModeBits & S_IXUSR)
2132 user += _T("x");
2134 if (unixModeBits & S_IRGRP)
2135 group += _T("r");
2136 if (unixModeBits & S_IWGRP)
2137 group += _T("w");
2138 if (unixModeBits & S_IXGRP)
2139 group += _T("x");
2141 if (unixModeBits & S_IROTH)
2142 other += _T("r");
2143 if (unixModeBits & S_IWOTH)
2144 other += _T("w");
2145 if (unixModeBits & S_IXOTH)
2146 other += _T("x");
2148 if (unixModeBits & S_ISUID)
2149 suid += _T("s");
2150 if (unixModeBits & S_ISGID)
2151 suid += _T("g");
2152 if (unixModeBits & S_ISVTX)
2153 suid += _T("v");
2155 return TRUE;
2158 return FALSE;
2161 void
2162 SetUnixModeBits( const CStringArray& files, const CString& user, const CString& group, const CString& other, const CString& suid )
2164 // set the unix file attributes for all paths in 'files'.
2165 LONG code;
2166 struct ViceIoctl blob;
2167 struct {
2168 cm_ioctlQueryOptions_t options;
2169 afs_uint32 unixModeBits;
2170 } inData;
2172 memset(&inData, 0, sizeof(inData));
2173 inData.options.size = sizeof(inData.options);
2174 inData.options.field_flags = 0;
2175 inData.options.literal = 0; /* always applying to target */
2176 blob.in_size = sizeof(inData); /* no variable length data */
2177 blob.in = &inData;
2178 blob.out = NULL;
2179 blob.out_size = 0;
2180 inData.unixModeBits = 0;
2182 if (user.Find(_T('r')) != -1)
2183 inData.unixModeBits |= S_IRUSR;
2184 if (user.Find(_T('w')) != -1)
2185 inData.unixModeBits |= S_IWUSR;
2186 if (user.Find(_T('x')) != -1)
2187 inData.unixModeBits |= S_IXUSR;
2189 if (group.Find(_T('r')) != -1)
2190 inData.unixModeBits |= S_IRGRP;
2191 if (group.Find(_T('w')) != -1)
2192 inData.unixModeBits |= S_IWGRP;
2193 if (group.Find(_T('x')) != -1)
2194 inData.unixModeBits |= S_IXGRP;
2196 if (other.Find(_T('r')) != -1)
2197 inData.unixModeBits |= S_IROTH;
2198 if (other.Find(_T('w')) != -1)
2199 inData.unixModeBits |= S_IWOTH;
2200 if (other.Find(_T('x')) != -1)
2201 inData.unixModeBits |= S_IXOTH;
2203 if (suid.Find(_T('s')) != -1)
2204 inData.unixModeBits |= S_ISUID;
2205 if (suid.Find(_T('g')) != -1)
2206 inData.unixModeBits |= S_ISGID;
2207 if (suid.Find(_T('v')) != -1)
2208 inData.unixModeBits |= S_ISVTX;
2210 for (int i = 0; i < files.GetSize(); i++)
2211 code = pioctl_T(files[i], VIOC_SETUNIXMODE, &blob, 1);
2214 CString GetMountpoint( const CString& strPath )
2216 LONG code;
2217 struct ViceIoctl blob;
2218 char space[AFS_PIOCTL_MAXSIZE];
2219 CString parent_dir; /* Parent directory of true name */
2220 CStringUtf8 last_component; /* Last component of true name */
2222 CString mountPoint;
2225 int last_slash = strPath.ReverseFind(_T('\\'));
2227 if (last_slash != -1) {
2228 last_component.SetString( strPath.Mid(last_slash + 1) );
2229 parent_dir.SetString( strPath.Left(last_slash + 1) );
2230 FixNetbiosPath(parent_dir);
2231 } else {
2232 // The path is of the form "C:foo" or just "foo". If
2233 // there is a drive, then use the current directory of
2234 // that drive. Otherwise we just use '.'.
2236 if (strPath.GetLength() >= 2 && strPath[1] == _T(':')) {
2237 parent_dir.Format(_T("%c:."), strPath[0]);
2238 last_component.SetString( strPath.Mid(2) );
2239 } else {
2240 parent_dir.SetString( _T("."));
2241 last_component.SetString( strPath );
2245 blob.in_size = last_component.GetLength() + 1;
2246 blob.in = last_component.GetBuffer();
2247 blob.out_size = AFS_PIOCTL_MAXSIZE;
2248 blob.out = space;
2249 memset(space, 0, AFS_PIOCTL_MAXSIZE);
2251 code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
2253 last_component.ReleaseBuffer();
2255 if (code == 0) {
2256 int nPos;
2257 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
2258 nPos = strlen(space) - 1;
2259 if (space[nPos] == '.')
2260 space[nPos] = 0;
2261 mountPoint = ParseMountPoint(StripPath(strPath), Utf8ToCString(space));
2262 } else {
2263 if (errno == EINVAL)
2264 mountPoint = GetMessageString(IDS_NOT_MOUNT_POINT_ERROR, StripPath(strPath));
2265 else
2266 mountPoint = GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(strPath)));
2269 return mountPoint;
2272 CString GetSymlink( const CString& strPath )
2274 LONG code;
2275 struct ViceIoctl blob;
2276 CString symlink;
2277 char space[AFS_PIOCTL_MAXSIZE];
2279 CString strParent = Parent(strPath);
2280 CStringUtf8 ustrLast(LastComponent(strPath));
2282 FixNetbiosPath(strParent);
2284 blob.in_size = ustrLast.GetLength() + 1;
2285 blob.in = ustrLast.GetBuffer();
2286 blob.out_size = AFS_PIOCTL_MAXSIZE;
2287 blob.out = space;
2288 memset(space, 0, AFS_PIOCTL_MAXSIZE);
2290 code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1);
2292 ustrLast.ReleaseBuffer();
2294 if (code == 0) {
2295 CString syml;
2296 int len;
2298 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
2299 syml = Utf8ToCString(space);
2300 len = syml.GetLength();
2302 if (len > 0) {
2303 if (syml[len - 1] == _T('.'))
2304 syml.Truncate(len - 1);
2307 symlink = ParseSymlink(StripPath(strPath), syml);
2309 } else {
2310 if (errno == EINVAL)
2311 symlink = GetMessageString(IDS_NOT_SYMLINK_ERROR, StripPath(strPath));
2312 else
2313 symlink = GetMessageString(IDS_LIST_MOUNT_POINT_ERROR, GetAfsError(errno, StripPath(strPath)));
2317 return symlink;