1 /* Copyright (C) 1990 Transarc Corporation - All rights reserved */
3 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
4 * Copyright TRANSARC CORPORATION 1989
5 * LICENSED MATERIALS - PROPERTY OF IBM
8 * Implementation of the volume operations used by the AFS user
13 * --------------------- Required definitions ---------------------
15 #include "uss_vol.h" /*Interface to this module*/
16 #include "uss_common.h" /*Common definitions*/
17 #include "uss_procs.h" /*Defs from procs module*/
18 #include "uss_fs.h" /*CacheManager ops*/
22 #include <sys/errno.h>
23 #include <afs/vlserver.h>
25 #include <afs/cellconfig.h>
27 #include <rx/rx_globals.h>
28 #include <afs/volser.h>
29 #include <afs/volint.h>
34 extern struct rx_connection *UV_Bind();
35 extern struct rx_securityClass *rxnull_NewClientSecurityObject();
37 extern int VL_GetEntryByID();
38 extern char *hostutil_GetNameByINet();
42 * ---------------------- Private definitions ---------------------
45 #undef USS_VOL_DB_SHOW_OVERRIDES
49 * --------------------- Exported definitions ---------------------
52 * The Volume Server interface imports the Ubik connection
53 * structure to use, expecting it to be named "cstruct". This
54 * is why we have two names here. Thus, the UV_CreateVolume()
55 * will work and we can avoid nasty little core dumps.
57 struct ubik_client *uconn_vldbP; /*Ubik connection struct*/
58 struct ubik_client *cstruct; /*Required name for above*/
61 * ------------------------ Private globals -----------------------
63 static int initDone = 0; /*Module initialized?*/
64 static int NoAuthFlag = 0; /*Use -noauth?*/
65 static struct rx_connection
66 *serverconns[VLDB_MAXSERVERS]; /*Connection(s) to VLDB
70 /*-----------------------------------------------------------------------
71 * static InitThisModule
74 * Set up this module, namely set up all the client state for
75 * dealing with the Volume Location Server(s), including
76 * network connections.
79 * a_noAuthFlag : Do we need authentication?
80 * a_confDir : Configuration directory to use.
81 * a_cellName : Cell we want to talk to.
84 * 0 if everything went fine, or
85 * lower-level error code otherwise.
88 * This routine will only be called once.
92 *------------------------------------------------------------------------*/
94 static afs_int32 InitThisModule(a_noAuthFlag, a_confDir, a_cellName)
101 static char rn[] = "uss_vol:InitThisModule";
102 register afs_int32 code; /*Return code*/
103 struct afsconf_dir *tdir; /*Ptr to conf dir info*/
104 struct afsconf_cell info; /*Info about chosen cell*/
105 struct ktc_principal sname; /*Service name*/
106 struct ktc_token ttoken; /*Service ticket*/
107 afs_int32 scIndex; /*Chosen security index*/
108 struct rx_securityClass *sc; /*Generated security object*/
109 afs_int32 i; /*Loop index*/
112 * Only once, guys, will 'ya?
116 printf("[%s] Called multiple times!\n", rn);
117 #endif /* USS_VOL_DB */
122 * Set up our Rx environment.
125 printf("[%s] Initializing Rx environment\n", rn);
126 #endif /* USS_VOL_DB */
129 fprintf(stderr,"%s: Couldn't initialize Rx.\n", uss_whoami);
132 rx_SetRxDeadTime(50);
135 * Find out all about our configuration.
138 printf("[%s] Handling configuration info\n", rn);
139 #endif /* USS_VOL_DB */
140 tdir = afsconf_Open(a_confDir);
142 fprintf(stderr, "%s: Couldn't open configuration directory (%s).\n",
143 uss_whoami, a_confDir);
146 code = afsconf_GetCellInfo(tdir, a_cellName, AFSCONF_VLDBSERVICE, &info);
148 printf("%s: Can't find VLDB server(s) for cell %s\n",
149 uss_whoami, a_cellName);
154 printf("[%s] Getting tickets if needed\n", rn);
155 #endif /* USS_VOL_DB */
158 * We don't need tickets for unauthenticated connections.
160 strcpy(sname.cell, info.name);
161 sname.instance[0] = 0;
162 strcpy(sname.name, "afs");
163 code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), (char *)0);
166 "%s: Couldn't get AFS tokens, running unauthenticated.\n",
172 * We got a ticket, go for an authenticated connection.
174 if (ttoken.kvno >= 0 && ttoken.kvno <= 255)
175 scIndex = 2; /*Kerberos*/
177 fprintf(stderr, "%s: Funny kvno (%d) in ticket, proceeding\n",
178 uss_whoami, ttoken.kvno);
182 } /*Authentication desired*/
187 * Generate the appropriate security object for the connection.
190 printf("[%s] Generating Rx security object\n", rn);
191 #endif /* USS_VOL_DB */
194 sc = (struct rx_securityClass *)
195 rxnull_NewClientSecurityObject();
202 sc = (struct rx_securityClass *)
203 rxkad_NewClientSecurityObject(rxkad_clear,
212 * Tell UV module about default authentication.
215 printf("[%s] Setting UV security: obj 0x%x, index %d\n",
217 #endif /* USS_VOL_DB */
218 UV_SetSecurity(sc, scIndex);
219 if (info.numServers > VLDB_MAXSERVERS) {
220 fprintf(stderr, "%s: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
221 uss_whoami, info.numServers, VLDB_MAXSERVERS);
226 * Connect to each VLDB server for the chosen cell.
228 for (i = 0; i < info.numServers; i++) {
230 printf("[%s] Connecting to VLDB server 0x%x, port %d, service id %d\n",
231 rn, info.hostAddr[i].sin_addr.s_addr,
232 info.hostAddr[i].sin_port,
234 #endif /* USS_VOL_DB */
235 serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
236 info.hostAddr[i].sin_port,
243 * Set up to execute Ubik transactions on the VLDB.
246 printf("[%s] Initializing Ubik interface\n", rn);
247 #endif /* USS_VOL_DB */
248 code = ubik_ClientInit(serverconns, &uconn_vldbP);
250 fprintf(stderr, "%s: Ubik client init failed.\n", uss_whoami);
254 printf("[%s] VLDB ubik connection structure at 0x%x\n",
256 #endif /* USS_VOL_DB */
259 * Place the ubik VLDB connection structure in its advertised
262 cstruct = uconn_vldbP;
273 /*-----------------------------------------------------------------------
274 * static HostIDToHostName
277 * Given a host ID (in network byte order), figure out the
278 * corresponding host name.
281 * a_hostID : Host ID in network byte order.
282 * a_hostName : Ptr to host name buffer.
288 * This routine simply calls the hostutil_GetNameByINet()
289 * function exported by the utility library (util.a).
293 *------------------------------------------------------------------------*/
295 char *hostutil_GetNameByINet();
297 static void HostIDToHostName(a_hostID, a_hostName)
301 { /*HostIDToHostName*/
303 strcpy(a_hostName, hostutil_GetNameByINet(a_hostID));
305 } /*HostIDToHostName*/
308 /*-----------------------------------------------------------------------
309 * static PartIDToPartName
312 * Given a partition ID (in network byte order), figure out the
313 * corresponding partition name.
316 * a_partID : Partition ID in network byte order.
317 * a_partName : Ptr to partition name buffer.
320 * 0 if everything went well, or
321 * -1 if the given partition ID couldn't be translated.
324 * Nothing interesting.
328 *------------------------------------------------------------------------*/
330 static afs_int32 PartIDToPartName(a_partID, a_partName)
334 { /*PartIDToPartName*/
336 static char rn[] = "PartIDToPartName";
339 printf("[%s] Translating partition id %d to its name\n",
341 #endif /* USS_VOL_DB */
343 if ((a_partID < 0) || (a_partID > VOLMAXPARTS))
347 strcpy(a_partName,"/vicep");
348 a_partName[6] = a_partID + 'a';
349 a_partName[7] = '\0';
351 strcpy(a_partName,"/vicep");
353 a_partName[6] = 'a' + (a_partID/26);
354 a_partName[7] = 'a' + (a_partID%26);
355 a_partName[8] = '\0';
359 printf("[%s] Translation for part ID %d is '%s'\n",
360 rn, a_partID, a_partName);
361 #endif /* USS_VOL_DB */
364 } /*PartIDToPartName*/
367 /*------------------------------------------------------------------------
368 * EXPORTED uss_Vol_GetServer
371 * Nothing interesting.
375 *------------------------------------------------------------------------*/
377 afs_int32 uss_vol_GetServer(a_name)
380 { /*uss_vol_GetServer*/
382 register struct hostent *th;
385 register afs_int32 code;
387 code = sscanf(a_name, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
390 * Parsed as 128.2.9.4, or similar; return it in network
391 * byte order (128 in byte 0).
393 addr = (((afs_int32)b1)<<24) | (((afs_int32)b2)<<16) | (((afs_int32)b3)<<8) | (afs_int32)b4;
397 th = gethostbyname(a_name);
400 bcopy(th->h_addr, &addr, sizeof(addr));
403 } /*uss_vol_GetServer*/
405 /*------------------------------------------------------------------------
406 * static GetVolumeType
409 * Translate the given char string representing a volume type to the
410 * numeric representation.
413 * a_type : Char string volume type.
416 * One of ROVOL, RWVOL, BACKVOL, or -1 on failure.
419 * Nothing interesting.
423 *------------------------------------------------------------------------*/
425 static afs_int32 GetVolumeType(a_type)
430 if(!strcmp(a_type,"ro"))
433 if(!strcmp(a_type, "rw"))
436 if(!strcmp(a_type,"bk"))
444 /*------------------------------------------------------------------------
445 * EXPORTED uss_Vol_GetPartitionID
448 * It is assumed that partition names may begin with ``/vicep''.
452 *------------------------------------------------------------------------*/
454 afs_int32 uss_vol_GetPartitionID(a_name)
457 { /*uss_vol_GetPartitionID*/
467 * Numbers go straight through.
469 if (tc >= '0' && tc <= '9') {
470 return(atoi(a_name));
474 * Otherwise, check for vicepa or /vicepa, or just plain "a"
477 if (strlen(a_name) <= 2) {
478 strcpy(ascii, a_name);
479 } else if (!strncmp(a_name, "/vicep", 6)) {
480 strncpy(ascii, a_name+6, 2);
482 else if (!strncmp(a_name, "vicep", 5)) {
483 strncpy(ascii, a_name+5, 2);
489 * Now, partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab,
490 * .../vicepzz, and are numbered from 0. Do the appropriate conversion.
494 * Single-char name, 0..25
496 if (ascii[0] < 'a' || ascii[0] > 'z')
497 return(-1); /* wrongo */
498 return(ascii[0] - 'a');
502 * Two-char name, 26 .. <whatever>
504 if (ascii[0] < 'a' || ascii[0] > 'z')
506 if (ascii[1] < 'a' || ascii[1] > 'z')
508 return((ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26);
510 } /*uss_vol_GetPartitionID*/
513 /*-----------------------------------------------------------------------
514 * static CheckDoubleMount
517 * Make sure we're not trying to mount a volume in the same place
521 * a_mp : Mountpoint pathname to check.
522 * a_oldmp : Ptr to buffer into which the old value of the
523 * mountpoint is placed (if any).
526 * 0 if the volume was not previously mounted.
527 * uss_procs_ANCIENT if there was already a mountpoint AND the
528 * user was already recorded in the password
530 * uss_procs_YOUNG if there was a mountpoint for the user taken
531 * from the directory pool, yet the user was not
532 * yet in the password file.
535 * Nothing interesting.
538 * May fill in the a_oldmp buffer with the value of the old
540 *------------------------------------------------------------------------*/
542 static int CheckDoubleMount(a_mp, a_oldmp)
546 { /*CheckDoubleMount*/
548 static char rn[] = "uss_vol:CheckDoubleMount";
549 int start, len, mlen, tlen;
554 pws = getpwuid(atoi(uss_Uid));
555 if (pws != (struct passwd *)0) {
557 * User exists in the password file, so they've been fully
558 * created and integrated. Return the ``ancient'' mountpoint.
560 strcpy(a_oldmp, pws->pw_dir);
561 return(uss_procs_ANCIENT);
566 * $AUTO used. Search among the possible directories.
568 len = strlen(uss_Auto);
570 while(strncmp(&a_mp[i], uss_Auto, len)) {
571 a_oldmp[i] = a_mp[i];
572 if (++i > (mlen - len)) {
577 if ((start = i) != -1) {
579 * $AUTO used in mountpoint.
581 for (i = 0; i < uss_NumGroups; i++) {
583 * Copy in the base and tail components.
585 tlen = strlen(uss_DirPool[i]);
586 strncpy(&a_oldmp[start], uss_DirPool[i], tlen);
587 strcpy(&a_oldmp[start+tlen], &a_mp[start+len]);
589 printf("%s: Checking '%s' for mount point\n",
591 #endif /* USS_VOL_DB */
592 if(lstat(a_oldmp, &stbuf) == 0) /*mp exists*/
593 if (strcmp(a_oldmp, a_mp)) /* and is different */
595 * The old mount point exists and is different
596 * from the current one, so return the fact
597 * that we have a ``young'' mountpoint.
599 return(uss_procs_YOUNG);
600 } /*Check each $AUTO directory*/
602 } /*$AUTO has been used*/
605 * No luck finding the old mount point, so we just return that
606 * this is the first time we've seen this volume.
610 } /*CheckDoubleMount*/
613 /*------------------------------------------------------------------------
614 * EXPORTED uss_vol_CreateVol
617 * Called from the code generated by the uss grammar.
621 *------------------------------------------------------------------------*/
623 afs_int32 uss_vol_CreateVol(a_volname, a_server, a_partition, a_quota, a_mpoint, a_owner, a_acl)
632 { /*uss_vol_CreateVol*/
635 "uss_vol_CreateVol"; /*Routine name*/
636 afs_int32 pname; /*Partition name*/
637 afs_int32 volid, code; /*Volume ID, return code*/
638 afs_int32 saddr; /*Socket info for server*/
639 int VolExistFlag = 0; /*Does the volume exist?*/
640 int mpExistFlag = 0; /*Does the mountpoint exist?*/
641 char *Oldmpoint = NULL; /*Old mountpoint name, if any*/
642 char tmp_str[uss_MAX_SIZE]; /*Useful string buffer*/
643 int o; /*Owner's user id*/
644 char userinput[64]; /*User's input*/
645 struct uss_subdir *new_dir; /*Used to remember original ACL*/
648 * Don't do anything if there's already a problem.
654 fprintf(stderr, "%s:uss_vol_CreateVol params:\n", rn);
655 fprintf(stderr, "%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
656 rn, a_volname, a_server, a_partition, a_quota, a_mpoint,
658 #endif /* USS_VOL_DB */
661 * All of the parameters passed in are taken from the template
662 * file. Override these values if the user has explicitly set
663 * them, namely if the uss commons have non-null strings.
665 if (uss_Server[0] != '\0') {
666 #ifdef USS_VOL_DB_SHOW_OVERRIDES
669 "%s: Overriding server field: template value is '%s', overridden to '%s'\n",
670 rn, a_server, uss_Server);
671 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
672 a_server = uss_Server;
675 if (uss_Partition[0] != '\0') {
676 #ifdef USS_VOL_DB_SHOW_OVERRIDES
678 fprintf(stderr, "%s: Overriding partition field: template value is '%s', overridden to '%s'\n",
679 rn, a_partition, uss_Partition);
680 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
681 a_partition = uss_Partition;
684 if (uss_MountPoint[0] != '\0') {
685 #ifdef USS_VOL_DB_SHOW_OVERRIDES
687 fprintf(stderr, "%s: overriding mountpoint field: template value is '%s', overridden to '%s'\n",
688 rn, a_mpoint, uss_MountPoint);
689 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
690 a_mpoint = uss_MountPoint;
693 #ifdef USS_VOL_DB_SHOW_OVERRIDES
694 printf("%s: Params after overrides:\n", uss_whoami);
695 printf("%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
696 uss_whoami, a_volname, a_server, a_partition, a_quota,
697 a_mpoint, a_owner, a_acl);
698 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
702 "Creating volume '%s' on server '%s', partition '%s'\n",
703 a_volname, a_server, a_partition);
705 saddr = uss_vol_GetServer(a_server);
707 uss_procs_PrintErr(line,
708 "File server '%s' not found in config info\n",
712 pname = uss_vol_GetPartitionID(a_partition);
714 uss_procs_PrintErr(line,
715 "Couldn't interpret partition name '%s'\n",
721 * Make sure our VLDB connection(s) is/are set up before actually
722 * trying to perform a volume creation creation.
725 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
727 com_err(uss_whoami, code,
728 "while inititializing VLDB connection(s)\n");
731 } /*Initialize VLDB connection(s)*/
735 printf("%s: Creating volume on srv 0x%x, part %d, vol name '%s'\n",
736 rn, saddr, pname, a_volname);
737 #endif /* USS_VOL_DB */
738 code = UV_CreateVolume(saddr, pname, a_volname, &volid);
740 if (code == VL_NAMEEXIST){
743 "%s: Warning; Volume '%s' exists, using existing one.\n",
744 uss_whoami, a_volname);
747 * We should get the volid here if we want to use it, but
748 * we don't need it right now. What we DO need, though, is
749 * to ask our caller if it's OK to overwrite the user's files
750 * if they're pre-existing.
752 if (!uss_OverwriteThisOne) {
753 printf("Overwrite files in pre-existing '%s' volume? [y, n]: ",
755 scanf("%s", userinput);
756 if ((userinput[0] == 'y') || (userinput[0] == 'Y')) {
757 printf("\t[Overwriting allowed]\n");
758 uss_OverwriteThisOne = 1;
761 printf("\t[Overwriting not permitted]\n");
762 } /*Overwriting not previously allowed*/
763 } /*Volume already existed*/
765 uss_procs_PrintErr(line,
766 "Couldn't create volume '%s' [error %d]: %s\n",
767 a_volname, code, sys_errlist[errno]);
769 } /*Failure was NOT because it already existed*/
770 } /*UV_CreateVolume failed*/
774 "\t[Dry run: Creating volume '%s' on '%s', partition '%s']\n",
775 a_volname, a_server, a_partition);
778 /* OK, we want to make sure we don't double-mount the volume.
779 * If the volume existed, it can be the case that it is
780 * already mounted somewhere else (because of $AUTO or others).
781 * Let's check for that. Note: we never enter this portion of
782 * the code if we're doing a dry run.
785 if ((Oldmpoint = (char *) malloc(strlen(a_mpoint)+50)) == NULL){
786 fprintf(stderr, "%s: No more memory!\n", uss_whoami);
790 mpExistFlag = CheckDoubleMount(a_mpoint, Oldmpoint);
791 if(mpExistFlag == uss_procs_ANCIENT) {
793 "%s:\t*** WARNING ***; This user (%s) is already in passwd file (or equivalent). IGNORED.\n", uss_whoami, uss_User);
795 uss_syntax_err = 1; /*I know, I know, it's not a SYNTAX error*/
799 if (mpExistFlag == uss_procs_YOUNG) {
801 "%s: Warning; Volume '%s' is already mounted on %s. Using the existing one.\n",
802 uss_whoami, a_volname, Oldmpoint);
803 a_mpoint = Oldmpoint;
807 if (mpExistFlag == 0) {
808 extern int local_Cell;
813 sprintf(tmp_str, "#%s.", a_volname);
815 sprintf(tmp_str, "#%s:%s.", uss_Cell, a_volname);
817 if (symlink(tmp_str, a_mpoint)) {
818 if (errno == EEXIST) {
820 "%s: Warning: Mount point '%s' already exists.\n",
821 uss_whoami, a_mpoint);
824 fprintf(stderr,"%s: Can't mount volume '%s' on '%s': %s\n",
825 uss_whoami, a_volname, a_mpoint, sys_errlist[errno]);
829 } /*There was already something mounted there*/
833 fprintf(stderr, "\t[Dry run: Mounting '%s' at '%s']\n",
836 } /*Mount point didn't already exist*/
839 * Set the volume disk quota.
842 if (code = uss_acl_SetDiskQuota(a_mpoint, atoi(a_quota)))
847 "\t[Dry run: Setting disk quota for '%s' to %s blocks]\n",
851 /*Copy mpoint into $MTPT for others to use*/
852 strcpy(uss_MountPoint, a_mpoint);
854 o = uss_procs_GetOwner(a_owner);
856 if (chown(a_mpoint, o, -1)) {
858 "%s: Can't chown() mountpoint '%s' to owner '%s' (uid %d): %s\n",
859 uss_whoami, a_mpoint, a_owner, o, sys_errlist[errno]);
867 "\t[Dry run: chown() mountpoint '%s' to be owned by user]\n",
872 * Set the ACL on the user's home directory so that, for the duration of
873 * the account creation, only the uss_AccountCreator has any rights on the
874 * files therein. Make sure to clear this ACL to remove anyone that might
875 * already be there due to volume creation defaults. We will set this ACL
876 * properly, as well as all ACLs of future subdirectories,as the very last
877 * thing we do to the new account.
879 new_dir = (struct uss_subdir *) malloc(sizeof(struct uss_subdir));
880 new_dir->previous = uss_currentDir;
881 new_dir->path = (char *) malloc(strlen(a_mpoint)+1);
882 strcpy(new_dir->path, a_mpoint);
883 new_dir->finalACL = (char *) malloc(strlen(a_acl)+1);
884 strcpy(new_dir->finalACL, a_acl);
885 uss_currentDir = new_dir;
886 sprintf(tmp_str, "%s %s all", a_mpoint, uss_AccountCreator);
893 fprintf(stderr, "Setting ACL: '%s'\n",
895 if (uss_acl_SetAccess(tmp_str, 1, 0))
899 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s)]\n", tmp_str);
902 } /*uss_vol_CreateVol*/
905 /*------------------------------------------------------------------------
906 * EXPORTED uss_vol_DeleteVol
909 * Nothing interesting.
913 *------------------------------------------------------------------------*/
915 afs_int32 uss_vol_DeleteVol(a_volName, a_volID, a_servName, a_servID, a_partName, a_partID)
923 { /*uss_vol_DeleteVol*/
925 static char rn[] = "uss_vol_DeleteVol"; /*Routine name*/
926 register afs_int32 code; /*Return code*/
929 * Make sure we've initialized our VLDB connection(s) before
933 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
940 * Go for the deletion.
943 printf("%s: Deleting volume '%s' (ID %d) on FileServer '%s' (0x%x), partition '%s' (%d)\n",
944 rn, a_volName, a_volID, a_servName, a_servID,
945 a_partName, a_partID);
946 #endif /* USS_VOL_DB */
948 code = UV_DeleteVolume(a_servID, a_partID, a_volID);
950 printf("%s: Can't delete volume '%s'\n",
951 uss_whoami, a_volName);
953 printf("\t[Dry run - volume '%s' NOT removed]\n", a_volName);
957 } /*uss_vol_DeleteVol*/
960 /*------------------------------------------------------------------------
961 * static GetServerAndPart
964 * Given a VLDB entry, return the server and partition IDs for
965 * the read/write volume.
968 * a_vldbEntryP : Ptr to VLDB entry.
969 * a_servIDP : Ptr to server ID to set.
970 * a_partIDP : Ptr to partition ID to set.
973 * 0 if everything went well, or
977 * Nothing interesting.
981 *------------------------------------------------------------------------*/
983 static afs_int32 GetServerAndPart(a_vldbEntryP, a_servIDP, a_partIDP)
984 struct vldbentry *a_vldbEntryP;
985 afs_int32 *a_servIDP;
986 afs_int32 *a_partIDP;
988 { /*GetServerAndPart*/
991 * It really looks like all we need to do is pull off the
992 * first entry's info.
994 *a_servIDP = a_vldbEntryP->serverNumber[0];
995 *a_partIDP = a_vldbEntryP->serverPartition[0];
998 } /*GetServerAndPart*/
1001 /*------------------------------------------------------------------------
1002 * EXPORTED uss_vol_GetVolInfoFromMountPoint
1005 * If the mountpoint path provided is not
1009 *------------------------------------------------------------------------*/
1011 afs_int32 uss_vol_GetVolInfoFromMountPoint(a_mountpoint)
1014 { /*uss_vol_GetVolInfoFromMountPoint*/
1016 static char rn[] = "uss_vol_GetVolInfoFromMountPoint";
1017 register afs_int32 code; /*Return code*/
1018 uss_VolumeStatus_t *statusP; /*Ptr to returned status*/
1019 afs_int32 volID; /*Volume ID*/
1020 struct vldbentry vldbEntry; /*VLDB entry for volume*/
1021 afs_int32 serverID; /*Addr of host FileServer*/
1022 afs_int32 partID; /*Volume's partition ID*/
1025 * Set up to ask the CacheManager to give us all the info
1026 * it has about the given mountpoint.
1028 code = uss_fs_GetVolStat(a_mountpoint,
1032 printf("[%s] Result of uss_fs_GetVolStat: code = %d, errno = %d\n",
1034 #endif /* USS_VOL_DB */
1036 if (errno == EINVAL ||
1040 * We were given a mountpoint pathname that doesn't
1041 * point to a volume, or a mountpoint that has already
1042 * been deleted. This means that there is no info
1043 * to get from this pathname. Zero out the volume,
1044 * server & partition info and return successfully.
1046 uss_Volume[0] = '\0';
1047 uss_Server[0] = '\0';
1048 uss_Partition[0] = '\0';
1051 uss_PartitionID = 0;
1053 printf("%s: Warning: Mountpoint pathname '%s': ",
1054 uss_whoami, a_mountpoint);
1055 if (errno == EINVAL)
1056 printf("Volume not reachable\n");
1057 else if (errno == ENODEV)
1058 printf("No such device\n");
1060 printf("Not found\n");
1065 printf("%s: Can't get volume information from mountpoint '%s'\n",
1066 uss_whoami, a_mountpoint);
1069 } /*Can't get volume status*/
1072 * Pull out the volume name from the returned information and store
1073 * it in the common area. It resides right after the basic volume
1076 statusP = (uss_VolumeStatus_t *)uss_fs_OutBuff;
1077 strcpy(uss_Volume, (((char *)statusP) + sizeof(*statusP)));
1078 volID = statusP->Vid;
1079 uss_VolumeID = volID;
1081 printf("%s: Illegal volume ID: %d\n",
1087 * With the volume name in hand, find out where that volume
1088 * lives. Make sure our VLDB stuff has been initialized first.
1091 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
1095 code = ubik_Call(VL_GetEntryByID, uconn_vldbP, 0, volID, -1, &vldbEntry);
1097 printf("%s: Can't fetch VLDB entry for volume ID %d\n",
1103 * Translate the given VLDB entry from network to host format, then
1104 * checking on the volume's validity. Specifically, it must be a
1105 * read/write volume and must only exist on one server.
1107 MapHostToNetwork(&vldbEntry);
1108 if (vldbEntry.volumeId[RWVOL] != volID) {
1109 printf("s: Volume '%s' (ID %d) is not a read/write volume!!\n",
1110 uss_whoami, uss_Volume, volID);
1113 if (vldbEntry.nServers != 1) {
1114 printf("s: Volume '%s' (ID %d) exists on multiple servers!!\n",
1115 uss_whoami, uss_Volume, volID);
1120 * Pull out the int32words containing the server and partition info
1121 * for the read/write volume.
1123 code = GetServerAndPart(&vldbEntry, &serverID, &partID);
1125 printf("%s: Can't get server/partition info from VLDB entry for volume '%s' (ID %d)\n",
1126 uss_whoami, uss_Volume, volID);
1131 * Store the raw data, then translate the FileServer address to a
1132 * host name, and the partition ID to a partition name.
1134 uss_ServerID = serverID;
1135 uss_PartitionID = partID;
1136 HostIDToHostName(serverID, uss_Server);
1138 printf("[%s] Server ID 0x%x translated to '%s'\n",
1139 rn, serverID, uss_Server);
1140 #endif /* USS_VOL_DB */
1141 code = PartIDToPartName(partID, uss_Partition);
1143 printf("%s: Error translating partition ID %d to partition name\n",
1144 uss_whoami, partID);
1149 * We got it, home boy.
1153 } /*uss_vol_GetVolInfoFromMountPoint*/