Ignore:
Timestamp:
Dec 18, 2005, 4:48:02 AM (20 years ago)
Author:
bird
Message:

o Ported all kmk builtins to win32.
o Fixed serveral bugs in kmk builtins.
o Probably broke both linux, bsd and OS/2. :-)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gmake/kmkbuiltin/install.c

    r368 r370  
    4242static char sccsid[] = "@(#)xinstall.c  8.1 (Berkeley) 7/21/93";
    4343#endif /* not lint */
    44 #endif
    4544
    4645#include <sys/cdefs.h>
    4746__FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 ssouhlal Exp $");
    48 
     47#endif
     48
     49#ifndef _MSC_VER
    4950#include <sys/param.h>
     51#ifdef USE_MMAP
    5052#include <sys/mman.h>
     53#endif
    5154#include <sys/mount.h>
     55#include <sys/wait.h>
     56#include <sys/time.h>
     57#else
     58#include <process.h>
     59#endif
    5260#include <sys/stat.h>
    53 #include <sys/time.h>
    54 #include <sys/wait.h>
    5561
    5662#include <ctype.h>
    57 #include <err.h>
     63#include "err.h"
    5864#include <errno.h>
    5965#include <fcntl.h>
     66#ifndef _MSC_VER
    6067#include <grp.h>
    6168#include <paths.h>
    6269#include <pwd.h>
     70#endif
    6371#include <stdio.h>
    6472#include <stdlib.h>
    6573#include <string.h>
     74#ifndef _MSC_VER
    6675#include <sysexits.h>
    6776#include <unistd.h>
     77#else
     78#include "mscfakes.h"
     79#endif
     80
     81extern void * setmode(const char *p);
     82extern mode_t getmode(const void *bbox, mode_t omode);
     83
     84#ifndef __unused
     85# define __unused
     86#endif
     87
     88#ifndef MAXBSIZE
     89# define MAXBSIZE 16384
     90#endif
    6891
    6992/* Bootstrap aid - this doesn't exist in most older releases */
     
    83106#endif
    84107
    85 static struct passwd *pp;
    86 static struct group *gp;
    87108static gid_t gid;
    88109static uid_t uid;
     
    91112static const char *suffix = BACKUP_SUFFIX;
    92113
    93 static void     copy(int, const char *, int, const char *, off_t);
     114static int      copy(int, const char *, int, const char *, off_t);
    94115static int      compare(int, const char *, size_t, int, const char *, size_t);
    95116static int      create_newfile(const char *, int, struct stat *);
    96117static int      create_tempfile(const char *, char *, size_t);
    97 static void     install(const char *, const char *, u_long, u_int);
    98 static void     install_dir(char *);
     118static int      install(const char *, const char *, u_long, u_int);
     119static int      install_dir(char *);
    99120static u_long   numeric_id(const char *, const char *);
    100 static void     strip(const char *);
     121static int      strip(const char *);
     122#ifdef USE_MMAP
    101123static int      trymmap(int);
    102 static void     usage(void);
     124#endif
     125static int      usage(void);
    103126
    104127int
     
    107130        struct stat from_sb, to_sb;
    108131        mode_t *set;
    109         u_long fset;
     132        u_long fset = 0;
    110133        int ch, no_target;
    111134        u_int iflags;
     
    132155                        dodir = 1;
    133156                        break;
    134                     case 'f':
     157                case 'f':
    135158#ifdef UF_IMMUTABLE
    136159                        flags = optarg;
    137160                        if (strtofflags(&flags, &fset, NULL))
    138                                 errx(EX_USAGE, "%s: invalid flag", flags);
     161                                return errx(EX_USAGE, "%s: invalid flag", flags);
    139162                        iflags |= SETFLAGS;
     163#else   
     164                        (void)flags;
    140165#endif
    141166                        break;
     
    152177                        if (!(set = setmode(optarg)))
    153178#endif
    154                                 errx(EX_USAGE, "invalid file mode: %s",
    155                                      optarg);
     179                                return errx(EX_USAGE, "invalid file mode: %s",
     180                                            optarg);
    156181                        mode = getmode(set, 0);
    157182                        free(set);
     
    174199                case '?':
    175200                default:
    176                         usage();
     201                        return usage();
    177202                }
    178203        argc -= optind;
     
    182207        if (dostrip && dodir) {
    183208                warnx("-d and -s may not be specified together");
    184                 usage();
     209                return usage();
    185210        }
    186211
    187212        /* must have at least two arguments, except when creating directories */
    188213        if (argc == 0 || (argc == 1 && !dodir))
    189                 usage();
     214                return usage();
    190215
    191216        /* need to make a temp copy so we can compare stripped version */
     
    195220        /* get group and owner id's */
    196221        if (group != NULL) {
     222#ifndef _MSC_VER
     223                struct group *gp;
    197224                if ((gp = getgrnam(group)) != NULL)
    198225                        gid = gp->gr_gid;
    199226                else
     227#endif
     228                {
    200229                        gid = (gid_t)numeric_id(group, "group");
     230                        if (gid == (gid_t)-1)
     231                                return 1;
     232                }
    201233        } else
    202234                gid = (gid_t)-1;
    203235
    204236        if (owner != NULL) {
     237#ifndef _MSC_VER
     238                struct passwd *pp;
    205239                if ((pp = getpwnam(owner)) != NULL)
    206240                        uid = pp->pw_uid;
    207241                else
     242#endif
     243                {
    208244                        uid = (uid_t)numeric_id(owner, "user");
     245                        if (uid == (uid_t)-1)
     246                                return 1;
     247                }
    209248        } else
    210249                uid = (uid_t)-1;
    211250
    212251        if (dodir) {
    213                 for (; *argv != NULL; ++argv)
    214                         install_dir(*argv);
    215                 exit(EX_OK);
     252                for (; *argv != NULL; ++argv) {
     253                        int rc = install_dir(*argv);
     254                        if (rc)
     255                                return rc;
     256                }
     257                return EX_OK;
    216258                /* NOTREACHED */
    217259        }
     
    219261        no_target = stat(to_name = argv[argc - 1], &to_sb);
    220262        if (!no_target && S_ISDIR(to_sb.st_mode)) {
    221                 for (; *argv != to_name; ++argv)
    222                         install(*argv, to_name, fset, iflags | DIRECTORY);
    223                 exit(EX_OK);
    224                 /* NOTREACHED */
     263                for (; *argv != to_name; ++argv) {
     264                        int rc = install(*argv, to_name, fset, iflags | DIRECTORY);
     265                        if (rc)
     266                                return rc;
     267                }
     268                return EX_OK;
    225269        }
    226270
     
    228272        if (argc != 2) {
    229273                warnx("wrong number or types of arguments");
    230                 usage();
     274                return usage();
    231275        }
    232276
    233277        if (!no_target) {
    234278                if (stat(*argv, &from_sb))
    235                         err(EX_OSERR, "%s", *argv);
     279                        return err(EX_OSERR, "%s", *argv);
    236280                if (!S_ISREG(to_sb.st_mode)) {
    237281                        errno = EFTYPE;
    238                         err(EX_OSERR, "%s", to_name);
     282                        return err(EX_OSERR, "%s", to_name);
    239283                }
    240284                if (to_sb.st_dev == from_sb.st_dev &&
    241                     to_sb.st_ino == from_sb.st_ino)
    242                         errx(EX_USAGE,
    243                             "%s and %s are the same file", *argv, to_name);
    244         }
    245         install(*argv, to_name, fset, iflags);
    246         exit(EX_OK);
    247         /* NOTREACHED */
    248 }
    249 
    250 u_long
     285                    to_sb.st_dev != 0 &&
     286                    to_sb.st_ino == from_sb.st_ino &&
     287                    to_sb.st_ino != 0)
     288                        return errx(EX_USAGE,
     289                                    "%s and %s are the same file", *argv, to_name);
     290        }
     291        return install(*argv, to_name, fset, iflags);
     292}
     293
     294static u_long
    251295numeric_id(const char *name, const char *type)
    252296{
     
    261305        val = strtoul(name, &ep, 10);
    262306        if (errno)
    263                 err(EX_NOUSER, "%s", name);
     307                return err(-1, "%s", name);
    264308        if (*ep != '\0')
    265                 errx(EX_NOUSER, "unknown %s %s", type, name);
     309                return errx(-1, "unknown %s %s", type, name);
    266310        return (val);
    267311}
     
    271315 *      build a path name and install the file
    272316 */
    273 void
     317static int
    274318install(const char *from_name, const char *to_name, u_long fset, u_int flags)
    275319{
     
    279323        int tempcopy, temp_fd, to_fd;
    280324        char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
     325        int rc = EX_OK;
    281326
    282327        files_match = 0;
    283328        from_fd = -1;
    284329        to_fd = -1;
     330        temp_fd = -1;
    285331
    286332        /* If try to install NULL file to a directory, fails. */
    287         if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
     333        if (flags & DIRECTORY
     334#if defined(__EMX__) || defined(_MSC_VER)
     335            || (   stricmp(from_name, _PATH_DEVNULL)
     336                && stricmp(from_name, "nul")
     337#ifdef __EMX__
     338                && stricmp(from_name, "/dev/nul")
     339#endif
     340               )
     341#else
     342            || strcmp(from_name, _PATH_DEVNULL)
     343#endif
     344            ) {
    288345                if (stat(from_name, &from_sb))
    289                         err(EX_OSERR, "%s", from_name);
     346                        return err(EX_OSERR, "%s", from_name);
    290347                if (!S_ISREG(from_sb.st_mode)) {
    291348                        errno = EFTYPE;
    292                         err(EX_OSERR, "%s", from_name);
     349                        return err(EX_OSERR, "%s", from_name);
    293350                }
    294351                /* Build the target path. */
     
    310367                errno = EFTYPE;
    311368                warn("%s", to_name);
    312                 return;
     369                return EX_OK;
    313370        }
    314371
     
    317374
    318375        if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0)
    319                 err(EX_OSERR, "%s", from_name);
     376                return err(EX_OSERR, "%s", from_name);
    320377
    321378        /* If we don't strip, we can compare first. */
    322379        if (docompare && !dostrip && target) {
    323                 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0)
    324                         err(EX_OSERR, "%s", to_name);
     380                if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
     381                        rc = err(EX_OSERR, "%s", to_name);
     382                        goto l_done;
     383                }
    325384                if (devnull)
    326385                        files_match = to_sb.st_size == 0;
     
    331390
    332391                /* Close "to" file unless we match. */
    333                 if (!files_match)
     392                if (!files_match) {
    334393                        (void)close(to_fd);
     394                        to_fd = -1;
     395                }
    335396        }
    336397
     
    339400                        to_fd = create_tempfile(to_name, tempfile,
    340401                            sizeof(tempfile));
    341                         if (to_fd < 0)
    342                                 err(EX_OSERR, "%s", tempfile);
     402                        if (to_fd < 0) {
     403                                rc = err(EX_OSERR, "%s", tempfile);
     404                                goto l_done;
     405                        }
    343406                } else {
    344407                        if ((to_fd = create_newfile(to_name, target,
    345                             &to_sb)) < 0)
    346                                 err(EX_OSERR, "%s", to_name);
     408                            &to_sb)) < 0) {
     409                                rc = err(EX_OSERR, "%s", to_name);
     410                                goto l_done;
     411                        }
    347412                        if (verbose)
    348413                                (void)printf("install: %s -> %s\n",
    349414                                    from_name, to_name);
    350415                }
    351                 if (!devnull)
    352                         copy(from_fd, from_name, to_fd,
    353                              tempcopy ? tempfile : to_name, from_sb.st_size);
     416                if (!devnull) {
     417                        rc = copy(from_fd, from_name, to_fd,
     418                                  tempcopy ? tempfile : to_name, from_sb.st_size);
     419                        if (rc)
     420                                goto l_done;
     421                }
    354422        }
    355423
    356424        if (dostrip) {
    357                 strip(tempcopy ? tempfile : to_name);
     425#if defined(__EMX__) || defined(_MSC_VER)
     426                /* close before we strip. */
     427                close(to_fd);
     428                to_fd = -1;
     429#endif
     430                rc = strip(tempcopy ? tempfile : to_name);
     431                if (rc)
     432                        goto l_done;
    358433
    359434                /*
     
    361436                 * that does not work in-place -- like GNU binutils strip.
    362437                 */
     438#if !defined(__EMX__) && !defined(_MSC_VER)
    363439                close(to_fd);
     440#endif
    364441                to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0);
    365                 if (to_fd < 0)
    366                         err(EX_OSERR, "stripping %s", to_name);
     442                if (to_fd < 0) {
     443                        rc = err(EX_OSERR, "stripping %s", to_name);
     444                        goto l_done;
     445                }
    367446        }
    368447
     
    374453
    375454                /* Re-open to_fd using the real target name. */
    376                 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0)
    377                         err(EX_OSERR, "%s", to_name);
     455                if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
     456                        rc = err(EX_OSERR, "%s", to_name);
     457                        goto l_done;
     458                }
    378459
    379460                if (fstat(temp_fd, &temp_sb)) {
     
    381462                        (void)unlink(tempfile);
    382463                        errno = serrno;
    383                         err(EX_OSERR, "%s", tempfile);
     464                        rc = err(EX_OSERR, "%s", tempfile);
     465                        goto l_done;
    384466                }
    385467
     
    391473                         * Need to preserve target file times, though.
    392474                         */
     475#if !defined(_MSC_VER) && !defined(__EMX__)
    393476                        if (to_sb.st_nlink != 1) {
    394477                                tvb[0].tv_sec = to_sb.st_atime;
     
    397480                                tvb[1].tv_usec = 0;
    398481                                (void)utimes(tempfile, tvb);
    399                         } else {
     482                        } else
     483#endif
     484                        {
     485
    400486                                files_match = 1;
    401487                                (void)unlink(tempfile);
    402488                        }
    403489                        (void) close(temp_fd);
     490                        temp_fd = -1;
    404491                }
    405492        }
     
    419506                            suffix) != strlen(to_name) + strlen(suffix)) {
    420507                                unlink(tempfile);
    421                                 errx(EX_OSERR, "%s: backup filename too long",
    422                                     to_name);
     508                                rc = errx(EX_OSERR, "%s: backup filename too long",
     509                                          to_name);
     510                                goto l_done;
    423511                        }
    424512                        if (verbose)
     
    428516                                unlink(tempfile);
    429517                                errno = serrno;
    430                                 err(EX_OSERR, "rename: %s to %s", to_name,
    431                                      backup);
     518                                rc = err(EX_OSERR, "rename: %s to %s", to_name,
     519                                         backup);
     520                                goto l_done;
    432521                        }
    433522                }
     
    438527                        unlink(tempfile);
    439528                        errno = serrno;
    440                         err(EX_OSERR, "rename: %s to %s",
    441                             tempfile, to_name);
     529                        rc = err(EX_OSERR, "rename: %s to %s",
     530                                 tempfile, to_name);
     531                        goto l_done;
    442532                }
    443533
    444534                /* Re-open to_fd so we aren't hosed by the rename(2). */
    445535                (void) close(to_fd);
    446                 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0)
    447                         err(EX_OSERR, "%s", to_name);
     536                if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
     537                        rc = err(EX_OSERR, "%s", to_name);
     538                        goto l_done;
     539                }
    448540        }
    449541
     
    463555                (void)unlink(to_name);
    464556                errno = serrno;
    465                 err(EX_OSERR, "%s", to_name);
     557                rc = err(EX_OSERR, "%s", to_name);
     558                goto l_done;
    466559        }
    467560
     
    486579                        (void)unlink(to_name);
    487580                        errno = serrno;
    488                         err(EX_OSERR,"%s: chown/chgrp", to_name);
     581                        rc = err(EX_OSERR,"%s: chown/chgrp", to_name);
     582                        goto l_done;
    489583                }
    490584
     
    494588                        (void)unlink(to_name);
    495589                        errno = serrno;
    496                         err(EX_OSERR, "%s: chmod", to_name);
     590                        rc = err(EX_OSERR, "%s: chmod", to_name);
     591                        goto l_done;
    497592                }
    498593
     
    516611                                (void)unlink(to_name);
    517612                                errno = serrno;
    518                                 err(EX_OSERR, "%s: chflags", to_name);
    519                         }
    520                 }
    521         }
    522 #endif
    523 
    524         (void)close(to_fd);
     613                                rc = err(EX_OSERR, "%s: chflags", to_name);
     614                                goto l_done;
     615                        }
     616                }
     617        }
     618#endif
     619
     620l_done:
     621        if (to_fd >= 0)
     622                (void)close(to_fd);
     623        if (temp_fd >= 0)
     624                (void)close(temp_fd);
    525625        if (!devnull)
    526626                (void)close(from_fd);
     627        return rc;
    527628}
    528629
     
    531632 *      compare two files; non-zero means files differ
    532633 */
    533 int
     634static int
    534635compare(int from_fd, const char *from_name __unused, size_t from_len,
    535636        int to_fd, const char *to_name __unused, size_t to_len)
     
    544645
    545646        if (from_len <= MAX_CMP_SIZE) {
    546 #if !defined(__EMX__) && !defined(_MSC_VER)
     647#ifdef USE_MMAP
    547648                done_compare = 0;
    548649                if (trymmap(from_fd) && trymmap(to_fd)) {
     
    561662                        done_compare = 1;
    562663                }
    563 #endif
    564664        out:
     665#else
     666        (void)p; (void)q;
     667        done_compare = 0;
     668#endif
    565669                if (!done_compare) {
    566670                        char buf1[MAXBSIZE];
     
    637741                if (dobackup) {
    638742                        if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s",
    639                             path, suffix) != strlen(path) + strlen(suffix))
     743                            path, suffix) != strlen(path) + strlen(suffix)) {
    640744                                errx(EX_OSERR, "%s: backup filename too long",
    641                                     path);
     745                                     path);
     746                                errno = ENAMETOOLONG;
     747                                return -1;
     748                        }
    642749                        (void)snprintf(backup, MAXPATHLEN, "%s%s",
    643750                            path, suffix);
     
    645752                                (void)printf("install: %s -> %s\n",
    646753                                    path, backup);
    647                         if (rename(path, backup) < 0)
     754                        if (rename(path, backup) < 0) {
    648755                                err(EX_OSERR, "rename: %s to %s", path, backup);
     756                                return -1;
     757                        }
    649758                } else
    650759                        if (unlink(path) < 0)
     
    662771 *      copy from one file to another
    663772 */
    664 void
     773static int
    665774copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
    666775    off_t size)
     
    673782        /* Rewind file descriptors. */
    674783        if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1)
    675                 err(EX_OSERR, "lseek: %s", from_name);
     784                return err(EX_OSERR, "lseek: %s", from_name);
    676785        if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1)
    677                 err(EX_OSERR, "lseek: %s", to_name);
     786                return err(EX_OSERR, "lseek: %s", to_name);
    678787
    679788        /*
     
    683792         */
    684793        done_copy = 0;
    685 #if !defined(__EMX__) && !defined(_MSC_VER)
     794#ifdef USE_MMAP
    686795        if (size <= 8 * 1048576 && trymmap(from_fd) &&
    687796            (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED,
     
    695804                done_copy = 1;
    696805        }
     806#else
     807        (void)p;
    697808#endif
    698809        if (!done_copy) {
     
    702813                                (void)unlink(to_name);
    703814                                errno = nw > 0 ? EIO : serrno;
    704                                 err(EX_OSERR, "%s", to_name);
     815                                return err(EX_OSERR, "%s", to_name);
    705816                        }
    706817                if (nr != 0) {
     
    708819                        (void)unlink(to_name);
    709820                        errno = serrno;
    710                         err(EX_OSERR, "%s", from_name);
    711                 }
    712         }
     821                        return err(EX_OSERR, "%s", from_name);
     822                }
     823        }
     824        return EX_OK;
    713825}
    714826
     
    717829 *      use strip(1) to strip the target file
    718830 */
    719 void
     831static int
    720832strip(const char *to_name)
    721833{
     834#if defined(__EMX__) || defined(_MSC_VER)
     835        const char *stripbin = getenv("STRIPBIN");
     836        if (stripbin == NULL)
     837                stripbin = "strip";
     838        return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL);
     839#else
    722840        const char *stripbin;
    723841        int serrno, status;
     
    743861                }
    744862        }
     863#endif
    745864}
    746865
     
    749868 *      build directory heirarchy
    750869 */
    751 void
     870static int
    752871install_dir(char *path)
    753872{
     
    762881                        if (stat(path, &sb)) {
    763882                                if (errno != ENOENT || mkdir(path, 0755) < 0) {
    764                                         err(EX_OSERR, "mkdir %s", path);
     883                                        return err(EX_OSERR, "mkdir %s", path);
    765884                                        /* NOTREACHED */
    766885                                } else if (verbose)
     
    768887                                                     path);
    769888                        } else if (!S_ISDIR(sb.st_mode))
    770                                 errx(EX_OSERR, "%s exists but is not a directory", path);
     889                                return errx(EX_OSERR, "%s exists but is not a directory", path);
    771890                        if (!(*p = ch))
    772891                                break;
     
    777896        if (chmod(path, mode))
    778897                warn("chmod %o %s", mode, path);
     898        return EX_OK;
    779899}
    780900
     
    783903 *      print a usage message and die
    784904 */
    785 void
     905static int
    786906usage()
    787907{
     
    792912"               [-o owner] file1 ... fileN directory\n"
    793913"       install -d [-v] [-g group] [-m mode] [-o owner] directory ...\n");
    794         exit(EX_USAGE);
    795         /* NOTREACHED */
    796 }
    797 
     914        return EX_USAGE;
     915}
     916
     917#ifdef USE_MMAP
    798918/*
    799919 * trymmap --
    800920 *      return true (1) if mmap should be tried, false (0) if not.
    801921 */
    802 int
     922static int
    803923trymmap(int fd)
    804924{
     
    818938        return (0);
    819939}
     940#endif
Note: See TracChangeset for help on using the changeset viewer.