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
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <afs/com_err.h>
29 #include <afs/opr_assert.h>
30 #include <rx/rx_globals.h>
34 #include <afs/afs_consts.h>
35 #include <afs/cellconfig.h>
36 #include <afs/ptserver.h>
37 #include <afs/ptuser.h>
38 #include <afs/volser.h>
39 #include <WINNT\afsreg.h>
47 #include "parsemode.h"
49 #define MAXINSIZE 1300 /* pioctl complains if data is larger than this */
50 #define VMSGSIZE 128 /* size of msg buf in volume hdr */
51 #define CELL_MAXNAMELEN 256
52 #define MAXHOSTCHARS 64
54 static char pn[] = "fs";
56 static char space[AFS_PIOCTL_MAXSIZE];
58 static struct ubik_client *uclient;
60 /* some forward references */
61 static int SetVolCmd(struct cmd_syndesc *as, void *arock);
63 static int GetCellName(char *cellNamep, struct afsconf_cell *infop);
64 static afs_int32 GetCell(char *fname, char *cellname, size_t cell_len);
66 static int VLDBInit(int noAuthFlag, struct afsconf_cell *infop);
67 static int GetClientAddrsCmd(struct cmd_syndesc *asp, void *arock);
68 static int SetClientAddrsCmd(struct cmd_syndesc *asp, void *arock);
69 static int FlushMountCmd(struct cmd_syndesc *asp, void *arock);
70 static int RxStatProcCmd(struct cmd_syndesc *asp, void *arock);
71 static int RxStatPeerCmd(struct cmd_syndesc *asp, void *arock);
73 static int MemDumpCmd(struct cmd_syndesc *asp, void *arock);
74 static int CSCPolicyCmd(struct cmd_syndesc *asp, void *arock);
75 static int MiniDumpCmd(struct cmd_syndesc *asp, void *arock);
77 static int rxInitDone = 0;
80 * Offset of -id switch in command structure for various commands.
81 * The -if switch is the next switch always.
83 static int parm_setacl_id, parm_copyacl_id, parm_listacl_id;
86 * Determine whether either the -id or -if switches are present, and
87 * return 0, 1 or 2, as appropriate. Abort if both switches are present.
89 /* int id; Offset of -id switch; -if is next switch */
91 getidf(struct cmd_syndesc *as, int id)
95 if (as->parms[id].items) {
98 if (as->parms[id + 1].items) {
103 "%s: you may specify either -id or -if, but not both switches\n",
111 PRights(afs_int32 arights, int dfs)
114 if (arights & PRSFS_READ)
116 if (arights & PRSFS_LOOKUP)
118 if (arights & PRSFS_INSERT)
120 if (arights & PRSFS_DELETE)
122 if (arights & PRSFS_WRITE)
124 if (arights & PRSFS_LOCK)
126 if (arights & PRSFS_ADMINISTER)
128 if (arights & PRSFS_USR0)
130 if (arights & PRSFS_USR1)
132 if (arights & PRSFS_USR2)
134 if (arights & PRSFS_USR3)
136 if (arights & PRSFS_USR4)
138 if (arights & PRSFS_USR5)
140 if (arights & PRSFS_USR6)
142 if (arights & PRSFS_USR7)
145 if (arights & DFS_READ)
149 if (arights & DFS_WRITE)
153 if (arights & DFS_EXECUTE)
157 if (arights & DFS_CONTROL)
161 if (arights & DFS_INSERT)
165 if (arights & DFS_DELETE)
169 if (arights & (DFS_USRALL))
171 if (arights & DFS_USR0)
173 if (arights & DFS_USR1)
175 if (arights & DFS_USR2)
177 if (arights & DFS_USR3)
179 if (arights & DFS_USR4)
181 if (arights & DFS_USR5)
183 if (arights & DFS_USR6)
185 if (arights & DFS_USR7)
192 Convert(char *arights, int dfs, enum rtype *rtypep)
198 *rtypep = add; /* add rights, by default */
200 /* analyze last character of string */
201 tcp = arights + strlen(arights);
202 if ( tcp-- > arights ) { /* assure non-empty string */
204 *rtypep = reladd; /* '+' indicates more rights */
205 else if ( *tcp == '-' )
206 *rtypep = reldel; /* '-' indicates less rights */
207 else if ( *tcp == '=' )
208 *rtypep = add; /* '=' also allows old behaviour */
210 tcp++; /* back to original null byte */
211 *tcp = '\0'; /* do not disturb old strcmp-s */
215 if (!strcmp(arights, "null")) {
219 if (!strcmp(arights,"read"))
220 return DFS_READ | DFS_EXECUTE;
221 if (!strcmp(arights, "write"))
222 return DFS_READ | DFS_EXECUTE | DFS_INSERT | DFS_DELETE |
224 if (!strcmp(arights, "all"))
225 return DFS_READ | DFS_EXECUTE | DFS_INSERT | DFS_DELETE |
226 DFS_WRITE | DFS_CONTROL;
228 if (!strcmp(arights,"read"))
229 return PRSFS_READ | PRSFS_LOOKUP;
230 if (!strcmp(arights, "write"))
231 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
232 PRSFS_WRITE | PRSFS_LOCK;
233 if (!strcmp(arights, "mail"))
234 return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP;
235 if (!strcmp(arights, "all"))
236 return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
237 PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
239 if (!strcmp(arights, "none")) {
240 *rtypep = destroy; /* Remove entire entry */
245 while ((tc = *tcp++)) {
278 fprintf(stderr, "%s: illegal DFS rights character '%c'.\n",
286 mode |= PRSFS_LOOKUP;
288 mode |= PRSFS_INSERT;
290 mode |= PRSFS_DELETE;
296 mode |= PRSFS_ADMINISTER;
314 fprintf(stderr, "%s: illegal rights character '%c'.\n", pn,
323 /* if no parm specified in a particular slot, set parm to be "." instead */
325 SetDotDefault(struct cmd_item **aitemp)
331 return; /* already has value */
332 /* otherwise, allocate an item representing "." */
333 ti = (struct cmd_item *) malloc(sizeof(struct cmd_item));
335 ti->next = (struct cmd_item *) 0;
336 ti->data = (char *) malloc(len_data);
338 if( FAILED(StringCbCopy(ti->data, len_data, "."))) {
339 fprintf (stderr, "data - not enough space");
346 PrintStatus(VolumeStatus *status, char *name, char *motd, char *offmsg)
348 printf("Volume status for vid = %u named %s is\n",status->Vid, name);
350 printf("Current offline message is %s\n",offmsg);
352 printf("Current message of the day is %s\n",motd);
353 printf("Current disk quota is ");
354 if (status->MaxQuota != 0)
355 printf("%d\n", status->MaxQuota);
357 printf("unlimited\n");
358 printf("Current blocks used are %d\n",status->BlocksInUse);
359 printf("The partition has %d blocks available out of %d\n",
360 status->PartBlocksAvail, status->PartMaxBlocks);
365 QuickPrintStatus(VolumeStatus *status, char *name)
367 double QuotaUsed =0.0;
368 double PartUsed =0.0;
370 printf("%-25.25s",name);
372 if (status->MaxQuota != 0) {
373 printf(" %10d %10d", status->MaxQuota, status->BlocksInUse);
374 QuotaUsed = ((((double)status->BlocksInUse)/status->MaxQuota) * 100.0);
376 printf(" no limit %10d", status->BlocksInUse);
378 if (QuotaUsed > 90.0){
379 printf(" %5.0f%%<<", QuotaUsed);
382 printf(" %5.0f%% ", QuotaUsed);
383 PartUsed = (100.0 - ((((double)status->PartBlocksAvail)/status->PartMaxBlocks) * 100.0));
384 if (PartUsed > 97.0){
385 printf(" %9.0f%%<<", PartUsed);
388 printf(" %9.0f%% ", PartUsed);
390 printf(" <<WARNING\n");
397 QuickPrintSpace(VolumeStatus *status, char *name)
399 double PartUsed =0.0;
401 printf("%-25.25s",name);
403 printf("%10d%10d%10d", status->PartMaxBlocks, status->PartMaxBlocks - status->PartBlocksAvail, status->PartBlocksAvail);
405 PartUsed = (100.0 - ((((double)status->PartBlocksAvail)/status->PartMaxBlocks) * 100.0));
406 if (PartUsed > 90.0){
407 printf(" %4.0f%%<<", PartUsed);
410 printf(" %4.0f%% ", PartUsed);
412 printf(" <<WARNING\n");
418 static DWORD IsFreelance(void)
425 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
426 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
427 if (code == ERROR_SUCCESS) {
428 dummyLen = sizeof(cm_freelanceEnabled);
429 code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
430 (BYTE *) &enabled, &dummyLen);
431 RegCloseKey (parmKey);
437 SetACLCmd(struct cmd_syndesc *as, void *arock)
440 struct ViceIoctl blob;
442 struct cmd_item *ti, *ui;
446 int idf = getidf(as, parm_setacl_id);
449 char cell[CELL_MAXNAMELEN];
451 if (as->parms[2].items)
455 plusp = !(as->parms[3].items);
456 for(ti=as->parms[0].items; ti;ti=ti->next) {
457 code = GetCell(ti->data, cell, sizeof(cell));
459 fs_Die(errno, ti->data);
464 if ( fs_IsFreelanceRoot(ti->data) ) {
465 fprintf(stderr,"%s: ACLs cannot be set on the Freelance root.afs volume.\n", pn);
469 blob.out_size = AFS_PIOCTL_MAXSIZE;
471 blob.in = blob.out = space;
472 code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
474 fs_Die(errno, ti->data);
480 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
483 "fs: %s: invalid acl data returned from VIOCGETAL\n",
488 if (!plusp && ta->dfs) {
490 "fs: %s: you may not use the -negative switch with DFS acl's.\n%s",
492 "(you may specify \"null\" to revoke all rights, however)\n");
499 ta = EmptyAcl(space);
501 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
504 "fs: %s: invalid acl data returned from VIOCGETAL\n",
510 for(ui=as->parms[1].items; ui; ui=ui->next->next) {
514 "%s: Missing second half of user/access pair.\n", pn);
518 rights = Convert(ui->next->data, ta->dfs, &rtype);
519 if (rtype == destroy && !ta->dfs) {
520 struct AclEntry *tlist;
522 tlist = (plusp ? ta->pluslist : ta->minuslist);
523 if (!FindList(tlist, ui->data))
526 if (rtype == deny && !ta->dfs)
528 if (rtype == destroy && ta->dfs)
530 ChangeList(ta, plusp, ui->data, rights, &rtype);
532 blob.in = AclToString(ta);
534 if( FAILED(StringCbLength(blob.in, sizeof(space), &len))) {
535 fprintf (stderr, "StringCbLength failure on blob.in");
538 blob.in_size = 1+(long)len;
539 code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1);
541 if (errno == EINVAL) {
543 static char *fsenv = 0;
545 fsenv = (char *)getenv("FS_EXPERT");
547 fprintf(stderr, "fs: \"Invalid argument\" was returned when you tried to store a DFS access list.\n");
550 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
551 "\nPossible reasons for this include:\n\n",
552 " -You may have specified an inappropriate combination of rights.\n",
553 " For example, some DFS-supported filesystems may not allow you to\n",
554 " drop the \"c\" right from \"user_obj\".\n\n",
555 " -A mask_obj may be required (it is likely required by the underlying\n",
556 " filesystem if you try to set anything other than the basic \"user_obj\"\n",
557 " \"mask_obj\", or \"group_obj\" entries). Unlike acl_edit, the fs command\n",
558 " does not automatically create or update the mask_obj. Try setting\n",
559 " the rights \"mask_obj all\" with \"fs sa\" before adding any explicit\n",
560 " users or groups. You can do this with a single command, such as\n",
561 " \"fs sa mask_obj all user:somename read\"\n\n",
562 " -A specified user or group may not exist.\n\n",
563 " -You may have tried to delete \"user_obj\", \"group_obj\", or \"other_obj\".\n",
564 " This is probably not allowed by the underlying file system.\n\n",
565 " -If you add a user or group to a DFS ACL, remember that it must be\n",
566 " fully specified as \"user:username\" or \"group:groupname\". In addition, there\n",
567 " may be local requirements on the format of the user or group name.\n",
568 " Check with your cell administrator.\n\n",
569 " -Or numerous other possibilities. It would be great if we could be more\n",
570 " precise about the actual problem, but for various reasons, this is\n",
571 " impractical via this interface. If you can't figure it out, you\n",
572 " might try logging into a DCE-equipped machine and use acl_edit (or\n",
573 " whatever is provided). You may get better results. Good luck!\n\n",
574 " (You may inhibit this message by setting \"FS_EXPERT\" in your environment)\n");
578 "%s: Invalid argument, possible reasons include:\n",
580 fprintf(stderr,"\t-File not in AFS\n");
582 "\t-Too many users on access control list\n");
584 "\t-Tried to add non-existent user to access control list\n");
587 fs_Die(errno, ti->data);
598 CopyACLCmd(struct cmd_syndesc *as, void *arock)
601 struct ViceIoctl blob;
602 struct Acl *fa, *ta = 0;
606 int idf = getidf(as, parm_copyacl_id);
609 char cell[CELL_MAXNAMELEN];
611 if (as->parms[2].items)
615 blob.out_size = AFS_PIOCTL_MAXSIZE;
617 blob.in = blob.out = space;
618 code = pioctl_utf8(as->parms[0].items->data, VIOCGETAL, &blob, 1);
620 fs_Die(errno, as->parms[0].items->data);
623 fa = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
626 "%s: %s: invalid acl data returned from VIOCGETAL\n",
627 pn, as->parms[0].items->data);
630 code = GetCell(as->parms[0].items->data, cell, sizeof(cell));
633 "%s: %s: unable to obtain cell name\n",
634 pn, as->parms[0].items->data);
638 for (ti=as->parms[1].items; ti;ti=ti->next) {
639 blob.out_size = AFS_PIOCTL_MAXSIZE;
641 blob.in = blob.out = space;
642 code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
644 fs_Die(errno, ti->data);
651 ta = EmptyAcl(space);
653 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
656 "%s: %s: invalid acl data returned from VIOCGETAL\n",
661 code = GetCell(ti->data, cell, sizeof(cell));
664 "%s: %s: unable to obtain cell name\n",
670 if (ta->dfs != fa->dfs) {
672 "%s: incompatible file system types: acl not copied to %s; aborted\n",
678 if (! clear && strcmp(ta->cell, fa->cell) != 0) {
680 "%s: default DCE cell differs for file %s: use \"-clear\" switch; acl not merged\n",
685 if( FAILED(StringCbCopy(ta->cell, sizeof(ta->cell), fa->cell))) {
686 fprintf (stderr, "cell - not enough space");
690 for (tp = fa->pluslist;tp;tp=tp->next)
691 ChangeList(ta, 1, tp->name, tp->rights, NULL);
692 for (tp = fa->minuslist;tp;tp=tp->next)
693 ChangeList(ta, 0, tp->name, tp->rights, NULL);
694 blob.in = AclToString(ta);
696 if( FAILED(StringCbLength(blob.in, sizeof(space), &len))) {
697 fprintf (stderr, "StringCbLength failure on blob.in");
700 blob.in_size = 1+(long)len;
701 code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1);
703 if (errno == EINVAL) {
705 "%s: Invalid argument, possible reasons include:\n", pn);
706 fprintf(stderr,"\t-File not in AFS\n");
708 fs_Die(errno, ti->data);
719 /* pioctl_utf8() call to get the cellname of a pathname */
721 GetCell(char *fname, char *cellname, size_t cell_len)
724 struct ViceIoctl blob;
727 blob.out_size = cell_len;
730 code = pioctl_utf8(fname, VIOC_FILE_CELL_NAME, &blob, 1);
732 cellname[blob.out_size - 1] = '\0';
736 /* clean up an acl to not have bogus entries */
738 CleanACLCmd(struct cmd_syndesc *as, void *arock)
742 struct ViceIoctl blob;
749 SetDotDefault(&as->parms[0].items);
750 for(ti=as->parms[0].items; ti; ti=ti->next) {
751 blob.out_size = AFS_PIOCTL_MAXSIZE;
754 code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
756 fs_Die(errno, ti->data);
762 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
765 "fs: %s: invalid acl data returned from VIOCGETAL\n",
772 "%s: cleanacl is not supported for DFS access lists.\n",
778 changes = CleanAcl(ta, ti->data);
781 /* now set the acl */
782 blob.in=AclToString(ta);
783 if( FAILED(StringCbLength(blob.in, sizeof(space), &len))) {
784 fprintf (stderr, "StringCbLength failure on blob.in");
787 blob.in_size = (long)len+1;
789 code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1);
791 if (errno == EINVAL) {
793 "%s: Invalid argument, possible reasons include\n",
795 fprintf(stderr,"%s: File not in vice or\n", pn);
797 "%s: Too many users on access control list or\n",
800 fs_Die(errno, ti->data);
806 /* now list the updated acl */
807 printf("Access list for %s is now\n", ti->data);
810 printf("Normal rights:\n");
811 for(te = ta->pluslist;te;te=te->next) {
812 printf(" %s ", te->name);
813 PRights(te->rights, ta->dfs);
817 if (ta->nminus > 0) {
818 printf("Negative rights:\n");
819 for(te = ta->minuslist;te;te=te->next) {
820 printf(" %s ", te->name);
821 PRights(te->rights, ta->dfs);
828 printf("Access list for %s is fine.\n", ti->data);
836 ListACLCmd(struct cmd_syndesc *as, void *arock)
840 struct ViceIoctl blob;
843 int idf = getidf(as, parm_listacl_id);
846 SetDotDefault(&as->parms[0].items);
847 for(ti=as->parms[0].items; ti; ti=ti->next) {
850 if ( fs_IsFreelanceRoot(ti->data) ) {
851 fprintf(stderr,"%s: ACLs are not set on the Freelance root.afs volume.\n", pn);
856 blob.out_size = AFS_PIOCTL_MAXSIZE;
858 blob.in = blob.out = space;
859 code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
861 fs_Die(errno, ti->data);
865 ta = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
868 "fs: %s: invalid acl data returned from VIOCGETAL\n",
873 if (as->parms[3].items) { /* -cmd */
874 printf("fs setacl -dir %s -acl ", ti->data);
876 for (te = ta->pluslist; te; te = te->next) {
877 printf(" %s ", te->name);
878 PRights(te->rights, ta->dfs);
882 if (ta->nminus > 0) {
883 printf("fs setacl -dir %s -acl ", ti->data);
884 for (te = ta->minuslist; te; te = te->next) {
885 printf(" %s ", te->name);
886 PRights(te->rights, ta->dfs);
888 printf(" -negative\n");
893 printf("Access list for %s is\n", ti->data);
896 printf("DFS access list for %s is\n", ti->data);
899 printf("DFS initial directory access list of %s is\n", ti->data);
902 printf("DFS initial file access list of %s is\n", ti->data);
906 printf(" Default cell = %s\n", ta->cell);
908 separator = ta->dfs? DFS_SEPARATOR : ' ';
911 printf("Normal rights:\n");
912 for(te = ta->pluslist;te;te=te->next) {
913 printf(" %s%c", te->name, separator);
914 PRights(te->rights, ta->dfs);
918 if (ta->nminus > 0) {
919 printf("Negative rights:\n");
920 for(te = ta->minuslist;te;te=te->next) {
921 printf(" %s ", te->name);
922 PRights(te->rights, ta->dfs);
935 GetCallerAccess(struct cmd_syndesc *as, void *arock)
938 struct ViceIoctl blob;
942 cm_ioctlQueryOptions_t options;
944 if (as->parms[1].items)
947 SetDotDefault(&as->parms[0].items);
948 for(ti=as->parms[0].items; ti; ti=ti->next) {
950 afs_uint32 rights[2];
953 memset(&fid, 0, sizeof(fid));
954 memset(&options, 0, sizeof(options));
955 options.size = sizeof(options);
956 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
957 options.literal = literal;
958 blob.in_size = options.size; /* no variable length data */
961 blob.out_size = sizeof(cm_fid_t);
962 blob.out = (char *) &fid;
963 if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) &&
964 blob.out_size == sizeof(cm_fid_t)) {
965 options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
968 fs_Die(errno, ti->data);
973 blob.out_size = sizeof(rights);
975 code = pioctl_utf8(ti->data, VIOC_GETCALLERACCESS, &blob, 1);
976 if (code || blob.out_size != sizeof(rights)) {
977 fs_Die(errno, ti->data);
982 printf("Callers access to '%s' is ", ti->data);
983 PRights(rights[0], 0);
990 FlushAllCmd(struct cmd_syndesc *as, void *arock)
993 struct ViceIoctl blob;
995 blob.in_size = blob.out_size = 0;
996 code = pioctl_utf8(NULL, VIOC_FLUSHALL, &blob, 0);
998 fprintf(stderr, "Error flushing all ");
1005 FlushVolumeCmd(struct cmd_syndesc *as, void *arock)
1008 struct ViceIoctl blob;
1009 struct cmd_item *ti;
1012 SetDotDefault(&as->parms[0].items);
1013 for(ti=as->parms[0].items; ti; ti=ti->next) {
1014 blob.in_size = blob.out_size = 0;
1015 code = pioctl_utf8(ti->data, VIOC_FLUSHVOLUME, &blob, 0);
1017 fprintf(stderr, "Error flushing volume ");
1027 FlushCmd(struct cmd_syndesc *as, void *arock)
1030 struct ViceIoctl blob;
1031 struct cmd_item *ti;
1034 cm_ioctlQueryOptions_t options;
1036 if (as->parms[1].items)
1039 for(ti=as->parms[0].items; ti; ti=ti->next) {
1041 memset(&options, 0, sizeof(options));
1042 options.size = sizeof(options);
1043 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
1044 options.literal = literal;
1045 blob.in_size = options.size; /* no variable length data */
1049 code = pioctl_utf8(ti->data, VIOCFLUSH, &blob, 0);
1051 if (errno == EMFILE) {
1052 fprintf(stderr, "%s: Can't flush active file %s\n", pn,
1055 fprintf(stderr, "%s: Error flushing file ", pn);
1065 /* all this command does is repackage its args and call SetVolCmd */
1067 SetQuotaCmd(struct cmd_syndesc *as, void *arock) {
1068 struct cmd_syndesc ts;
1070 /* copy useful stuff from our command slot; we may later have to reorder */
1072 memcpy(&ts, as, sizeof(ts)); /* copy whole thing */
1074 err = memcpy_s(&ts, sizeof(ts), as, sizeof(ts)); /* copy whole thing */
1076 fprintf (stderr, "memcpy_s failure on ts");
1080 return SetVolCmd(&ts, arock);
1084 SetVolCmd(struct cmd_syndesc *as, void *arock) {
1086 struct ViceIoctl blob;
1087 struct cmd_item *ti;
1088 struct VolumeStatus *status;
1089 char *motd, *offmsg, *input, *destEnd;
1090 size_t destRemaining;
1094 SetDotDefault(&as->parms[0].items);
1095 for(ti=as->parms[0].items; ti; ti=ti->next) {
1097 destRemaining = sizeof(space);
1098 blob.out_size = AFS_PIOCTL_MAXSIZE;
1099 blob.in_size = sizeof(*status) + 3; /* for the three terminating nulls */
1102 status = (VolumeStatus *)space;
1103 status->MinQuota = status->MaxQuota = -1;
1104 motd = offmsg = NULL;
1105 if (as->parms[1].items) {
1106 code = util_GetHumanInt32(as->parms[1].items->data, &status->MaxQuota);
1108 fprintf(stderr,"%s: bad integer specified for quota.\n", pn);
1113 if (as->parms[2].items)
1114 motd = as->parms[2].items->data;
1115 if (as->parms[3].items)
1116 offmsg = as->parms[3].items->data;
1117 input = (char *)status + sizeof(*status);
1118 *(input++) = '\0'; /* never set name: this call doesn't change vldb */
1119 destRemaining -= sizeof(*status) + 1;
1121 if( FAILED(StringCbLength(offmsg, VMSGSIZE, &len))) {
1122 fprintf(stderr,"%s: message must be shorter than %d characters\n",
1127 if( FAILED(StringCbCopyEx(input, destRemaining, offmsg, &destEnd, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
1128 fprintf (stderr, "input - not enough space");
1131 blob.in_size += destEnd - input;
1132 input = destEnd + 1;
1133 destRemaining -= sizeof(char);
1136 destRemaining -= sizeof(char);
1139 if( FAILED(StringCbLength(motd, VMSGSIZE, &len))) {
1140 fprintf(stderr,"%s: message must be shorter than %d characters\n",
1144 if( FAILED(StringCbCopyEx(input, destRemaining, motd, &destEnd, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
1145 fprintf (stderr, "input - not enough space");
1148 blob.in_size += (long)(destEnd - input);
1149 input = destEnd + 1;
1150 destRemaining -= sizeof(char);
1153 destRemaining -= sizeof(char);
1155 code = pioctl_utf8(ti->data,VIOCSETVOLSTAT, &blob, 1);
1157 fs_Die(errno, ti->data);
1165 ExamineCmd(struct cmd_syndesc *as, void *arock)
1168 struct ViceIoctl blob;
1169 struct cmd_item *ti;
1170 struct VolumeStatus *status;
1171 char *name, *offmsg, *motd;
1174 cm_ioctlQueryOptions_t options;
1177 if (as->parms[1].items)
1180 SetDotDefault(&as->parms[0].items);
1181 for(ti=as->parms[0].items; ti; ti=ti->next) {
1183 afs_uint32 filetype;
1185 afs_uint32 unixModeBits;
1186 char cell[CELL_MAXNAMELEN];
1189 memset(&fid, 0, sizeof(fid));
1190 memset(&options, 0, sizeof(options));
1192 options.size = sizeof(options);
1193 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
1194 options.literal = literal;
1195 blob.in_size = options.size; /* no variable length data */
1198 blob.out_size = sizeof(cm_fid_t);
1199 blob.out = (char *) &fid;
1200 if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) &&
1201 blob.out_size == sizeof(cm_fid_t)) {
1202 options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
1205 fs_Die(errno, ti->data);
1210 blob.out_size = sizeof(filetype);
1211 blob.out = &filetype;
1213 code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
1214 if (code || blob.out_size != sizeof(filetype)) {
1215 fs_Die(errno, ti->data);
1220 blob.out_size = CELL_MAXNAMELEN;
1223 code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
1225 cell[blob.out_size-1] = '\0';
1226 printf("%s %s (%u.%u.%u) contained in cell %s\n",
1227 fs_filetypestr(filetype),
1228 ti->data, fid.volume, fid.vnode, fid.unique,
1229 code ? "unknown-cell" : cell);
1231 blob.out_size = 2 * sizeof(afs_uint32);
1232 blob.out = (char *) &owner;
1233 if (0 == pioctl_utf8(ti->data, VIOCGETOWNER, &blob, 1) &&
1234 blob.out_size == 2 * sizeof(afs_uint32)) {
1235 char oname[PR_MAXNAMELEN] = "(unknown)";
1236 char gname[PR_MAXNAMELEN] = "(unknown)";
1239 /* Go to the PRDB and see if this all number username is valid */
1240 cm_GetConfigDir(confDir, sizeof(confDir));
1242 pr_Initialize(1, confDir, cell);
1243 pr_SIdToName(owner[0], oname);
1244 pr_SIdToName(owner[1], gname);
1245 printf("Owner %s (%d) Group %s (%d)\n", oname, owner[0], gname, owner[1]);
1248 blob.out_size = sizeof(afs_uint32);
1249 blob.out = (char *) &unixModeBits;
1250 if (0 == pioctl_utf8(ti->data, VIOC_GETUNIXMODE, &blob, 1) &&
1251 blob.out_size == sizeof(afs_uint32)) {
1252 printf("UNIX mode 0%o\n", unixModeBits);
1256 blob.out_size = AFS_PIOCTL_MAXSIZE;
1257 code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
1259 space[blob.out_size - 1] = '\0';
1260 status = (VolumeStatus *)space;
1261 name = (char *)status + sizeof(*status);
1262 if( FAILED(StringCbLength(name, sizeof(space) - (name - space), &len))) {
1263 fprintf (stderr, "StringCbLength failure on name");
1266 offmsg = name + len + 1;
1267 if( FAILED(StringCbLength(offmsg, sizeof(space) - (offmsg - space), &len))) {
1268 fprintf (stderr, "StringCbLength failure on offmsg");
1271 motd = offmsg + len + 1;
1272 PrintStatus(status, name, motd, offmsg);
1274 fs_Die(errno, ti->data);
1278 code = pioctl_utf8(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1);
1281 printf("Volume is online\n");
1284 printf("Volume is offline\n");
1287 printf("All Volume servers are down\n");
1290 printf("All volume servers are busy\n");
1293 printf("Unknown volume state\n");
1294 fs_Die(errno, ti->data);
1302 ListQuotaCmd(struct cmd_syndesc *as, void *arock)
1305 struct ViceIoctl blob;
1306 struct cmd_item *ti;
1307 struct VolumeStatus *status;
1312 printf("%-25s%-11s%-11s%-7s%-13s\n", "Volume Name", " Quota",
1313 " Used", " %Used", " Partition");
1314 SetDotDefault(&as->parms[0].items);
1315 for(ti=as->parms[0].items; ti; ti=ti->next) {
1317 blob.out_size = AFS_PIOCTL_MAXSIZE;
1320 code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
1322 fs_Die(errno, ti->data);
1326 space[blob.out_size - 1] = '\0';
1327 status = (VolumeStatus *)space;
1328 name = (char *)status + sizeof(*status);
1329 QuickPrintStatus(status, name);
1335 WhereIsCmd(struct cmd_syndesc *as, void *arock)
1338 struct ViceIoctl blob;
1339 struct cmd_item *ti;
1345 cm_ioctlQueryOptions_t options;
1347 if (as->parms[1].items)
1350 SetDotDefault(&as->parms[0].items);
1351 for(ti=as->parms[0].items; ti; ti=ti->next) {
1353 afs_uint32 filetype;
1356 memset(&fid, 0, sizeof(fid));
1357 memset(&options, 0, sizeof(options));
1359 options.size = sizeof(options);
1360 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
1361 options.literal = literal;
1362 blob.in_size = options.size; /* no variable length data */
1365 blob.out_size = sizeof(cm_fid_t);
1366 blob.out = (char *) &fid;
1367 if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) &&
1368 blob.out_size == sizeof(cm_fid_t)) {
1369 options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
1372 fs_Die(errno, ti->data);
1377 blob.out_size = sizeof(filetype);
1378 blob.out = &filetype;
1380 code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
1381 if (code || blob.out_size != sizeof(filetype)) {
1382 fs_Die(errno, ti->data);
1386 blob.out_size = AFS_PIOCTL_MAXSIZE;
1388 memset(space, 0, sizeof(space));
1389 code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1);
1391 fs_Die(errno, ti->data);
1395 hosts = (afs_int32 *) space;
1396 printf("%s %s is on host%s ",
1397 fs_filetypestr(filetype),
1399 (hosts[0] && !hosts[1]) ? "": "s");
1400 for(j=0; j<AFS_MAXHOSTS; j++) {
1403 tp = hostutil_GetNameByINet(hosts[j]);
1413 DiskFreeCmd(struct cmd_syndesc *as, void *arock)
1416 struct ViceIoctl blob;
1417 struct cmd_item *ti;
1419 struct VolumeStatus *status;
1422 printf("%-25s%-10s%-10s%-10s%-6s\n", "Volume Name", " kbytes",
1423 " used", " avail", " %used");
1424 SetDotDefault(&as->parms[0].items);
1425 for(ti=as->parms[0].items; ti; ti=ti->next) {
1427 blob.out_size = AFS_PIOCTL_MAXSIZE;
1430 code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
1432 fs_Die(errno, ti->data);
1436 space[blob.out_size - 1] = '\0';
1437 status = (VolumeStatus *)space;
1438 name = (char *)status + sizeof(*status);
1439 QuickPrintSpace(status, name);
1445 QuotaCmd(struct cmd_syndesc *as, void *arock)
1448 struct ViceIoctl blob;
1449 struct cmd_item *ti;
1451 struct VolumeStatus *status;
1454 SetDotDefault(&as->parms[0].items);
1455 for(ti=as->parms[0].items; ti; ti=ti->next) {
1457 blob.out_size = AFS_PIOCTL_MAXSIZE;
1460 code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
1462 * The response is VolumeStatus, volume name, offline message, and motd
1464 if (code || blob.out_size < sizeof(*status)) {
1465 fs_Die(errno, ti->data);
1470 status = (VolumeStatus *)space;
1471 if (status->MaxQuota)
1472 quotaPct = ((((double)status->BlocksInUse)/status->MaxQuota) * 100.0);
1475 printf("%2.0f%% of quota used.\n", quotaPct);
1481 ListMountCmd(struct cmd_syndesc *as, void *arock)
1484 struct ViceIoctl blob;
1485 struct cmd_item *ti;
1486 char orig_name[1024]; /*Original name, may be modified*/
1487 char true_name[1024]; /*``True'' dirname (e.g., symlink target)*/
1488 char parent_dir[1024]; /*Parent directory of true name*/
1489 char *last_component; /*Last component of true name*/
1493 struct stat statbuff; /*Buffer for status info*/
1494 #endif /* not WIN32 */
1496 int link_chars_read; /*Num chars read in readlink()*/
1497 #endif /* not WIN32 */
1498 int thru_symlink; /*Did we get to a mount point via a symlink?*/
1501 for(ti=as->parms[0].items; ti; ti=ti->next) {
1505 if( FAILED(StringCbCopy(orig_name, sizeof(orig_name), ti->data))) {
1506 fprintf (stderr, "orig_name - not enough space");
1509 #else /* not WIN32 */
1511 if( FAILED(StringCbPrintf(orig_name, sizeof(orig_name), "%s%s",
1512 (ti->data[0] == '/') ? "" : "./",
1514 fprintf (stderr, "orig_name - cannot be populated");
1517 #endif /* not WIN32 */
1520 if (lstat(orig_name, &statbuff) < 0) {
1521 /* if lstat fails, we should still try the pioctl, since it
1522 * may work (for example, lstat will fail, but pioctl will
1523 * work if the volume of offline (returning ENODEV). */
1524 statbuff.st_mode = S_IFDIR; /* lie like pros */
1528 * The lstat succeeded. If the given file is a symlink, substitute
1529 * the file name with the link name.
1531 if ((statbuff.st_mode & S_IFMT) == S_IFLNK) {
1534 * Read name of resolved file.
1536 link_chars_read = readlink(orig_name, true_name, 1024);
1537 if (link_chars_read <= 0) {
1539 "%s: Can't read target name for '%s' symbolic link!\n",
1546 * Add a trailing null to what was read, bump the length.
1548 true_name[link_chars_read++] = 0;
1551 * If the symlink is an absolute pathname, we're fine. Otherwise, we
1552 * have to create a full pathname using the original name and the
1553 * relative symlink name. Find the rightmost slash in the original
1554 * name (we know there is one) and splice in the symlink value.
1556 if (true_name[0] != '\\') {
1557 last_component = (char *) strrchr(orig_name, '\\');
1558 if( FAILED(StringCbCopy(++last_component, sizeof(orig_name) - (last_component - orig_name) * sizeof(char), true_name))) {
1559 fprintf (stderr, "last_component - not enough space");
1562 if( FAILED(StringCbCopy(true_name, sizeof(true_name), orig_name))) {
1563 fprintf (stderr, "true_name - not enough space");
1568 if( FAILED(StringCbCopy(true_name, sizeof(true_name), orig_name))) {
1569 fprintf (stderr, "true_name - not enough space");
1574 if( FAILED(StringCbCopy(true_name, sizeof(true_name), orig_name))) {
1575 fprintf (stderr, "true_name - not enough space");
1581 * Find rightmost slash, if any.
1584 last_component = (char *) strrchr(true_name, '\\');
1585 if (!last_component)
1587 last_component = (char *) strrchr(true_name, '/');
1588 if (last_component) {
1590 * Found it. Designate everything before it as the parent directory,
1591 * everything after it as the final component.
1593 if( FAILED(StringCchCopyN(parent_dir, sizeof(parent_dir) / sizeof(char), true_name, last_component - true_name + 1))) {
1594 fprintf (stderr, "parent_dir - not enough space");
1597 parent_dir[last_component - true_name + 1] = 0;
1598 last_component++; /*Skip the slash*/
1600 if (!fs_InAFS(parent_dir)) {
1601 const char * nbname = fs_NetbiosName();
1602 if( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
1603 fprintf (stderr, "StringCbLength failure on nbname");
1606 if (parent_dir[0] == '\\' && parent_dir[1] == '\\' &&
1607 parent_dir[len+2] == '\\' &&
1608 parent_dir[len+3] == '\0' &&
1609 !strnicmp(nbname,&parent_dir[2],len))
1611 if( FAILED(StringCbPrintf(parent_dir, sizeof(parent_dir),"\\\\%s\\all\\", nbname))) {
1612 fprintf (stderr, "parent_dir - cannot be populated");
1620 * No slash appears in the given file name. Set parent_dir to the current
1621 * directory, and the last component as the given name.
1623 fs_ExtractDriveLetter(true_name, parent_dir);
1624 if( FAILED(StringCbCat(parent_dir, sizeof(parent_dir), "."))) {
1625 fprintf (stderr, "parent_dir - not enough space");
1628 last_component = true_name;
1629 fs_StripDriveLetter(true_name, true_name, sizeof(true_name));
1632 if (strcmp(last_component, ".") == 0 || strcmp(last_component, "..") == 0) {
1633 fprintf(stderr,"%s: you may not use '.' or '..' as the last component\n",pn);
1634 fprintf(stderr,"%s: of a name in the 'fs lsmount' command.\n",pn);
1639 blob.in = last_component;
1640 if( FAILED(StringCchLength(last_component, sizeof(true_name) / sizeof(char) - (last_component - true_name), &len))) {
1641 fprintf (stderr, "StringCbLength failure on last_component");
1644 blob.in_size = (long)len+1;
1645 blob.out_size = AFS_PIOCTL_MAXSIZE;
1647 memset(space, 0, AFS_PIOCTL_MAXSIZE);
1649 code = pioctl_utf8(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
1652 printf("'%s' is a %smount point for volume '%.*s'\n",
1654 (thru_symlink ? "symbolic link, leading to a " : ""),
1659 if (errno == EINVAL) {
1660 fprintf(stderr,"'%s' is not a mount point.\n", ti->data);
1662 fs_Die(errno, (ti->data ? ti->data : parent_dir));
1671 MakeMountCmd(struct cmd_syndesc *as, void *arock)
1674 char *cellName, *volName, *tmpName;
1676 char localCellName[128];
1678 char path[1024] = "";
1679 struct afsconf_cell info;
1680 struct vldbentry vldbEntry;
1681 struct ViceIoctl blob;
1685 memset(&info, 0, sizeof(info));
1687 if (as->parms[2].items) /* cell name specified */
1688 cellName = as->parms[2].items->data;
1691 volName = as->parms[1].items->data;
1692 if( FAILED(StringCbLength(volName, VL_MAXNAMELEN, &len))) {
1693 fprintf(stderr,"%s: volume name too long (length must be <= 64 characters)\n", pn);
1697 /* Check for a cellname in the volume specification, and complain
1698 * if it doesn't match what was specified with -cell */
1699 if (tmpName = strchr(volName, ':')) {
1702 if (strcasecmp(cellName,volName)) {
1703 fprintf(stderr,"fs: cellnames do not match.\n");
1708 volName = ++tmpName;
1711 parent = fs_GetParent(as->parms[0].items->data);
1712 if (!fs_InAFS(parent)) {
1714 const char * nbname = fs_NetbiosName();
1715 if ( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
1716 fprintf (stderr, "StringCbLength failure on nbname");
1719 if (parent[0] == '\\' && parent[1] == '\\' &&
1720 (parent[len+2] == '\\' && parent[len+3] == '\0' || parent[len+2] == '\0') &&
1721 !strnicmp(nbname,&parent[2],len))
1723 if( FAILED(StringCbPrintf(path, sizeof(path),"%s%sall%s", parent,
1724 parent[len+2]?"":"\\",
1725 &as->parms[0].items->data[len+2]))) {
1726 fprintf (stderr, "path - cannot be populated");
1729 parent = fs_GetParent(path);
1730 if (!fs_InAFS(parent)) {
1731 fprintf(stderr,"%s: mount points must be created within the AFS file system\n", pn);
1737 fprintf(stderr,"%s: mount points must be created within the AFS file system\n", pn);
1742 if( FAILED(StringCbLength(path, sizeof(path), &len))) {
1743 fprintf (stderr, "StringCbLength failure on path");
1747 if( FAILED(StringCbCopy(path, sizeof(path), as->parms[0].items->data))) {
1748 fprintf (stderr, "path - not enough space");
1752 if ( fs_IsFreelanceRoot(parent) ) {
1753 if ( !fs_IsAdmin() ) {
1754 fprintf(stderr,"%s: Only AFS Client Administrators may alter the Freelance root.afs volume\n", pn);
1760 blob.out_size = sizeof(localCellName);
1761 blob.out = localCellName;
1762 code = pioctl_utf8(parent, VIOC_GET_WS_CELL, &blob, 1);
1764 localCellName[sizeof(localCellName) - 1] = '\0';
1765 cellName = localCellName;
1770 code = GetCell(parent, space, sizeof(space));
1776 code = GetCellName(cellName?cellName:space, &info);
1780 if (!(as->parms[4].items)) {
1781 /* not fast, check which cell the mountpoint is being created in */
1783 /* not fast, check name with VLDB */
1785 code = VLDBInit(1, &info);
1787 /* make the check. Don't complain if there are problems with init */
1788 code = ubik_VL_GetEntryByNameO(uclient, 0, volName, &vldbEntry);
1789 if (code == VL_NOENT) {
1790 fprintf(stderr,"%s: warning, volume %s does not exist in cell %s.\n",
1791 pn, volName, cellName ? cellName : space);
1796 if (as->parms[3].items) { /* if -rw specified */
1797 if( FAILED(StringCbCopy(space, sizeof(space), "%"))) {
1798 fprintf (stderr, "space arr - not enough space");
1802 if( FAILED(StringCbCopy(space, sizeof(space), "#"))) {
1803 fprintf (stderr, "space arr - not enough space");
1808 /* cellular mount point, prepend cell prefix */
1809 if( FAILED(StringCbCat(space, sizeof(space), info.name))) {
1810 fprintf (stderr, "space arr - not enough space");
1813 if( FAILED(StringCbCat(space, sizeof(space), ":"))) {
1814 fprintf (stderr, "space arr - not enough space");
1818 if( FAILED(StringCbCat(space, sizeof(space), volName))) { /* append volume name */
1819 fprintf (stderr, "space arr - not enough space");
1822 if( FAILED(StringCbCat(space, sizeof(space), "."))) { /* stupid convention; these end with a period */
1823 fprintf (stderr, "space arr - not enough space");
1827 /* create symlink with a special pioctl for Windows NT, since it doesn't
1828 * have a symlink system call.
1831 if( FAILED(StringCbLength(space, sizeof(space), &len))) {
1832 fprintf (stderr, "StringCbLength failure on space");
1835 blob.in_size = 1 + (long)len;
1838 code = pioctl_utf8(path, VIOC_AFS_CREATE_MT_PT, &blob, 0);
1839 #else /* not WIN32 */
1840 code = symlink(space, path);
1841 #endif /* not WIN32 */
1843 if (info.linkedCell)
1844 free(info.linkedCell);
1847 fs_Die(errno, path);
1854 * Delete AFS mount points. Variables are used as follows:
1855 * tbuffer: Set to point to the null-terminated directory name of the mount point
1856 * (or ``.'' if none is provided)
1857 * tp: Set to point to the actual name of the mount point to nuke.
1860 RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
1862 struct ViceIoctl blob;
1863 struct cmd_item *ti;
1865 char lsbuffer[1024];
1870 for(ti=as->parms[0].items; ti; ti=ti->next) {
1872 tp = (char *) strrchr(ti->data, '\\');
1874 tp = (char *) strrchr(ti->data, '/');
1876 if( FAILED(StringCchCopyN(tbuffer, sizeof(tbuffer) / sizeof(char), ti->data, code=(afs_int32)(tp-ti->data+1)))) { /* the dir name */
1877 fprintf (stderr, "tbuffer - not enough space");
1880 tp++; /* skip the slash */
1883 if (!fs_InAFS(tbuffer)) {
1884 const char * nbname = fs_NetbiosName();
1885 if( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
1886 fprintf (stderr, "StringCbLength failure on nbname");
1890 if (tbuffer[0] == '\\' && tbuffer[1] == '\\' &&
1891 tbuffer[len+2] == '\\' &&
1892 tbuffer[len+3] == '\0' &&
1893 !strnicmp(nbname,&tbuffer[2],len))
1895 if( FAILED(StringCbPrintf(tbuffer, sizeof(tbuffer),"\\\\%s\\all\\", nbname))) {
1896 fprintf (stderr, "tbuffer - cannot be populated");
1903 fs_ExtractDriveLetter(ti->data, tbuffer);
1904 if( FAILED(StringCbCat(tbuffer, sizeof(tbuffer), "."))) {
1905 fprintf (stderr, "tbuffer - not enough space");
1909 fs_StripDriveLetter(tp, tp, strlen(tp) + 1);
1912 if( FAILED(StringCbLength(tp, AFS_PIOCTL_MAXSIZE, &len))) {
1913 fprintf (stderr, "StringCbLength failure on tp");
1916 blob.in_size = (long)len+1;
1917 blob.out = lsbuffer;
1918 blob.out_size = sizeof(lsbuffer);
1919 code = pioctl_utf8(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0);
1921 if (errno == EINVAL) {
1922 fprintf(stderr,"%s: '%s' is not a mount point.\n", pn, ti->data);
1924 fs_Die(errno, ti->data);
1927 continue; /* don't bother trying */
1930 if ( fs_IsFreelanceRoot(tbuffer) && !fs_IsAdmin() ) {
1931 fprintf(stderr,"%s: Only AFS Client Administrators may alter the Freelance root.afs volume\n", pn);
1933 continue; /* skip */
1938 if( FAILED(StringCbLength(tp, AFS_PIOCTL_MAXSIZE, &len))) {
1939 fprintf (stderr, "StringCbLength failure on tp");
1942 blob.in_size = (long)len+1;
1943 code = pioctl_utf8(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0);
1945 fs_Die(errno, ti->data);
1956 CheckServersCmd(struct cmd_syndesc *as, void *arock)
1959 struct ViceIoctl blob;
1963 struct afsconf_cell info;
1964 struct chservinfo checkserv;
1968 memset(&info, 0, sizeof(info));
1969 memset(&checkserv, 0, sizeof(struct chservinfo));
1970 blob.in_size=sizeof(struct chservinfo);
1971 blob.in=(caddr_t)&checkserv;
1973 blob.out_size = AFS_PIOCTL_MAXSIZE;
1975 memset(space, 0, sizeof(afs_int32)); /* so we assure zero when nothing is copied back */
1977 /* prepare flags for checkservers command */
1978 temp = 2; /* default to checking local cell only */
1979 if (as->parms[2].items)
1980 temp |= 1; /* set fast flag */
1981 if (as->parms[1].items)
1982 temp &= ~2; /* turn off local cell check */
1984 checkserv.magic = 0x12345678; /* XXX */
1985 checkserv.tflags=temp;
1987 /* now copy in optional cell name, if specified */
1988 if (as->parms[0].items) {
1989 code = GetCellName(as->parms[0].items->data, &info);
1993 if( FAILED(StringCbCopy(checkserv.tbuffer, sizeof(checkserv.tbuffer), info.name))) {
1994 fprintf (stderr, "tbuffer - not enough space");
1997 if( FAILED(StringCbLength(info.name, sizeof(info.name), &len))) {
1998 fprintf (stderr, "StringCbLength failure on info.name");
2001 checkserv.tsize=(int)len+1;
2002 if (info.linkedCell)
2003 free(info.linkedCell);
2005 if( FAILED(StringCbCopy(checkserv.tbuffer, sizeof(checkserv.tbuffer),"\0"))) {
2006 fprintf (stderr, "tbuffer - not enough space");
2012 if(as->parms[3].items) {
2013 checkserv.tinterval=atol(as->parms[3].items->data);
2016 if(checkserv.tinterval<0) {
2017 printf("Warning: The negative -interval is ignored; treated as an inquiry\n");
2018 checkserv.tinterval=-1;
2019 } else if(checkserv.tinterval> 600) {
2020 printf("Warning: The maximum -interval value is 10 mins (600 secs)\n");
2021 checkserv.tinterval=600; /* 10 min max interval */
2024 checkserv.tinterval = -1; /* don't change current interval */
2027 if ( checkserv.tinterval >= 0 ) {
2029 if ( !fs_IsAdmin() ) {
2030 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
2035 fprintf (stderr,"Permission denied: requires root access.\n");
2041 code = pioctl_utf8(0, VIOCCKSERV, &blob, 1);
2043 if ((errno == EACCES) && (checkserv.tinterval > 0)) {
2044 printf("Must be root to change -interval\n");
2051 memcpy(&temp, space, sizeof(afs_int32));
2053 err = memcpy_s(&temp, sizeof(temp), space, sizeof(afs_int32));
2055 fprintf (stderr, "memcpy_s failure on temp");
2060 if (checkserv.tinterval >= 0) {
2061 if (checkserv.tinterval > 0)
2062 printf("The new down server probe interval (%d secs) is now in effect (old interval was %d secs)\n",
2063 checkserv.tinterval, temp);
2065 printf("The current down server probe interval is %d secs\n", temp);
2069 printf("All servers are running.\n");
2071 printf("These servers unavailable due to network or server problems: ");
2072 for(j=0; j < AFS_MAXHOSTS; j++) {
2074 memcpy(&temp, space + j*sizeof(afs_int32), sizeof(afs_int32));
2076 err = memcpy_s(&temp, sizeof(temp), space + j*sizeof(afs_int32), sizeof(afs_int32));
2078 fprintf (stderr, "memcpy_s failure on temp");
2085 tp = hostutil_GetNameByINet(temp);
2095 MessagesCmd(struct cmd_syndesc *as, void *arock)
2098 struct ViceIoctl blob;
2099 struct gaginfo gagflags;
2100 struct cmd_item *show;
2102 memset(&gagflags, 0, sizeof(struct gaginfo));
2103 blob.in_size = sizeof(struct gaginfo);
2104 blob.in = (caddr_t ) &gagflags;
2105 blob.out_size = AFS_PIOCTL_MAXSIZE;
2107 memset(space, 0, sizeof(afs_int32)); /* so we assure zero when nothing is copied back */
2109 if (show = as->parms[0].items) {
2110 if (!strcasecmp (show->data, "user"))
2111 gagflags.showflags |= GAGUSER;
2112 else if (!strcasecmp (show->data, "console"))
2113 gagflags.showflags |= GAGCONSOLE;
2114 else if (!strcasecmp (show->data, "all"))
2115 gagflags.showflags |= GAGCONSOLE | GAGUSER;
2116 else if (!strcasecmp (show->data, "none"))
2120 "unrecognized flag %s: must be in {user,console,all,none}\n",
2129 code = pioctl_utf8(0, VIOC_GAG, &blob, 1);
2138 CheckVolumesCmd(struct cmd_syndesc *as, void *arock)
2141 struct ViceIoctl blob;
2145 code = pioctl_utf8(0, VIOCCKBACK, &blob, 1);
2150 printf("All volumeID/name mappings checked.\n");
2156 SetCacheSizeCmd(struct cmd_syndesc *as, void *arock)
2159 struct ViceIoctl blob;
2163 if ( !fs_IsAdmin() ) {
2164 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
2169 fprintf (stderr,"Permission denied: requires root access.\n");
2174 if (!as->parms[0].items && !as->parms[1].items) {
2175 fprintf(stderr,"%s: syntax error in set cache size cmd.\n", pn);
2178 if (as->parms[0].items) {
2179 code = util_GetHumanInt32(as->parms[0].items->data, &temp);
2181 fprintf(stderr,"%s: bad integer specified for cache size.\n", pn);
2186 blob.in = (char *) &temp;
2187 blob.in_size = sizeof(afs_int32);
2189 code = pioctl_utf8(0, VIOCSETCACHESIZE, &blob, 1);
2191 fs_Die(errno, (char *) 0);
2195 printf("New cache size set.\n");
2200 GetCacheParmsCmd(struct cmd_syndesc *as, void *arock)
2203 struct ViceIoctl blob;
2204 cm_cacheParms_t parms;
2206 memset(&parms, 0, sizeof(parms));
2209 blob.out_size = sizeof(parms);
2210 blob.out = (char *) &parms;
2211 code = pioctl_utf8(0, VIOCGETCACHEPARMS, &blob, 1);
2212 if (code || blob.out_size != sizeof(parms)) {
2213 fs_Die(errno, NULL);
2217 printf("AFS using %I64u of the cache's available %I64u 1K byte blocks.\n",
2218 parms.parms[1], parms.parms[0]);
2219 if (parms.parms[1] > parms.parms[0])
2220 printf("[Cache guideline temporarily deliberately exceeded; it will be adjusted down but you may wish to increase the cache size.]\n");
2225 ListCellsCmd(struct cmd_syndesc *as, void *arock)
2228 afs_int32 i, j, *lp, magic, size;
2230 afs_int32 addr, maxa = AFS_OMAXHOSTS;
2231 struct ViceIoctl blob;
2235 resolve = !(as->parms[0].items); /* -numeric */
2237 for(i=0;i<1000;i++) {
2240 memcpy(tp, &i, sizeof(afs_int32));
2242 err = memcpy_s(tp, sizeof(space), &i, sizeof(afs_int32));
2244 fprintf (stderr, "memcpy_s failure on tp");
2248 tp = (char *)(space + sizeof(afs_int32));
2249 lp = (afs_int32 *)tp;
2251 size = sizeof(afs_int32) + sizeof(afs_int32);
2252 blob.out_size = AFS_PIOCTL_MAXSIZE;
2253 blob.in_size = sizeof(afs_int32);
2256 code = pioctl_utf8(0, VIOCGETCELL, &blob, 1);
2259 break; /* done with the list */
2265 memcpy(&magic, tp, sizeof(afs_int32));
2267 err = memcpy_s(&magic, sizeof(magic), tp, sizeof(afs_int32));
2269 fprintf (stderr, "memcpy_s failure on magic");
2273 if (magic == 0x12345678) {
2274 maxa = AFS_MAXHOSTS;
2275 tp += sizeof(afs_int32);
2277 printf("Cell %s on hosts", tp+maxa*sizeof(afs_int32));
2278 for(j=0; j < maxa && j*sizeof(afs_int32) < AFS_PIOCTL_MAXSIZE; j++) {
2279 char *name, tbuffer[20];
2281 memcpy(&addr, tp + j*sizeof(afs_int32), sizeof(afs_int32));
2283 err = memcpy_s(&addr, sizeof(addr), tp + j*sizeof(afs_int32), sizeof(afs_int32));
2285 fprintf (stderr, "memcpy_s failure on addr");
2293 name = hostutil_GetNameByINet(addr);
2296 if( FAILED(StringCbPrintf(tbuffer, sizeof(tbuffer), "%d.%d.%d.%d", (addr >> 24) & 0xff,
2297 (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff))) {
2298 fprintf (stderr, "tbuffer - cannot be populated");
2303 printf(" %s", name);
2312 ListAliasesCmd(struct cmd_syndesc *as, void *arock)
2315 char *tp, *aliasName, *realName;
2316 struct ViceIoctl blob;
2323 memcpy(tp, &i, sizeof(afs_int32));
2325 err = memcpy_s(tp, sizeof(space), &i, sizeof(afs_int32));
2327 fprintf (stderr, "memcpy_s failure on tp");
2331 blob.out_size = AFS_PIOCTL_MAXSIZE;
2332 blob.in_size = sizeof(afs_int32);
2335 code = pioctl_utf8(0, VIOC_GETALIAS, &blob, 1);
2338 break; /* done with the list */
2342 space[blob.out_size - 1] = '\0';
2345 if( FAILED(StringCbLength(aliasName, sizeof(space), &len))) {
2346 fprintf (stderr, "StringCbLength failure on aliasName");
2351 printf("Alias %s for cell %s\n", aliasName, realName);
2357 CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
2360 struct ViceIoctl blob;
2361 struct cmd_item *ti;
2363 struct hostent *thp;
2367 ti = as->parms[0].items;
2370 thp = hostutil_GetHostByName(ti->data);
2372 fprintf(stderr, "host %s not found in host table.\n", ti->data);
2376 memcpy(&hostAddr, thp->h_addr, sizeof(afs_int32));
2378 err = memcpy_s(&hostAddr, sizeof(hostAddr), thp->h_addr, sizeof(afs_int32));
2380 fprintf (stderr, "memcpy_s failure on hostAddr");
2385 hostAddr = 0; /* means don't set host */
2386 setp = 0; /* aren't setting host */
2389 /* now do operation */
2390 blob.in_size = sizeof(afs_int32);
2391 blob.out_size = sizeof(afs_int32);
2392 blob.in = (char *) &hostAddr;
2393 blob.out = (char *) &hostAddr;
2395 code = pioctl_utf8(0, VIOC_CBADDR, &blob, 1);
2405 NewCellCmd(struct cmd_syndesc *as, void *arock)
2407 afs_uint32 code, linkedstate=0, size=0, count=0, *lp;
2408 afs_uint32 usedns=0, useregistry=0;
2409 struct ViceIoctl blob;
2410 struct cmd_item *ti;
2411 char *tp, *cellname=0, *linked_cellname=0;
2412 afs_uint32 fsport = 0, vlport = 0;
2413 size_t destRemaining;
2415 if ( !fs_IsAdmin() ) {
2416 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
2420 /* if there is no cell specified, use old Windows behavior */
2421 if (as->parms[0].items == NULL) {
2423 blob.in = (char *) 0;
2424 blob.out_size = AFS_PIOCTL_MAXSIZE;
2427 code = pioctl_utf8((char *) 0, VIOCNEWCELL, &blob, 1);
2430 fs_Die(errno, (char *) 0);
2434 printf("Cell servers information refreshed\n");
2437 cellname = as->parms[0].items->data;
2440 if (as->parms[2].items) {
2442 * Link the cell, for the purposes of volume location, to the specified
2445 linked_cellname = as->parms[2].items->data;
2449 if (as->parms[3].items) {
2450 code = util_GetInt32(as->parms[2].items->data, &vlport);
2452 fprintf(stderr,"fs: bad integer specified for the fileserver port.\n");
2456 if (as->parms[4].items) {
2457 code = util_GetInt32(as->parms[3].items->data, &fsport);
2459 fprintf(stderr,"fs: bad integer specified for the vldb server port.\n");
2464 if (as->parms[5].items) {
2468 if (as->parms[6].items) {
2472 /* Count the number of hostnames */
2473 for (ti=as->parms[1].items; ti && count < AFS_MAXHOSTS; ti=ti->next, count++);
2475 if (!usedns && count == 0) {
2476 fprintf( stderr, "fs: at least one vldb server must be specified.");
2480 if (count > AFS_MAXHOSTS) {
2481 fprintf( stderr, "fs: at most %u servers may be specified.", AFS_MAXHOSTS);
2486 * The pioctl data buffer consists of the following structure:
2489 * afs_uint32 alternative fs port
2490 * afs_uint32 alternative vl port
2491 * afs_uint32 count of vldb servers
2494 * n * char[] hostnames
2497 memset(space, 0, sizeof(space));
2499 lp = (afs_uint32 *)tp;
2503 *lp |= VIOC_NEWCELL2_FLAG_USEDNS;
2506 *lp |= VIOC_NEWCELL2_FLAG_USEREG;
2509 *lp |= VIOC_NEWCELL2_FLAG_LINKED;
2518 /* count of server names */
2521 /* Switch back to char pointer */
2524 /* Add nul-terminated cellname */
2525 destRemaining = sizeof(space) - (tp - space);
2526 if( FAILED(StringCbCopyEx( tp,
2528 as->parms[0].items->data,
2531 STRSAFE_FILL_ON_FAILURE))) {
2532 fprintf (stderr, " not enough space for cellname");
2535 /* Move beyond the terminating nul */
2537 destRemaining -= sizeof(char);
2539 /* Add nul-terminated linkname */
2540 if( FAILED(StringCbCopyEx( tp,
2542 linkedstate ? linked_cellname : "",
2545 STRSAFE_FILL_ON_FAILURE))) {
2546 fprintf (stderr, " not enough space for linked cellname");
2549 /* Move beyond the terminating nul */
2551 destRemaining -= sizeof(char);
2553 /* Add the servers */
2554 for (ti=as->parms[1].items; ti; ti=ti->next) {
2555 if( FAILED(StringCbCopyEx( tp,
2560 STRSAFE_FILL_ON_FAILURE))) {
2561 fprintf (stderr, " not enough space for server %s", ti->data);
2564 /* Move beyond the terminating nul */
2566 destRemaining -= sizeof(char);
2569 blob.in_size = (tp - space);
2573 code = pioctl_utf8(NULL, VIOCNEWCELL2, &blob, 1);
2576 fs_Die(errno, as->parms[0].items->data);
2580 printf("Cell servers information for %s added or updated.\n",
2581 as->parms[0].items->data);
2587 NewAliasCmd(struct cmd_syndesc *as, void *arock)
2590 struct ViceIoctl blob;
2592 char *aliasName, *realName;
2593 size_t destRemaining = sizeof(space);
2595 /* Setup and do the NEWALIAS pioctl call */
2596 aliasName = as->parms[0].items->data;
2597 realName = as->parms[1].items->data;
2599 if( FAILED(StringCbCopyEx(tp, destRemaining, aliasName, &tp, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
2600 fprintf (stderr, "tp - not enough space");
2604 destRemaining -= sizeof(char);
2605 if( FAILED(StringCbCopyEx(tp, destRemaining, realName, &tp, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
2606 fprintf (stderr, "tp - not enough space");
2610 destRemaining -= sizeof(char);
2612 blob.in_size = tp - space;
2616 code = pioctl_utf8(0, VIOC_NEWALIAS, &blob, 1);
2618 if (errno == EEXIST) {
2620 "%s: cell name `%s' in use by an existing cell.\n", pn,
2632 WhichCellCmd(struct cmd_syndesc *as, void *arock)
2635 struct cmd_item *ti;
2636 struct ViceIoctl blob;
2639 cm_ioctlQueryOptions_t options;
2641 if (as->parms[1].items)
2644 SetDotDefault(&as->parms[0].items);
2645 for(ti=as->parms[0].items; ti; ti=ti->next) {
2647 afs_uint32 filetype;
2648 char cell[CELL_MAXNAMELEN];
2651 memset(&fid, 0, sizeof(fid));
2652 memset(&options, 0, sizeof(options));
2654 options.size = sizeof(options);
2655 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
2656 options.literal = literal;
2657 blob.in_size = options.size; /* no variable length data */
2660 blob.out_size = sizeof(cm_fid_t);
2661 blob.out = (char *) &fid;
2662 if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) &&
2663 blob.out_size == sizeof(cm_fid_t)) {
2664 options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
2667 fs_Die(errno, ti->data);
2672 blob.out_size = sizeof(filetype);
2673 blob.out = &filetype;
2675 code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
2676 if (code || blob.out_size != sizeof(filetype)) {
2677 fs_Die(errno, ti->data);
2681 blob.out_size = CELL_MAXNAMELEN;
2684 code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
2686 if (errno == ENOENT)
2687 fprintf(stderr,"%s: no such cell as '%s'\n", pn, ti->data);
2689 fs_Die(errno, ti->data);
2693 cell[CELL_MAXNAMELEN - 1] = '\0';
2694 printf("%s %s lives in cell '%s'\n",
2695 fs_filetypestr(filetype),
2702 WSCellCmd(struct cmd_syndesc *as, void *arock)
2705 struct ViceIoctl blob;
2709 blob.out_size = AFS_PIOCTL_MAXSIZE;
2712 code = pioctl_utf8(NULL, VIOC_GET_WS_CELL, &blob, 1);
2715 fs_Die(errno, NULL);
2718 space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
2719 printf("This workstation belongs to cell '%s'\n", space);
2725 PrimaryCellCmd(struct cmd_syndesc *as, void *arock)
2727 fprintf(stderr,"This command is obsolete, as is the concept of a primary token.\n");
2732 #ifndef AFS_NT40_ENV
2734 MonitorCmd(struct cmd_syndesc *as, void *arock)
2737 struct ViceIoctl blob;
2738 struct cmd_item *ti;
2740 struct hostent *thp;
2745 ti = as->parms[0].items;
2749 if (!strcmp(ti->data, "off")) {
2750 hostAddr = 0xffffffff;
2752 thp = hostutil_GetHostByName(ti->data);
2754 if (!strcmp(ti->data, "localhost")) {
2755 fprintf(stderr,"localhost not in host table, assuming 127.0.0.1\n");
2756 hostAddr = htonl(0x7f000001);
2758 fprintf(stderr,"host %s not found in host table.\n", ti->data);
2763 memcpy(&hostAddr, thp->h_addr, sizeof(afs_int32));
2765 err = memcpy_s(&hostAddr, sizeof(hostAddr), thp->h_addr, sizeof(afs_int32));
2767 fprintf (stderr, "memcpy_s failure on hostAddr");
2774 hostAddr = 0; /* means don't set host */
2775 setp = 0; /* aren't setting host */
2778 /* now do operation */
2779 blob.in_size = sizeof(afs_int32);
2780 blob.out_size = sizeof(afs_int32);
2781 blob.in = (char *) &hostAddr;
2782 blob.out = (char *) &hostAddr;
2783 code = pioctl_utf8(0, VIOC_AFS_MARINER_HOST, &blob, 1);
2784 if (code || blob.out_size != sizeof(afs_int32)) {
2789 printf("%s: new monitor host set.\n", pn);
2791 /* now decode old address */
2792 if (hostAddr == 0xffffffff) {
2793 printf("Cache monitoring is currently disabled.\n");
2795 tp = hostutil_GetNameByINet(hostAddr);
2796 printf("Using host %s for monitor services.\n", tp);
2801 #endif /* AFS_NT40_ENV */
2804 SysNameCmd(struct cmd_syndesc *as, void *arock)
2807 struct ViceIoctl blob;
2808 struct cmd_item *ti;
2809 char *input = space;
2812 size_t destRemaining = sizeof(space);
2815 ti = as->parms[0].items;
2818 if ( !fs_IsAdmin() ) {
2819 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
2824 fprintf (stderr,"Permission denied: requires root access.\n");
2832 blob.out_size = AFS_PIOCTL_MAXSIZE;
2833 blob.in_size = sizeof(afs_int32);
2835 memcpy(input, &setp, sizeof(afs_int32));
2837 err = memcpy_s(input, destRemaining, &setp, sizeof(afs_int32));
2839 fprintf (stderr, "memcpy_s failure on input");
2843 input += sizeof(afs_int32);
2844 destRemaining -= sizeof(afs_int32);
2845 for (; ti; ti = ti->next) {
2847 if( FAILED(StringCbCopyEx(input, destRemaining, ti->data, &input, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
2848 fprintf(stderr, "%s: sysname%s too long.\n", pn,
2849 setp > 1 ? "s" : "");
2853 destRemaining -= sizeof(char);
2855 blob.in_size = (input - space) * sizeof(char);
2857 memcpy(space, &setp, sizeof(afs_int32));
2859 err = memcpy_s(space, sizeof(space), &setp, sizeof(afs_int32));
2861 fprintf (stderr, "memcpy_s failure on space");
2866 code = pioctl_utf8(0, VIOC_AFS_SYSNAME, &blob, 1);
2872 printf("%s: new sysname%s set.\n", pn, setp > 1 ? " list" : "");
2878 memcpy(&setp, input, sizeof(afs_int32));
2880 err = memcpy_s(&setp, sizeof(setp), input, sizeof(afs_int32));
2882 fprintf (stderr, "memcpy_s failure on setp");
2886 input += sizeof(afs_int32);
2888 fprintf(stderr,"No sysname name value was found\n");
2891 space[blob.out_size - 1] = '\0';
2892 printf("Current sysname%s is", setp > 1 ? " list" : "");
2893 for (; setp > 0; --setp ) {
2894 printf(" \'%s\'", input);
2895 if( FAILED(StringCbLength(input, sizeof(space) - (input - space), &len))) {
2896 fprintf (stderr, "StringCbLength failure on input");
2905 #ifndef AFS_NT40_ENV
2906 static char *exported_types[] = {"null", "nfs", ""};
2907 static int ExportAfsCmd(struct cmd_syndesc *as, void *arock)
2910 struct ViceIoctl blob;
2911 struct cmd_item *ti;
2912 int export = 0, type = 0, mode = 0, exp = 0, gstat = 0;
2913 int exportcall, pwsync = 0, smounts = 0;
2916 if ( !fs_IsAdmin() ) {
2917 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
2922 fprintf (stderr,"Permission denied: requires root access.\n");
2927 ti = as->parms[0].items;
2928 if (strcmp(ti->data, "nfs") == 0)
2929 type = 0x71; /* NFS */
2932 "Invalid exporter type, '%s', Only the 'nfs' exporter is currently supported\n", ti->data);
2935 ti = as->parms[1].items;
2937 if (strcmp(ti->data, "on") == 0)
2939 else if (strcmp(ti->data, "off") == 0)
2942 fprintf(stderr, "Illegal argument %s\n", ti->data);
2947 if (ti = as->parms[2].items) { /* -noconvert */
2948 if (strcmp(ti->data, "on") == 0)
2950 else if (strcmp(ti->data, "off") == 0)
2953 fprintf(stderr, "Illegal argument %s\n", ti->data);
2957 if (ti = as->parms[3].items) { /* -uidcheck */
2958 if (strcmp(ti->data, "on") == 0)
2960 else if (strcmp(ti->data, "off") == 0)
2963 fprintf(stderr, "Illegal argument %s\n", ti->data);
2967 if (ti = as->parms[4].items) { /* -submounts */
2968 if (strcmp(ti->data, "on") == 0)
2970 else if (strcmp(ti->data, "off") == 0)
2973 fprintf(stderr, "Illegal argument %s\n", ti->data);
2977 exportcall = (type << 24) | (mode << 6) | (pwsync << 4) | (smounts << 2) | export;
2980 blob.in = (char *) &exportcall;
2981 blob.in_size = sizeof(afs_int32);
2982 blob.out = (char *) &exportcall;
2983 blob.out_size = sizeof(afs_int32);
2984 code = pioctl_utf8(0, VIOC_EXPORTAFS, &blob, 1);
2986 if (errno == ENODEV) {
2988 "Sorry, the %s-exporter type is currently not supported on this AFS client\n", exported_types[type]);
2995 if (exportcall & 1) {
2996 printf("'%s' translator is enabled with the following options:\n\tRunning in %s mode\n\tRunning in %s mode\n\t%s\n",
2997 exported_types[type], (exportcall & 2 ? "strict unix" : "convert owner mode bits to world/other"),
2998 (exportcall & 4 ? "strict 'passwd sync'" : "no 'passwd sync'"),
2999 (exportcall & 8 ? "Allow mounts of /afs/.. subdirs" : "Only mounts to /afs allowed"));
3001 printf("'%s' translator is disabled\n", exported_types[type]);
3010 GetCellCmd(struct cmd_syndesc *as, void *arock)
3013 struct ViceIoctl blob;
3014 struct afsconf_cell info;
3015 struct cmd_item *ti;
3023 memset(&info, 0, sizeof(info));
3024 memset(&args, 0, sizeof(args)); /* avoid Purify UMR error */
3025 for(ti=as->parms[0].items; ti; ti=ti->next) {
3027 blob.out_size = sizeof(args);
3028 blob.out = (caddr_t) &args;
3029 code = GetCellName(ti->data, &info);
3034 if (info.linkedCell)
3035 free(info.linkedCell);
3036 if( FAILED(StringCbLength(info.name, sizeof(info.name), &len))) {
3037 fprintf (stderr, "StringCbLength failure on info.name");
3040 blob.in_size = 1+(long)len;
3041 blob.in = info.name;
3042 code = pioctl_utf8(0, VIOC_GETCELLSTATUS, &blob, 1);
3044 if (errno == ENOENT)
3045 fprintf(stderr,"%s: the cell named '%s' does not exist\n", pn, info.name);
3047 fs_Die(errno, info.name);
3051 printf("Cell %s status: ", info.name);
3057 printf("no setuid allowed");
3059 printf("setuid allowed");
3061 printf(", using old VLDB");
3067 static int SetCellCmd(struct cmd_syndesc *as, void *arock)
3070 struct ViceIoctl blob;
3071 struct afsconf_cell info;
3072 struct cmd_item *ti;
3080 memset(&info, 0, sizeof(info));
3082 /* Check arguments. */
3083 if (as->parms[1].items && as->parms[2].items) {
3084 fprintf(stderr, "Cannot specify both -suid and -nosuid.\n");
3088 /* figure stuff to set */
3093 if ( !fs_IsAdmin() ) {
3094 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
3099 fprintf (stderr,"Permission denied: requires root access.\n");
3104 if (! as->parms[1].items)
3105 args.stat |= CM_SETCELLFLAG_SUID; /* default to -nosuid */
3107 /* set stat for all listed cells */
3108 for(ti=as->parms[0].items; ti; ti=ti->next) {
3110 code = GetCellName(ti->data, &info);
3115 if (info.linkedCell)
3116 free(info.linkedCell);
3117 if( FAILED(StringCbCopy(args.cname, sizeof(args.cname), info.name))) {
3118 fprintf (stderr, "cname - not enough space");
3121 blob.in_size = sizeof(args);
3122 blob.in = (caddr_t) &args;
3124 blob.out = (caddr_t) 0;
3125 code = pioctl_utf8(0, VIOC_SETCELLSTATUS, &blob, 1);
3127 fs_Die(errno, info.name); /* XXX added cell name to fs_Die() call */
3135 GetCellName(char *cellNamep, struct afsconf_cell *infop)
3137 if( FAILED(StringCbCopy(infop->name, sizeof(infop->name), cellNamep))) {
3138 fprintf (stderr, "name - not enough space");
3145 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
3151 cm_GetConfigDir(confDir, sizeof(confDir));
3153 secFlags = AFSCONF_SECOPTS_FALLBACK_NULL;
3156 secFlags |= AFSCONF_SECOPTS_NOAUTH;
3158 code = ugen_ClientInitFlags(confDir, info->name, secFlags,
3159 &uclient, NULL, VLDB_MAXSERVERS,
3160 AFSCONF_VLDBSERVICE, 50);
3166 static struct ViceIoctl gblob;
3167 static int debug = 0;
3169 * here follow some routines in support of the setserverprefs and
3170 * getserverprefs commands. They are:
3171 * SetPrefCmd "top-level" routine
3172 * addServer adds a server to the list of servers to be poked into the
3173 * kernel. Will poke the list into the kernel if it threatens
3175 * pokeServers pokes the existing list of servers and ranks into the kernel
3176 * GetPrefCmd reads the Cache Manager's current list of server ranks
3185 code = pioctl_utf8(0, VIOC_SETSPREFS, &gblob, 1);
3187 ssp = (cm_SSetPref_t *)space;
3188 gblob.in_size = (long)(((char *)&(ssp->servers[0])) - (char *)ssp);
3194 * returns -1 if error message printed,
3196 * errno value if error and no error message printed
3203 code = pioctl_utf8(0, VIOC_SETSPREFS, &gblob, 1);
3204 if (code && (errno == EINVAL)) {
3205 struct setspref *ssp;
3206 ssp = (struct setspref *)gblob.in;
3207 if (!(ssp->flags & DBservers)) {
3208 gblob.in = (void *)&(ssp->servers[0]);
3209 gblob.in_size -= ((char *)&(ssp->servers[0])) - (char *)ssp;
3210 code = pioctl_utf8(0, VIOC_SETSPREFS33, &gblob, 1);
3211 return code ? errno : 0;
3214 "This cache manager does not support VL server preferences.\n");
3218 return code ? errno : 0;
3224 addServer(char *name, unsigned short rank)
3229 struct hostent *thostent;
3234 #define MAXUSHORT ((unsigned short) 2*MAXSHORT+1) /* assumes two's complement binary system */
3236 #define MAXUSHORT ((unsigned short) ~0)
3241 thostent = hostutil_GetHostByName(name);
3243 fprintf (stderr, "%s: couldn't resolve name.\n", name);
3247 ssp = (cm_SSetPref_t *)(gblob.in);
3249 if (gblob.in_size > MAXINSIZE - sizeof(cm_SPref_t)) {
3250 code = pokeServers();
3251 ssp->num_servers = 0;
3254 sp = (cm_SPref_t *)((char*)gblob.in + gblob.in_size);
3256 memcpy (&(sp->host.s_addr), thostent->h_addr, sizeof(afs_uint32));
3258 err = memcpy_s (&(sp->host.s_addr), sizeof(afs_uint32), thostent->h_addr, sizeof(afs_uint32));
3260 fprintf (stderr, "memcpy_s failure on sp->host.s_addr");
3265 sp->rank = (rank > MAXUSHORT ? MAXUSHORT : rank);
3266 gblob.in_size += sizeof(cm_SPref_t);
3269 if (debug) fprintf(stderr, "adding server %s, rank %d, ip addr 0x%lx\n",name,sp->rank,sp->host.s_addr);
3275 * returns -1 if error message printed,
3277 * errno value if error and no error message printed
3280 addServer(char *name, afs_int32 rank)
3283 struct setspref *ssp;
3285 struct hostent *thostent;
3292 #define MAXUSHORT ((unsigned short) 2*MAXSHORT+1) /* assumes two's complement binary system */
3294 #define MAXUSHORT ((unsigned short) ~0)
3298 thostent = hostutil_GetHostByName(name);
3300 fprintf(stderr, "%s: couldn't resolve name.\n", name);
3304 ssp = (struct setspref *)(gblob.in);
3306 for (t = 0; thostent->h_addr_list[t]; t++) {
3307 if (gblob.in_size > MAXINSIZE - sizeof(struct spref)) {
3308 code = pokeServers();
3311 ssp->num_servers = 0;
3314 sp = (struct spref *)(gblob.in + gblob.in_size);
3316 memcpy(&(sp->server.s_addr), thostent->h_addr_list[t],
3317 sizeof(afs_uint32));
3319 err = memcpy_s(&(sp->server.s_addr), sizeof(afs_uint32), thostent->h_addr_list[t],
3320 sizeof(afs_uint32));
3322 fprintf (stderr, "memcpy_s failure on sp->server.s_addr");
3327 sp->rank = (rank > MAXUSHORT ? MAXUSHORT : rank);
3328 gblob.in_size += sizeof(struct spref);
3332 fprintf(stderr, "adding server %s, rank %d, ip addr 0x%lx\n",
3333 name, sp->rank, sp->server.s_addr);
3341 static BOOL IsWindowsNT (void)
3343 static BOOL fChecked = FALSE;
3344 static BOOL fIsWinNT = FALSE;
3348 OSVERSIONINFO Version;
3352 memset (&Version, 0x00, sizeof(Version));
3353 Version.dwOSVersionInfoSize = sizeof(Version);
3355 if (GetVersionEx (&Version))
3357 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
3367 SetPrefCmd(struct cmd_syndesc *as, void * arock)
3371 struct cmd_item *ti;
3376 ssp = (cm_SSetPref_t *)space;
3378 ssp->num_servers = 0;
3379 gblob.in_size = (long)(((char*)&(ssp->servers[0])) - (char *)ssp);
3382 gblob.out_size = AFS_PIOCTL_MAXSIZE;
3384 if ( !fs_IsAdmin() ) {
3385 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
3391 ti = as->parms[2].items; /* -file */
3393 if (debug) fprintf(stderr,"opening file %s\n",ti->data);
3394 if (!(infd = fopen(ti->data,"r" ))) {
3396 fs_Die(errno,ti->data);
3399 while ( fscanf(infd, "%79s%ld", name, &rank) != EOF) {
3400 code = addServer (name, (unsigned short) rank);
3403 while ( fscanf_s(infd, "%79s%ld", name, sizeof(name), &rank) != EOF) {
3404 code = addServer (name, (unsigned short) rank);
3411 ti = as->parms[3].items; /* -stdin */
3414 while ( scanf("%79s%ld", name, &rank) != EOF) {
3415 code = addServer (name, (unsigned short) rank);
3418 while ( scanf_s("%79s%ld", name, sizeof(name), &rank) != EOF) {
3419 code = addServer (name, (unsigned short) rank);
3424 for (ti = as->parms[0].items;ti;ti=ti->next) {/*list of servers, ranks */
3429 code = addServer (ti->data, (unsigned short) atol(ti->next->data));
3431 printf("set fs prefs %s %s\n", ti->data, ti->next->data);
3435 code = pokeServers();
3437 printf("now working on vlservers, code=%d, errno=%d\n",code,errno);
3439 ssp = (cm_SSetPref_t *)space;
3440 gblob.in_size = (long)(((char*)&(ssp->servers[0])) - (char *)ssp);
3442 ssp->flags = CM_SPREF_VLONLY;
3443 ssp->num_servers = 0;
3445 for (ti = as->parms[1].items;ti;ti=ti->next) { /* list of dbservers, ranks */
3450 code = addServer (ti->data, (unsigned short) atol(ti->next->data));
3452 printf("set vl prefs %s %s\n", ti->data, ti->next->data);
3457 if (as->parms[1].items) {
3459 printf("now poking vlservers\n");
3460 code = pokeServers();
3470 SetPrefCmd(struct cmd_syndesc *as, void *arock)
3474 struct cmd_item *ti;
3477 struct setspref *ssp;
3478 int error = 0; /* -1 means error message printed,
3479 * >0 means errno value for unprinted message */
3481 ssp = (struct setspref *)space;
3483 ssp->num_servers = 0;
3484 gblob.in_size = ((char *)&(ssp->servers[0])) - (char *)ssp;
3487 gblob.out_size = AFS_PIOCTL_MAXSIZE;
3491 fprintf(stderr, "Permission denied: requires root access.\n");
3495 ti = as->parms[2].items; /* -file */
3498 fprintf(stderr, "opening file %s\n", ti->data);
3499 if (!(infd = fopen(ti->data, "r"))) {
3504 while (fscanf(infd, "%79s%ld", name, &rank) != EOF) {
3505 code = addServer(name, (unsigned short)rank);
3510 while (fscanf_s(infd, "%79s%ld", name, sizeof(name), &rank) != EOF) {
3511 code = addServer(name, (unsigned short)rank);
3520 ti = as->parms[3].items; /* -stdin */
3523 while (scanf("%79s%ld", name, &rank) != EOF) {
3524 code = addServer(name, (unsigned short)rank);
3529 while (scanf_s("%79s%ld", name, sizeof(name), &rank) != EOF) {
3530 code = addServer(name, (unsigned short)rank);
3537 for (ti = as->parms[0].items; ti; ti = ti->next) { /* list of servers, ranks */
3542 code = addServer(ti->data, (unsigned short)atol(ti->next->data));
3546 printf("set fs prefs %s %s\n", ti->data, ti->next->data);
3550 code = pokeServers();
3554 printf("now working on vlservers, code=%d\n", code);
3556 ssp = (struct setspref *)space;
3557 ssp->flags = DBservers;
3558 ssp->num_servers = 0;
3559 gblob.in_size = ((char *)&(ssp->servers[0])) - (char *)ssp;
3562 for (ti = as->parms[1].items; ti; ti = ti->next) { /* list of dbservers, ranks */
3567 code = addServer(ti->data, (unsigned short)atol(ti->next->data));
3571 printf("set vl prefs %s %s\n", ti->data, ti->next->data);
3576 if (as->parms[1].items) {
3578 printf("now poking vlservers\n");
3579 code = pokeServers();
3587 return error ? 1 : 0;
3593 GetPrefCmd(struct cmd_syndesc *as, void *arock)
3596 struct cmd_item *ti;
3597 char *name, tbuffer[20];
3602 struct ViceIoctl blob;
3603 struct cm_SPrefRequest *in;
3604 struct cm_SPrefInfo *out;
3608 ti = as->parms[0].items; /* -file */
3610 if (debug) fprintf(stderr,"opening file %s\n",ti->data);
3611 if (!(outfd = freopen(ti->data,"w",stdout))) {
3612 fs_Die(errno,ti->data);
3617 ti = as->parms[1].items; /* -numeric */
3619 ti = as->parms[2].items; /* -vlservers */
3620 vlservers = (ti ? CM_SPREF_VLONLY : 0);
3621 /* ti = as->parms[3].items; -cell */
3623 in = (struct cm_SPrefRequest *)space;
3627 blob.in_size=sizeof(struct cm_SPrefRequest);
3628 blob.in = (char *)in;
3630 blob.out_size = AFS_PIOCTL_MAXSIZE;
3632 in->num_servers = (AFS_PIOCTL_MAXSIZE - 2*sizeof(short))/sizeof(struct cm_SPref);
3633 in->flags = vlservers;
3635 code = pioctl_utf8(0, VIOC_GETSPREFS, &blob, 1);
3637 perror("getserverprefs pioctl");
3641 out = (struct cm_SPrefInfo *) blob.out;
3643 for (i=0;i<out->num_servers;i++) {
3645 name = hostutil_GetNameByINet(out->servers[i].host.s_addr);
3648 addr = ntohl(out->servers[i].host.s_addr);
3649 if( FAILED(StringCbPrintf(tbuffer, sizeof(tbuffer), "%d.%d.%d.%d", (addr>>24) & 0xff, (addr>>16) & 0xff,
3650 (addr>>8) & 0xff, addr & 0xff))) {
3651 fprintf (stderr, "tbuffer - cannot be populated");
3656 printf ("%-50s %5u\n",name,out->servers[i].rank);
3659 in->offset = out->next_offset;
3661 } while (!code && out->next_offset > 0);
3667 GetPrefCmd(struct cmd_syndesc *as, void *arock)
3670 struct cmd_item *ti;
3671 char *name, tbuffer[20];
3672 afs_int32 rank, addr;
3676 struct ViceIoctl blob;
3677 struct sprefrequest *in;
3678 struct sprefinfo *out;
3681 ti = as->parms[0].items; /* -file */
3684 fprintf(stderr, "opening file %s\n", ti->data);
3685 if (!(outfd = freopen(ti->data, "w", stdout))) {
3691 ti = as->parms[1].items; /* -numeric */
3693 ti = as->parms[2].items; /* -vlservers */
3694 vlservers |= (ti ? DBservers : 0);
3695 /* ti = as->parms[3].items; -cell */
3697 in = (struct sprefrequest *)space;
3701 blob.in_size = sizeof(struct sprefrequest);
3702 blob.in = (char *)in;
3704 blob.out_size = AFS_PIOCTL_MAXSIZE;
3707 (AFS_PIOCTL_MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
3708 in->flags = vlservers;
3710 code = pioctl_utf8(0, VIOC_GETSPREFS, &blob, 1);
3712 perror("getserverprefs pioctl");
3716 out = (struct sprefinfo *)blob.out;
3718 for (i = 0; i < out->num_servers; i++) {
3720 name = hostutil_GetNameByINet(out->servers[i].server.s_addr);
3722 addr = ntohl(out->servers[i].server.s_addr);
3723 if( FAILED(StringCbPrintf(tbuffer, sizeof(tbuffer), "%d.%d.%d.%d", (addr >> 24) & 0xff,
3724 (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff))) {
3725 fprintf (stderr, "tbuffer - cannot be populated");
3730 printf("%-50s %5u\n", name, out->servers[i].rank);
3733 in->offset = out->next_offset;
3734 } while (out->next_offset > 0);
3741 SmbUnicodeCmd(struct cmd_syndesc * asp, void * arock)
3747 struct ViceIoctl blob;
3749 if (asp->parms[0].items) {
3753 } else if (asp->parms[1].items) {
3759 if (inValue != 0 && !fs_IsAdmin()) {
3760 fprintf (stderr, "Permission denied: Requires AFS Client Administrator access.\n");
3764 blob.in_size = sizeof(inValue);
3765 blob.in = (char *) &inValue;
3766 blob.out_size = sizeof(outValue);
3767 blob.out = (char *) &outValue;
3769 code = pioctl_utf8(NULL, VIOC_UNICODECTL, &blob, 1);
3771 fs_Die(errno, NULL);
3775 if (outValue != 2) {
3776 printf("Unicode support is %s%s.\n",
3777 ((outValue != 0)? "enabled":"disabled"),
3778 ((inValue != 0)? " for new SMB connections":""));
3780 printf("Unicode support is absent in this installation of OpenAFS.\n");
3787 GetFidCmd(struct cmd_syndesc *as, void *arock)
3790 struct ViceIoctl blob;
3791 struct cmd_item *ti;
3794 cm_ioctlQueryOptions_t options;
3796 if (as->parms[1].items)
3799 SetDotDefault(&as->parms[0].items);
3800 for(ti=as->parms[0].items; ti; ti=ti->next) {
3802 afs_uint32 filetype;
3803 char cell[CELL_MAXNAMELEN];
3806 memset(&fid, 0, sizeof(fid));
3807 memset(&options, 0, sizeof(options));
3809 options.size = sizeof(options);
3810 options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
3811 options.literal = literal;
3812 blob.in_size = options.size; /* no variable length data */
3815 blob.out_size = sizeof(cm_fid_t);
3816 blob.out = (char *) &fid;
3817 if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) &&
3818 blob.out_size == sizeof(cm_fid_t)) {
3819 options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
3822 fs_Die(errno, ti->data);
3827 blob.out_size = sizeof(filetype);
3828 blob.out = &filetype;
3830 code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
3831 if (code || blob.out_size != sizeof(filetype)) {
3832 fs_Die(errno, ti->data);
3836 blob.out_size = CELL_MAXNAMELEN;
3839 code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
3841 cell[CELL_MAXNAMELEN - 1] = '\0';
3842 printf("%s %s (%u.%u.%u) contained in cell %s\n",
3843 fs_filetypestr(filetype),
3844 ti->data, fid.volume, fid.vnode, fid.unique,
3845 code ? "unknown-cell" : cell);
3851 UuidCmd(struct cmd_syndesc *asp, void *arock)
3856 struct ViceIoctl blob;
3857 char * uuidstring = NULL;
3859 if (asp->parms[0].items) {
3861 if ( !fs_IsAdmin() ) {
3862 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
3867 fprintf (stderr, "Permission denied: requires root access.\n");
3871 inValue = 1; /* generate new UUID */
3873 inValue = 0; /* just show the current UUID */
3876 blob.in_size = sizeof(inValue);
3877 blob.in = (char *) &inValue;
3878 blob.out_size = sizeof(outValue);
3879 blob.out = (char *) &outValue;
3881 code = pioctl_utf8(NULL, VIOC_UUIDCTL, &blob, 1);
3882 if (code || blob.out_size != sizeof(outValue)) {
3883 fs_Die(errno, NULL);
3887 UuidToString((UUID *) &outValue, &uuidstring);
3889 printf("%sUUID: %s",
3890 ((inValue == 1)?"New ":""),
3894 RpcStringFree(&uuidstring);
3900 TraceCmd(struct cmd_syndesc *asp, void *arock)
3903 struct ViceIoctl blob;
3908 if ( !fs_IsAdmin() ) {
3909 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
3914 fprintf (stderr,"Permission denied: requires root access.\n");
3919 if ((asp->parms[0].items && asp->parms[1].items)) {
3920 fprintf(stderr, "fs trace: must use at most one of '-off' or '-on'\n");
3924 /* determine if we're turning this tracing on or off */
3926 if (asp->parms[0].items)
3927 inValue = 3; /* enable */
3928 else if (asp->parms[1].items)
3929 inValue = 2; /* disable */
3930 if (asp->parms[2].items)
3931 inValue |= 4; /* do reset */
3932 if (asp->parms[3].items)
3933 inValue |= 8; /* dump */
3935 blob.in_size = sizeof(long);
3936 blob.in = (char *) &inValue;
3937 blob.out_size = sizeof(long);
3938 blob.out = (char *) &outValue;
3940 code = pioctl_utf8(NULL, VIOC_TRACECTL, &blob, 1);
3941 if (code || blob.out_size != sizeof(long)) {
3942 fs_Die(errno, NULL);
3947 printf("AFS tracing enabled.\n");
3949 printf("AFS tracing disabled.\n");
3954 static void sbusage(void)
3956 fprintf(stderr, "example usage: %s storebehind -files *.o -kb 99999 -default 0\n", pn);
3957 fprintf(stderr, " %s sb 50000 *.[ao] -default 10\n", pn);
3960 /* fs sb -kbytes 9999 -files *.o -default 64 */
3962 StoreBehindCmd(struct cmd_syndesc *as, void *arock)
3965 struct ViceIoctl blob;
3966 struct cmd_item *ti;
3967 struct sbstruct tsb, tsb2;
3974 if ( !fs_IsAdmin() ) {
3975 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
3980 tsb.sb_thisfile = -1;
3981 ti = as->parms[0].items; /* -kbytes */
3983 if (!as->parms[1].items) {
3984 fprintf(stderr, "%s: you must specify -files with -kbytes.\n",
3988 tsb.sb_thisfile = strtol(ti->data, &t, 10) * 1024;
3989 if (errno == ERANGE) {
3990 fprintf(stderr, "%s: ti->data must within long int range", pn);
3993 if ((tsb.sb_thisfile < 0) || (*t != '\0')) {
3994 fprintf(stderr, "%s: %s must be 0 or a positive number.\n", pn,
4000 allfiles = tsb.sb_default = -1; /* Don't set allfiles yet */
4001 ti = as->parms[2].items; /* -allfiles */
4003 allfiles = strtol(ti->data, &t, 10) * 1024;
4004 if (errno == ERANGE) {
4005 fprintf(stderr, "%s: ti->data must within long int range", pn);
4008 if ((allfiles < 0) || (*t != '\0')) {
4009 fprintf(stderr, "%s: %s must be 0 or a positive number.\n", pn,
4015 /* -verbose or -file only or no options */
4016 if (as->parms[3].items || (as->parms[1].items && !as->parms[0].items)
4017 || (!as->parms[0].items && !as->parms[1].items
4018 && !as->parms[2].items))
4021 blob.in = (char *)&tsb;
4022 blob.out = (char *)&tsb2;
4023 blob.in_size = blob.out_size = sizeof(struct sbstruct);
4024 memset(&tsb2, 0, sizeof(tsb2));
4026 /* once per -file */
4027 for (ti = as->parms[1].items; ti; ti = ti->next) {
4028 /* Do this solely to see if the file is there */
4029 code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1);
4031 fs_Die(errno, ti->data);
4036 code = pioctl_utf8(ti->data, VIOC_STOREBEHIND, &blob, 1);
4038 fs_Die(errno, ti->data);
4043 if (verbose && (blob.out_size == sizeof(tsb2))) {
4044 if (tsb2.sb_thisfile == -1) {
4045 fprintf(stdout, "Will store %s according to default.\n",
4049 "Will store up to %d kbytes of %s asynchronously.\n",
4050 (tsb2.sb_thisfile / 1024), ti->data);
4055 /* If no files - make at least one pioctl call, or
4056 * set the allfiles default if we need to.
4058 if (!as->parms[1].items || (allfiles != -1)) {
4059 tsb.sb_default = allfiles;
4060 code = pioctl_utf8(0, VIOC_STOREBEHIND, &blob, 1);
4062 fs_Die(errno, ((allfiles == -1) ? 0 : "-allfiles"));
4067 /* Having no arguments also reports the default store asynchrony */
4068 if (verbose && (blob.out_size == sizeof(tsb2))) {
4069 fprintf(stdout, "Default store asynchrony is %d kbytes.\n",
4070 (tsb2.sb_default / 1024));
4077 SetCryptCmd(struct cmd_syndesc *as, void *arock)
4079 afs_int32 code = 0, flag;
4080 struct ViceIoctl blob;
4084 if ( !fs_IsAdmin() ) {
4085 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
4090 tp = as->parms[0].items->data;
4091 if (strcmp(tp, "on") == 0)
4093 else if (strcmp(tp, "off") == 0)
4095 else if (strcmp(tp, "auth") == 0)
4098 fprintf (stderr, "%s: %s must be \"on\", \"auth\", or \"off\".\n", pn, tp);
4102 blob.in = (char *) &flag;
4103 blob.in_size = sizeof(flag);
4105 code = pioctl_utf8(0, VIOC_SETRXKCRYPT, &blob, 1);
4112 GetCryptCmd(struct cmd_syndesc *as, void *arock)
4114 afs_int32 code = 0, flag;
4115 struct ViceIoctl blob;
4121 blob.out_size = sizeof(flag);
4124 code = pioctl_utf8(0, VIOC_GETRXKCRYPT, &blob, 1);
4126 if (code || blob.out_size != sizeof(flag))
4131 memcpy(&flag, tp, sizeof(afs_int32));
4133 err = memcpy_s(&flag, sizeof(flag), tp, sizeof(afs_int32));
4135 fprintf (stderr, "memcpy_s failure on flag");
4140 printf("Security level is currently ");
4142 printf("auth (data integrity).\n");
4144 printf("crypt (data security).\n");
4152 MemDumpCmd(struct cmd_syndesc *asp, void *arock)
4155 struct ViceIoctl blob;
4159 if ( !fs_IsAdmin() ) {
4160 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
4164 if ((asp->parms[0].items && asp->parms[1].items)) {
4165 fprintf(stderr, "%s trace: must use at most one of '-begin' or '-end'\n", pn);
4169 /* determine if we're turning this tracing on or off */
4170 if (asp->parms[0].items)
4171 inValue = 1; /* begin */
4172 else if (asp->parms[1].items)
4173 inValue = 0; /* end */
4176 blob.in_size = sizeof(long);
4177 blob.in = (char *) &inValue;
4178 blob.out_size = sizeof(long);
4179 blob.out = (char *) &outValue;
4181 code = pioctl_utf8(NULL, VIOC_TRACEMEMDUMP, &blob, 1);
4182 if (code || blob.out_size != sizeof(long)) {
4183 fs_Die(errno, NULL);
4188 printf("AFS memdump created.\n");
4191 printf("AFS memdump failed.\n");
4197 MiniDumpCmd(struct cmd_syndesc *asp, void *arock)
4200 SERVICE_STATUS status;
4201 SC_HANDLE hManager = NULL;
4202 SC_HANDLE hService = NULL;
4204 if ( !fs_IsAdmin() ) {
4205 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
4209 hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
4213 hService = OpenService(hManager, "TransarcAFSDaemon", SERVICE_USER_DEFINED_CONTROL);
4217 success = ControlService(hService, SERVICE_CONTROL_CUSTOM_DUMP, &status);
4220 CloseServiceHandle(hService);
4221 CloseServiceHandle(hManager);
4223 printf("AFS minidump generated.\n");
4229 CloseServiceHandle(hService);
4231 CloseServiceHandle(hManager);
4233 printf("AFS minidump failed.\n");
4238 CSCPolicyCmd(struct cmd_syndesc *asp, void *arock)
4240 struct cmd_item *ti;
4245 if ( !fs_IsAdmin() ) {
4246 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
4250 for(ti=asp->parms[0].items; ti;ti=ti->next) {
4262 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
4263 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
4266 REG_OPTION_NON_VOLATILE,
4267 (IsWow64()?KEY_WOW64_64KEY:0)|KEY_WRITE,
4272 if ( hkCSCPolicy == NULL ) {
4273 fprintf (stderr,"Permission denied: requires Administrator access.\n");
4277 if ( !fs_IsAdmin() ) {
4278 fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
4279 RegCloseKey(hkCSCPolicy);
4286 if (asp->parms[1].items) {
4290 if (asp->parms[2].items) {
4291 policy = "programs";
4294 if (asp->parms[3].items) {
4295 policy = "documents";
4298 if (asp->parms[4].items) {
4302 RegSetValueEx( hkCSCPolicy, share, 0, REG_SZ, policy, (DWORD)len+1);
4304 printf("CSC policy on share \"%s\" changed to \"%s\".\n\n", share, policy);
4305 printf("Close all applications that accessed files on this share or restart AFS Client for the change to take effect.\n");
4309 DWORD dwIndex, dwPolicies;
4310 char policyName[256];
4311 DWORD policyNameLen;
4316 /* list current csc policies */
4318 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
4319 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
4322 REG_OPTION_NON_VOLATILE,
4323 (IsWow64()?KEY_WOW64_64KEY:0)|KEY_READ|KEY_QUERY_VALUE,
4328 RegQueryInfoKey( hkCSCPolicy,
4330 NULL, /* lpcClass */
4331 NULL, /* lpReserved */
4332 NULL, /* lpcSubKeys */
4333 NULL, /* lpcMaxSubKeyLen */
4334 NULL, /* lpcMaxClassLen */
4335 &dwPolicies, /* lpcValues */
4336 NULL, /* lpcMaxValueNameLen */
4337 NULL, /* lpcMaxValueLen */
4338 NULL, /* lpcbSecurityDescriptor */
4339 NULL /* lpftLastWriteTime */
4342 printf("Current CSC policies:\n");
4343 for ( dwIndex = 0; dwIndex < dwPolicies; dwIndex ++ ) {
4345 policyNameLen = sizeof(policyName);
4346 policyLen = sizeof(policy);
4347 RegEnumValue( hkCSCPolicy, dwIndex, policyName, &policyNameLen, NULL,