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