LCOV - app.info - config/nsinstall.c

LCOV - code coverage report
| Current view: | directory - config - nsinstall.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 207 | 111 | 53.6 %
| Date: | 2012-04-07 | Functions: | 7 | 3 | 42.9 %

           1                 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 : /*
          38                 : ** Netscape portable install command.
          39                 : **
          40                 : ** Brendan Eich, 7/20/95
          41                 : */
          42                 : #include <stdio.h>  /* OSF/1 requires this before grp.h, so put it first */
          43                 : #include <assert.h>
          44                 : #include <fcntl.h>
          45                 : #include <errno.h>
          46                 : #include <dirent.h>
          47                 : #include <limits.h>
          48                 : #include <grp.h>
          49                 : #include <pwd.h>
          50                 : #include <stdio.h>
          51                 : #include <stdlib.h>
          52                 : #include <string.h>
          53                 : #include <unistd.h>
          54                 : #include <utime.h>
          55                 : #include <sys/types.h>
          56                 : #include <sys/stat.h>
          57                 : #include "pathsub.h"
          58                 :
          59                 : #ifdef HAVE_GETOPT_H
          60                 : #include <getopt.h>
          61                 : #endif
          62                 :
          63                 : #ifdef SUNOS4
          64                 : #include "sunos4.h"
          65                 : #endif
          66                 :
          67                 : #ifdef NEXTSTEP
          68                 : #include <bsd/libc.h>
          69                 : #endif
          70                 :
          71                 : #ifdef __QNX__
          72                 : #include <unix.h>
          73                 : #endif
          74                 :
          75                 : #ifdef NEED_S_ISLNK
          76                 : #if !defined(S_ISLNK) && defined(S_IFLNK)
          77                 : #define S_ISLNK(a)      (((a) & S_IFMT) == S_IFLNK)
          78                 : #endif
          79                 : #endif
          80                 :
          81                 : #ifndef _DIRECTORY_SEPARATOR
          82                 : #define _DIRECTORY_SEPARATOR "/"
          83                 : #endif /* _DIRECTORY_SEPARATOR */
          84                 :
          85                 : #ifdef NEED_FCHMOD_PROTO
          86                 : extern int fchmod(int fildes, mode_t mode);
          87                 : #endif
          88                 :
          89                 : static void
          90               0 : usage(void)
          91                 : {
          92               0 :     fprintf(stderr,
          93                 :         "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
          94                 :         "       %*s [-DdltR] file [file ...] directory\n",
          95               0 :         program, (int) strlen(program), "");
          96               0 :     exit(2);
          97                 : }
          98                 :
          99                 : static int
         100             956 : mkdirs(char *path, mode_t mode)
         101                 : {
         102                 :     char *cp;
         103                 :     struct stat sb;
         104                 :     int res;
         105                 :     int l;
         106                 :
         107                 :     /* strip trailing "/." */
         108             956 :     l = strlen(path);
         109             956 :     if(l > 1 && path[l - 1] == '.' && path[l - 2] == '/')
         110               0 :         path[l - 2] = 0;
         111                 :
         112            1912 :     while (*path == '/' && path[1] == '/')
         113               0 :         path++;
         114             956 :     for (cp = strrchr(path, '/'); cp && cp != path && *(cp - 1) == '/'; cp--);
         115             956 :     if (cp && cp != path) {
         116             955 :         *cp = '\0';
         117            1433 :         if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
         118             478 :             mkdirs(path, mode) < 0) {
         119               0 :             return -1;
         120                 :         }
         121             955 :         *cp = '/';
         122                 :     }
         123                 :
         124             956 :     res = mkdir(path, mode);
         125             956 :     if ((res != 0) && (errno == EEXIST))
         126               8 :       return 0;
         127                 :     else
         128             948 :       return res;
         129                 : }
         130                 :
         131                 : static uid_t
         132               0 : touid(char *owner)
         133                 : {
         134                 :     struct passwd *pw;
         135                 :     uid_t uid;
         136                 :     char *cp;
         137                 :
         138               0 :     pw = getpwnam(owner);
         139               0 :     if (pw)
         140               0 :         return pw->pw_uid;
         141               0 :     uid = strtol(owner, &cp, 0);
         142               0 :     if (uid == 0 && cp == owner)
         143               0 :         fail("cannot find uid for %s", owner);
         144               0 :     return uid;
         145                 : }
         146                 :
         147                 : static gid_t
         148               0 : togid(char *group)
         149                 : {
         150                 :     struct group *gr;
         151                 :     gid_t gid;
         152                 :     char *cp;
         153                 :
         154               0 :     gr = getgrnam(group);
         155               0 :     if (gr)
         156               0 :         return gr->gr_gid;
         157               0 :     gid = strtol(group, &cp, 0);
         158               0 :     if (gid == 0 && cp == group)
         159               0 :         fail("cannot find gid for %s", group);
         160               0 :     return gid;
         161                 : }
         162                 :
         163                 : static void
         164              43 : copyfile( char *name, char *toname, mode_t mode, char *group, char *owner,
         165                 :           int dotimes, uid_t uid, gid_t gid )
         166                 : {
         167              43 :   int fromfd, tofd = -1, cc, wc, exists;
         168                 :   char buf[BUFSIZ], *bp;
         169                 :   struct stat sb, tosb;
         170                 :   struct utimbuf utb;
         171                 :
         172              43 :   exists = (lstat(toname, &tosb) == 0);
         173                 :
         174              43 :   fromfd = open(name, O_RDONLY);
         175              43 :   if (fromfd < 0 || fstat(fromfd, &sb) < 0)
         176               0 :     fail("cannot access %s", name);
         177              43 :   if (exists) {
         178               0 :     if (S_ISREG(tosb.st_mode)) {
         179                 :       /* See if we can open it. This is more reliable than 'access'. */
         180               0 :       tofd = open(toname, O_CREAT | O_WRONLY, 0666);
         181                 :     }
         182               0 :     if (tofd < 0) {
         183               0 :       (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
         184                 :     }
         185                 :   }
         186              43 :   if (tofd < 0) {
         187              43 :     tofd = open(toname, O_CREAT | O_WRONLY, 0666);
         188              43 :     if (tofd < 0)
         189               0 :       fail("cannot create %s", toname);
         190                 :   }
         191                 :
         192              43 :   bp = buf;
         193             423 :   while ((cc = read(fromfd, bp, sizeof buf)) > 0)
         194                 :   {
         195             674 :     while ((wc = write(tofd, bp, (unsigned int)cc)) > 0)
         196                 :     {
         197             337 :       if ((cc -= wc) == 0)
         198             337 :         break;
         199               0 :       bp += wc;
         200                 :     }
         201             337 :     if (wc < 0)
         202               0 :       fail("cannot write to %s", toname);
         203                 :   }
         204              43 :   if (cc < 0)
         205               0 :     fail("cannot read from %s", name);
         206                 :
         207              43 :   if (ftruncate(tofd, sb.st_size) < 0)
         208               0 :     fail("cannot truncate %s", toname);
         209                 : #if !defined(VMS)
         210              43 :   if (dotimes)
         211                 :   {
         212              18 :     utb.actime = sb.st_atime;
         213              18 :     utb.modtime = sb.st_mtime;
         214              18 :     if (utime(toname, &utb) < 0)
         215               0 :       fail("cannot set times of %s", toname);
         216                 :   }
         217                 : #ifdef HAVE_FCHMOD
         218                 :   if (fchmod(tofd, mode) < 0)
         219                 : #else
         220              43 :   if (chmod(toname, mode) < 0)
         221                 : #endif
         222               0 :     fail("cannot change mode of %s", toname);
         223                 : #endif
         224              43 :   if ((owner || group) && fchown(tofd, uid, gid) < 0)
         225               0 :     fail("cannot change owner of %s", toname);
         226                 :
         227                 :   /* Must check for delayed (NFS) write errors on close. */
         228              43 :   if (close(tofd) < 0)
         229               0 :     fail("cannot write to %s", toname);
         230              43 :   close(fromfd);
         231                 : #if defined(VMS)
         232                 :   if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
         233                 :     fail("cannot change mode of %s", toname);
         234                 :   if (dotimes)
         235                 :   {
         236                 :     utb.actime = sb.st_atime;
         237                 :     utb.modtime = sb.st_mtime;
         238                 :     if (utime(toname, &utb) < 0)
         239                 :       fail("cannot set times of %s", toname);
         240                 :   }
         241                 : #endif
         242              43 : }
         243                 :
         244                 : static void
         245               0 : copydir( char *from, char *to, mode_t mode, char *group, char *owner,
         246                 :          int dotimes, uid_t uid, gid_t gid)
         247                 : {
         248                 :   int i;
         249                 :   DIR *dir;
         250                 :   struct dirent *ep;
         251                 :   struct stat sb;
         252                 :   char *base, *destdir, *direntry, *destentry;
         253                 :
         254               0 :   base = xbasename(from);
         255                 :
         256                 :   /* create destination directory */
         257               0 :   destdir = xmalloc((unsigned int)(strlen(to) + 1 + strlen(base) + 1));
         258               0 :   sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
         259               0 :   if (mkdirs(destdir, mode) != 0) {
         260               0 :     fail("cannot make directory %s\n", destdir);
         261               0 :     free(destdir);
         262               0 :     return;
         263                 :   }
         264                 :
         265               0 :   if (!(dir = opendir(from))) {
         266               0 :     fail("cannot open directory %s\n", from);
         267               0 :     free(destdir);
         268               0 :     return;
         269                 :   }
         270                 :
         271               0 :   direntry = xmalloc((unsigned int)PATH_MAX);
         272               0 :   destentry = xmalloc((unsigned int)PATH_MAX);
         273                 :
         274               0 :   while ((ep = readdir(dir)))
         275                 :   {
         276               0 :     if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
         277               0 :       continue;
         278                 :
         279               0 :     sprintf(direntry, "%s/%s", from, ep->d_name);
         280               0 :     sprintf(destentry, "%s%s%s", destdir, _DIRECTORY_SEPARATOR, ep->d_name);
         281                 :
         282               0 :     if (stat(direntry, &sb) == 0 && S_ISDIR(sb.st_mode))
         283               0 :       copydir( direntry, destdir, mode, group, owner, dotimes, uid, gid );
         284                 :     else
         285               0 :       copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
         286                 :   }
         287                 :
         288               0 :   free(destdir);
         289               0 :   free(direntry);
         290               0 :   free(destentry);
         291               0 :   closedir(dir);
         292                 : }
         293                 :
         294                 : int
         295            1628 : main(int argc, char **argv)
         296                 : {
         297                 :     int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
         298            1628 :     mode_t mode = 0755;
         299                 :     char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
         300                 :     uid_t uid;
         301                 :     gid_t gid;
         302                 :     struct stat sb, tosb, fromsb;
         303                 :     struct utimbuf utb;
         304                 :
         305            1628 :     program = argv[0];
         306            1628 :     cwd = linkname = linkprefix = owner = group = 0;
         307            1628 :     onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
         308                 :
         309            5921 :     while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
         310            2665 :         switch (opt) {
         311                 :           case 'C':
         312               0 :             cwd = optarg;
         313               0 :             break;
         314                 :           case 'D':
         315             110 :             onlydir = 1;
         316             110 :             break;
         317                 :           case 'd':
         318               0 :             dodir = 1;
         319               0 :             break;
         320                 :           case 'l':
         321               0 :             dolink = 1;
         322               0 :             break;
         323                 :           case 'L':
         324               0 :             linkprefix = optarg;
         325               0 :             lplen = strlen(linkprefix);
         326               0 :             dolink = 1;
         327               0 :             break;
         328                 :      case 'R':
         329            1491 :             dolink = dorelsymlink = 1;
         330            1491 :             break;
         331                 :           case 'm':
         332            1047 :             mode = strtoul(optarg, &cp, 8);
         333            1047 :             if (mode == 0 && cp == optarg)
         334               0 :                 usage();
         335            1047 :             break;
         336                 :           case 'o':
         337               0 :             owner = optarg;
         338               0 :             break;
         339                 :           case 'g':
         340               0 :             group = optarg;
         341               0 :             break;
         342                 :           case 't':
         343              17 :             dotimes = 1;
         344              17 :             break;
         345                 :           default:
         346               0 :             usage();
         347                 :         }
         348                 :     }
         349                 :
         350            1628 :     argc -= optind;
         351            1628 :     argv += optind;
         352            1628 :     if (argc < 2 - onlydir)
         353               0 :         usage();
         354                 :
         355            1628 :     todir = argv[argc-1];
         356            2106 :     if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
         357             478 :         mkdirs(todir, 0777) < 0) {
         358               0 :         fail("cannot make directory %s", todir);
         359                 :     }
         360            1628 :     if (onlydir)
         361             110 :         return 0;
         362                 :
         363            1518 :     if (!cwd) {
         364                 : #ifndef NEEDS_GETCWD
         365                 : #ifndef GETCWD_CANT_MALLOC
         366            1518 :         cwd = getcwd(0, PATH_MAX);
         367                 : #else
         368                 :         cwd = malloc(PATH_MAX + 1);
         369                 :         cwd = getcwd(cwd, PATH_MAX);
         370                 : #endif
         371                 : #else
         372                 :         cwd = malloc(PATH_MAX + 1);
         373                 :         cwd = getwd(cwd);
         374                 : #endif
         375                 :     }
         376                 :
         377            1518 :     xchdir(todir);
         378                 : #ifndef NEEDS_GETCWD
         379                 : #ifndef GETCWD_CANT_MALLOC
         380            1518 :     todir = getcwd(0, PATH_MAX);
         381                 : #else
         382                 :     todir = malloc(PATH_MAX + 1);
         383                 :     todir = getcwd(todir, PATH_MAX);
         384                 : #endif
         385                 : #else
         386                 :     todir = malloc(PATH_MAX + 1);
         387                 :     todir = getwd(todir);
         388                 : #endif
         389            1518 :     tdlen = strlen(todir);
         390            1518 :     xchdir(cwd);
         391            1518 :     tdlen = strlen(todir);
         392                 :
         393            1518 :     uid = owner ? touid(owner) : (uid_t)(-1);
         394            1518 :     gid = group ? togid(group) : (gid_t)(-1);
         395                 :
         396           17704 :     while (--argc > 0) {
         397           14668 :         name = *argv++;
         398           14668 :         len = strlen(name);
         399           14668 :         base = xbasename(name);
         400           14668 :         bnlen = strlen(base);
         401           14668 :         toname = xmalloc((unsigned int)(tdlen + 1 + bnlen + 1));
         402           14668 :         sprintf(toname, "%s%s%s", todir, _DIRECTORY_SEPARATOR, base);
         403           14668 :         exists = (lstat(toname, &tosb) == 0);
         404                 :
         405           14668 :         if (dodir) {
         406                 :             /* -d means create a directory, always */
         407               0 :             if (exists && !S_ISDIR(tosb.st_mode)) {
         408               0 :                 (void) unlink(toname);
         409               0 :                 exists = 0;
         410                 :             }
         411               0 :             if (!exists && mkdir(toname, mode) < 0)
         412               0 :                 fail("cannot make directory %s", toname);
         413               0 :             if ((owner || group) && chown(toname, uid, gid) < 0)
         414               0 :                 fail("cannot change owner of %s", toname);
         415           14668 :         } else if (dolink) {
         416           14625 :             if (access(name, R_OK) != 0) {
         417               0 :                 fail("cannot access %s", name);
         418                 :             }
         419           14625 :             if (*name == '/') {
         420                 :                 /* source is absolute pathname, link to it directly */
         421           12569 :                 linkname = 0;
         422                 :             } else {
         423            2056 :                 if (linkprefix) {
         424                 :                     /* -L implies -l and prefixes names with a $cwd arg. */
         425               0 :                     len += lplen + 1;
         426               0 :                     linkname = xmalloc((unsigned int)(len + 1));
         427               0 :                     sprintf(linkname, "%s/%s", linkprefix, name);
         428            2056 :                 } else if (dorelsymlink) {
         429                 :                     /* Symlink the relative path from todir to source name. */
         430            2056 :                     linkname = xmalloc(PATH_MAX);
         431                 :
         432            2056 :                     if (*todir == '/') {
         433                 :                         /* todir is absolute: skip over common prefix. */
         434            2056 :                         lplen = relatepaths(todir, cwd, linkname);
         435            2056 :                         strcpy(linkname + lplen, name);
         436                 :                     } else {
         437                 :                         /* todir is named by a relative path: reverse it. */
         438               0 :                         reversepath(todir, name, len, linkname);
         439               0 :                         xchdir(cwd);
         440                 :                     }
         441                 :
         442            2056 :                     len = strlen(linkname);
         443                 :                 }
         444            2056 :                 name = linkname;
         445                 :             }
         446                 :
         447                 :             /* Check for a pre-existing symlink with identical content. */
         448           14834 :             if ((exists && (!S_ISLNK(tosb.st_mode) ||
         449             418 :                                                 readlink(toname, buf, sizeof buf) != len ||
         450           14834 :                                                 strncmp(buf, name, (unsigned int)len) != 0)) ||
         451           27853 :                         ((stat(name, &fromsb) == 0) &&
         452           13228 :                          (fromsb.st_mtime > tosb.st_mtime))) {
         453           13174 :                 (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
         454           13174 :                 exists = 0;
         455                 :             }
         456           14625 :             if (!exists && symlink(name, toname) < 0)
         457               0 :                 fail("cannot make symbolic link %s", toname);
         458                 : #ifdef HAVE_LCHOWN
         459                 :             if ((owner || group) && lchown(toname, uid, gid) < 0)
         460                 :                 fail("cannot change owner of %s", toname);
         461                 : #endif
         462                 :
         463           14625 :             if (linkname) {
         464            2056 :                 free(linkname);
         465            2056 :                 linkname = 0;
         466                 :             }
         467                 :         } else {
         468                 :             /* Copy from name to toname, which might be the same file. */
         469              43 :       if( stat(name, &sb) == 0 && S_IFDIR & sb.st_mode )
         470                 :       {
         471                 :         /* then is directory: must explicitly create destination dir  */
         472                 :         /*  and manually copy files over                              */
         473               0 :         copydir( name, todir, mode, group, owner, dotimes, uid, gid );
         474                 :       }
         475                 :       else
         476                 :       {
         477              43 :         copyfile(name, toname, mode, group, owner, dotimes, uid, gid);
         478                 :       }
         479                 :     }
         480                 :
         481           14668 :         free(toname);
         482                 :     }
         483                 :
         484            1518 :     free(cwd);
         485            1518 :     free(todir);
         486            1518 :     return 0;
         487                 : }

Generated by: LCOV version 1.7