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>
23 #include <afs/com_err.h>
24 #include <afs/vlserver.h>
25 #include <afs/vldbint.h>
27 #include <afs/cellconfig.h>
28 #include <rx/rx_globals.h>
29 #include <afs/afsint.h>
30 #include <afs/volser.h>
31 #include <afs/volser_prototypes.h>
32 #include <afs/volint.h>
34 #include <afs/afsutil.h>
39 #include "uss_vol.h" /*Interface to this module */
40 #include "uss_common.h" /*Common definitions */
41 #include "uss_procs.h" /*Defs from procs module */
42 #include "uss_fs.h" /*CacheManager ops */
48 * ---------------------- Private definitions ---------------------
51 #undef USS_VOL_DB_SHOW_OVERRIDES
55 * --------------------- Exported definitions ---------------------
58 * The Volume Server interface imports the Ubik connection
59 * structure to use, expecting it to be named "cstruct". This
60 * is why we have two names here. Thus, the UV_CreateVolume()
61 * will work and we can avoid nasty little core dumps.
63 struct ubik_client *uconn_vldbP; /*Ubik connection struct */
64 extern struct ubik_client *cstruct; /*Required name for above */
67 * ------------------------ Private globals -----------------------
69 static int initDone = 0; /*Module initialized? */
70 static int NoAuthFlag = 0; /*Use -noauth? */
71 static struct rx_connection
72 *serverconns[VLDB_MAXSERVERS]; /*Connection(s) to VLDB
76 /*-----------------------------------------------------------------------
77 * static InitThisModule
80 * Set up this module, namely set up all the client state for
81 * dealing with the Volume Location Server(s), including
82 * network connections.
85 * a_noAuthFlag : Do we need authentication?
86 * a_confDir : Configuration directory to use.
87 * a_cellName : Cell we want to talk to.
90 * 0 if everything went fine, or
91 * lower-level error code otherwise.
94 * This routine will only be called once.
98 *------------------------------------------------------------------------*/
101 InitThisModule(int a_noAuthFlag, char *a_confDir, char *a_cellName)
102 { /*InitThisModule */
104 static char rn[] = "uss_vol:InitThisModule";
106 afs_int32 code; /*Return code */
107 struct afsconf_dir *tdir; /*Ptr to conf dir info */
108 struct afsconf_cell info; /*Info about chosen cell */
109 afs_int32 scIndex; /*Chosen security index */
111 struct rx_securityClass *sc; /*Generated security object */
112 afs_int32 i; /*Loop index */
115 * Only once, guys, will 'ya?
119 printf("[%s] Called multiple times!\n", rn);
120 #endif /* USS_VOL_DB */
125 * Set up our Rx environment.
128 printf("[%s] Initializing Rx environment\n", rn);
129 #endif /* USS_VOL_DB */
132 fprintf(stderr, "%s: Couldn't initialize Rx.\n", uss_whoami);
135 rx_SetRxDeadTime(50);
138 * Find out all about our configuration.
141 printf("[%s] Handling configuration info\n", rn);
142 #endif /* USS_VOL_DB */
143 tdir = afsconf_Open(a_confDir);
145 fprintf(stderr, "%s: Couldn't open configuration directory (%s).\n",
146 uss_whoami, a_confDir);
149 code = afsconf_GetCellInfo(tdir, a_cellName, AFSCONF_VLDBSERVICE, &info);
151 printf("%s: Can't find VLDB server(s) for cell %s\n", uss_whoami,
156 printf("[%s] Getting tickets if needed\n", rn);
157 #endif /* USS_VOL_DB */
159 secFlags = AFSCONF_SECOPTS_FALLBACK_NULL;
161 secFlags |= AFSCONF_SECOPTS_NOAUTH;
163 code = afsconf_PickClientSecObj(tdir, secFlags, &info, a_cellName,
164 &sc, &scIndex, NULL);
166 printf("%s: Can't create client security object\n", uss_whoami);
169 if (scIndex == RX_SECIDX_NULL && !a_noAuthFlag) {
171 "%s: Couldn't get AFS tokens, running unauthenticated.\n",
176 * Tell UV module about default authentication.
179 printf("[%s] Setting UV security: obj 0x%x, index %d\n", rn, sc, scIndex);
180 #endif /* USS_VOL_DB */
181 UV_SetSecurity(sc, scIndex);
182 if (info.numServers > VLDB_MAXSERVERS) {
183 fprintf(stderr, "%s: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
184 uss_whoami, info.numServers, VLDB_MAXSERVERS);
189 * Connect to each VLDB server for the chosen cell.
191 for (i = 0; i < info.numServers; i++) {
194 ("[%s] Connecting to VLDB server 0x%x, port %d, service id %d\n",
195 rn, info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port,
197 #endif /* USS_VOL_DB */
199 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
200 info.hostAddr[i].sin_port, USER_SERVICE_ID, sc,
205 * Set up to execute Ubik transactions on the VLDB.
208 printf("[%s] Initializing Ubik interface\n", rn);
209 #endif /* USS_VOL_DB */
210 code = ubik_ClientInit(serverconns, &uconn_vldbP);
212 fprintf(stderr, "%s: Ubik client init failed.\n", uss_whoami);
216 printf("[%s] VLDB ubik connection structure at 0x%x\n", rn, uconn_vldbP);
217 #endif /* USS_VOL_DB */
220 * Place the ubik VLDB connection structure in its advertised
223 cstruct = uconn_vldbP;
231 } /*InitThisModule */
234 /*-----------------------------------------------------------------------
235 * static HostIDToHostName
238 * Given a host ID (in network byte order), figure out the
239 * corresponding host name.
242 * a_hostID : Host ID in network byte order.
243 * a_hostName : Ptr to host name buffer.
249 * This routine simply calls the hostutil_GetNameByINet()
250 * function exported by the utility library (util.a).
254 *------------------------------------------------------------------------*/
257 HostIDToHostName(afs_int32 a_hostID, char *a_hostName)
258 { /*HostIDToHostName */
260 strcpy(a_hostName, hostutil_GetNameByINet(a_hostID));
262 } /*HostIDToHostName */
265 /*-----------------------------------------------------------------------
266 * static PartIDToPartName
269 * Given a partition ID (in network byte order), figure out the
270 * corresponding partition name.
273 * a_partID : Partition ID in network byte order.
274 * a_partName : Ptr to partition name buffer.
277 * 0 if everything went well, or
278 * -1 if the given partition ID couldn't be translated.
281 * Nothing interesting.
285 *------------------------------------------------------------------------*/
288 PartIDToPartName(afs_int32 a_partID, char *a_partName)
289 { /*PartIDToPartName */
291 static char rn[] = "PartIDToPartName";
294 printf("[%s] Translating partition id %d to its name\n", rn, a_partID);
295 #endif /* USS_VOL_DB */
297 if ((a_partID < 0) || (a_partID > VOLMAXPARTS))
301 strcpy(a_partName, "/vicep");
302 a_partName[6] = a_partID + 'a';
303 a_partName[7] = '\0';
305 strcpy(a_partName, "/vicep");
307 a_partName[6] = 'a' + (a_partID / 26);
308 a_partName[7] = 'a' + (a_partID % 26);
309 a_partName[8] = '\0';
313 printf("[%s] Translation for part ID %d is '%s'\n", rn, a_partID,
315 #endif /* USS_VOL_DB */
318 } /*PartIDToPartName */
321 /*------------------------------------------------------------------------
322 * EXPORTED uss_Vol_GetServer
325 * Nothing interesting.
329 *------------------------------------------------------------------------*/
332 uss_vol_GetServer(char *a_name)
333 { /*uss_vol_GetServer */
337 afs_int32 b1, b2, b3, b4;
340 code = sscanf(a_name, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
343 * Parsed as 128.2.9.4, or similar; return it in network
344 * byte order (128 in byte 0).
346 addr = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
350 th = gethostbyname(a_name);
353 memcpy(&addr, th->h_addr, sizeof(addr));
356 } /*uss_vol_GetServer */
358 /*------------------------------------------------------------------------
359 * EXPORTED uss_Vol_GetPartitionID
362 * It is assumed that partition names may begin with ``/vicep''.
366 *------------------------------------------------------------------------*/
369 uss_vol_GetPartitionID(char *a_name)
370 { /*uss_vol_GetPartitionID */
380 * Numbers go straight through.
382 if (tc >= '0' && tc <= '9') {
383 return (atoi(a_name));
387 * Otherwise, check for vicepa or /vicepa, or just plain "a"
390 if (strlen(a_name) <= 2) {
391 strcpy(ascii, a_name);
392 } else if (!strncmp(a_name, "/vicep", 6)) {
393 strncpy(ascii, a_name + 6, 2);
394 } else if (!strncmp(a_name, "vicep", 5)) {
395 strncpy(ascii, a_name + 5, 2);
400 * Now, partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab,
401 * .../vicepzz, and are numbered from 0. Do the appropriate conversion.
405 * Single-char name, 0..25
407 if (ascii[0] < 'a' || ascii[0] > 'z')
408 return (-1); /* wrongo */
409 return (ascii[0] - 'a');
412 * Two-char name, 26 .. <whatever>
414 if (ascii[0] < 'a' || ascii[0] > 'z')
416 if (ascii[1] < 'a' || ascii[1] > 'z')
418 return ((ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26);
420 } /*uss_vol_GetPartitionID */
423 /*-----------------------------------------------------------------------
424 * static CheckDoubleMount
427 * Make sure we're not trying to mount a volume in the same place
431 * a_mp : Mountpoint pathname to check.
432 * a_oldmp : Ptr to buffer into which the old value of the
433 * mountpoint is placed (if any).
436 * 0 if the volume was not previously mounted.
437 * uss_procs_ANCIENT if there was already a mountpoint AND the
438 * user was already recorded in the password
440 * uss_procs_YOUNG if there was a mountpoint for the user taken
441 * from the directory pool, yet the user was not
442 * yet in the password file.
445 * Nothing interesting.
448 * May fill in the a_oldmp buffer with the value of the old
450 *------------------------------------------------------------------------*/
453 CheckDoubleMount(char *a_mp, char *a_oldmp)
454 { /*CheckDoubleMount */
457 static char rn[] = "uss_vol:CheckDoubleMount";
459 int start, len, mlen, tlen;
464 pws = getpwuid(atoi(uss_Uid));
467 * User exists in the password file, so they've been fully
468 * created and integrated. Return the ``ancient'' mountpoint.
470 strcpy(a_oldmp, pws->pw_dir);
471 return (uss_procs_ANCIENT);
476 * $AUTO used. Search among the possible directories.
478 len = strlen(uss_Auto);
480 while (strncmp(&a_mp[i], uss_Auto, len)) {
481 a_oldmp[i] = a_mp[i];
482 if (++i > (mlen - len)) {
487 if ((start = i) != -1) {
489 * $AUTO used in mountpoint.
491 for (i = 0; i < uss_NumGroups; i++) {
493 * Copy in the base and tail components.
495 tlen = strlen(uss_DirPool[i]);
496 strncpy(&a_oldmp[start], uss_DirPool[i], tlen);
497 strcpy(&a_oldmp[start + tlen], &a_mp[start + len]);
499 printf("%s: Checking '%s' for mount point\n", rn, a_oldmp);
500 #endif /* USS_VOL_DB */
501 if (lstat(a_oldmp, &stbuf) == 0) /*mp exists */
502 if (strcmp(a_oldmp, a_mp))
503 /* and is different */
505 * The old mount point exists and is different
506 * from the current one, so return the fact
507 * that we have a ``young'' mountpoint.
509 return (uss_procs_YOUNG);
510 } /*Check each $AUTO directory */
514 /*$AUTO has been used */
516 * No luck finding the old mount point, so we just return that
517 * this is the first time we've seen this volume.
521 } /*CheckDoubleMount */
524 /*------------------------------------------------------------------------
525 * EXPORTED uss_vol_CreateVol
528 * Called from the code generated by the uss grammar.
532 *------------------------------------------------------------------------*/
535 uss_vol_CreateVol(char *a_volname, char *a_server, char *a_partition,
536 char *a_quota, char *a_mpoint, char *a_owner,
538 { /*uss_vol_CreateVol */
540 static char rn[] = "uss_vol_CreateVol"; /*Routine name */
542 afs_int32 pname; /*Partition name */
543 afs_uint32 volid; /*Volume ID */
544 afs_int32 code; /*return code */
545 afs_int32 saddr; /*Socket info for server */
546 int VolExistFlag = 0; /*Does the volume exist? */
547 int mpExistFlag = 0; /*Does the mountpoint exist? */
548 char *Oldmpoint = NULL; /*Old mountpoint name, if any */
549 char tmp_str[uss_MAX_SIZE]; /*Useful string buffer */
550 int o; /*Owner's user id */
551 int checkch, ch; /*Read user's confirmation input */
552 struct uss_subdir *new_dir; /*Used to remember original ACL */
555 * Don't do anything if there's already a problem.
561 fprintf(stderr, "%s:uss_vol_CreateVol params:\n", rn);
563 "%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
564 rn, a_volname, a_server, a_partition, a_quota, a_mpoint, a_owner,
566 #endif /* USS_VOL_DB */
569 * All of the parameters passed in are taken from the template
570 * file. Override these values if the user has explicitly set
571 * them, namely if the uss commons have non-null strings.
573 if (uss_Server[0] != '\0') {
574 #ifdef USS_VOL_DB_SHOW_OVERRIDES
577 "%s: Overriding server field: template value is '%s', overridden to '%s'\n",
578 rn, a_server, uss_Server);
579 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
580 a_server = uss_Server;
583 if (uss_Partition[0] != '\0') {
584 #ifdef USS_VOL_DB_SHOW_OVERRIDES
587 "%s: Overriding partition field: template value is '%s', overridden to '%s'\n",
588 rn, a_partition, uss_Partition);
589 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
590 a_partition = uss_Partition;
593 if (uss_MountPoint[0] != '\0') {
594 #ifdef USS_VOL_DB_SHOW_OVERRIDES
597 "%s: overriding mountpoint field: template value is '%s', overridden to '%s'\n",
598 rn, a_mpoint, uss_MountPoint);
599 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
600 a_mpoint = uss_MountPoint;
602 #ifdef USS_VOL_DB_SHOW_OVERRIDES
603 printf("%s: Params after overrides:\n", uss_whoami);
605 ("%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
606 uss_whoami, a_volname, a_server, a_partition, a_quota, a_mpoint,
608 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
612 "Creating volume '%s' on server '%s', partition '%s'\n",
613 a_volname, a_server, a_partition);
615 saddr = uss_vol_GetServer(a_server);
617 uss_procs_PrintErr(line,
618 "File server '%s' not found in config info\n",
622 pname = uss_vol_GetPartitionID(a_partition);
624 uss_procs_PrintErr(line, "Couldn't interpret partition name '%s'\n",
630 * Make sure our VLDB connection(s) is/are set up before actually
631 * trying to perform a volume creation creation.
634 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
636 afs_com_err(uss_whoami, code,
637 "while inititializing VLDB connection(s)\n");
641 /*Initialize VLDB connection(s) */
644 printf("%s: Creating volume on srv 0x%x, part %d, vol name '%s'\n",
645 rn, saddr, pname, a_volname);
646 #endif /* USS_VOL_DB */
647 code = UV_CreateVolume(saddr, pname, a_volname, &volid);
649 if (code == VL_NAMEEXIST) {
652 "%s: Warning; Volume '%s' exists, using existing one.\n",
653 uss_whoami, a_volname);
656 * We should get the volid here if we want to use it, but
657 * we don't need it right now. What we DO need, though, is
658 * to ask our caller if it's OK to overwrite the user's files
659 * if they're pre-existing.
661 if (!uss_OverwriteThisOne) {
663 ("Overwrite files in pre-existing '%s' volume? [y, n]: ",
667 checkch = ch = getchar();
668 while (ch != '\n' && ch != EOF)
670 if (checkch == 'y' || checkch == 'Y') {
671 printf("\t[Overwriting allowed]\n");
672 uss_OverwriteThisOne = 1;
674 printf("\t[Overwriting not permitted]\n");
675 } /*Overwriting not previously allowed */
676 } /*Volume already existed */
678 uss_procs_PrintErr(line,
679 "Couldn't create volume '%s' [error %d]: %s\n",
680 a_volname, code, strerror(errno));
682 } /*Failure was NOT because it already existed */
683 } /*UV_CreateVolume failed */
687 "\t[Dry run: Creating volume '%s' on '%s', partition '%s']\n",
688 a_volname, a_server, a_partition);
691 /* OK, we want to make sure we don't double-mount the volume.
692 * If the volume existed, it can be the case that it is
693 * already mounted somewhere else (because of $AUTO or others).
694 * Let's check for that. Note: we never enter this portion of
695 * the code if we're doing a dry run.
698 if ((Oldmpoint = malloc(strlen(a_mpoint) + 50)) == NULL) {
699 fprintf(stderr, "%s: No more memory!\n", uss_whoami);
703 mpExistFlag = CheckDoubleMount(a_mpoint, Oldmpoint);
704 if (mpExistFlag == uss_procs_ANCIENT) {
706 "%s:\t*** WARNING ***; This user (%s) is already in passwd file (or equivalent). IGNORED.\n",
707 uss_whoami, uss_User);
709 uss_syntax_err = 1; /*I know, I know, it's not a SYNTAX error */
713 if (mpExistFlag == uss_procs_YOUNG) {
715 "%s: Warning; Volume '%s' is already mounted on %s. Using the existing one.\n",
716 uss_whoami, a_volname, Oldmpoint);
717 a_mpoint = Oldmpoint;
721 if (mpExistFlag == 0) {
722 extern int local_Cell;
727 sprintf(tmp_str, "#%s.", a_volname);
729 sprintf(tmp_str, "#%s:%s.", uss_Cell, a_volname);
731 if (symlink(tmp_str, a_mpoint)) {
732 if (errno == EEXIST) {
734 "%s: Warning: Mount point '%s' already exists.\n",
735 uss_whoami, a_mpoint);
738 "%s: Can't mount volume '%s' on '%s': %s\n",
739 uss_whoami, a_volname, a_mpoint, strerror(errno));
743 } /*There was already something mounted there */
747 fprintf(stderr, "\t[Dry run: Mounting '%s' at '%s']\n", tmp_str,
752 /*Mount point didn't already exist */
754 * Set the volume disk quota.
757 if ((code = uss_acl_SetDiskQuota(a_mpoint, atoi(a_quota))))
762 "\t[Dry run: Setting disk quota for '%s' to %s blocks]\n",
766 /*Copy mpoint into $MTPT for others to use */
767 strcpy(uss_MountPoint, a_mpoint);
769 o = uss_procs_GetOwner(a_owner);
771 if (chown(a_mpoint, o, -1)) {
773 "%s: Can't chown() mountpoint '%s' to owner '%s' (uid %d): %s\n",
774 uss_whoami, a_mpoint, a_owner, o, strerror(errno));
782 "\t[Dry run: chown() mountpoint '%s' to be owned by user]\n",
787 * Set the ACL on the user's home directory so that, for the duration of
788 * the account creation, only the uss_AccountCreator has any rights on the
789 * files therein. Make sure to clear this ACL to remove anyone that might
790 * already be there due to volume creation defaults. We will set this ACL
791 * properly, as well as all ACLs of future subdirectories,as the very last
792 * thing we do to the new account.
794 new_dir = malloc(sizeof(struct uss_subdir));
795 new_dir->previous = uss_currentDir;
796 new_dir->path = strdup(a_mpoint);
797 new_dir->finalACL = strdup(a_acl);
798 uss_currentDir = new_dir;
799 sprintf(tmp_str, "%s %s all", a_mpoint, uss_AccountCreator);
806 fprintf(stderr, "Setting ACL: '%s'\n", tmp_str);
807 if (uss_acl_SetAccess(tmp_str, 1, 0))
811 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s)]\n", tmp_str);
814 } /*uss_vol_CreateVol */
817 /*------------------------------------------------------------------------
818 * EXPORTED uss_vol_DeleteVol
821 * Nothing interesting.
825 *------------------------------------------------------------------------*/
828 uss_vol_DeleteVol(char *a_volName, afs_int32 a_volID, char *a_servName,
829 afs_int32 a_servID, char *a_partName, afs_int32 a_partID)
830 { /*uss_vol_DeleteVol */
833 static char rn[] = "uss_vol_DeleteVol"; /*Routine name */
835 afs_int32 code = 0; /*Return code */
838 * Make sure we've initialized our VLDB connection(s) before
842 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
849 * Go for the deletion.
853 ("%s: Deleting volume '%s' (ID %d) on FileServer '%s' (0x%x), partition '%s' (%d)\n",
854 rn, a_volName, a_volID, a_servName, a_servID, a_partName,
856 #endif /* USS_VOL_DB */
858 code = UV_DeleteVolume(a_servID, a_partID, a_volID);
860 printf("%s: Can't delete volume '%s'\n", uss_whoami, a_volName);
862 printf("\t[Dry run - volume '%s' NOT removed]\n", a_volName);
866 } /*uss_vol_DeleteVol */
869 /*------------------------------------------------------------------------
870 * static GetServerAndPart
873 * Given a VLDB entry, return the server and partition IDs for
874 * the read/write volume.
877 * a_vldbEntryP : Ptr to VLDB entry.
878 * a_servIDP : Ptr to server ID to set.
879 * a_partIDP : Ptr to partition ID to set.
882 * 0 if everything went well, or
886 * Nothing interesting.
890 *------------------------------------------------------------------------*/
893 GetServerAndPart(struct nvldbentry *a_vldbEntryP, afs_int32 *a_servIDP,
894 afs_int32 *a_partIDP)
895 { /*GetServerAndPart */
898 * It really looks like all we need to do is pull off the
899 * first entry's info.
901 *a_servIDP = a_vldbEntryP->serverNumber[0];
902 *a_partIDP = a_vldbEntryP->serverPartition[0];
905 } /*GetServerAndPart */
908 /*------------------------------------------------------------------------
909 * static ovlentry_to_nvlentry
912 * Converts a vldbentry to nvldbentry.
915 * oentryp IN : Ptr to vldbentry.
916 * nentryp OUT : Ptr to nvldbentry.
922 * Nothing interesting.
926 *------------------------------------------------------------------------*/
929 ovlentry_to_nvlentry(struct vldbentry *oentryp,
930 struct nvldbentry *nentryp)
934 memset(nentryp, 0, sizeof(struct nvldbentry));
935 strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
936 for (i = 0; i < oentryp->nServers; i++) {
937 nentryp->serverNumber[i] = oentryp->serverNumber[i];
938 nentryp->serverPartition[i] = oentryp->serverPartition[i];
939 nentryp->serverFlags[i] = oentryp->serverFlags[i];
941 nentryp->nServers = oentryp->nServers;
942 for (i = 0; i < MAXTYPES; i++)
943 nentryp->volumeId[i] = oentryp->volumeId[i];
944 nentryp->cloneId = oentryp->cloneId;
945 nentryp->flags = oentryp->flags;
949 /*------------------------------------------------------------------------
950 * static uss_vol_GetEntryByID
953 * Obtains a nvldbentry whether new or old forms of
954 * ubik_VL_GetEntryByID are required.
957 * cstruct : Ptr to ubik_client.
958 * volid : Volume ID for which entry is being obtained.
959 * voltype : Required volume type
960 * entryp : Ptr to nvldbentry to receive the output on success.
963 * 0 if everything went well, or
964 * ubik return code otherwise.
967 * Nothing interesting.
971 *------------------------------------------------------------------------*/
974 uss_vol_GetEntryByID(struct ubik_client *cstruct, afs_uint32 volid,
975 afs_int32 voltype, struct nvldbentry *entryp)
977 struct vldbentry oentry;
980 code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, entryp);
981 if (code == RXGEN_OPCODE) {
983 ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
985 ovlentry_to_nvlentry(&oentry, entryp);
991 /*------------------------------------------------------------------------
992 * EXPORTED uss_vol_GetVolInfoFromMountPoint
995 * If the mountpoint path provided is not
999 *------------------------------------------------------------------------*/
1002 uss_vol_GetVolInfoFromMountPoint(char *a_mountpoint)
1003 { /*uss_vol_GetVolInfoFromMountPoint */
1005 static char rn[] = "uss_vol_GetVolInfoFromMountPoint";
1007 afs_int32 code; /*Return code */
1008 uss_VolumeStatus_t *statusP; /*Ptr to returned status */
1009 afs_int32 volID; /*Volume ID */
1010 struct nvldbentry vldbEntry; /*VLDB entry for volume */
1011 afs_int32 serverID; /*Addr of host FileServer */
1012 afs_int32 partID; /*Volume's partition ID */
1015 * Set up to ask the CacheManager to give us all the info
1016 * it has about the given mountpoint.
1018 code = uss_fs_GetVolStat(a_mountpoint, uss_fs_OutBuff, USS_FS_MAX_SIZE);
1020 printf("[%s] Result of uss_fs_GetVolStat: code = %d, errno = %d\n", rn,
1022 #endif /* USS_VOL_DB */
1024 if (errno == EINVAL || errno == ENOENT || errno == ENODEV) {
1026 * We were given a mountpoint pathname that doesn't
1027 * point to a volume, or a mountpoint that has already
1028 * been deleted. This means that there is no info
1029 * to get from this pathname. Zero out the volume,
1030 * server & partition info and return successfully.
1032 uss_Volume[0] = '\0';
1033 uss_Server[0] = '\0';
1034 uss_Partition[0] = '\0';
1037 uss_PartitionID = 0;
1039 printf("%s: Warning: Mountpoint pathname '%s': ", uss_whoami,
1041 if (errno == EINVAL)
1042 printf("Volume not reachable\n");
1043 else if (errno == ENODEV)
1044 printf("No such device\n");
1046 printf("Not found\n");
1050 printf("%s: Can't get volume information from mountpoint '%s'\n",
1051 uss_whoami, a_mountpoint);
1056 /*Can't get volume status */
1058 * Pull out the volume name from the returned information and store
1059 * it in the common area. It resides right after the basic volume
1062 statusP = (uss_VolumeStatus_t *) uss_fs_OutBuff;
1063 strcpy(uss_Volume, (((char *)statusP) + sizeof(*statusP)));
1064 volID = statusP->Vid;
1065 uss_VolumeID = volID;
1067 printf("%s: Illegal volume ID: %d\n", uss_whoami, volID);
1072 * With the volume name in hand, find out where that volume
1073 * lives. Make sure our VLDB stuff has been initialized first.
1076 code = InitThisModule(NoAuthFlag, uss_ConfDir, uss_Cell);
1080 code = uss_vol_GetEntryByID( uconn_vldbP, volID, -1, &vldbEntry);
1082 printf("%s: Can't fetch VLDB entry for volume ID %d\n", uss_whoami,
1088 * Translate the given VLDB entry from network to host format, then
1089 * checking on the volume's validity. Specifically, it must be a
1090 * read/write volume and must only exist on one server.
1092 MapHostToNetwork(&vldbEntry);
1093 if (vldbEntry.volumeId[RWVOL] != volID) {
1094 printf("%s: Volume '%s' (ID %d) is not a read/write volume!!\n",
1095 uss_whoami, uss_Volume, volID);
1098 if (vldbEntry.nServers != 1) {
1099 printf("%s: Volume '%s' (ID %d) exists on multiple servers!!\n",
1100 uss_whoami, uss_Volume, volID);
1105 * Pull out the int32words containing the server and partition info
1106 * for the read/write volume.
1108 code = GetServerAndPart(&vldbEntry, &serverID, &partID);
1111 ("%s: Can't get server/partition info from VLDB entry for volume '%s' (ID %d)\n",
1112 uss_whoami, uss_Volume, volID);
1117 * Store the raw data, then translate the FileServer address to a
1118 * host name, and the partition ID to a partition name.
1120 uss_ServerID = serverID;
1121 uss_PartitionID = partID;
1122 HostIDToHostName(serverID, uss_Server);
1124 printf("[%s] Server ID 0x%x translated to '%s'\n", rn, serverID,
1126 #endif /* USS_VOL_DB */
1127 code = PartIDToPartName(partID, uss_Partition);
1129 printf("%s: Error translating partition ID %d to partition name\n",
1130 uss_whoami, partID);
1135 * We got it, home boy.
1139 } /*uss_vol_GetVolInfoFromMountPoint */