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
11 * Implementation of the volume operations used by the AFS user
16 * --------------------- Required definitions ---------------------
18 #include <afsconfig.h>
19 #include <afs/param.h>
24 #include "uss_vol.h" /*Interface to this module */
25 #include "uss_common.h" /*Common definitions */
26 #include "uss_procs.h" /*Defs from procs module */
27 #include "uss_fs.h" /*CacheManager ops */
41 #include <afs/vlserver.h>
43 #include <afs/cellconfig.h>
44 #include <rx/rx_globals.h>
45 #include <afs/volser.h>
46 #include <afs/volint.h>
50 extern struct rx_connection *UV_Bind();
52 extern int VL_GetEntryByID();
53 extern char *hostutil_GetNameByINet();
57 * ---------------------- Private definitions ---------------------
60 #undef USS_VOL_DB_SHOW_OVERRIDES
64 * --------------------- Exported definitions ---------------------
67 * The Volume Server interface imports the Ubik connection
68 * structure to use, expecting it to be named "cstruct". This
69 * is why we have two names here. Thus, the UV_CreateVolume()
70 * will work and we can avoid nasty little core dumps.
72 struct ubik_client *uconn_vldbP; /*Ubik connection struct */
73 struct ubik_client *cstruct; /*Required name for above */
76 * ------------------------ Private globals -----------------------
78 static int initDone = 0; /*Module initialized? */
79 static int NoAuthFlag = 0; /*Use -noauth? */
80 static struct rx_connection
81 *serverconns[VLDB_MAXSERVERS]; /*Connection(s) to VLDB
85 /*-----------------------------------------------------------------------
86 * static InitThisModule
89 * Set up this module, namely set up all the client state for
90 * dealing with the Volume Location Server(s), including
91 * network connections.
94 * a_noAuthFlag : Do we need authentication?
95 * a_confDir : Configuration directory to use.
96 * a_cellName : Cell we want to talk to.
99 * 0 if everything went fine, or
100 * lower-level error code otherwise.
103 * This routine will only be called once.
107 *------------------------------------------------------------------------*/
110 InitThisModule(a_noAuthFlag, a_confDir, a_cellName)
115 { /*InitThisModule */
117 static char rn[] = "uss_vol:InitThisModule";
118 register afs_int32 code; /*Return code */
119 struct afsconf_dir *tdir; /*Ptr to conf dir info */
120 struct afsconf_cell info; /*Info about chosen cell */
121 struct ktc_principal sname; /*Service name */
122 struct ktc_token ttoken; /*Service ticket */
123 afs_int32 scIndex; /*Chosen security index */
124 struct rx_securityClass *sc; /*Generated security object */
125 afs_int32 i; /*Loop index */
128 * Only once, guys, will 'ya?
132 printf("[%s] Called multiple times!\n", rn);
133 #endif /* USS_VOL_DB */
138 * Set up our Rx environment.
141 printf("[%s] Initializing Rx environment\n", rn);
142 #endif /* USS_VOL_DB */
145 fprintf(stderr, "%s: Couldn't initialize Rx.\n", uss_whoami);
148 rx_SetRxDeadTime(50);
151 * Find out all about our configuration.
154 printf("[%s] Handling configuration info\n", rn);
155 #endif /* USS_VOL_DB */
156 tdir = afsconf_Open(a_confDir);
158 fprintf(stderr, "%s: Couldn't open configuration directory (%s).\n",
159 uss_whoami, a_confDir);
162 code = afsconf_GetCellInfo(tdir, a_cellName, AFSCONF_VLDBSERVICE, &info);
164 printf("%s: Can't find VLDB server(s) for cell %s\n", uss_whoami,
169 printf("[%s] Getting tickets if needed\n", rn);
170 #endif /* USS_VOL_DB */
173 * We don't need tickets for unauthenticated connections.
175 strcpy(sname.cell, info.name);
176 sname.instance[0] = 0;
177 strcpy(sname.name, "afs");
178 code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
181 "%s: Couldn't get AFS tokens, running unauthenticated.\n",
186 * We got a ticket, go for an authenticated connection.
188 if (ttoken.kvno >= 0 && ttoken.kvno <= 255)
189 scIndex = 2; /*Kerberos */
191 fprintf(stderr, "%s: Funny kvno (%d) in ticket, proceeding\n",
192 uss_whoami, ttoken.kvno);
196 } /*Authentication desired */
201 * Generate the appropriate security object for the connection.
204 printf("[%s] Generating Rx security object\n", rn);
205 #endif /* USS_VOL_DB */
208 sc = (struct rx_securityClass *)
209 rxnull_NewClientSecurityObject();
216 sc = (struct rx_securityClass *)
217 rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
218 ttoken.kvno, ttoken.ticketLen,
224 * Tell UV module about default authentication.
227 printf("[%s] Setting UV security: obj 0x%x, index %d\n", rn, sc, scIndex);
228 #endif /* USS_VOL_DB */
229 UV_SetSecurity(sc, scIndex);
230 if (info.numServers > VLDB_MAXSERVERS) {
231 fprintf(stderr, "%s: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
232 uss_whoami, info.numServers, VLDB_MAXSERVERS);
237 * Connect to each VLDB server for the chosen cell.
239 for (i = 0; i < info.numServers; i++) {
242 ("[%s] Connecting to VLDB server 0x%x, port %d, service id %d\n",
243 rn, info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port,
245 #endif /* USS_VOL_DB */
247 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
248 info.hostAddr[i].sin_port, USER_SERVICE_ID, sc,
253 * Set up to execute Ubik transactions on the VLDB.
256 printf("[%s] Initializing Ubik interface\n", rn);
257 #endif /* USS_VOL_DB */
258 code = ubik_ClientInit(serverconns, &uconn_vldbP);
260 fprintf(stderr, "%s: Ubik client init failed.\n", uss_whoami);
264 printf("[%s] VLDB ubik connection structure at 0x%x\n", rn, uconn_vldbP);
265 #endif /* USS_VOL_DB */
268 * Place the ubik VLDB connection structure in its advertised
271 cstruct = uconn_vldbP;
279 } /*InitThisModule */
282 /*-----------------------------------------------------------------------
283 * static HostIDToHostName
286 * Given a host ID (in network byte order), figure out the
287 * corresponding host name.
290 * a_hostID : Host ID in network byte order.
291 * a_hostName : Ptr to host name buffer.
297 * This routine simply calls the hostutil_GetNameByINet()
298 * function exported by the utility library (util.a).
302 *------------------------------------------------------------------------*/
304 char *hostutil_GetNameByINet();
307 HostIDToHostName(a_hostID, a_hostName)
311 { /*HostIDToHostName */
313 strcpy(a_hostName, hostutil_GetNameByINet(a_hostID));
315 } /*HostIDToHostName */
318 /*-----------------------------------------------------------------------
319 * static PartIDToPartName
322 * Given a partition ID (in network byte order), figure out the
323 * corresponding partition name.
326 * a_partID : Partition ID in network byte order.
327 * a_partName : Ptr to partition name buffer.
330 * 0 if everything went well, or
331 * -1 if the given partition ID couldn't be translated.
334 * Nothing interesting.
338 *------------------------------------------------------------------------*/
341 PartIDToPartName(a_partID, a_partName)
345 { /*PartIDToPartName */
347 static char rn[] = "PartIDToPartName";
350 printf("[%s] Translating partition id %d to its name\n", rn, a_partID);
351 #endif /* USS_VOL_DB */
353 if ((a_partID < 0) || (a_partID > VOLMAXPARTS))
357 strcpy(a_partName, "/vicep");
358 a_partName[6] = a_partID + 'a';
359 a_partName[7] = '\0';
361 strcpy(a_partName, "/vicep");
363 a_partName[6] = 'a' + (a_partID / 26);
364 a_partName[7] = 'a' + (a_partID % 26);
365 a_partName[8] = '\0';
369 printf("[%s] Translation for part ID %d is '%s'\n", rn, a_partID,
371 #endif /* USS_VOL_DB */
374 } /*PartIDToPartName */
377 /*------------------------------------------------------------------------
378 * EXPORTED uss_Vol_GetServer
381 * Nothing interesting.
385 *------------------------------------------------------------------------*/
388 uss_vol_GetServer(a_name)
391 { /*uss_vol_GetServer */
393 register struct hostent *th;
396 register afs_int32 code;
398 code = sscanf(a_name, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
401 * Parsed as 128.2.9.4, or similar; return it in network
402 * byte order (128 in byte 0).
405 (((afs_int32) b1) << 24) | (((afs_int32) b2) << 16) |
406 (((afs_int32) b3) << 8) | (afs_int32) b4;
410 th = gethostbyname(a_name);
413 memcpy(&addr, th->h_addr, sizeof(addr));
416 } /*uss_vol_GetServer */
418 /*------------------------------------------------------------------------
419 * static GetVolumeType
422 * Translate the given char string representing a volume type to the
423 * numeric representation.
426 * a_type : Char string volume type.
429 * One of ROVOL, RWVOL, BACKVOL, or -1 on failure.
432 * Nothing interesting.
436 *------------------------------------------------------------------------*/
439 GetVolumeType(a_type)
444 if (!strcmp(a_type, "ro"))
446 else if (!strcmp(a_type, "rw"))
448 else if (!strcmp(a_type, "bk"))
456 /*------------------------------------------------------------------------
457 * EXPORTED uss_Vol_GetPartitionID
460 * It is assumed that partition names may begin with ``/vicep''.
464 *------------------------------------------------------------------------*/
467 uss_vol_GetPartitionID(a_name)
470 { /*uss_vol_GetPartitionID */
480 * Numbers go straight through.
482 if (tc >= '0' && tc <= '9') {
483 return (atoi(a_name));
487 * Otherwise, check for vicepa or /vicepa, or just plain "a"
490 if (strlen(a_name) <= 2) {
491 strcpy(ascii, a_name);
492 } else if (!strncmp(a_name, "/vicep", 6)) {
493 strncpy(ascii, a_name + 6, 2);
494 } else if (!strncmp(a_name, "vicep", 5)) {
495 strncpy(ascii, a_name + 5, 2);
500 * Now, partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab,
501 * .../vicepzz, and are numbered from 0. Do the appropriate conversion.
505 * Single-char name, 0..25
507 if (ascii[0] < 'a' || ascii[0] > 'z')
508 return (-1); /* wrongo */
509 return (ascii[0] - 'a');
512 * Two-char name, 26 .. <whatever>
514 if (ascii[0] < 'a' || ascii[0] > 'z')
516 if (ascii[1] < 'a' || ascii[1] > 'z')
518 return ((ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26);
520 } /*uss_vol_GetPartitionID */
523 /*-----------------------------------------------------------------------
524 * static CheckDoubleMount
527 * Make sure we're not trying to mount a volume in the same place
531 * a_mp : Mountpoint pathname to check.
532 * a_oldmp : Ptr to buffer into which the old value of the
533 * mountpoint is placed (if any).
536 * 0 if the volume was not previously mounted.
537 * uss_procs_ANCIENT if there was already a mountpoint AND the
538 * user was already recorded in the password
540 * uss_procs_YOUNG if there was a mountpoint for the user taken
541 * from the directory pool, yet the user was not
542 * yet in the password file.
545 * Nothing interesting.
548 * May fill in the a_oldmp buffer with the value of the old
550 *------------------------------------------------------------------------*/
553 CheckDoubleMount(a_mp, a_oldmp)
557 { /*CheckDoubleMount */
559 static char rn[] = "uss_vol:CheckDoubleMount";
560 int start, len, mlen, tlen;
565 pws = getpwuid(atoi(uss_Uid));
568 * User exists in the password file, so they've been fully
569 * created and integrated. Return the ``ancient'' mountpoint.
571 strcpy(a_oldmp, pws->pw_dir);
572 return (uss_procs_ANCIENT);
577 * $AUTO used. Search among the possible directories.
579 len = strlen(uss_Auto);
581 while (strncmp(&a_mp[i], uss_Auto, len)) {
582 a_oldmp[i] = a_mp[i];
583 if (++i > (mlen - len)) {
588 if ((start = i) != -1) {
590 * $AUTO used in mountpoint.
592 for (i = 0; i < uss_NumGroups; i++) {
594 * Copy in the base and tail components.
596 tlen = strlen(uss_DirPool[i]);
597 strncpy(&a_oldmp[start], uss_DirPool[i], tlen);
598 strcpy(&a_oldmp[start + tlen], &a_mp[start + len]);
600 printf("%s: Checking '%s' for mount point\n", rn, a_oldmp);
601 #endif /* USS_VOL_DB */
602 if (lstat(a_oldmp, &stbuf) == 0) /*mp exists */
603 if (strcmp(a_oldmp, a_mp))
604 /* and is different */
606 * The old mount point exists and is different
607 * from the current one, so return the fact
608 * that we have a ``young'' mountpoint.
610 return (uss_procs_YOUNG);
611 } /*Check each $AUTO directory */
615 /*$AUTO has been used */
617 * No luck finding the old mount point, so we just return that
618 * this is the first time we've seen this volume.
622 } /*CheckDoubleMount */
625 /*------------------------------------------------------------------------
626 * EXPORTED uss_vol_CreateVol
629 * Called from the code generated by the uss grammar.
633 *------------------------------------------------------------------------*/
636 uss_vol_CreateVol(a_volname, a_server, a_partition, a_quota, a_mpoint,
646 { /*uss_vol_CreateVol */
648 static char rn[] = "uss_vol_CreateVol"; /*Routine name */
649 afs_int32 pname; /*Partition name */
650 afs_int32 volid, code; /*Volume ID, return code */
651 afs_int32 saddr; /*Socket info for server */
652 int VolExistFlag = 0; /*Does the volume exist? */
653 int mpExistFlag = 0; /*Does the mountpoint exist? */
654 char *Oldmpoint = NULL; /*Old mountpoint name, if any */
655 char tmp_str[uss_MAX_SIZE]; /*Useful string buffer */
656 int o; /*Owner's user id */
657 char userinput[64]; /*User's input */
658 struct uss_subdir *new_dir; /*Used to remember original ACL */
661 * Don't do anything if there's already a problem.
667 fprintf(stderr, "%s:uss_vol_CreateVol params:\n", rn);
669 "%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
670 rn, a_volname, a_server, a_partition, a_quota, a_mpoint, a_owner,
672 #endif /* USS_VOL_DB */
675 * All of the parameters passed in are taken from the template
676 * file. Override these values if the user has explicitly set
677 * them, namely if the uss commons have non-null strings.
679 if (uss_Server[0] != '\0') {
680 #ifdef USS_VOL_DB_SHOW_OVERRIDES
683 "%s: Overriding server field: template value is '%s', overridden to '%s'\n",
684 rn, a_server, uss_Server);
685 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
686 a_server = uss_Server;
689 if (uss_Partition[0] != '\0') {
690 #ifdef USS_VOL_DB_SHOW_OVERRIDES
693 "%s: Overriding partition field: template value is '%s', overridden to '%s'\n",
694 rn, a_partition, uss_Partition);
695 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
696 a_partition = uss_Partition;
699 if (uss_MountPoint[0] != '\0') {
700 #ifdef USS_VOL_DB_SHOW_OVERRIDES
703 "%s: overriding mountpoint field: template value is '%s', overridden to '%s'\n",
704 rn, a_mpoint, uss_MountPoint);
705 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
706 a_mpoint = uss_MountPoint;
708 #ifdef USS_VOL_DB_SHOW_OVERRIDES
709 printf("%s: Params after overrides:\n", uss_whoami);
711 ("%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
712 uss_whoami, a_volname, a_server, a_partition, a_quota, a_mpoint,
714 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
718 "Creating volume '%s' on server '%s', partition '%s'\n",
719 a_volname, a_server, a_partition);
721 saddr = uss_vol_GetServer(a_server);
723 uss_procs_PrintErr(line,
724 "File server '%s' not found in config info\n",
728 pname = uss_vol_GetPartitionID(a_partition);
730 uss_procs_PrintErr(line, "Couldn't interpret partition name '%s'\n",
736 * Make sure our VLDB connection(s) is/are set up before actually
737 * trying to perform a volume creation creation.
740 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
742 afs_com_err(uss_whoami, code,
743 "while inititializing VLDB connection(s)\n");
747 /*Initialize VLDB connection(s) */
750 printf("%s: Creating volume on srv 0x%x, part %d, vol name '%s'\n",
751 rn, saddr, pname, a_volname);
752 #endif /* USS_VOL_DB */
753 code = UV_CreateVolume(saddr, pname, a_volname, &volid);
755 if (code == VL_NAMEEXIST) {
758 "%s: Warning; Volume '%s' exists, using existing one.\n",
759 uss_whoami, a_volname);
762 * We should get the volid here if we want to use it, but
763 * we don't need it right now. What we DO need, though, is
764 * to ask our caller if it's OK to overwrite the user's files
765 * if they're pre-existing.
767 if (!uss_OverwriteThisOne) {
769 ("Overwrite files in pre-existing '%s' volume? [y, n]: ",
771 scanf("%s", userinput);
772 if ((userinput[0] == 'y') || (userinput[0] == 'Y')) {
773 printf("\t[Overwriting allowed]\n");
774 uss_OverwriteThisOne = 1;
776 printf("\t[Overwriting not permitted]\n");
777 } /*Overwriting not previously allowed */
778 } /*Volume already existed */
780 uss_procs_PrintErr(line,
781 "Couldn't create volume '%s' [error %d]: %s\n",
782 a_volname, code, strerror(errno));
784 } /*Failure was NOT because it already existed */
785 } /*UV_CreateVolume failed */
789 "\t[Dry run: Creating volume '%s' on '%s', partition '%s']\n",
790 a_volname, a_server, a_partition);
793 /* OK, we want to make sure we don't double-mount the volume.
794 * If the volume existed, it can be the case that it is
795 * already mounted somewhere else (because of $AUTO or others).
796 * Let's check for that. Note: we never enter this portion of
797 * the code if we're doing a dry run.
800 if ((Oldmpoint = (char *)malloc(strlen(a_mpoint) + 50)) == NULL) {
801 fprintf(stderr, "%s: No more memory!\n", uss_whoami);
805 mpExistFlag = CheckDoubleMount(a_mpoint, Oldmpoint);
806 if (mpExistFlag == uss_procs_ANCIENT) {
808 "%s:\t*** WARNING ***; This user (%s) is already in passwd file (or equivalent). IGNORED.\n",
809 uss_whoami, uss_User);
811 uss_syntax_err = 1; /*I know, I know, it's not a SYNTAX error */
815 if (mpExistFlag == uss_procs_YOUNG) {
817 "%s: Warning; Volume '%s' is already mounted on %s. Using the existing one.\n",
818 uss_whoami, a_volname, Oldmpoint);
819 a_mpoint = Oldmpoint;
823 if (mpExistFlag == 0) {
824 extern int local_Cell;
829 sprintf(tmp_str, "#%s.", a_volname);
831 sprintf(tmp_str, "#%s:%s.", uss_Cell, a_volname);
833 if (symlink(tmp_str, a_mpoint)) {
834 if (errno == EEXIST) {
836 "%s: Warning: Mount point '%s' already exists.\n",
837 uss_whoami, a_mpoint);
840 "%s: Can't mount volume '%s' on '%s': %s\n",
841 uss_whoami, a_volname, a_mpoint, strerror(errno));
845 } /*There was already something mounted there */
849 fprintf(stderr, "\t[Dry run: Mounting '%s' at '%s']\n", tmp_str,
854 /*Mount point didn't already exist */
856 * Set the volume disk quota.
859 if (code = uss_acl_SetDiskQuota(a_mpoint, atoi(a_quota)))
864 "\t[Dry run: Setting disk quota for '%s' to %s blocks]\n",
868 /*Copy mpoint into $MTPT for others to use */
869 strcpy(uss_MountPoint, a_mpoint);
871 o = uss_procs_GetOwner(a_owner);
873 if (chown(a_mpoint, o, -1)) {
875 "%s: Can't chown() mountpoint '%s' to owner '%s' (uid %d): %s\n",
876 uss_whoami, a_mpoint, a_owner, o, strerror(errno));
884 "\t[Dry run: chown() mountpoint '%s' to be owned by user]\n",
889 * Set the ACL on the user's home directory so that, for the duration of
890 * the account creation, only the uss_AccountCreator has any rights on the
891 * files therein. Make sure to clear this ACL to remove anyone that might
892 * already be there due to volume creation defaults. We will set this ACL
893 * properly, as well as all ACLs of future subdirectories,as the very last
894 * thing we do to the new account.
896 new_dir = (struct uss_subdir *)malloc(sizeof(struct uss_subdir));
897 new_dir->previous = uss_currentDir;
898 new_dir->path = (char *)malloc(strlen(a_mpoint) + 1);
899 strcpy(new_dir->path, a_mpoint);
900 new_dir->finalACL = (char *)malloc(strlen(a_acl) + 1);
901 strcpy(new_dir->finalACL, a_acl);
902 uss_currentDir = new_dir;
903 sprintf(tmp_str, "%s %s all", a_mpoint, uss_AccountCreator);
910 fprintf(stderr, "Setting ACL: '%s'\n", tmp_str);
911 if (uss_acl_SetAccess(tmp_str, 1, 0))
915 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s)]\n", tmp_str);
918 } /*uss_vol_CreateVol */
921 /*------------------------------------------------------------------------
922 * EXPORTED uss_vol_DeleteVol
925 * Nothing interesting.
929 *------------------------------------------------------------------------*/
932 uss_vol_DeleteVol(a_volName, a_volID, a_servName, a_servID, a_partName,
941 { /*uss_vol_DeleteVol */
943 static char rn[] = "uss_vol_DeleteVol"; /*Routine name */
944 register afs_int32 code; /*Return code */
947 * Make sure we've initialized our VLDB connection(s) before
951 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
958 * Go for the deletion.
962 ("%s: Deleting volume '%s' (ID %d) on FileServer '%s' (0x%x), partition '%s' (%d)\n",
963 rn, a_volName, a_volID, a_servName, a_servID, a_partName,
965 #endif /* USS_VOL_DB */
967 code = UV_DeleteVolume(a_servID, a_partID, a_volID);
969 printf("%s: Can't delete volume '%s'\n", uss_whoami, a_volName);
971 printf("\t[Dry run - volume '%s' NOT removed]\n", a_volName);
975 } /*uss_vol_DeleteVol */
978 /*------------------------------------------------------------------------
979 * static GetServerAndPart
982 * Given a VLDB entry, return the server and partition IDs for
983 * the read/write volume.
986 * a_vldbEntryP : Ptr to VLDB entry.
987 * a_servIDP : Ptr to server ID to set.
988 * a_partIDP : Ptr to partition ID to set.
991 * 0 if everything went well, or
995 * Nothing interesting.
999 *------------------------------------------------------------------------*/
1002 GetServerAndPart(a_vldbEntryP, a_servIDP, a_partIDP)
1003 struct vldbentry *a_vldbEntryP;
1004 afs_int32 *a_servIDP;
1005 afs_int32 *a_partIDP;
1007 { /*GetServerAndPart */
1010 * It really looks like all we need to do is pull off the
1011 * first entry's info.
1013 *a_servIDP = a_vldbEntryP->serverNumber[0];
1014 *a_partIDP = a_vldbEntryP->serverPartition[0];
1017 } /*GetServerAndPart */
1020 /*------------------------------------------------------------------------
1021 * EXPORTED uss_vol_GetVolInfoFromMountPoint
1024 * If the mountpoint path provided is not
1028 *------------------------------------------------------------------------*/
1031 uss_vol_GetVolInfoFromMountPoint(a_mountpoint)
1034 { /*uss_vol_GetVolInfoFromMountPoint */
1036 static char rn[] = "uss_vol_GetVolInfoFromMountPoint";
1037 register afs_int32 code; /*Return code */
1038 uss_VolumeStatus_t *statusP; /*Ptr to returned status */
1039 afs_int32 volID; /*Volume ID */
1040 struct vldbentry vldbEntry; /*VLDB entry for volume */
1041 afs_int32 serverID; /*Addr of host FileServer */
1042 afs_int32 partID; /*Volume's partition ID */
1045 * Set up to ask the CacheManager to give us all the info
1046 * it has about the given mountpoint.
1048 code = uss_fs_GetVolStat(a_mountpoint, uss_fs_OutBuff, USS_FS_MAX_SIZE);
1050 printf("[%s] Result of uss_fs_GetVolStat: code = %d, errno = %d\n", rn,
1052 #endif /* USS_VOL_DB */
1054 if (errno == EINVAL || errno == ENOENT || errno == ENODEV) {
1056 * We were given a mountpoint pathname that doesn't
1057 * point to a volume, or a mountpoint that has already
1058 * been deleted. This means that there is no info
1059 * to get from this pathname. Zero out the volume,
1060 * server & partition info and return successfully.
1062 uss_Volume[0] = '\0';
1063 uss_Server[0] = '\0';
1064 uss_Partition[0] = '\0';
1067 uss_PartitionID = 0;
1069 printf("%s: Warning: Mountpoint pathname '%s': ", uss_whoami,
1071 if (errno == EINVAL)
1072 printf("Volume not reachable\n");
1073 else if (errno == ENODEV)
1074 printf("No such device\n");
1076 printf("Not found\n");
1080 printf("%s: Can't get volume information from mountpoint '%s'\n",
1081 uss_whoami, a_mountpoint);
1086 /*Can't get volume status */
1088 * Pull out the volume name from the returned information and store
1089 * it in the common area. It resides right after the basic volume
1092 statusP = (uss_VolumeStatus_t *) uss_fs_OutBuff;
1093 strcpy(uss_Volume, (((char *)statusP) + sizeof(*statusP)));
1094 volID = statusP->Vid;
1095 uss_VolumeID = volID;
1097 printf("%s: Illegal volume ID: %d\n", uss_whoami, volID);
1102 * With the volume name in hand, find out where that volume
1103 * lives. Make sure our VLDB stuff has been initialized first.
1106 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
1110 code = ubik_Call(VL_GetEntryByID, uconn_vldbP, 0, volID, -1, &vldbEntry);
1112 printf("%s: Can't fetch VLDB entry for volume ID %d\n", uss_whoami,
1118 * Translate the given VLDB entry from network to host format, then
1119 * checking on the volume's validity. Specifically, it must be a
1120 * read/write volume and must only exist on one server.
1122 MapHostToNetwork(&vldbEntry);
1123 if (vldbEntry.volumeId[RWVOL] != volID) {
1124 printf("%s: Volume '%s' (ID %d) is not a read/write volume!!\n",
1125 uss_whoami, uss_Volume, volID);
1128 if (vldbEntry.nServers != 1) {
1129 printf("s: Volume '%s' (ID %d) exists on multiple servers!!\n",
1130 uss_whoami, uss_Volume, volID);
1135 * Pull out the int32words containing the server and partition info
1136 * for the read/write volume.
1138 code = GetServerAndPart(&vldbEntry, &serverID, &partID);
1141 ("%s: Can't get server/partition info from VLDB entry for volume '%s' (ID %d)\n",
1142 uss_whoami, uss_Volume, volID);
1147 * Store the raw data, then translate the FileServer address to a
1148 * host name, and the partition ID to a partition name.
1150 uss_ServerID = serverID;
1151 uss_PartitionID = partID;
1152 HostIDToHostName(serverID, uss_Server);
1154 printf("[%s] Server ID 0x%x translated to '%s'\n", rn, serverID,
1156 #endif /* USS_VOL_DB */
1157 code = PartIDToPartName(partID, uss_Partition);
1159 printf("%s: Error translating partition ID %d to partition name\n",
1160 uss_whoami, partID);
1165 * We got it, home boy.
1169 } /*uss_vol_GetVolInfoFromMountPoint */