1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <locale.h>
  30 #include <stdio.h>
  31 #include <string.h>
  32 #include <sys/param.h>
  33 #include <unistd.h>
  34 
  35 #define MAIN    1
  36 #include "rules.h"
  37 #include "elfrd.h"
  38 
  39 int verbose = 0;
  40 struct libpath *libp, libp_hd;
  41 
  42 int
  43 main(int argc, char **argv)
  44 {
  45         int prtfn();
  46         int packfn();
  47         int unpackfn();
  48         int inquirefn();
  49         FILE *open_rulesfile();
  50         FILE *rfd;
  51         int c;
  52         int fflag = 0;
  53         int Bflag = 0;
  54         int index;
  55         char *rulesfile;
  56         int typearg = 0;
  57         int (*wrkfunc)();
  58         extern char *optarg;
  59         extern int optind, opterr;
  60         extern void bld_pack_list();
  61         extern void usage();
  62 
  63         (void) setlocale(LC_ALL, "");
  64 #if !defined(TEXT_DOMAIN)
  65 #define TEXT_DOMAIN     "SYS_TEST"
  66 #endif
  67         (void) textdomain(TEXT_DOMAIN);
  68 
  69         global_flags = LF_NULL;
  70 
  71         rfd = open_rulesfile();
  72 
  73         libp = &libp_hd;
  74         get_libsrch_path(libp);
  75 
  76         /* create hash table for tracking libraries */
  77         if (hcreate(10000) == 0) {
  78                 /* unlikely this ever happens or I would work around it */
  79                 fprintf(stderr,
  80                     gettext("cachefspack: can't create hash table\n"));
  81                 exit(1);
  82         }
  83 
  84         while ((c = getopt(argc, argv, "df:hiprsuvB:I:L:U:")) != -1) {
  85                 switch (c) {
  86                 case 'd':
  87                         wrkfunc = prtfn;
  88                         typearg++;
  89                         break;
  90                 case 'f':
  91                         fflag++;
  92                         rulesfile = strdup(optarg);
  93                         break;
  94                 case 'h':
  95                         usage();
  96                         exit(0);
  97                         break;
  98                 case 'i':
  99                         wrkfunc = inquirefn;
 100                         typearg++;
 101                         break;
 102                 case 'p':
 103                         wrkfunc = packfn;
 104                         typearg++;
 105                         break;
 106                 case 'r':
 107                         global_flags |= LF_REGEX;
 108                         break;
 109                 case 's':
 110                         global_flags |= LF_STRIP_DOTSLASH;
 111                         break;
 112                 case 'u':
 113                         wrkfunc = unpackfn;
 114                         typearg++;
 115                         break;
 116                 case 'v':
 117                         verbose = 1;
 118                         break;
 119                 case 'B':
 120                         Bflag++;
 121                         fprintf(rfd, "BASE %s\n", optarg);
 122                         break;
 123                 case 'I':
 124                         fprintf(rfd, "IGNORE %s\n", optarg);
 125                         break;
 126                 case 'L':
 127                         fprintf(rfd, "LIST %s\n", optarg);
 128                         break;
 129                 case 'U':
 130                         typearg++;
 131                         wrkfunc = unpackfn;
 132                         bld_pack_list(rfd, optarg);
 133                         break;
 134                 default:
 135                         usage();
 136                         exit(1);
 137                 }
 138         }
 139 
 140         def_lign_flags = LF_NULL;
 141         def_gign_flags = LF_NULL;
 142         def_list_flags = LF_REGEX;
 143         bang_list_flags = LF_STRIP_DOTSLASH;
 144         if (global_flags != 0) {
 145                 def_list_flags = global_flags;
 146                 bang_list_flags = global_flags;
 147         }
 148 
 149         if (fflag & Bflag) {
 150                 fprintf(stderr, gettext(
 151                     "cachefspack: B and f options are mutually exclusive\n"));
 152                 exit(1);
 153         }
 154 
 155         if (fflag) {
 156                 fclose(rfd);
 157                 rfd = fopen(rulesfile, "r");
 158                 if (rfd == NULL) {
 159                         fprintf(stderr, gettext(
 160                             "cachefspack: can't open file associated"
 161                             " with -f\n"));
 162                         exit(1);
 163                 }
 164         }
 165 
 166         if (typearg != 1) {
 167                 if (typearg == 0) {
 168                         wrkfunc = packfn;
 169                 } else {
 170                         fprintf(stderr,
 171                             gettext(
 172                             "cachefspack: only one 'd', 'i', 'p' or 'u' "));
 173                         fprintf(stderr,
 174                             gettext(" option allowed\n"));
 175                         exit(1);
 176                 }
 177         }
 178         if (optind < argc) {
 179                 if (fflag || Bflag) {
 180                         fprintf(stderr,
 181                             gettext(
 182                             "cachefspack: 'B' or 'f' specified "));
 183                         fprintf(stderr,
 184                             gettext("with filenames\n"));
 185                         exit(1);
 186                 }
 187                 for (index = optind; index < argc; index++) {
 188 #ifdef  DEBUG
 189                         printf("argv[%d] = %s\n", index, argv[index]);
 190 #endif /* DEBUG */
 191                         bld_pack_list(rfd, argv[index]);
 192                 }
 193         }
 194         rewind(rfd);
 195         read_rules(rfd, wrkfunc);
 196         fclose(rfd);
 197         return (0);
 198 }
 199 
 200 /*
 201  * The bld_pack_list() function is used to write the temporary packing
 202  * list function. When the BASE directory changes, a new BASE command is
 203  * generated. If the  filename argument(fnam) starts with a '/', then the
 204  * filename is assumed to be an absolute pathname. Otherwise, the filename
 205  * is assumed to be realtive to the current directory.
 206  */
 207 void
 208 bld_pack_list(FILE *fd, char *filename)
 209 {
 210         static char last_base[MAXPATHLEN+1] = {" "};
 211         static char fnam[MAXPATHLEN+1];
 212         static int last_base_sz = 1;
 213         char *lastsl_pos;
 214         int sz;
 215         int endpos;
 216         char *cwd;
 217 
 218         /* strip off any trailing /'s */
 219         strcpy(fnam, filename);
 220         for (endpos = strlen(fnam) - 1; endpos > 0; endpos--) {
 221                 if (fnam[endpos] == '/')
 222                         fnam[endpos] = '\0';
 223                 else
 224                         break;
 225         }
 226 
 227         if (*fnam == '/') {     /* absolute pathname */
 228                 lastsl_pos = strrchr(fnam, '/');
 229                 sz = (int)lastsl_pos - (int)fnam + 1;
 230                 if ((last_base_sz != sz) ||
 231                     (strncmp(last_base, fnam, sz) != 0)) {
 232                         fprintf(fd, "BASE %.*s\n", (sz <= 1 ? sz : sz-1), fnam);
 233                         last_base_sz = sz;
 234                         strncpy(last_base, fnam, sz);
 235                 }
 236                 fprintf(fd, "LIST %s\n", &fnam[sz]);
 237         } else {                /* relative pathname */
 238                 /* Really only need to call this once, ... */
 239                 cwd = getcwd(NULL, MAXPATHLEN+1);
 240                 sz = strlen(cwd);
 241                 if ((last_base_sz != sz) ||
 242                     (strncmp(last_base, cwd, sz) != 0)) {
 243                         fprintf(fd, "BASE %s\n", cwd);
 244                         last_base_sz = sz;
 245                         strncpy(last_base, cwd, sz);
 246                 }
 247                 free(cwd);
 248                 fprintf(fd, "LIST %s\n", fnam);
 249         }
 250 }
 251 
 252 void
 253 usage()
 254 {
 255 #ifdef  DEBUG
 256         printf(
 257             gettext("cachefspack -[dipu] -[fBIL] [-h] [-r] [-s] [-U dir]"));
 258 #else  /* DEBUG */
 259         printf(
 260             gettext("cachefspack -[dipu] -[f] [-h] [-r] [-s] [-U dir]"));
 261 #endif /* DEBUG */
 262         printf(gettext(" [files]\n"));
 263         printf("\n");
 264         printf(
 265             gettext("Must select 1 and only 1 of the following 5 options\n"));
 266         printf(gettext("-d Display selected filenames\n"));
 267         printf(gettext("-i Display selected filenames packing status\n"));
 268         printf(gettext("-p Pack selected filenames\n"));
 269         printf(gettext("-u Unpack selected filenames\n"));
 270         printf(gettext("-U Unpack all files in directory 'dir'\n"));
 271         printf(gettext("\n"));
 272         printf(gettext("-f Specify input file containing rules\n"));
 273 #ifdef  DEBUG
 274         printf(gettext("-B Specify BASE rule on command line\n"));
 275         printf(gettext("-I Specify IGNORE rule on command line\n"));
 276         printf(gettext("-L Specify LIST rule on command line\n"));
 277         printf(gettext("\n"));
 278 #endif /* DEBUG */
 279         printf(gettext("-h Print usage information\n"));
 280         printf(gettext(
 281             "-r Interpret strings in LIST rules as regular expressions\n"));
 282         printf(gettext("-s Strip './' from the beginning of a pattern name\n"));
 283         printf(gettext("-v Verbose option\n"));
 284         printf(gettext("files - a list of filenames to be packed/unpacked\n"));
 285 }