aix53-20050424
[openafs.git] / src / afsd / afsd.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11   *         Information Technology Center
12   *         October 1987
13   *
14   * Description:
15   *     The Andrew File System startup process.  It is responsible for
16   * reading and parsing the various configuration files, starting up
17   * the kernel processes required by AFS and feeding the configuration
18   * information to the kernel.
19   *
20   * Recognized flags are:
21   *     -blocks     The number of blocks available in the workstation cache.
22   *     -files      The target number of files in the workstation cache (Default:
23   *                 1000).
24   *     -rootvol            The name of the root volume to use.
25   *     -stat       The number of stat cache entries.
26   *     -hosts      List of servers to check for volume location info FOR THE
27   *                 HOME CELL.
28   *     -memcache   Use an in-memory cache rather than disk.
29   *     -cachedir    The base directory for the workstation cache.
30   *     -mountdir   The directory on which the AFS is to be mounted.
31   *     -confdir    The configuration directory .
32   *     -nosettime  Don't keep checking the time to avoid drift (default).
33   *     -settime    Keep checking the time to avoid drift.
34   *     -verbose     Be chatty.
35   *     -debug     Print out additional debugging info.
36   *     -kerndev    [OBSOLETE] The kernel device for AFS.
37   *     -dontfork   [OBSOLETE] Don't fork off as a new process.
38   *     -daemons   The number of background daemons to start (Default: 2).
39   *     -rmtsys    Also fires up an afs remote sys call (e.g. pioctl, setpag)
40   *                support daemon 
41   *     -chunksize [n]   2^n is the chunksize to be used.  0 is default.
42   *     -dcache    The number of data cache entries.
43   *     -biods     Number of bkg I/O daemons (AIX3.1 only)
44   *     -prealloc  Number of preallocated "small" memory blocks
45   *     -pininodes Number of inodes which can be spared from inode[] for 
46   *                pointing at Vfiles.  If this is set too high, you may have
47   *                system problems, which can only be ameliorated by changing
48   *                NINODE (or equivalent) and rebuilding the kernel.
49   *                This option is now disabled.
50   *     -logfile   Place where to put the logfile (default in <cache>/etc/AFSLog.
51   *     -waitclose make close calls always synchronous (slows em down, tho)
52   *     -files_per_subdir [n]   number of files per cache subdir. (def=2048)
53   *     -shutdown  Shutdown afs daemons
54   *---------------------------------------------------------------------------*/
55
56 #include <afsconfig.h>
57 #include <afs/param.h>
58
59 RCSID
60     ("$Header$");
61
62 #define VFS 1
63
64 #include <afs/cmd.h>
65
66 #include <assert.h>
67 #include <potpourri.h>
68 #include <afs/afsutil.h>
69 #include <stdlib.h>
70 #include <stdio.h>
71 #include <signal.h>
72 #include <string.h>
73 #include <stdlib.h>
74 #include <time.h>
75 #include <sys/types.h>
76 #include <sys/stat.h>
77 #include <sys/file.h>
78 #include <errno.h>
79 #include <sys/time.h>
80 #include <dirent.h>
81
82
83 #ifdef HAVE_SYS_PARAM_H
84 #include <sys/param.h>
85 #endif
86
87 #ifdef HAVE_SYS_FS_TYPES_H
88 #include <sys/fs_types.h>
89 #endif
90
91 #ifdef HAVE_SYS_MOUNT_H
92 #include <sys/mount.h>
93 #endif
94
95 #ifdef HAVE_SYS_FCNTL_H
96 #include <sys/fcntl.h>
97 #endif
98
99 #ifdef HAVE_SYS_MNTTAB_H
100 #include <sys/mnttab.h>
101 #endif
102
103 #ifdef HAVE_SYS_MNTENT_H
104 #include <sys/mntent.h>
105 #endif
106
107 #ifdef HAVE_MNTENT_H
108 #include <mntent.h>
109 #endif
110
111 #ifdef HAVE_SYS_MOUNT_H
112 #include <sys/mount.h>
113 #endif
114
115 #ifdef HAVE_SYS_VFS_H
116 #include <sys/vfs.h>
117 #endif
118
119 #ifdef HAVE_SYS_FSTYP_H
120 #include <sys/fstyp.h>
121 #endif
122
123 #ifdef HAVE_UNISTD_H
124 #include <unistd.h>
125 #endif
126
127 #ifdef HAVE_FCNTL_H
128 #include <fcntl.h>
129 #endif
130
131 #include <netinet/in.h>
132 #include <afs/afs_args.h>
133 #include <afs/cellconfig.h>
134 #include <afs/auth.h>
135 #include <ctype.h>
136 #include <afs/afssyscalls.h>
137 #include <afs/afsutil.h>
138
139 #ifdef AFS_SGI61_ENV
140 #include <unistd.h>
141 #include <libelf.h>
142 #include <dwarf.h>
143 #include <libdwarf.h>
144 void set_staticaddrs(void);
145 #endif /* AFS_SGI61_ENV */
146 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
147 #include <sym.h>
148 #include <symconst.h>
149 #endif
150 #ifdef AFS_SGI65_ENV
151 #include <sched.h>
152 #endif
153 #ifdef AFS_LINUX20_ENV
154 #include <sys/resource.h>
155 #endif
156 #ifdef AFS_DARWIN_ENV
157 #include <mach/mach.h>
158 /* Symbols from the DiskArbitration framework */
159 kern_return_t DiskArbStart(mach_port_t *);
160 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
161                                                          char *);
162 #define DISK_ARB_NETWORK_DISK_FLAG 8
163 #endif /* AFS_DARWIN_ENV */
164
165 #ifndef MOUNT_AFS
166 #define MOUNT_AFS AFS_MOUNT_AFS
167 #endif /* MOUNT_AFS */
168
169 #if AFS_HAVE_STATVFS
170 #include <sys/statvfs.h>
171 #else
172 #if defined(AFS_SUN_ENV)
173 #include <sys/vfs.h>
174 #else
175 #if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
176 #include <sys/statfs.h>
177 #endif
178 #endif
179 #endif
180
181
182 #undef  VIRTUE
183 #undef  VICE
184
185
186 #define CACHEINFOFILE   "cacheinfo"
187 #define AFSLOGFILE      "AFSLog"
188 #define DCACHEFILE      "CacheItems"
189 #define VOLINFOFILE     "VolumeItems"
190 #define CELLINFOFILE    "CellItems"
191
192 #define MAXIPADDRS 1024
193
194 char LclCellName[64];
195
196 #define MAX_CACHE_LOOPS 4
197
198
199 /*
200  * Internet address (old style... should be updated).  This was pulled out of the old 4.2
201  * version of <netinet/in.h>, since it's still useful.
202  */
203 struct in_addr_42 {
204     union {
205         struct {
206             u_char s_b1, s_b2, s_b3, s_b4;
207         } S_un_b;
208         struct {
209             u_short s_w1, s_w2;
210         } S_un_w;
211         afs_uint32 S_addr;
212     } S_un;
213 #define s_host  S_un.S_un_b.s_b2        /* host on imp */
214 #define s_net   S_un.S_un_b.s_b1        /* network */
215 #define s_imp   S_un.S_un_w.s_w2        /* imp */
216 #define s_impno S_un.S_un_b.s_b4        /* imp # */
217 #define s_lh    S_un.S_un_b.s_b3        /* logical host */
218 };
219
220 #define mPrintIPAddr(ipaddr)  printf("[%d.%d.%d.%d] ",          \
221       ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b1,      \
222       ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b2,      \
223       ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b3,      \
224       ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b4)
225
226 /*
227  * Global configuration variables.
228  */
229 afs_int32 enable_rxbind = 0;
230 afs_int32 afs_shutdown = 0;
231 afs_int32 cacheBlocks;          /*Num blocks in the cache */
232 afs_int32 cacheFiles = 1000;    /*Optimal # of files in workstation cache */
233 afs_int32 cacheStatEntries = 300;       /*Number of stat cache entries */
234 char cacheBaseDir[1024];        /*Where the workstation AFS cache lives */
235 char confDir[1024];             /*Where the workstation AFS configuration lives */
236 char fullpn_DCacheFile[1024];   /*Full pathname of DCACHEFILE */
237 char fullpn_VolInfoFile[1024];  /*Full pathname of VOLINFOFILE */
238 char fullpn_CellInfoFile[1024]; /*Full pathanem of CELLINFOFILE */
239 char fullpn_AFSLogFile[1024];   /*Full pathname of AFSLOGFILE */
240 char fullpn_CacheInfo[1024];    /*Full pathname of CACHEINFO */
241 char fullpn_VFile[1024];        /*Full pathname of data cache files */
242 char *vFilePtr;                 /*Ptr to the number part of above pathname */
243 int sawCacheMountDir = 0;       /* from cmd line */
244 int sawCacheBaseDir = 0;
245 int sawCacheBlocks = 0;
246 int sawDCacheSize = 0;
247 int sawBiod = 0;
248 char cacheMountDir[1024];       /*Mount directory for AFS */
249 char rootVolume[64] = "root.afs";       /*AFS root volume name */
250 afs_int32 cacheSetTime = FALSE; /*Keep checking time to avoid drift? */
251 afs_int32 isHomeCell;           /*Is current cell info for the home cell? */
252 #ifdef AFS_XBSD_ENV
253 int createAndTrunc = O_RDWR | O_CREAT | O_TRUNC;        /*Create & truncate on open */
254 #else
255 int createAndTrunc = O_CREAT | O_TRUNC; /*Create & truncate on open */
256 #endif
257 int ownerRWmode = 0600;         /*Read/write OK by owner */
258 static int filesSet = 0;        /*True if number of files explicitly set */
259 static int nFilesPerDir = 2048; /* # files per cache dir */
260 static int nDaemons = 2;        /* Number of background daemons */
261 static int chunkSize = 0;       /* 2^chunkSize bytes per chunk */
262 static int dCacheSize = 300;    /* # of dcache entries */
263 static int vCacheSize = 50;     /* # of volume cache entries */
264 static int rootVolSet = 0;      /*True if root volume name explicitly set */
265 int addrNum;                    /*Cell server address index being printed */
266 static int cacheFlags = 0;      /*Flags to cache manager */
267 static int nBiods = 5;          /* AIX3.1 only */
268 static int preallocs = 400;     /* Def # of allocated memory blocks */
269 static int enable_peer_stats = 0;       /* enable rx stats */
270 static int enable_process_stats = 0;    /* enable rx stats */
271 #ifdef AFS_AFSDB_ENV
272 static int enable_afsdb = 0;    /* enable AFSDB support */
273 #endif
274 static int enable_dynroot = 0;  /* enable dynroot support */
275 static int enable_fakestat = 0; /* enable fakestat support */
276 static int enable_backuptree = 0;       /* enable backup tree support */
277 static int enable_nomount = 0;  /* do not mount */
278 #ifdef notdef
279 static int inodes = 60;         /* VERY conservative, but has to be */
280 #endif
281 int afsd_verbose = 0;           /*Are we being chatty? */
282 int afsd_debug = 0;             /*Are we printing debugging info? */
283 int afsd_CloseSynch = 0;        /*Are closes synchronous or not? */
284
285 #ifdef AFS_SGI62_ENV
286 #define AFSD_INO_T ino64_t
287 #else
288 #define AFSD_INO_T afs_uint32
289 #endif
290 struct afsd_file_list {
291     int fileNum;
292     struct afsd_file_list *next;
293 };
294 struct afsd_file_list **cache_dir_filelist = NULL;
295 int *cache_dir_list = NULL;     /* Array of cache subdirs */
296 int *dir_for_V = NULL;          /* Array: dir of each cache file.
297                                  * -1: file does not exist
298                                  * -2: file exists in top-level
299                                  * >=0: file exists in Dxxx
300                                  */
301 AFSD_INO_T *inode_for_V;        /* Array of inodes for desired
302                                  * cache files */
303 int missing_DCacheFile = 1;     /*Is the DCACHEFILE missing? */
304 int missing_VolInfoFile = 1;    /*Is the VOLINFOFILE missing? */
305 int missing_CellInfoFile = 1;   /*Is the CELLINFOFILE missing? */
306 int afsd_rmtsys = 0;            /* Default: don't support rmtsys */
307 struct afs_cacheParams cparams; /* params passed to cache manager */
308
309 static int HandleMTab();
310
311 /* ParseArgs is now obsolete, being handled by cmd */
312
313 /*------------------------------------------------------------------------------
314   * ParseCacheInfoFile
315   *
316   * Description:
317   *     Open the file containing the description of the workstation's AFS cache
318   *     and pull out its contents.  The format of this file is as follows:
319   *
320   *         cacheMountDir:cacheBaseDir:cacheBlocks
321   *
322   * Arguments:
323   *     None.
324   *
325   * Returns:
326   *     0 if everything went well,
327   *     1 otherwise.
328   *
329   * Environment:
330   *     Nothing interesting.
331   *
332   *  Side Effects:
333   *     Sets globals.
334   *---------------------------------------------------------------------------*/
335
336 int ParseCacheInfoFile(void)
337 {
338     static char rn[] = "ParseCacheInfoFile";    /*This routine's name */
339     FILE *cachefd;              /*Descriptor for cache info file */
340     int parseResult;            /*Result of our fscanf() */
341     afs_int32 tCacheBlocks;
342     char tCacheBaseDir[1024], *tbd, tCacheMountDir[1024], *tmd;
343
344     if (afsd_debug)
345         printf("%s: Opening cache info file '%s'...\n", rn, fullpn_CacheInfo);
346
347     cachefd = fopen(fullpn_CacheInfo, "r");
348     if (!cachefd) {
349         printf("%s: Can't read cache info file '%s'\n", rn, fullpn_CacheInfo);
350         return (1);
351     }
352
353     /*
354      * Parse the contents of the cache info file.  All chars up to the first
355      * colon are the AFS mount directory, all chars to the next colon are the
356      * full path name of the workstation cache directory and all remaining chars
357      * represent the number of blocks in the cache.
358      */
359     tCacheMountDir[0] = tCacheBaseDir[0] = '\0';
360     parseResult =
361         fscanf(cachefd, "%1024[^:]:%1024[^:]:%d", tCacheMountDir,
362                tCacheBaseDir, &tCacheBlocks);
363
364     /*
365      * Regardless of how the parse went, we close the cache info file.
366      */
367     fclose(cachefd);
368
369     if (parseResult == EOF || parseResult < 3) {
370         printf("%s: Format error in cache info file!\n", rn);
371         if (parseResult == EOF)
372             printf("\tEOF encountered before any field parsed.\n");
373         else
374             printf("\t%d out of 3 fields successfully parsed.\n",
375                    parseResult);
376
377         return (1);
378     }
379
380     for (tmd = tCacheMountDir; *tmd == '\n' || *tmd == ' ' || *tmd == '\t';
381          tmd++);
382     for (tbd = tCacheBaseDir; *tbd == '\n' || *tbd == ' ' || *tbd == '\t';
383          tbd++);
384     /* now copy in the fields not explicitly overridden by cmd args */
385     if (!sawCacheMountDir)
386         strcpy(cacheMountDir, tmd);
387     if (!sawCacheBaseDir)
388         strcpy(cacheBaseDir, tbd);
389     if (!sawCacheBlocks)
390         cacheBlocks = tCacheBlocks;
391
392     if (afsd_debug) {
393         printf("%s: Cache info file successfully parsed:\n", rn);
394         printf
395             ("\tcacheMountDir: '%s'\n\tcacheBaseDir: '%s'\n\tcacheBlocks: %d\n",
396              tmd, tbd, tCacheBlocks);
397     }
398     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
399         return(PartSizeOverflow(tbd, cacheBlocks));
400     }
401
402     return (0);
403 }
404
405 /*
406  * All failures to open the partition are ignored. Also if the cache dir 
407  * isn't a mounted partition it's also ignored since we can't guarantee 
408  * what will be stored afterwards. Too many if's. This is now purely
409  * advisory. ODS with over 2G partition also gives warning message.
410  *
411  * Returns:
412  *      0 if everything went well,
413  *      1 otherwise.
414  */
415 int PartSizeOverflow(char *path, int cs)
416 {
417     int bsize = -1, totalblks, mint;
418 #if AFS_HAVE_STATVFS
419     struct statvfs statbuf;
420
421     if (statvfs(path, &statbuf) != 0) {
422         if (afsd_debug)
423             printf
424                 ("statvfs failed on %s; skip checking for adequate partition space\n",
425                  path);
426         return 0;
427     }
428     totalblks = statbuf.f_blocks;
429     bsize = statbuf.f_frsize;
430 #if AFS_AIX51_ENV
431     if(strcmp(statbuf.f_basetype, "jfs")) {
432         fprintf(stderr, "Cache filesystem '%s' must be jfs (now %s)\n",
433                 path, statbuf.f_basetype);
434         return 1;
435     }
436 #endif /* AFS_AIX51_ENV */
437
438 #else /* AFS_HAVE_STATVFS */
439     struct statfs statbuf;
440
441     if (statfs(path, &statbuf) < 0) {
442         if (afsd_debug)
443             printf
444                 ("statfs failed on %s; skip checking for adequate partition space\n",
445                  path);
446         return 0;
447     }
448     totalblks = statbuf.f_blocks;
449     bsize = statbuf.f_bsize;
450 #endif
451     if (bsize == -1)
452         return 0;               /* sucess */
453
454     /* now free and totalblks are in fragment units, but we want them in 1K units */
455     if (bsize >= 1024) {
456         totalblks *= (bsize / 1024);
457     } else {
458         totalblks /= (1024 / bsize);
459     }
460
461     mint = totalblks - ((totalblks * 5) / 100);
462     if (cs > mint) {
463         printf
464             ("Cache size (%d) must be less than 95%% of partition size (which is %d). Lower cache size\n",
465              cs, mint);
466         return 1;
467     }
468
469     return 0;
470 }
471
472 /*-----------------------------------------------------------------------------
473   * GetVFileNumber
474   *
475   * Description:
476   *     Given the final component of a filename expected to be a data cache file,
477   *     return the integer corresponding to the file.  Note: we reject names that
478   *     are not a ``V'' followed by an integer.  We also reject those names having
479   *     the right format but lying outside the range [0..cacheFiles-1].
480   *
481   * Arguments:
482   *     fname : Char ptr to the filename to parse.
483   *     max   : integer for the highest number to accept
484   *
485   * Returns:
486   *     >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
487   *     -1      otherwise.
488   *
489   * Environment:
490   *     Nothing interesting.
491   *
492   * Side Effects:
493   *     None.
494   *---------------------------------------------------------------------------*/
495
496 static int
497 doGetXFileNumber(fname, filechar, maxNum)
498      char *fname;
499      char filechar;
500      int maxNum;
501 {
502     int computedVNumber;        /*The computed file number we return */
503     int filenameLen;            /*Number of chars in filename */
504     int currDigit;              /*Current digit being processed */
505
506     /*
507      * The filename must have at least two characters, the first of which must be a ``filechar''
508      * and the second of which cannot be a zero unless the file is exactly two chars long.
509      */
510     filenameLen = strlen(fname);
511     if (filenameLen < 2)
512         return (-1);
513     if (fname[0] != filechar)
514         return (-1);
515     if ((filenameLen > 2) && (fname[1] == '0'))
516         return (-1);
517
518     /*
519      * Scan through the characters in the given filename, failing immediately if a non-digit
520      * is found.
521      */
522     for (currDigit = 1; currDigit < filenameLen; currDigit++)
523         if (isdigit(fname[currDigit]) == 0)
524             return (-1);
525
526     /*
527      * All relevant characters are digits.  Pull out the decimal number they represent.
528      * Reject it if it's out of range, otherwise return it.
529      */
530     computedVNumber = atoi(++fname);
531     if (computedVNumber < cacheFiles)
532         return (computedVNumber);
533     else
534         return (-1);
535 }
536
537 int
538 GetVFileNumber(fname, maxFile)
539      char *fname;
540      int maxFile;
541 {
542     return doGetXFileNumber(fname, 'V', maxFile);
543 }
544
545 int
546 GetDDirNumber(fname, maxDir)
547      char *fname;
548      int maxDir;
549 {
550     return doGetXFileNumber(fname, 'D', maxDir);
551 }
552
553
554 /*-----------------------------------------------------------------------------
555   * CreateCacheFile
556   *
557   * Description:
558   *     Given a full pathname for a file we need to create for the workstation AFS
559   *     cache, go ahead and create the file.
560   *
561   * Arguments:
562   *     fname : Full pathname of file to create.
563   *     statp : A pointer to a stat buffer which, if NON-NULL, will be
564   *             filled by fstat()
565   *
566   * Returns:
567   *     0   iff the file was created,
568   *     -1  otherwise.
569   *
570   * Environment:
571   *     The given cache file has been found to be missing.
572   *
573   * Side Effects:
574   *     As described.
575   *---------------------------------------------------------------------------*/
576
577 static int
578 CreateCacheSubDir(basename, dirNum)
579      char *basename;
580      int dirNum;
581 {
582     static char rn[] = "CreateCacheSubDir";     /* Routine Name */
583     char dir[1024];
584     int ret;
585
586     /* Build the new cache subdirectory */
587     sprintf(dir, "%s/D%d", basename, dirNum);
588
589     if (afsd_verbose)
590         printf("%s: Creating cache subdir '%s'\n", rn, dir);
591
592     if ((ret = mkdir(dir, 0700)) != 0) {
593         printf("%s: Can't create '%s', error return is %d (%d)\n", rn, dir,
594                ret, errno);
595         if (errno != EEXIST)
596             return (-1);
597     }
598
599     /* Mark this directory as created */
600     cache_dir_list[dirNum] = 0;
601
602     /* And return success */
603     return (0);
604 }
605
606 static int
607 MoveCacheFile(basename, fromDir, toDir, cacheFile, maxDir)
608      char *basename;
609      int fromDir, toDir, cacheFile, maxDir;
610 {
611     static char rn[] = "MoveCacheFile";
612     char from[1024], to[1024];
613     int ret;
614
615     if (cache_dir_list[toDir] < 0
616         && (ret = CreateCacheSubDir(basename, toDir))) {
617         printf("%s: Can't create directory '%s/D%d'\n", rn, basename, toDir);
618         return ret;
619     }
620
621     /* Build the from,to dir */
622     if (fromDir < 0) {
623         /* old-style location */
624         snprintf(from, sizeof(from), "%s/V%d", basename, cacheFile);
625     } else {
626         snprintf(from, sizeof(from), "%s/D%d/V%d", basename, fromDir,
627                  cacheFile);
628     }
629
630     snprintf(to, sizeof(from), "%s/D%d/V%d", basename, toDir, cacheFile);
631
632     if (afsd_verbose)
633         printf("%s: Moving cacheFile from '%s' to '%s'\n", rn, from, to);
634
635     if ((ret = rename(from, to)) != 0) {
636         printf("%s: Can't rename '%s' to '%s', error return is %d (%d)\n", rn,
637                from, to, ret, errno);
638         return -1;
639     }
640
641     /* Reset directory pointer; fix file counts */
642     dir_for_V[cacheFile] = toDir;
643     cache_dir_list[toDir]++;
644     if (fromDir < maxDir && fromDir >= 0)
645         cache_dir_list[fromDir]--;
646
647     return 0;
648 }
649
650 int
651 CreateCacheFile(fname, statp)
652      char *fname;
653      struct stat *statp;
654 {
655     static char rn[] = "CreateCacheFile";       /*Routine name */
656     int cfd;                    /*File descriptor to AFS cache file */
657     int closeResult;            /*Result of close() */
658
659     if (afsd_verbose)
660         printf("%s: Creating cache file '%s'\n", rn, fname);
661     cfd = open(fname, createAndTrunc, ownerRWmode);
662     if (cfd <= 0) {
663         printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
664                cfd, errno);
665         return (-1);
666     }
667     if (statp != NULL) {
668         closeResult = fstat(cfd, statp);
669         if (closeResult) {
670             printf
671                 ("%s: Can't stat newly-created AFS cache file '%s' (code %d)\n",
672                  rn, fname, errno);
673             return (-1);
674         }
675     }
676     closeResult = close(cfd);
677     if (closeResult) {
678         printf
679             ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
680              rn, fname, errno);
681         return (-1);
682     }
683
684     return (0);
685 }
686
687 static void
688 CreateFileIfMissing(char *fullpn, int missing)
689 {
690     if (missing) {
691         if (afsd_verbose)
692             printf("CreateFileIfMissing: Creating '%s'\n", fullpn);
693         if (CreateCacheFile(fullpn, NULL))
694             printf("CreateFileIfMissing: Can't create '%s'\n", fullpn);
695     }
696 }
697
698 /*-----------------------------------------------------------------------------
699   * SweepAFSCache
700   *
701   * Description:
702   *     Sweep through the AFS cache directory, recording the inode number for
703   *     each valid data cache file there.  Also, delete any file that doesn't belong
704   *     in the cache directory during this sweep, and remember which of the other
705   *     residents of this directory were seen.  After the sweep, we create any data
706   *     cache files that were missing.
707   *
708   * Arguments:
709   *     vFilesFound : Set to the number of data cache files found.
710   *
711   * Returns:
712   *     0   if everything went well,
713   *     -1 otherwise.
714   *
715   * Environment:
716   *     This routine may be called several times.  If the number of data cache files
717   *     found is less than the global cacheFiles, then the caller will need to call it
718   *     again to record the inodes of the missing zero-length data cache files created
719   *     in the previous call.
720   *
721   * Side Effects:
722   *     Fills up the global inode_for_V array, may create and/or delete files as
723   *     explained above.
724   *---------------------------------------------------------------------------*/
725
726
727 static int
728 doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
729      int *vFilesFound;
730      char *directory;           /* /path/to/cache/directory */
731      int dirNum;                /* current directory number */
732      int maxDir;                /* maximum directory number */
733 {
734     static char rn[] = "doSweepAFSCache";       /* Routine Name */
735     char fullpn_FileToDelete[1024];     /*File to be deleted from cache */
736     char *fileToDelete;         /*Ptr to last component of above */
737     DIR *cdirp;                 /*Ptr to cache directory structure */
738 #ifdef AFS_SGI62_ENV
739     struct dirent64 *currp;     /*Current directory entry */
740 #else
741     struct dirent *currp;       /*Current directory entry */
742 #endif
743     int vFileNum;               /*Data cache file's associated number */
744     int thisDir;                /* A directory number */
745     int highDir = 0;
746
747     if (afsd_debug)
748         printf("%s: Opening cache directory '%s'\n", rn, directory);
749
750     if (chmod(directory, 0700)) {       /* force it to be 700 */
751         printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
752                directory);
753         return (-1);
754     }
755     cdirp = opendir(directory);
756     if (cdirp == (DIR *) 0) {
757         printf("%s: Can't open AFS cache directory, '%s'.\n", rn, directory);
758         return (-1);
759     }
760
761     /*
762      * Scan the directory entries, remembering data cache file inodes
763      * and the existance of other important residents.  Recurse into
764      * the data subdirectories.
765      *
766      * Delete all files and directories that don't belong here.
767      */
768     sprintf(fullpn_FileToDelete, "%s/", directory);
769     fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
770
771 #ifdef AFS_SGI62_ENV
772     for (currp = readdir64(cdirp); currp; currp = readdir64(cdirp))
773 #else
774     for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
775 #endif
776     {
777         if (afsd_debug) {
778             printf("%s: Current directory entry:\n", rn);
779 #ifdef AFS_SGI62_ENV
780             printf("\tinode=%lld, reclen=%d, name='%s'\n", currp->d_ino,
781                    currp->d_reclen, currp->d_name);
782 #else
783             printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
784                    currp->d_reclen, currp->d_name);
785 #endif
786         }
787
788         /*
789          * If dirNum < 0, we are a top-level cache directory and should
790          * only contain sub-directories and other sundry files.  Therefore,
791          * V-files are valid only if dirNum >= 0, and Directories are only
792          * valid if dirNum < 0.
793          */
794
795         if (*(currp->d_name) == 'V'
796             && ((vFileNum = GetVFileNumber(currp->d_name, cacheFiles)) >=
797                 0)) {
798             /*
799              * Found a valid data cache filename.  Remember this
800              * file's inode, directory, and bump the number of files found
801              * total and in this directory.
802              */
803             inode_for_V[vFileNum] = currp->d_ino;
804             dir_for_V[vFileNum] = dirNum;       /* remember this directory */
805
806             if (!maxDir) {
807                 /* If we're in a real subdir, mark this file to be moved
808                  * if we've already got too many files in this directory
809                  */
810                 assert(dirNum >= 0);
811                 cache_dir_list[dirNum]++;       /* keep directory's file count */
812                 if (cache_dir_list[dirNum] > nFilesPerDir) {
813                     /* Too many files -- add to filelist */
814                     struct afsd_file_list *tmp = (struct afsd_file_list *)
815                         malloc(sizeof(*tmp));
816                     if (!tmp)
817                         printf
818                             ("%s: MALLOC FAILED allocating file_list entry\n",
819                              rn);
820                     else {
821                         tmp->fileNum = vFileNum;
822                         tmp->next = cache_dir_filelist[dirNum];
823                         cache_dir_filelist[dirNum] = tmp;
824                     }
825                 }
826             }
827             (*vFilesFound)++;
828         } else if (dirNum < 0 && (*(currp->d_name) == 'D')
829                    && GetDDirNumber(currp->d_name, 1 << 30) >= 0) {
830             int retval = 0;
831             if ((vFileNum = GetDDirNumber(currp->d_name, maxDir)) >= 0) {
832                 /* Found a valid cachefile sub-Directory.  Remember this number
833                  * and recurse into it.  Note that subdirs cannot have subdirs.
834                  */
835                 retval = 1;
836             } else if ((vFileNum = GetDDirNumber(currp->d_name, 1 << 30)) >=
837                        0) {
838                 /* This directory is going away, but figure out if there
839                  * are any cachefiles in here that should be saved by
840                  * moving them to other cache directories.  This directory
841                  * will be removed later.
842                  */
843                 retval = 2;
844             }
845
846             /* Save the highest directory number we've seen */
847             if (vFileNum > highDir)
848                 highDir = vFileNum;
849
850             /* If this directory is staying, be sure to mark it as 'found' */
851             if (retval == 1)
852                 cache_dir_list[vFileNum] = 0;
853
854             /* Print the dirname for recursion */
855             sprintf(fileToDelete, "%s", currp->d_name);
856
857             /* Note: vFileNum is the directory number */
858             retval =
859                 doSweepAFSCache(vFilesFound, fullpn_FileToDelete, vFileNum,
860                                 (retval == 1 ? 0 : -1));
861             if (retval) {
862                 printf("%s: Recursive sweep failed on directory %s\n", rn,
863                        currp->d_name);
864                 return retval;
865             }
866         } else if (dirNum < 0 && strcmp(currp->d_name, DCACHEFILE) == 0) {
867             /*
868              * Found the file holding the dcache entries.
869              */
870             missing_DCacheFile = 0;
871         } else if (dirNum < 0 && strcmp(currp->d_name, VOLINFOFILE) == 0) {
872             /*
873              * Found the file holding the volume info.
874              */
875             missing_VolInfoFile = 0;
876         } else if (dirNum < 0 && strcmp(currp->d_name, CELLINFOFILE) == 0) {
877             /*
878              * Found the file holding the cell info.
879              */
880             missing_CellInfoFile = 0;
881         } else if ((strcmp(currp->d_name, ".") == 0)
882                    || (strcmp(currp->d_name, "..") == 0) ||
883 #ifdef AFS_DECOSF_ENV
884                    /* these are magic AdvFS files */
885                    (strcmp(currp->d_name, ".tags") == 0)
886                    || (strcmp(currp->d_name, "quota.user") == 0)
887                    || (strcmp(currp->d_name, "quota.group") == 0) ||
888 #endif
889 #ifdef AFS_LINUX22_ENV
890                    /* this is the ext3 journal file */
891                    (strcmp(currp->d_name, ".journal") == 0) ||
892 #endif
893                    (strcmp(currp->d_name, "lost+found") == 0)) {
894             /*
895              * Don't do anything - this file is legit, and is to be left alone.
896              */
897         } else {
898             /*
899              * This file/directory doesn't belong in the cache.  Nuke it.
900              */
901             sprintf(fileToDelete, "%s", currp->d_name);
902             if (afsd_verbose)
903                 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
904             if (unlink(fullpn_FileToDelete)) {
905                 if (errno == EISDIR && *fileToDelete == 'D') {
906                     if (rmdir(fullpn_FileToDelete)) {
907                         printf("%s: Can't rmdir '%s', errno is %d\n", rn,
908                                fullpn_FileToDelete, errno);
909                     }
910                 } else
911                     printf("%s: Can't unlink '%s', errno is %d\n", rn,
912                            fullpn_FileToDelete, errno);
913             }
914         }
915     }
916
917     if (dirNum < 0) {
918
919         /*
920          * Create all the cache files that are missing.
921          */
922         CreateFileIfMissing(fullpn_DCacheFile, missing_DCacheFile);
923         CreateFileIfMissing(fullpn_VolInfoFile, missing_VolInfoFile);
924         CreateFileIfMissing(fullpn_CellInfoFile, missing_CellInfoFile);
925
926         /* ADJUST CACHE FILES */
927
928         /* First, let's walk through the list of files and figure out
929          * if there are any leftover files in extra directories or
930          * missing files.  Move the former and create the latter in
931          * subdirs with extra space.
932          */
933
934         thisDir = 0;            /* Keep track of which subdir has space */
935
936         for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++) {
937             if (dir_for_V[vFileNum] == -1) {
938                 /* This file does not exist.  Create it in the first
939                  * subdir that still has extra space.
940                  */
941                 while (thisDir < maxDir
942                        && cache_dir_list[thisDir] >= nFilesPerDir)
943                     thisDir++;
944                 if (thisDir >= maxDir)
945                     printf("%s: can't find directory to create V%d\n", rn,
946                            vFileNum);
947                 else {
948                     struct stat statb;
949                     assert(inode_for_V[vFileNum] == (AFSD_INO_T) 0);
950                     sprintf(vFilePtr, "D%d/V%d", thisDir, vFileNum);
951                     if (afsd_verbose)
952                         printf("%s: Creating '%s'\n", rn, fullpn_VFile);
953                     if (cache_dir_list[thisDir] < 0
954                         && CreateCacheSubDir(directory, thisDir))
955                         printf("%s: Can't create directory for '%s'\n", rn,
956                                fullpn_VFile);
957                     if (CreateCacheFile(fullpn_VFile, &statb))
958                         printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
959                     else {
960                         inode_for_V[vFileNum] = statb.st_ino;
961                         dir_for_V[vFileNum] = thisDir;
962                         cache_dir_list[thisDir]++;
963                         (*vFilesFound)++;
964                     }
965                 }
966
967             } else if (dir_for_V[vFileNum] >= maxDir
968                        || dir_for_V[vFileNum] == -2) {
969                 /* This file needs to move; move it to the first subdir
970                  * that has extra space.  (-2 means it's in the toplevel)
971                  */
972                 while (thisDir < maxDir
973                        && cache_dir_list[thisDir] >= nFilesPerDir)
974                     thisDir++;
975                 if (thisDir >= maxDir)
976                     printf("%s: can't find directory to move V%d\n", rn,
977                            vFileNum);
978                 else {
979                     if (MoveCacheFile
980                         (directory, dir_for_V[vFileNum], thisDir, vFileNum,
981                          maxDir)) {
982                         /* Cannot move.  Ignore this file??? */
983                         /* XXX */
984                     }
985                 }
986             }
987         }                       /* for */
988
989         /* At this point, we've moved all of the valid cache files
990          * into the valid subdirs, and created all the extra
991          * cachefiles we need to create.  Next, rebalance any subdirs
992          * with too many cache files into the directories with not
993          * enough cache files.  Note that thisDir currently sits at
994          * the lowest subdir that _may_ have room.
995          */
996
997         for (dirNum = 0; dirNum < maxDir; dirNum++) {
998             struct afsd_file_list *thisFile;
999
1000             for (thisFile = cache_dir_filelist[dirNum];
1001                  thisFile && cache_dir_list[dirNum] >= nFilesPerDir;
1002                  thisFile = thisFile->next) {
1003                 while (thisDir < maxDir
1004                        && cache_dir_list[thisDir] >= nFilesPerDir)
1005                     thisDir++;
1006                 if (thisDir >= maxDir)
1007                     printf("%s: can't find directory to move V%d\n", rn,
1008                            vFileNum);
1009                 else {
1010                     if (MoveCacheFile
1011                         (directory, dirNum, thisDir, thisFile->fileNum,
1012                          maxDir)) {
1013                         /* Cannot move.  Ignore this file??? */
1014                         /* XXX */
1015                     }
1016                 }
1017             }                   /* for each file to move */
1018         }                       /* for each directory */
1019
1020         /* Remove any directories >= maxDir -- they should be empty */
1021         for (; highDir >= maxDir; highDir--) {
1022             sprintf(fileToDelete, "D%d", highDir);
1023             if (unlink(fullpn_FileToDelete)) {
1024                 if (errno == EISDIR && *fileToDelete == 'D') {
1025                     if (rmdir(fullpn_FileToDelete)) {
1026                         printf("%s: Can't rmdir '%s', errno is %d\n", rn,
1027                                fullpn_FileToDelete, errno);
1028                     }
1029                 } else
1030                     printf("%s: Can't unlink '%s', errno is %d\n", rn,
1031                            fullpn_FileToDelete, errno);
1032             }
1033         }
1034     }
1035
1036     /* dirNum < 0 */
1037     /*
1038      * Close the directory, return success.
1039      */
1040     if (afsd_debug)
1041         printf("%s: Closing cache directory.\n", rn);
1042     closedir(cdirp);
1043     return (0);
1044 }
1045
1046 char *
1047 CheckCacheBaseDir(char *dir)
1048 {
1049     struct stat statbuf;
1050
1051     if (!dir) {
1052         return "cache base dir not specified";
1053     }
1054     if (stat(dir, &statbuf) != 0) {
1055         return "unable to stat cache base directory";
1056     }
1057
1058     /* might want to check here for anything else goofy, like cache pointed at a non-dedicated directory, etc */
1059
1060 #ifdef AFS_LINUX24_ENV
1061     {
1062         int res;
1063         struct statfs statfsbuf;
1064
1065         res = statfs(dir, &statfsbuf);
1066         if (res != 0) {
1067             return "unable to statfs cache base directory";
1068         }
1069         if (statfsbuf.f_type == 0x52654973) {   /* REISERFS_SUPER_MAGIC */
1070             return "cannot use reiserfs as cache partition";
1071         } else if  (statfsbuf.f_type == 0x58465342) { /* XFS_SUPER_MAGIC */
1072             return "cannot use xfs as cache partition";
1073         }
1074     }
1075 #endif
1076
1077 #ifdef AFS_HPUX_ENV
1078     {
1079         int res;
1080         struct statfs statfsbuf;
1081         char name[FSTYPSZ];
1082
1083         res = statfs(dir, &statfsbuf);
1084         if (res != 0) {
1085             return "unable to statfs cache base directory";
1086         }
1087
1088         if (sysfs(GETFSTYP, statfsbuf.f_fsid[1], name) != 0) {
1089             return "unable to determine filesystem type for cache base dir";
1090         }
1091
1092         if (strcmp(name, "hfs")) {
1093             return "can only use hfs filesystem for cache partition on hpux";
1094         }
1095     }
1096 #endif
1097
1098 #ifdef AFS_SUN5_ENV
1099     {
1100         FILE *vfstab;
1101         struct mnttab mnt;
1102         struct stat statmnt, statci;
1103
1104         if ((stat(dir, &statci) == 0)
1105             && ((vfstab = fopen(MNTTAB, "r")) != NULL)) {
1106             while (getmntent(vfstab, &mnt) == 0) {
1107                 if (strcmp(dir, mnt.mnt_mountp) != 0) {
1108                     char *cp;
1109                     int rdev = 0;
1110
1111                     if (cp = hasmntopt(&mnt, "dev="))
1112                         rdev =
1113                             (int)strtol(cp + strlen("dev="), (char **)NULL,
1114                                         16);
1115
1116                     if ((rdev == 0) && (stat(mnt.mnt_mountp, &statmnt) == 0))
1117                         rdev = statmnt.st_dev;
1118
1119                     if ((rdev == statci.st_dev)
1120                         && (hasmntopt(&mnt, "logging") != NULL)) {
1121
1122                         fclose(vfstab);
1123                         return
1124                             "mounting a multi-use partition which contains the AFS cache with the\n\"logging\" option may deadlock your system.\n\n";
1125                     }
1126                 }
1127             }
1128
1129             fclose(vfstab);
1130         }
1131     }
1132 #endif
1133
1134     return NULL;
1135 }
1136
1137 int
1138 SweepAFSCache(vFilesFound)
1139      int *vFilesFound;
1140 {
1141     static char rn[] = "SweepAFSCache"; /*Routine name */
1142     int maxDir = (cacheFiles + nFilesPerDir - 1) / nFilesPerDir;
1143     int i;
1144
1145     *vFilesFound = 0;
1146
1147     if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1148         if (afsd_debug)
1149             printf("%s: Memory Cache, no cache sweep done\n", rn);
1150         return 0;
1151     }
1152
1153     if (cache_dir_list == NULL) {
1154         cache_dir_list = (int *)malloc(maxDir * sizeof(*cache_dir_list));
1155         if (cache_dir_list == NULL) {
1156             printf("%s: Malloc Failed!\n", rn);
1157             return (-1);
1158         }
1159         for (i = 0; i < maxDir; i++)
1160             cache_dir_list[i] = -1;     /* Does not exist */
1161     }
1162
1163     if (cache_dir_filelist == NULL) {
1164         cache_dir_filelist = (struct afsd_file_list **)
1165             malloc(maxDir * sizeof(*cache_dir_filelist));
1166         if (cache_dir_filelist == NULL) {
1167             printf("%s: Malloc Failed!\n", rn);
1168             return (-1);
1169         }
1170         memset(cache_dir_filelist, 0, maxDir * sizeof(*cache_dir_filelist));
1171     }
1172
1173     if (dir_for_V == NULL) {
1174         dir_for_V = (int *)malloc(cacheFiles * sizeof(*dir_for_V));
1175         if (dir_for_V == NULL) {
1176             printf("%s: Malloc Failed!\n", rn);
1177             return (-1);
1178         }
1179         for (i = 0; i < cacheFiles; i++)
1180             dir_for_V[i] = -1;  /* Does not exist */
1181     }
1182
1183     /* Note, setting dirNum to -2 here will cause cachefiles found in
1184      * the toplevel directory to be marked in directory "-2".  This
1185      * allows us to differentiate between 'file not seen' (-1) and
1186      * 'file seen in top-level' (-2).  Then when we try to move the
1187      * file into a subdirectory, we know it's in the top-level instead
1188      * of some other cache subdir.
1189      */
1190     return doSweepAFSCache(vFilesFound, cacheBaseDir, -2, maxDir);
1191 }
1192
1193 static
1194 ConfigCell(aci, arock, adir)
1195      register struct afsconf_cell *aci;
1196      char *arock;
1197      struct afsconf_dir *adir;
1198 {
1199     register int isHomeCell;
1200     register int i, code;
1201     afs_int32 cellFlags = 0;
1202     afs_int32 hosts[MAXHOSTSPERCELL];
1203
1204     /* figure out if this is the home cell */
1205     isHomeCell = (strcmp(aci->name, LclCellName) == 0);
1206     if (!isHomeCell)
1207         cellFlags = 2;          /* not home, suid is forbidden */
1208
1209     /* build address list */
1210     for (i = 0; i < MAXHOSTSPERCELL; i++)
1211         memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1212
1213     if (aci->linkedCell)
1214         cellFlags |= 4;         /* Flag that linkedCell arg exists,
1215                                  * for upwards compatibility */
1216
1217     /* configure one cell */
1218     code = call_syscall(AFSOP_ADDCELL2, hosts,  /* server addresses */
1219                         aci->name,      /* cell name */
1220                         cellFlags,      /* is this the home cell? */
1221                         aci->linkedCell);       /* Linked cell, if any */
1222     if (code)
1223         printf("Adding cell '%s': error %d\n", aci->name, code);
1224     return 0;
1225 }
1226
1227 static
1228 ConfigCellAlias(aca, arock, adir)
1229      register struct afsconf_cellalias *aca;
1230      char *arock;
1231      struct afsconf_dir *adir;
1232 {
1233     /* push the alias into the kernel */
1234     call_syscall(AFSOP_ADDCELLALIAS, aca->aliasName, aca->realName);
1235     return 0;
1236 }
1237
1238 #ifdef AFS_AFSDB_ENV
1239 static
1240 AfsdbLookupHandler()
1241 {
1242     afs_int32 kernelMsg[64];
1243     char acellName[128];
1244     afs_int32 code;
1245     struct afsconf_cell acellInfo;
1246     int i;
1247
1248     kernelMsg[0] = 0;
1249     kernelMsg[1] = 0;
1250     acellName[0] = '\0';
1251
1252     while (1) {
1253         /* On some platforms you only get 4 args to an AFS call */
1254         int sizeArg = ((sizeof acellName) << 16) | (sizeof kernelMsg);
1255         code =
1256             call_syscall(AFSOP_AFSDB_HANDLER, acellName, kernelMsg, sizeArg);
1257         if (code) {             /* Something is wrong? */
1258             sleep(1);
1259             continue;
1260         }
1261
1262         if (*acellName == 1)    /* Shutting down */
1263             break;
1264
1265         code = afsconf_GetAfsdbInfo(acellName, 0, &acellInfo);
1266         if (code) {
1267             kernelMsg[0] = 0;
1268             kernelMsg[1] = 0;
1269         } else {
1270             kernelMsg[0] = acellInfo.numServers;
1271             if (acellInfo.timeout)
1272                 kernelMsg[1] = acellInfo.timeout - time(0);
1273             else
1274                 kernelMsg[1] = 0;
1275             for (i = 0; i < acellInfo.numServers; i++)
1276                 kernelMsg[i + 2] = acellInfo.hostAddr[i].sin_addr.s_addr;
1277             strncpy(acellName, acellInfo.name, sizeof(acellName));
1278             acellName[sizeof(acellName) - 1] = '\0';
1279         }
1280     }
1281
1282     exit(1);
1283 }
1284 #endif
1285
1286 #ifdef mac2
1287 #include <sys/ioctl.h>
1288 #endif /* mac2 */
1289
1290 #ifdef AFS_SGI65_ENV
1291 #define SET_RTPRI(P) {  \
1292     struct sched_param sp; \
1293     sp.sched_priority = P; \
1294     if (sched_setscheduler(0, SCHED_RR, &sp)<0) { \
1295         perror("sched_setscheduler"); \
1296     } \
1297 }
1298 #define SET_AFSD_RTPRI() SET_RTPRI(68)
1299 #define SET_RX_RTPRI()   SET_RTPRI(199)
1300 #else
1301 #ifdef AFS_LINUX20_ENV
1302 #define SET_AFSD_RTPRI()
1303 #define SET_RX_RTPRI()  do { if (setpriority(PRIO_PROCESS, 0, -10)<0) \
1304                            perror("setting rx priority"); \
1305                          } while (0)
1306 #else
1307 #define SET_AFSD_RTPRI()
1308 #define SET_RX_RTPRI()
1309 #endif
1310 #endif
1311
1312 mainproc(as, arock)
1313      struct cmd_syndesc *as;
1314      char *arock;
1315 {
1316     static char rn[] = "afsd";  /*Name of this routine */
1317     register afs_int32 code;    /*Result of fork() */
1318     register int i;
1319     int currVFile;              /*Current AFS cache file number passed in */
1320     int mountFlags;             /*Flags passed to mount() */
1321     int lookupResult;           /*Result of GetLocalCellName() */
1322     int cacheIteration;         /*How many times through cache verification */
1323     int vFilesFound;            /*How many data cache files were found in sweep */
1324     struct afsconf_dir *cdir;   /* config dir */
1325     FILE *logfd;
1326     char *fsTypeMsg = NULL;
1327 #ifdef  AFS_SUN5_ENV
1328     struct stat st;
1329 #endif
1330     afs_int32 vfs1_type = -1;
1331 #ifdef AFS_SGI65_ENV
1332     struct sched_param sp;
1333 #endif
1334
1335 #ifdef AFS_SGI_VNODE_GLUE
1336     if (afs_init_kernel_config(-1) < 0) {
1337         printf("Can't determine NUMA configuration, not starting AFS.\n");
1338         exit(1);
1339     }
1340 #endif
1341
1342     /* call atoi on the appropriate parsed results */
1343     if (as->parms[0].items) {
1344         /* -blocks */
1345         cacheBlocks = atoi(as->parms[0].items->data);
1346         sawCacheBlocks = 1;
1347     }
1348     if (as->parms[1].items) {
1349         /* -files */
1350         cacheFiles = atoi(as->parms[1].items->data);
1351         filesSet = 1;           /* set when spec'd on cmd line */
1352     }
1353     if (as->parms[2].items) {
1354         /* -rootvol */
1355         strcpy(rootVolume, as->parms[2].items->data);
1356         rootVolSet = 1;
1357     }
1358     if (as->parms[3].items) {
1359         /* -stat */
1360         cacheStatEntries = atoi(as->parms[3].items->data);
1361     }
1362     if (as->parms[4].items) {
1363         /* -memcache */
1364         cacheBaseDir[0] = '\0';
1365         sawCacheBaseDir = 1;
1366         cacheFlags |= AFSCALL_INIT_MEMCACHE;
1367         if (chunkSize == 0)
1368             chunkSize = 13;
1369     }
1370     if (as->parms[5].items) {
1371         /* -cachedir */
1372         strcpy(cacheBaseDir, as->parms[5].items->data);
1373         sawCacheBaseDir = 1;
1374     }
1375     if (as->parms[6].items) {
1376         /* -mountdir */
1377         strcpy(cacheMountDir, as->parms[6].items->data);
1378         sawCacheMountDir = 1;
1379     }
1380     if (as->parms[7].items) {
1381         /* -daemons */
1382         nDaemons = atoi(as->parms[7].items->data);
1383     }
1384     if (as->parms[8].items) {
1385         /* -nosettime */
1386         cacheSetTime = FALSE;
1387     }
1388     if (as->parms[9].items) {
1389         /* -verbose */
1390         afsd_verbose = 1;
1391     }
1392     if (as->parms[10].items) {
1393         /* -rmtsys */
1394         afsd_rmtsys = 1;
1395     }
1396     if (as->parms[11].items) {
1397         /* -debug */
1398         afsd_debug = 1;
1399         afsd_verbose = 1;
1400     }
1401     if (as->parms[12].items) {
1402         /* -chunksize */
1403         chunkSize = atoi(as->parms[12].items->data);
1404         if (chunkSize < 0 || chunkSize > 30) {
1405             printf("afsd:invalid chunk size (not in range 0-30), using default\n");
1406             chunkSize = 0;
1407         }
1408     }
1409     if (as->parms[13].items) {
1410         /* -dcache */
1411         dCacheSize = atoi(as->parms[13].items->data);
1412         sawDCacheSize = 1;
1413     }
1414     if (as->parms[14].items) {
1415         /* -volumes */
1416         vCacheSize = atoi(as->parms[14].items->data);
1417     }
1418     if (as->parms[15].items) {
1419         /* -biods */
1420 #ifndef AFS_AIX32_ENV
1421         printf
1422             ("afsd: [-biods] currently only enabled for aix3.x VM supported systems\n");
1423 #else
1424         nBiods = atoi(as->parms[15].items->data);
1425         sawBiod = 1;
1426 #endif
1427     }
1428     if (as->parms[16].items) {
1429         /* -prealloc */
1430         preallocs = atoi(as->parms[16].items->data);
1431     }
1432 #ifdef notdef
1433     if (as->parms[17].items) {
1434         /* -pininodes */
1435         inodes = atoi(as->parms[17].items->data);
1436     }
1437 #endif
1438     strcpy(confDir, AFSDIR_CLIENT_ETC_DIRPATH);
1439     if (as->parms[17].items) {
1440         /* -confdir */
1441         strcpy(confDir, as->parms[17].items->data);
1442     }
1443     sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1444     sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1445     if (as->parms[18].items) {
1446         /* -logfile */
1447         strcpy(fullpn_AFSLogFile, as->parms[18].items->data);
1448     }
1449     if (as->parms[19].items) {
1450         /* -waitclose */
1451         afsd_CloseSynch = 1;
1452     }
1453     if (as->parms[20].items) {
1454         /* -shutdown */
1455         afs_shutdown = 1;
1456         /* 
1457          * Cold shutdown is the default
1458          */
1459         printf("afsd: Shutting down all afs processes and afs state\n");
1460         code = call_syscall(AFSOP_SHUTDOWN, 1);
1461         if (code) {
1462             printf("afsd: AFS still mounted; Not shutting down\n");
1463             exit(1);
1464         }
1465         exit(0);
1466     }
1467     if (as->parms[21].items) {
1468         /* -enable_peer_stats */
1469         enable_peer_stats = 1;
1470     }
1471     if (as->parms[22].items) {
1472         /* -enable_process_stats */
1473         enable_process_stats = 1;
1474     }
1475     if (as->parms[23].items) {
1476         /* -mem_alloc_sleep */
1477         cacheFlags |= AFSCALL_INIT_MEMCACHE_SLEEP;
1478     }
1479     if (as->parms[24].items) {
1480         /* -afsdb */
1481 #ifdef AFS_AFSDB_ENV
1482         enable_afsdb = 1;
1483 #else
1484         printf("afsd: No AFSDB support; ignoring -afsdb");
1485 #endif
1486     }
1487     if (as->parms[25].items) {
1488         /* -files_per_subdir */
1489         int res = atoi(as->parms[25].items->data);
1490         if (res < 10 || res > 2 ^ 30) {
1491             printf
1492                 ("afsd:invalid number of files per subdir, \"%s\". Ignored\n",
1493                  as->parms[25].items->data);
1494         } else {
1495             nFilesPerDir = res;
1496         }
1497     }
1498     if (as->parms[26].items) {
1499         /* -dynroot */
1500         enable_dynroot = 1;
1501     }
1502     if (as->parms[27].items) {
1503         /* -fakestat */
1504         enable_fakestat = 2;
1505     }
1506     if (as->parms[28].items) {
1507         /* -fakestat-all */
1508         enable_fakestat = 1;
1509     }
1510     if (as->parms[29].items) {
1511         /* -nomount */
1512         enable_nomount = 1;
1513     }
1514     if (as->parms[30].items) {
1515         /* -backuptree */
1516         enable_backuptree = 1;
1517     }
1518     if (as->parms[31].items) {
1519         /* -rxbind */
1520         enable_rxbind = 1;
1521     }
1522     if (as->parms[32].items) {
1523        /* -settime */
1524        cacheSetTime = TRUE;
1525     }
1526
1527     /* set rx_extraPackets */
1528     if (as->parms[33].items) {
1529         /* -rxpck */
1530         int rxpck = atoi(as->parms[33].items->data);
1531         printf("afsd: set rxpck = %d\n",rxpck);
1532         code = call_syscall(AFSOP_SET_RXPCK, rxpck);
1533         if (code) {
1534         printf("afsd: failed to set rxpck\n");
1535         exit(1);
1536         }
1537     }
1538     
1539     /*
1540      * Pull out all the configuration info for the workstation's AFS cache and
1541      * the cellular community we're willing to let our users see.
1542      */
1543     cdir = afsconf_Open(confDir);
1544     if (!cdir) {
1545         printf("afsd: some file missing or bad in %s\n", confDir);
1546         exit(1);
1547     }
1548
1549     lookupResult =
1550         afsconf_GetLocalCell(cdir, LclCellName, sizeof(LclCellName));
1551     if (lookupResult) {
1552         printf("%s: Can't get my home cell name!  [Error is %d]\n", rn,
1553                lookupResult);
1554     } else {
1555         if (afsd_verbose)
1556             printf("%s: My home cell is '%s'\n", rn, LclCellName);
1557     }
1558
1559     /* parse cacheinfo file if this is a diskcache */
1560     if (ParseCacheInfoFile()) {
1561         exit(1);
1562     }
1563
1564     if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
1565         if (afsd_verbose)
1566             printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1567         if (CreateCacheFile(fullpn_AFSLogFile, NULL)) {
1568             printf
1569                 ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
1570                  rn, fullpn_AFSLogFile);
1571             exit(1);
1572         }
1573     } else
1574         fclose(logfd);
1575
1576     /* do some random computations in memcache case to get things to work
1577      * reasonably no matter which parameters you set.
1578      */
1579     if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1580         /* memory cache: size described either as blocks or dcache entries, but
1581          * not both.
1582          */
1583         if (sawDCacheSize) {
1584             if (sawCacheBlocks) {
1585                 printf
1586                     ("%s: can't set cache blocks and dcache size simultaneously when diskless.\n",
1587                      rn);
1588                 exit(1);
1589             }
1590             /* compute the cache size based on # of chunks times the chunk size */
1591             i = (chunkSize == 0 ? 13 : chunkSize);
1592             i = (1 << i);       /* bytes per chunk */
1593             cacheBlocks = i * dCacheSize;
1594             sawCacheBlocks = 1; /* so that ParseCacheInfoFile doesn't overwrite */
1595         } else {
1596             /* compute the dcache size from overall cache size and chunk size */
1597             i = (chunkSize == 0 ? 13 : chunkSize);
1598             /* dCacheSize = (cacheBlocks << 10) / (1<<i); */
1599             if (i > 10) {
1600                 dCacheSize = (cacheBlocks >> (i - 10));
1601             } else if (i < 10) {
1602                 dCacheSize = (cacheBlocks << (10 - i));
1603             } else {
1604                 dCacheSize = cacheBlocks;
1605             }
1606             /* don't have to set sawDCacheSize here since it isn't overwritten
1607              * by ParseCacheInfoFile.
1608              */
1609         }
1610         /* kernel computes # of dcache entries as min of cacheFiles and dCacheSize,
1611          * so we now make them equal.
1612          */
1613         cacheFiles = dCacheSize;
1614     } else {
1615         /* Disk cache:
1616          * Compute the number of cache files based on cache size,
1617          * but only if -files isn't given on the command line.
1618          * Don't let # files be so small as to prevent full utilization 
1619          * of the cache unless user has explicitly asked for it.
1620          * average V-file is ~10K, according to tentative empirical studies.
1621          */
1622         if (!filesSet) {
1623             cacheFiles = cacheBlocks / 10;
1624             if (cacheFiles < 100)
1625                 cacheFiles = 100;
1626             /* Always allow more files than chunks.  Presume average V-file 
1627              * is ~67% of a chunk...  (another guess, perhaps Honeyman will
1628              * have a grad student write a paper).  i is KILOBYTES.
1629              */
1630             i = 1 << (chunkSize ==
1631                       0 ? 6 : (chunkSize < 10 ? 0 : chunkSize - 10));
1632             cacheFiles = max(cacheFiles, 1.5 * (cacheBlocks / i));
1633             /* never permit more files than blocks, while leaving space for
1634              * VolumeInfo and CacheItems files.  VolumeInfo is usually 20K,
1635              * CacheItems is 50 Bytes / file (== 1K/20)
1636              */
1637 #define VOLINFOSZ 20
1638 #define CACHEITMSZ (cacheFiles / 20)
1639 #ifdef AFS_AIX_ENV
1640             cacheFiles =
1641                 min(cacheFiles, (cacheBlocks - VOLINFOSZ - CACHEITMSZ) / 4);
1642 #else
1643             cacheFiles =
1644                 min(cacheFiles, cacheBlocks - VOLINFOSZ - CACHEITMSZ);
1645 #endif
1646             if (cacheFiles < 100)
1647                 fprintf(stderr, "%s: WARNING: cache probably too small!\n",
1648                         rn);
1649         }
1650         if (!sawDCacheSize) {
1651             if ((cacheFiles / 2) > dCacheSize)
1652                 dCacheSize = cacheFiles / 2;
1653             if (dCacheSize > 2000)
1654                 dCacheSize = 2000;
1655         }
1656     }
1657
1658     /*
1659      * Create and zero the inode table for the desired cache files.
1660      */
1661     inode_for_V = (AFSD_INO_T *) malloc(cacheFiles * sizeof(AFSD_INO_T));
1662     if (inode_for_V == (AFSD_INO_T *) 0) {
1663         printf
1664             ("%s: malloc() failed for cache file inode table with %d entries.\n",
1665              rn, cacheFiles);
1666         exit(1);
1667     }
1668     memset(inode_for_V, '\0', (cacheFiles * sizeof(AFSD_INO_T)));
1669     if (afsd_debug)
1670         printf("%s: %d inode_for_V entries at 0x%x, %d bytes\n", rn,
1671                cacheFiles, inode_for_V, (cacheFiles * sizeof(AFSD_INO_T)));
1672
1673     /*
1674      * Set up all the pathnames we'll need for later.
1675      */
1676     sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1677     sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1678     sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
1679     sprintf(fullpn_VFile, "%s/", cacheBaseDir);
1680     vFilePtr = fullpn_VFile + strlen(fullpn_VFile);
1681
1682     if  (!(cacheFlags & AFSCALL_INIT_MEMCACHE) && (fsTypeMsg = CheckCacheBaseDir(cacheBaseDir))) {
1683         printf("%s: WARNING: Cache dir check failed (%s)\n", rn, fsTypeMsg);
1684     }
1685 #if 0
1686     fputs(AFS_GOVERNMENT_MESSAGE, stdout);
1687     fflush(stdout);
1688 #endif
1689
1690     /*
1691      * Set up all the kernel processes needed for AFS.
1692      */
1693 #ifdef mac2
1694     setpgrp(getpid(), 0);
1695 #endif /* mac2 */
1696
1697     /* Initialize RX daemons and services */
1698
1699     /* initialize the rx random number generator from user space */
1700     {
1701         /* parse multihomed address files */
1702         afs_int32 addrbuf[MAXIPADDRS], maskbuf[MAXIPADDRS],
1703             mtubuf[MAXIPADDRS];
1704         char reason[1024];
1705         code =
1706             parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS, reason,
1707                           AFSDIR_CLIENT_NETINFO_FILEPATH,
1708                           AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1709         if (code > 0) {
1710             if (enable_rxbind)
1711                 code = code | 0x80000000;
1712             call_syscall(AFSOP_ADVISEADDR, code, addrbuf, maskbuf, mtubuf);
1713         } else
1714             printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
1715                    reason);
1716     }
1717
1718     /* Set realtime priority for most threads to same as for biod's. */
1719     SET_AFSD_RTPRI();
1720
1721 #ifdef  AFS_SGI53_ENV
1722 #ifdef AFS_SGI61_ENV
1723     set_staticaddrs();
1724 #else /* AFS_SGI61_ENV */
1725     code = get_nfsstaticaddr();
1726     if (code)
1727         call_syscall(AFSOP_NFSSTATICADDR, code);
1728 #endif /* AFS_SGI61_ENV */
1729 #endif /* AFS_SGI_53_ENV */
1730
1731     /* Start listener, then callback listener. Lastly, start rx event daemon.
1732      * Change in ordering is so that Linux port has socket fd in listener
1733      * process.
1734      * preallocs are passed for both listener and callback server. Only
1735      * the one which actually does the initialization uses them though.
1736      */
1737     if (preallocs < cacheStatEntries + 50)
1738         preallocs = cacheStatEntries + 50;
1739 #ifdef RXK_LISTENER_ENV
1740     if (afsd_verbose)
1741         printf("%s: Forking rx listener daemon.\n", rn);
1742     code = fork();
1743     if (code == 0) {
1744         /* Child */
1745         SET_RX_RTPRI();         /* max advised for non-interrupts */
1746         call_syscall(AFSOP_RXLISTENER_DAEMON, preallocs, enable_peer_stats,
1747                      enable_process_stats);
1748         exit(1);
1749     }
1750 #endif
1751     if (afsd_verbose)
1752         printf("%s: Forking rx callback listener.\n", rn);
1753     code = fork();
1754     if (code == 0) {
1755         /* Child */
1756         call_syscall(AFSOP_START_RXCALLBACK, preallocs);
1757         exit(1);
1758     }
1759 #if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
1760     if (afsd_verbose)
1761         printf("%s: Forking rxevent daemon.\n", rn);
1762     code = fork();
1763     if (code == 0) {
1764         /* Child */
1765         SET_RX_RTPRI();         /* max advised for non-interrupts */
1766         call_syscall(AFSOP_RXEVENT_DAEMON);
1767         exit(1);
1768     }
1769 #endif
1770
1771 #ifdef AFS_AFSDB_ENV
1772     if (enable_afsdb) {
1773         if (afsd_verbose)
1774             printf("%s: Forking AFSDB lookup handler.\n", rn);
1775         code = fork();
1776         if (code == 0) {
1777             /* Since the AFSDB lookup handler runs as a user process, 
1778              * need to drop the controlling TTY, etc.
1779              */
1780             if (daemon(0, 0) == -1) {
1781                 printf("Error starting AFSDB lookup handler: %s\n",
1782                         strerror(errno));
1783                 exit(1);
1784             }
1785             AfsdbLookupHandler();
1786             exit(1);
1787         }
1788     }
1789 #endif
1790
1791     code = call_syscall(AFSOP_BASIC_INIT, 1);
1792     if (code)
1793         printf("%s: Error %d in basic initialization.\n", rn, code);
1794
1795     /*
1796      * Tell the kernel some basic information about the workstation's cache.
1797      */
1798     if (afsd_verbose)
1799         printf
1800             ("%s: Calling AFSOP_CACHEINIT: %d stat cache entries, %d optimum cache files, %d blocks in the cache, flags = 0x%x, dcache entries %d\n",
1801              rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
1802              dCacheSize);
1803     memset(&cparams, '\0', sizeof(cparams));
1804     cparams.cacheScaches = cacheStatEntries;
1805     cparams.cacheFiles = cacheFiles;
1806     cparams.cacheBlocks = cacheBlocks;
1807     cparams.cacheDcaches = dCacheSize;
1808     cparams.cacheVolumes = vCacheSize;
1809     cparams.chunkSize = chunkSize;
1810     cparams.setTimeFlag = cacheSetTime;
1811     cparams.memCacheFlag = cacheFlags;
1812 #ifdef notdef
1813     cparams.inodes = inodes;
1814 #endif
1815     call_syscall(AFSOP_CACHEINIT, &cparams);
1816     if (afsd_CloseSynch)
1817         call_syscall(AFSOP_CLOSEWAIT);
1818
1819     /*
1820      * Sweep the workstation AFS cache directory, remembering the inodes of
1821      * valid files and deleting extraneous files.  Keep sweeping until we
1822      * have the right number of data cache files or we've swept too many
1823      * times.
1824      *
1825      * This also creates files in the cache directory like VolumeItems and
1826      * CellItems, and thus must be ran before those are sent to the kernel.
1827      */
1828     if (afsd_verbose)
1829         printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
1830     cacheIteration = 0;
1831     /* Memory-cache based system doesn't need any of this */
1832     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1833         do {
1834             cacheIteration++;
1835             if (SweepAFSCache(&vFilesFound)) {
1836                 printf("%s: Error on sweep %d of workstation AFS cache \
1837                        directory.\n", rn, cacheIteration);
1838                 exit(1);
1839             }
1840             if (afsd_verbose)
1841                 printf
1842                     ("%s: %d out of %d data cache files found in sweep %d.\n",
1843                      rn, vFilesFound, cacheFiles, cacheIteration);
1844         } while ((vFilesFound < cacheFiles)
1845                  && (cacheIteration < MAX_CACHE_LOOPS));
1846     } else if (afsd_verbose)
1847         printf("%s: Using memory cache, not swept\n", rn);
1848
1849     /*
1850      * Pass the kernel the name of the workstation cache file holding the 
1851      * dcache entries.
1852      */
1853     if (afsd_debug)
1854         printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
1855                fullpn_DCacheFile);
1856     /* once again, meaningless for a memory-based cache. */
1857     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1858         call_syscall(AFSOP_CACHEINFO, fullpn_DCacheFile);
1859
1860     /*
1861      * Pass the kernel the name of the workstation cache file holding the
1862      * cell information.
1863      */
1864     if (afsd_debug)
1865         printf("%s: Calling AFSOP_CELLINFO: cell info file is '%s'\n", rn,
1866                fullpn_CellInfoFile);
1867     call_syscall(AFSOP_CELLINFO, fullpn_CellInfoFile);
1868
1869     if (enable_dynroot) {
1870         if (afsd_verbose)
1871             printf("%s: Enabling dynroot support in kernel.\n", rn);
1872         code = call_syscall(AFSOP_SET_DYNROOT, 1);
1873         if (code)
1874             printf("%s: Error enabling dynroot support.\n", rn);
1875     }
1876
1877     if (enable_fakestat) {
1878         if (afsd_verbose)
1879             printf("%s: Enabling fakestat support in kernel.\n", rn);
1880         code = call_syscall(AFSOP_SET_FAKESTAT, enable_fakestat);
1881         if (code)
1882             printf("%s: Error enabling fakestat support.\n", rn);
1883     }
1884
1885     if (enable_backuptree) {
1886         if (afsd_verbose)
1887             printf("%s: Enabling backup tree support in kernel.\n", rn);
1888         code = call_syscall(AFSOP_SET_BACKUPTREE, enable_backuptree);
1889         if (code)
1890             printf("%s: Error enabling backup tree support.\n", rn);
1891     }
1892
1893     /*
1894      * Tell the kernel about each cell in the configuration.
1895      */
1896     afsconf_CellApply(cdir, ConfigCell, NULL);
1897     afsconf_CellAliasApply(cdir, ConfigCellAlias, NULL);
1898
1899     /*
1900      * Set the primary cell name.
1901      */
1902     call_syscall(AFSOP_SET_THISCELL, LclCellName);
1903
1904     /* Initialize AFS daemon threads. */
1905     if (afsd_verbose)
1906         printf("%s: Forking AFS daemon.\n", rn);
1907     code = fork();
1908     if (code == 0) {
1909         /* Child */
1910         call_syscall(AFSOP_START_AFS);
1911         exit(1);
1912     }
1913
1914     if (afsd_verbose)
1915         printf("%s: Forking Check Server Daemon.\n", rn);
1916     code = fork();
1917     if (code == 0) {
1918         /* Child */
1919         code = call_syscall(AFSOP_START_CS);
1920         if (code)
1921             printf("%s: No check server daemon in client.\n", rn);
1922         exit(1);
1923     }
1924
1925     if (afsd_verbose)
1926         printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1927 #if defined(AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
1928     /* Add one because for sgi we always "steal" the first daemon for a
1929      * different task if we only have a 4K stack.
1930      */
1931     nDaemons++;
1932 #endif
1933     for (i = 0; i < nDaemons; i++) {
1934         code = fork();
1935         if (code == 0) {
1936             /* Child */
1937 #ifdef  AFS_AIX32_ENV
1938             call_syscall(AFSOP_START_BKG, 0);
1939 #else
1940             call_syscall(AFSOP_START_BKG);
1941 #endif
1942             exit(1);
1943         }
1944     }
1945 #ifdef  AFS_AIX32_ENV
1946     if (!sawBiod)
1947         nBiods = nDaemons * 2;
1948     if (nBiods < 5)
1949         nBiods = 5;
1950     for (i = 0; i < nBiods; i++) {
1951         code = fork();
1952         if (code == 0) {        /* Child */
1953             call_syscall(AFSOP_START_BKG, nBiods);
1954             exit(1);
1955         }
1956     }
1957 #endif
1958
1959     /*
1960      * If the root volume has been explicitly set, tell the kernel.
1961      */
1962     if (rootVolSet) {
1963         if (afsd_verbose)
1964             printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn,
1965                    rootVolume);
1966         call_syscall(AFSOP_ROOTVOLUME, rootVolume);
1967     }
1968
1969     /*
1970      * Pass the kernel the name of the workstation cache file holding the
1971      * volume information.
1972      */
1973     if (afsd_debug)
1974         printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
1975                fullpn_VolInfoFile);
1976     /* once again, meaningless for a memory-based cache. */
1977     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) 
1978         call_syscall(AFSOP_VOLUMEINFO, fullpn_VolInfoFile);
1979
1980     /*
1981      * Pass the kernel the name of the afs logging file holding the volume
1982      * information.
1983      */
1984     if (afsd_debug)
1985         printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
1986                fullpn_AFSLogFile);
1987 #if defined(AFS_SGI_ENV)
1988     /* permit explicit -logfile argument to enable logging on memcache systems */
1989     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE) || as->parms[18].items)
1990 #else
1991     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))  /* ... nor this ... */
1992 #endif
1993         call_syscall(AFSOP_AFSLOG, fullpn_AFSLogFile);
1994
1995     /*
1996      * Give the kernel the names of the AFS files cached on the workstation's
1997      * disk.
1998      */
1999     if (afsd_debug)
2000         printf
2001             ("%s: Calling AFSOP_CACHEINODE for each of the %d files in '%s'\n",
2002              rn, cacheFiles, cacheBaseDir);
2003     if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))  /* ... and again ... */
2004         for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
2005 #ifdef AFS_SGI62_ENV
2006             call_syscall(AFSOP_CACHEINODE,
2007                          (afs_uint32) (inode_for_V[currVFile] >> 32),
2008                          (afs_uint32) (inode_for_V[currVFile] & 0xffffffff));
2009 #else
2010             call_syscall(AFSOP_CACHEINODE, inode_for_V[currVFile]);
2011 #endif
2012         }
2013
2014
2015     /*end for */
2016     /*
2017      * All the necessary info has been passed into the kernel to run an AFS
2018      * system.  Give the kernel our go-ahead.
2019      */
2020     if (afsd_debug)
2021         printf("%s: Calling AFSOP_GO with cacheSetTime = %d\n", rn,
2022                cacheSetTime);
2023     call_syscall(AFSOP_GO, cacheSetTime);
2024
2025     /*
2026      * At this point, we have finished passing the kernel all the info 
2027      * it needs to set up the AFS.  Mount the AFS root.
2028      */
2029     printf("%s: All AFS daemons started.\n", rn);
2030
2031     if (afsd_verbose)
2032         printf("%s: Forking trunc-cache daemon.\n", rn);
2033     code = fork();
2034     if (code == 0) {
2035         /* Child */
2036         call_syscall(AFSOP_START_TRUNCDAEMON);
2037         exit(1);
2038     }
2039
2040     if (!enable_nomount) {
2041
2042         mountFlags = 0;         /* Read/write file system, can do setuid() */
2043 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
2044 #ifdef  AFS_SUN5_ENV
2045         mountFlags |= MS_DATA;
2046 #else
2047         mountFlags |= M_NEWTYPE;        /* This searches by name in vfs_conf.c so don't need to recompile vfs.c because MOUNT_MAXTYPE has changed; it seems that Sun fixed this at last... */
2048 #endif
2049 #endif
2050
2051 #if defined(AFS_HPUX100_ENV)
2052         mountFlags |= MS_DATA;
2053 #endif
2054
2055         if (afsd_verbose)
2056             printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn,
2057                    cacheMountDir, mountFlags);
2058 #ifdef AFS_FBSD_ENV
2059         if ((mount("AFS", cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
2060 #elif defined(AFS_AIX_ENV)
2061         if (aix_vmount()) {
2062 #elif defined(AFS_HPUX100_ENV)
2063         if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
2064 #elif defined(AFS_SUN5_ENV)
2065         if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
2066 #elif defined(AFS_SGI_ENV)
2067         mountFlags = MS_FSS;
2068         if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS))
2069             < 0) {
2070 #elif defined(AFS_LINUX20_ENV)
2071         if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) {
2072 #else
2073 /* This is the standard mount used by the suns and rts */
2074         if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
2075 #endif
2076             printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir,
2077                    errno);
2078             exit(1);
2079         }
2080
2081         HandleMTab();
2082
2083     }
2084
2085     if (afsd_rmtsys) {
2086         if (afsd_verbose)
2087             printf("%s: Forking 'rmtsys' daemon.\n", rn);
2088         code = fork();
2089         if (code == 0) {
2090             /* Child */
2091             rmtsysd();
2092             exit(1);
2093         }
2094     }
2095     /*
2096      * Exit successfully.
2097      */
2098     exit(0);
2099 }
2100
2101 #include "AFS_component_version_number.c"
2102
2103
2104
2105 main(argc, argv)
2106      int argc;
2107      char **argv;
2108 {
2109     struct cmd_syndesc *ts;
2110
2111     ts = cmd_CreateSyntax(NULL, mainproc, NULL, "start AFS");
2112     cmd_AddParm(ts, "-blocks", CMD_SINGLE, CMD_OPTIONAL,
2113                 "1024 byte blocks in cache");
2114     cmd_AddParm(ts, "-files", CMD_SINGLE, CMD_OPTIONAL, "files in cache");
2115     cmd_AddParm(ts, "-rootvol", CMD_SINGLE, CMD_OPTIONAL,
2116                 "name of AFS root volume");
2117     cmd_AddParm(ts, "-stat", CMD_SINGLE, CMD_OPTIONAL,
2118                 "number of stat entries");
2119     cmd_AddParm(ts, "-memcache", CMD_FLAG, CMD_OPTIONAL, "run diskless");
2120     cmd_AddParm(ts, "-cachedir", CMD_SINGLE, CMD_OPTIONAL, "cache directory");
2121     cmd_AddParm(ts, "-mountdir", CMD_SINGLE, CMD_OPTIONAL, "mount location");
2122     cmd_AddParm(ts, "-daemons", CMD_SINGLE, CMD_OPTIONAL,
2123                 "number of daemons to use");
2124     cmd_AddParm(ts, "-nosettime", CMD_FLAG, CMD_OPTIONAL,
2125                 "don't set the time");
2126     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL,
2127                 "display lots of information");
2128     cmd_AddParm(ts, "-rmtsys", CMD_FLAG, CMD_OPTIONAL,
2129                 "start NFS rmtsysd program");
2130     cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL, "display debug info");
2131     cmd_AddParm(ts, "-chunksize", CMD_SINGLE, CMD_OPTIONAL,
2132                 "log(2) of chunk size");
2133     cmd_AddParm(ts, "-dcache", CMD_SINGLE, CMD_OPTIONAL,
2134                 "number of dcache entries");
2135     cmd_AddParm(ts, "-volumes", CMD_SINGLE, CMD_OPTIONAL,
2136                 "number of volume entries");
2137     cmd_AddParm(ts, "-biods", CMD_SINGLE, CMD_OPTIONAL,
2138                 "number of bkg I/O daemons (aix vm)");
2139
2140     cmd_AddParm(ts, "-prealloc", CMD_SINGLE, CMD_OPTIONAL,
2141                 "number of 'small' preallocated blocks");
2142 #ifdef notdef
2143     cmd_AddParm(ts, "-pininodes", CMD_SINGLE, CMD_OPTIONAL,
2144                 "number of inodes to hog");
2145 #endif
2146     cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL,
2147                 "configuration directory");
2148     cmd_AddParm(ts, "-logfile", CMD_SINGLE, CMD_OPTIONAL,
2149                 "Place to keep the CM log");
2150     cmd_AddParm(ts, "-waitclose", CMD_FLAG, CMD_OPTIONAL,
2151                 "make close calls synchronous");
2152     cmd_AddParm(ts, "-shutdown", CMD_FLAG, CMD_OPTIONAL,
2153                 "Shutdown all afs state");
2154     cmd_AddParm(ts, "-enable_peer_stats", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE,
2155                 "Collect rpc statistics by peer");
2156     cmd_AddParm(ts, "-enable_process_stats", CMD_FLAG,
2157                 CMD_OPTIONAL | CMD_HIDE,
2158                 "Collect rpc statistics for this process");
2159     cmd_AddParm(ts, "-mem_alloc_sleep", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
2160                 "Allow sleeps when allocating memory cache");
2161     cmd_AddParm(ts, "-afsdb", CMD_FLAG, (CMD_OPTIONAL
2162 #ifndef AFS_AFSDB_ENV
2163                                          | CMD_HIDE
2164 #endif
2165                 ), "Enable AFSDB support");
2166     cmd_AddParm(ts, "-files_per_subdir", CMD_SINGLE, CMD_OPTIONAL,
2167                 "log(2) of the number of cache files per cache subdirectory");
2168     cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL,
2169                 "Enable dynroot support");
2170     cmd_AddParm(ts, "-fakestat", CMD_FLAG, CMD_OPTIONAL,
2171                 "Enable fakestat support for cross-cell mounts");
2172     cmd_AddParm(ts, "-fakestat-all", CMD_FLAG, CMD_OPTIONAL,
2173                 "Enable fakestat support for all mounts");
2174     cmd_AddParm(ts, "-nomount", CMD_FLAG, CMD_OPTIONAL, "Do not mount AFS");
2175     cmd_AddParm(ts, "-backuptree", CMD_FLAG, CMD_OPTIONAL,
2176                 "Prefer backup volumes for mointpoints in backup volumes");
2177     cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL, "Bind the Rx socket (one interface only)");
2178     cmd_AddParm(ts, "-settime", CMD_FLAG, CMD_OPTIONAL,
2179                "don't set the time");
2180     cmd_AddParm(ts, "-rxpck", CMD_SINGLE, CMD_OPTIONAL, "set rx_extraPackets to this value");
2181     return (cmd_Dispatch(argc, argv));
2182 }
2183
2184
2185 #ifdef  AFS_HPUX_ENV
2186 #define MOUNTED_TABLE   MNT_MNTTAB
2187 #else
2188 #ifdef  AFS_SUN5_ENV
2189 #define MOUNTED_TABLE   MNTTAB
2190 #else
2191 #define MOUNTED_TABLE   MOUNTED
2192 #endif
2193 #endif
2194
2195 static int
2196 HandleMTab()
2197 {
2198 #if (defined (AFS_SUN_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)) && !defined(AFS_SUN58_ENV)
2199     FILE *tfilep;
2200 #ifdef  AFS_SUN5_ENV
2201     char tbuf[16];
2202     struct mnttab tmntent;
2203
2204     memset(&tmntent, '\0', sizeof(struct mnttab));
2205     if (!(tfilep = fopen(MOUNTED_TABLE, "a+"))) {
2206         printf("Can't open %s\n", MOUNTED_TABLE);
2207         perror(MNTTAB);
2208         exit(-1);
2209     }
2210     tmntent.mnt_special = "AFS";
2211     tmntent.mnt_mountp = cacheMountDir;
2212     tmntent.mnt_fstype = "xx";
2213     tmntent.mnt_mntopts = "rw";
2214     sprintf(tbuf, "%ld", (long)time((time_t *) 0));
2215     tmntent.mnt_time = tbuf;
2216     putmntent(tfilep, &tmntent);
2217     fclose(tfilep);
2218 #else
2219 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
2220     struct mntent tmntent;
2221
2222     tfilep = setmntent("/etc/mtab", "a+");
2223     tmntent.mnt_fsname = "AFS";
2224     tmntent.mnt_dir = cacheMountDir;
2225     tmntent.mnt_type = "afs";
2226     tmntent.mnt_opts = "rw";
2227     tmntent.mnt_freq = 1;
2228     tmntent.mnt_passno = 3;
2229     addmntent(tfilep, &tmntent);
2230     endmntent(tfilep);
2231 #else
2232     struct mntent tmntent;
2233
2234     memset(&tmntent, '\0', sizeof(struct mntent));
2235     tfilep = setmntent(MOUNTED_TABLE, "a+");
2236     if (!tfilep) {
2237         printf("Can't open %s for write; Not adding afs entry to it\n",
2238                MOUNTED_TABLE);
2239         return 1;
2240     }
2241     tmntent.mnt_fsname = "AFS";
2242     tmntent.mnt_dir = cacheMountDir;
2243     tmntent.mnt_type = "xx";
2244     tmntent.mnt_opts = "rw";
2245     tmntent.mnt_freq = 1;
2246     tmntent.mnt_passno = 3;
2247 #ifdef  AFS_HPUX_ENV
2248     tmntent.mnt_type = "afs";
2249     tmntent.mnt_time = time(0);
2250     tmntent.mnt_cnode = 0;
2251 #endif
2252     addmntent(tfilep, &tmntent);
2253     endmntent(tfilep);
2254 #endif /* AFS_SGI_ENV */
2255 #endif /* AFS_SUN5_ENV */
2256 #endif /* unreasonable systems */
2257 #ifdef AFS_DARWIN_ENV
2258     mach_port_t diskarb_port;
2259     kern_return_t status;
2260
2261     status = DiskArbStart(&diskarb_port);
2262     if (status == KERN_SUCCESS) {
2263         status =
2264             DiskArbDiskAppearedWithMountpointPing_auto("AFS",
2265                                                        DISK_ARB_NETWORK_DISK_FLAG,
2266                                                        cacheMountDir);
2267     }
2268
2269     return status;
2270 #endif /* AFS_DARWIN_ENV */
2271     return 0;
2272 }
2273
2274 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
2275
2276 call_syscall(param1, param2, param3, param4, param5, param6, param7)
2277      long param1, param2, param3, param4, param5, param6, param7;
2278 {
2279     int error;
2280 #ifdef AFS_LINUX20_ENV
2281     long eparm[4];
2282     struct afsprocdata syscall_data;
2283     int fd = open(PROC_SYSCALL_FNAME,O_RDWR);
2284     if (fd < 0)
2285         fd = open(PROC_SYSCALL_ARLA_FNAME,O_RDWR);
2286     eparm[0] = param4;
2287     eparm[1] = param5;
2288     eparm[2] = param6;
2289     eparm[3] = param7;
2290
2291     param4 = (long)eparm;
2292
2293     syscall_data.syscall = AFSCALL_CALL;
2294     syscall_data.param1 = param1;
2295     syscall_data.param2 = param2;
2296     syscall_data.param3 = param3;
2297     syscall_data.param4 = param4;
2298     if(fd > 0) {
2299        error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
2300        close(fd);
2301     }
2302     else
2303 #endif
2304     error =
2305         syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4,
2306                 param5, param6, param7);
2307
2308     if (afsd_verbose)
2309         printf("SScall(%d, %d, %d)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1,
2310                error);
2311     return (error);
2312 }
2313 #else /* AFS_AIX32_ENV */
2314 #if defined(AFS_SGI_ENV)
2315 call_syscall(call, parm0, parm1, parm2, parm3, parm4)
2316 {
2317
2318     int error;
2319
2320     error = afs_syscall(call, parm0, parm1, parm2, parm3, parm4);
2321     if (afsd_verbose)
2322         printf("SScall(%d, %d)=%d ", call, parm0, error);
2323
2324     return error;
2325 }
2326 #else
2327 call_syscall(call, parm0, parm1, parm2, parm3, parm4, parm5, parm6)
2328 {
2329
2330     return syscall(AFSCALL_CALL, call, parm0, parm1, parm2, parm3, parm4,
2331                    parm5, parm6);
2332 }
2333 #endif /* AFS_SGI_ENV */
2334 #endif /* AFS_AIX32_ENV */
2335
2336
2337 #ifdef  AFS_AIX_ENV
2338 /* Special handling for AIX's afs mount operation since they require much more miscl. information before making the vmount(2) syscall */
2339 #include <sys/vfs.h>
2340
2341 #define ROUNDUP(x)  (((x) + 3) & ~3)
2342
2343 aix_vmount()
2344 {
2345     struct vmount *vmountp;
2346     int size, error;
2347
2348     size = sizeof(struct vmount) + ROUNDUP(strlen(cacheMountDir) + 1) + 5 * 4;
2349     /* Malloc the vmount structure */
2350     if ((vmountp = (struct vmount *)malloc(size)) == (struct vmount *)NULL) {
2351         printf("Can't allocate space for the vmount structure (AIX)\n");
2352         exit(1);
2353     }
2354
2355     /* zero out the vmount structure */
2356     memset(vmountp, '\0', size);
2357
2358     /* transfer info into the vmount structure */
2359     vmountp->vmt_revision = VMT_REVISION;
2360     vmountp->vmt_length = size;
2361     vmountp->vmt_fsid.fsid_dev = 0;
2362     vmountp->vmt_fsid.fsid_type = AFS_MOUNT_AFS;
2363     vmountp->vmt_vfsnumber = 0;
2364     vmountp->vmt_time = 0;      /* We'll put the time soon! */
2365     vmountp->vmt_flags = VFS_DEVMOUNT;  /* read/write permission */
2366     vmountp->vmt_gfstype = AFS_MOUNT_AFS;
2367     vmountdata(vmountp, "AFS", cacheMountDir, "", "", "", "rw");
2368
2369     /* Do the actual mount system call */
2370     error = vmount(vmountp, size);
2371     free(vmountp);
2372     return (error);
2373 }
2374
2375 vmountdata(vmtp, obj, stub, host, hostsname, info, args)
2376      struct vmount *vmtp;
2377      char *obj, *stub, *host, *hostsname, *info, *args;
2378 {
2379     register struct data {
2380         short vmt_off;
2381         short vmt_size;
2382     } *vdp, *vdprev;
2383     register int size;
2384
2385     vdp = (struct data *)vmtp->vmt_data;
2386     vdp->vmt_off = sizeof(struct vmount);
2387     size = ROUNDUP(strlen(obj) + 1);
2388     vdp->vmt_size = size;
2389     strcpy(vmt2dataptr(vmtp, VMT_OBJECT), obj);
2390
2391     vdprev = vdp;
2392     vdp++;
2393     vdp->vmt_off = vdprev->vmt_off + size;
2394     size = ROUNDUP(strlen(stub) + 1);
2395     vdp->vmt_size = size;
2396     strcpy(vmt2dataptr(vmtp, VMT_STUB), stub);
2397
2398     vdprev = vdp;
2399     vdp++;
2400     vdp->vmt_off = vdprev->vmt_off + size;
2401     size = ROUNDUP(strlen(host) + 1);
2402     vdp->vmt_size = size;
2403     strcpy(vmt2dataptr(vmtp, VMT_HOST), host);
2404
2405     vdprev = vdp;
2406     vdp++;
2407     vdp->vmt_off = vdprev->vmt_off + size;
2408     size = ROUNDUP(strlen(hostsname) + 1);
2409     vdp->vmt_size = size;
2410     strcpy(vmt2dataptr(vmtp, VMT_HOSTNAME), hostsname);
2411
2412
2413     vdprev = vdp;
2414     vdp++;
2415     vdp->vmt_off = vdprev->vmt_off + size;
2416     size = ROUNDUP(strlen(info) + 1);
2417     vdp->vmt_size = size;
2418     strcpy(vmt2dataptr(vmtp, VMT_INFO), info);
2419
2420     vdprev = vdp;
2421     vdp++;
2422     vdp->vmt_off = vdprev->vmt_off + size;
2423     size = ROUNDUP(strlen(args) + 1);
2424     vdp->vmt_size = size;
2425     strcpy(vmt2dataptr(vmtp, VMT_ARGS), args);
2426 }
2427 #endif /* AFS_AIX_ENV */
2428
2429 #ifdef  AFS_SGI53_ENV
2430 #ifdef AFS_SGI61_ENV
2431 /* The dwarf structures are searched to find entry points of static functions
2432  * and the addresses of static variables. The file name as well as the
2433  * sybmol name is reaquired.
2434  */
2435
2436 /* Contains list of names to find in given file. */
2437 typedef struct {
2438     char *name;                 /* Name of variable or function. */
2439     afs_hyper_t addr;           /* Address of function, undefined if not found. */
2440     Dwarf_Half type;            /* DW_AT_location for vars, DW_AT_lowpc for func's */
2441     char found;                 /* set if found. */
2442 } staticAddrList;
2443
2444 typedef struct {
2445     char *file;                 /* Name of file containing vars or funcs */
2446     staticAddrList *addrList;   /* List of vars and/or funcs. */
2447     int nAddrs;                 /* # of addrList's */
2448     int found;                  /* set if we've found this file already. */
2449 } staticNameList;
2450
2451 /* routines used to find addresses in /unix */
2452 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2453 void findMDebugStaticAddresses(staticNameList *, int, int);
2454 #endif
2455 void findDwarfStaticAddresses(staticNameList *, int);
2456 void findElfAddresses(Dwarf_Debug, Dwarf_Die, staticNameList *);
2457 void getElfAddress(Dwarf_Debug, Dwarf_Die, staticAddrList *);
2458
2459 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2460 #define AFS_N_FILELISTS 2
2461 #define AFS_SYMS_NEEDED 3
2462 #else /* AFS_SGI62_ENV */
2463 #define AFS_N_FILELISTS 1
2464 #endif /* AFS_SGI62_ENV */
2465
2466
2467
2468 void
2469 set_staticaddrs(void)
2470 {
2471     staticNameList fileList[AFS_N_FILELISTS];
2472
2473     fileList[0].addrList =
2474         (staticAddrList *) calloc(1, sizeof(staticAddrList));
2475     if (!fileList[0].addrList) {
2476         printf("set_staticaddrs: Can't calloc fileList[0].addrList\n");
2477         return;
2478     }
2479     fileList[0].file = "nfs_server.c";
2480     fileList[0].found = 0;
2481     fileList[0].nAddrs = 1;
2482     fileList[0].addrList[0].name = "rfsdisptab_v2";
2483     fileList[0].addrList[0].type = DW_AT_location;
2484     fileList[0].addrList[0].found = 0;
2485
2486 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2487     fileList[1].addrList =
2488         (staticAddrList *) calloc(2, sizeof(staticAddrList));
2489     if (!fileList[1].addrList) {
2490         printf("set_staticaddrs: Can't malloc fileList[1].addrList\n");
2491         return;
2492     }
2493     fileList[1].file = "uipc_socket.c";
2494     fileList[1].found = 0;
2495     fileList[1].nAddrs = 2;
2496     fileList[1].addrList[0].name = "sblock";
2497     fileList[1].addrList[0].type = DW_AT_low_pc;
2498     fileList[1].addrList[0].found = 0;
2499     fileList[1].addrList[1].name = "sbunlock";
2500     fileList[1].addrList[1].type = DW_AT_low_pc;
2501     fileList[1].addrList[1].found = 0;
2502
2503     if (64 != sysconf(_SC_KERN_POINTERS))
2504         findMDebugStaticAddresses(fileList, AFS_N_FILELISTS, AFS_SYMS_NEEDED);
2505     else
2506 #endif /* AFS_SGI62_ENV */
2507         findDwarfStaticAddresses(fileList, AFS_N_FILELISTS);
2508
2509     if (fileList[0].addrList[0].found) {
2510         call_syscall(AFSOP_NFSSTATICADDR2, fileList[0].addrList[0].addr.high,
2511                      fileList[0].addrList[0].addr.low);
2512     } else {
2513         if (afsd_verbose)
2514             printf("NFS V2 is not present in the kernel.\n");
2515     }
2516     free(fileList[0].addrList);
2517 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2518     if (fileList[1].addrList[0].found && fileList[1].addrList[1].found) {
2519         call_syscall(AFSOP_SBLOCKSTATICADDR2,
2520                      fileList[1].addrList[0].addr.high,
2521                      fileList[1].addrList[0].addr.low,
2522                      fileList[1].addrList[1].addr.high,
2523                      fileList[1].addrList[1].addr.low);
2524     } else {
2525         if (!fileList[1].addrList[0].found)
2526             printf("Can't find %s in kernel. Exiting.\n",
2527                    fileList[1].addrList[0].name);
2528         if (!fileList[1].addrList[0].found)
2529             printf("Can't find %s in kernel. Exiting.\n",
2530                    fileList[1].addrList[1].name);
2531         exit(1);
2532     }
2533     free(fileList[1].addrList);
2534 #endif /* AFS_SGI62_ENV */
2535 }
2536
2537
2538 /* Find addresses for static variables and functions. */
2539 void
2540 findDwarfStaticAddresses(staticNameList * nameList, int nLists)
2541 {
2542     int fd;
2543     int i;
2544     int found = 0;
2545     int code;
2546     char *s;
2547     char *hname = (char *)0;
2548     Dwarf_Unsigned dwarf_access = O_RDONLY;
2549     Dwarf_Debug dwarf_debug;
2550     Dwarf_Error dwarf_error;
2551     Dwarf_Unsigned dwarf_cu_header_length;
2552     Dwarf_Unsigned dwarf_abbrev_offset;
2553     Dwarf_Half dwarf_address_size;
2554     Dwarf_Unsigned next_cu_header;
2555     Dwarf_Die dwarf_die;
2556     Dwarf_Die dwarf_next_die;
2557     Dwarf_Die dwarf_child_die;
2558
2559     if (elf_version(EV_CURRENT) == EV_NONE) {
2560         printf("findDwarfStaticAddresses: Bad elf version.\n");
2561         return;
2562     }
2563
2564     if ((fd = open("/unix", O_RDONLY, 0)) < 0) {
2565         printf("findDwarfStaticAddresses: Failed to open /unix.\n");
2566         return;
2567     }
2568     code =
2569         dwarf_init(fd, dwarf_access, NULL, NULL, &dwarf_debug, &dwarf_error);
2570     if (code != DW_DLV_OK) {
2571         /* Nope hope for the elves and dwarves, try intermediate code. */
2572         close(fd);
2573         return;
2574     }
2575
2576     found = 0;
2577     while (1) {
2578         /* Run through the headers until we find ones for files we've
2579          * specified in nameList.
2580          */
2581         code =
2582             dwarf_next_cu_header(dwarf_debug, &dwarf_cu_header_length, NULL,
2583                                  &dwarf_abbrev_offset, &dwarf_address_size,
2584                                  &next_cu_header, &dwarf_error);
2585         if (code == DW_DLV_NO_ENTRY) {
2586             break;
2587         } else if (code == DW_DLV_ERROR) {
2588             printf("findDwarfStaticAddresses: Error reading headers: %s\n",
2589                    dwarf_errmsg(dwarf_error));
2590             break;
2591         }
2592
2593         code = dwarf_siblingof(dwarf_debug, NULL, &dwarf_die, &dwarf_error);
2594         if (code != DW_DLV_OK) {
2595             printf("findDwarfStaticAddresses: Can't get first die. %s\n",
2596                    (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2597             break;
2598         }
2599
2600         /* This is the header, test the name. */
2601         code = dwarf_diename(dwarf_die, &hname, &dwarf_error);
2602         if (code == DW_DLV_OK) {
2603             s = strrchr(hname, '/');
2604             for (i = 0; i < nLists; i++) {
2605                 if (s && !strcmp(s + 1, nameList[i].file)) {
2606                     findElfAddresses(dwarf_debug, dwarf_die, &nameList[i]);
2607                     found++;
2608                     break;
2609                 }
2610             }
2611         } else {
2612             printf
2613                 ("findDwarfStaticAddresses: Can't get name of current header. %s\n",
2614                  (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2615             break;
2616         }
2617         dwarf_dealloc(dwarf_debug, hname, DW_DLA_STRING);
2618         hname = (char *)0;
2619         if (found >= nLists) {  /* we're done */
2620             break;
2621         }
2622     }
2623
2624     /* Frees up all allocated space. */
2625     (void)dwarf_finish(dwarf_debug, &dwarf_error);
2626     close(fd);
2627 }
2628
2629 void
2630 findElfAddresses(Dwarf_Debug dwarf_debug, Dwarf_Die dwarf_die,
2631                  staticNameList * nameList)
2632 {
2633     int i;
2634     Dwarf_Error dwarf_error;
2635     Dwarf_Die dwarf_next_die;
2636     Dwarf_Die dwarf_child_die;
2637     Dwarf_Attribute dwarf_return_attr;
2638     char *vname = (char *)0;
2639     int found = 0;
2640     int code;
2641
2642     /* Drop into this die to find names in addrList. */
2643     code = dwarf_child(dwarf_die, &dwarf_child_die, &dwarf_error);
2644     if (code != DW_DLV_OK) {
2645         printf("findElfAddresses: Can't get child die. %s\n",
2646                (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2647         return;
2648     }
2649
2650     /* Try to find names in each sibling. */
2651     dwarf_next_die = (Dwarf_Die) 0;
2652     do {
2653         code = dwarf_diename(dwarf_child_die, &vname, &dwarf_error);
2654         /* It's possible that some siblings don't have names. */
2655         if (code == DW_DLV_OK) {
2656             for (i = 0; i < nameList->nAddrs; i++) {
2657                 if (!nameList->addrList[i].found) {
2658                     if (!strcmp(vname, nameList->addrList[i].name)) {
2659                         getElfAddress(dwarf_debug, dwarf_child_die,
2660                                       &(nameList->addrList[i]));
2661                         found++;
2662                         break;
2663                     }
2664                 }
2665             }
2666         }
2667         if (dwarf_next_die)
2668             dwarf_dealloc(dwarf_debug, dwarf_next_die, DW_DLA_DIE);
2669
2670         if (found >= nameList->nAddrs) {        /* we're done. */
2671             break;
2672         }
2673
2674         dwarf_next_die = dwarf_child_die;
2675         code =
2676             dwarf_siblingof(dwarf_debug, dwarf_next_die, &dwarf_child_die,
2677                             &dwarf_error);
2678
2679     } while (code == DW_DLV_OK);
2680 }
2681
2682 /* Get address out of current die. */
2683 void
2684 getElfAddress(Dwarf_Debug dwarf_debug, Dwarf_Die dwarf_child_die,
2685               staticAddrList * addrList)
2686 {
2687     int i;
2688     Dwarf_Error dwarf_error;
2689     Dwarf_Attribute dwarf_return_attr;
2690     Dwarf_Bool dwarf_return_bool;
2691     Dwarf_Locdesc *llbuf = NULL;
2692     Dwarf_Signed listlen;
2693     off64_t addr = (off64_t) 0;
2694     int code;
2695
2696     code =
2697         dwarf_hasattr(dwarf_child_die, addrList->type, &dwarf_return_bool,
2698                       &dwarf_error);
2699     if ((code != DW_DLV_OK) || (!dwarf_return_bool)) {
2700         printf("getElfAddress: no address given for %s. %s\n", addrList->name,
2701                (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2702         return;
2703     }
2704     code =
2705         dwarf_attr(dwarf_child_die, addrList->type, &dwarf_return_attr,
2706                    &dwarf_error);
2707     if (code != DW_DLV_OK) {
2708         printf("getElfAddress: Can't get attribute. %s\n",
2709                (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2710         return;
2711     }
2712
2713     switch (addrList->type) {
2714     case DW_AT_location:
2715         code =
2716             dwarf_loclist(dwarf_return_attr, &llbuf, &listlen, &dwarf_error);
2717         if (code != DW_DLV_OK) {
2718             printf("getElfAddress: Can't get location for %s. %s\n",
2719                    addrList->name,
2720                    (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2721             return;
2722         }
2723         if ((listlen != 1) || (llbuf[0].ld_cents != 1)) {
2724             printf("getElfAddress: %s has more than one address.\n",
2725                    addrList->name);
2726             return;
2727         }
2728         addr = llbuf[0].ld_s[0].lr_number;
2729         break;
2730
2731     case DW_AT_low_pc:
2732         code =
2733             dwarf_lowpc(dwarf_child_die, (Dwarf_Addr *) & addr, &dwarf_error);
2734         if (code != DW_DLV_OK) {
2735             printf("getElfAddress: Can't get lowpc for %s. %s\n",
2736                    addrList->name,
2737                    (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2738             return;
2739         }
2740         break;
2741
2742     default:
2743         printf("getElfAddress: Bad case %d in switch.\n", addrList->type);
2744         return;
2745     }
2746
2747     addrList->addr.high = (addr >> 32) & 0xffffffff;
2748     addrList->addr.low = addr & 0xffffffff;
2749     addrList->found = 1;
2750 }
2751
2752 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2753 /* Find symbols in the .mdebug section for 32 bit kernels. */
2754 /*
2755  * do_mdebug()
2756  * On 32bit platforms, we're still using the ucode compilers to build
2757  * the kernel, so we need to get our static text/data from the .mdebug
2758  * section instead of the .dwarf sections.
2759  */
2760 /* SearchNameList searches our bizarre structs for the given string.
2761  * If found, sets the found bit and the address and returns 1.
2762  * Not found returns 0.
2763  */
2764 int
2765 SearchNameList(char *name, afs_uint32 addr, staticNameList * nameList,
2766                int nLists)
2767 {
2768     int i, j;
2769     for (i = 0; i < nLists; i++) {
2770         for (j = 0; j < nameList[i].nAddrs; j++) {
2771             if (nameList[i].addrList[j].found)
2772                 continue;
2773             if (!strcmp(name, nameList[i].addrList[j].name)) {
2774                 nameList[i].addrList[j].addr.high = 0;
2775                 nameList[i].addrList[j].addr.low = addr;
2776                 nameList[i].addrList[j].found = 1;
2777                 return 1;
2778             }
2779         }
2780     }
2781     return 0;
2782 }
2783
2784 static void
2785 SearchMDebug(Elf_Scn * scnp, Elf32_Shdr * shdrp, staticNameList * nameList,
2786              int nLists, int needed)
2787 {
2788     long *buf = (long *)(elf_getdata(scnp, NULL)->d_buf);
2789     u_long addr, mdoff = shdrp->sh_offset;
2790     HDRR *hdrp;
2791     SYMR *symbase, *symp, *symend;
2792     FDR *fdrbase, *fdrp;
2793     int i, j;
2794     char *strbase, *str;
2795     int ifd;
2796     int nFound = 0;
2797
2798     /* get header */
2799     addr = (__psunsigned_t) buf;
2800     hdrp = (HDRR *) addr;
2801
2802     /* setup base addresses */
2803     addr = (u_long) buf + (u_long) (hdrp->cbFdOffset - mdoff);
2804     fdrbase = (FDR *) addr;
2805     addr = (u_long) buf + (u_long) (hdrp->cbSymOffset - mdoff);
2806     symbase = (SYMR *) addr;
2807     addr = (u_long) buf + (u_long) (hdrp->cbSsOffset - mdoff);
2808     strbase = (char *)addr;
2809
2810 #define KEEPER(a,b)     ((a == stStaticProc && b == scText) || \
2811                          (a == stStatic && (b == scData || b == scBss || \
2812                                             b == scSBss || b == scSData)))
2813
2814     for (fdrp = fdrbase; fdrp < &fdrbase[hdrp->ifdMax]; fdrp++) {
2815         str = strbase + fdrp->issBase + fdrp->rss;
2816
2817         /* local symbols for each fd */
2818         for (symp = &symbase[fdrp->isymBase];
2819              symp < &symbase[fdrp->isymBase + fdrp->csym]; symp++) {
2820             if (KEEPER(symp->st, symp->sc)) {
2821                 if (symp->value == 0)
2822                     continue;
2823
2824                 str = strbase + fdrp->issBase + symp->iss;
2825                 /* Look for AFS symbols of interest */
2826                 if (SearchNameList(str, symp->value, nameList, nLists)) {
2827                     nFound++;
2828                     if (nFound >= needed)
2829                         return;
2830                 }
2831             }
2832         }
2833     }
2834 }
2835
2836 /*
2837  * returns section with the name of scn_name, & puts its header in shdr64 or
2838  * shdr32 based on elf's file type
2839  *
2840  */
2841 Elf_Scn *
2842 findMDebugSection(Elf * elf, char *scn_name)
2843 {
2844     Elf64_Ehdr *ehdr64;
2845     Elf32_Ehdr *ehdr32;
2846     Elf_Scn *scn = NULL;
2847     Elf64_Shdr *shdr64;
2848     Elf32_Shdr *shdr32;
2849
2850     if ((ehdr32 = elf32_getehdr(elf)) == NULL)
2851         return (NULL);
2852     do {
2853         if ((scn = elf_nextscn(elf, scn)) == NULL)
2854             break;
2855         if ((shdr32 = elf32_getshdr(scn)) == NULL)
2856             return (NULL);
2857     } while (strcmp
2858              (scn_name,
2859               elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name)));
2860
2861     return (scn);
2862 }
2863
2864
2865 void
2866 findMDebugStaticAddresses(staticNameList * nameList, int nLists, int needed)
2867 {
2868     int fd;
2869     Elf *elf;
2870     Elf_Scn *mdebug_scn;
2871     Elf32_Shdr *mdebug_shdr;
2872     char *names;
2873
2874     if ((fd = open("/unix", O_RDONLY)) == -1) {
2875         printf("findMDebugStaticAddresses: Failed to open /unix.\n");
2876         return;
2877     }
2878
2879     (void)elf_version(EV_CURRENT);
2880     if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
2881         printf
2882             ("findMDebugStaticAddresses: /unix doesn't seem to be an elf file\n");
2883         close(fd);
2884         return;
2885     }
2886     mdebug_scn = findMDebugSection(elf, ".mdebug");
2887     if (!mdebug_scn) {
2888         printf("findMDebugStaticAddresses: Can't find .mdebug section.\n");
2889         goto find_end;
2890     }
2891     mdebug_shdr = elf32_getshdr(mdebug_scn);
2892     if (!mdebug_shdr) {
2893         printf("findMDebugStaticAddresses: Can't find .mdebug header.\n");
2894         goto find_end;
2895     }
2896
2897     (void)SearchMDebug(mdebug_scn, mdebug_shdr, nameList, nLists, needed);
2898
2899   find_end:
2900     elf_end(elf);
2901     close(fd);
2902 }
2903 #endif /* AFS_SGI62_ENV */
2904
2905 #else /* AFS_SGI61_ENV */
2906 #include <nlist.h>
2907 struct nlist nlunix[] = {
2908     {"rfsdisptab_v2"},
2909     {0},
2910 };
2911
2912 get_nfsstaticaddr()
2913 {
2914     int i, j, kmem, count;
2915
2916     if ((kmem = open("/dev/kmem", O_RDONLY)) < 0) {
2917         printf("Warning: can't open /dev/kmem\n");
2918         return 0;
2919     }
2920     if ((j = nlist("/unix", nlunix)) < 0) {
2921         printf("Warning: can't nlist /unix\n");
2922         return 0;
2923     }
2924     i = nlunix[0].n_value;
2925     if (lseek(kmem, i, L_SET /*0 */ ) != i) {
2926         printf("Warning: can't lseek to %x\n", i);
2927         return 0;
2928     }
2929     if ((j = read(kmem, &count, sizeof count)) != sizeof count) {
2930         printf("WARNING: kmem read at %x failed\n", i);
2931         return 0;
2932     }
2933     return i;
2934 }
2935 #endif /* AFS_SGI61_ENV */
2936 #endif /* AFS_SGI53_ENV */