Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/coreutils/install.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    2  *  Copyright (C) 2003 by Glenn McGrath <bug1@iinet.net.au>
     3 * Copyright (C) 2003 by Glenn McGrath
     4 * SELinux support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
    35 *
    4  *  This program is free software; you can redistribute it and/or modify
    5  *  it under the terms of the GNU General Public License as published by
    6  *  the Free Software Foundation; either version 2 of the License, or
    7  *  (at your option) any later version.
    8  *
    9  *  This program is distributed in the hope that it will be useful,
    10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  *  GNU Library General Public License for more details.
    13  *
    14  *  You should have received a copy of the GNU General Public License
    15  *  along with this program; if not, write to the Free Software
    16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    17  *
     6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    187 *
    198 * TODO: -d option, need a way of recursively making directories and changing
     
    2110 */
    2211
    23 #include <sys/stat.h>
    24 #include <sys/types.h>
    25 #include <errno.h>
    26 #include <stdlib.h>
    27 #include <string.h>
    28 #include <unistd.h>
     12#include <libgen.h>
    2913#include <getopt.h> /* struct option */
    3014
    31 #include "busybox.h"
     15#include "libbb.h"
    3216#include "libcoreutils/coreutils.h"
    3317
    34 #define INSTALL_OPT_CMD 1
    35 #define INSTALL_OPT_DIRECTORY   2
    36 #define INSTALL_OPT_PRESERVE_TIME   4
    37 #define INSTALL_OPT_STRIP   8
    38 #define INSTALL_OPT_GROUP  16
    39 #define INSTALL_OPT_MODE  32
    40 #define INSTALL_OPT_OWNER  64
    41 
    4218#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
    43 static const struct option install_long_options[] = {
    44     { "directory",  0,  NULL,   'd' },
    45     { "preserve-timestamps",    0,  NULL,   'p' },
    46     { "strip",  0,  NULL,   's' },
    47     { "group",  0,  NULL,   'g' },
    48     { "mode",   0,  NULL,   'm' },
    49     { "owner",  0,  NULL,   'o' },
    50     { 0,    0,  0,  0 }
    51 };
    52 #endif
    53 
     19static const char install_longopts[] ALIGN1 =
     20    "directory\0"           No_argument       "d"
     21    "preserve-timestamps\0" No_argument       "p"
     22    "strip\0"               No_argument       "s"
     23    "group\0"               No_argument       "g"
     24    "mode\0"                No_argument       "m"
     25    "owner\0"               No_argument       "o"
     26/* autofs build insists of using -b --suffix=.orig */
     27/* TODO? (short option for --suffix is -S) */
     28#if ENABLE_SELINUX
     29    "context\0"             Required_argument "Z"
     30    "preserve_context\0"    No_argument       "\xff"
     31    "preserve-context\0"    No_argument       "\xff"
     32#endif
     33    ;
     34#endif
     35
     36
     37#if ENABLE_SELINUX
     38static void setdefaultfilecon(const char *path)
     39{
     40    struct stat s;
     41    security_context_t scontext = NULL;
     42
     43    if (!is_selinux_enabled()) {
     44        return;
     45    }
     46    if (lstat(path, &s) != 0) {
     47        return;
     48    }
     49
     50    if (matchpathcon(path, s.st_mode, &scontext) < 0) {
     51        goto out;
     52    }
     53    if (strcmp(scontext, "<<none>>") == 0) {
     54        goto out;
     55    }
     56
     57    if (lsetfilecon(path, scontext) < 0) {
     58        if (errno != ENOTSUP) {
     59            bb_perror_msg("warning: failed to change context of %s to %s", path, scontext);
     60        }
     61    }
     62
     63 out:
     64    freecon(scontext);
     65}
     66
     67#endif
     68
     69int install_main(int argc, char **argv);
    5470int install_main(int argc, char **argv)
    5571{
     72    struct stat statbuf;
    5673    mode_t mode;
    5774    uid_t uid;
    5875    gid_t gid;
    59     char *gid_str = "-1";
    60     char *uid_str = "-1";
    61     char *mode_str = "0755";
     76    char *arg, *last;
     77    const char *gid_str;
     78    const char *uid_str;
     79    const char *mode_str;
    6280    int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
    63     int ret = EXIT_SUCCESS, flags, i, isdir;
     81    int flags;
     82    int ret = EXIT_SUCCESS;
     83    int isdir;
     84#if ENABLE_SELINUX
     85    security_context_t scontext;
     86    bool use_default_selinux_context = 1;
     87#endif
     88    enum {
     89        OPT_c             = 1 << 0,
     90        OPT_v             = 1 << 1,
     91        OPT_b             = 1 << 2,
     92        OPT_DIRECTORY     = 1 << 3,
     93        OPT_PRESERVE_TIME = 1 << 4,
     94        OPT_STRIP         = 1 << 5,
     95        OPT_GROUP         = 1 << 6,
     96        OPT_MODE          = 1 << 7,
     97        OPT_OWNER         = 1 << 8,
     98#if ENABLE_SELINUX
     99        OPT_SET_SECURITY_CONTEXT = 1 << 9,
     100        OPT_PRESERVE_SECURITY_CONTEXT = 1 << 10,
     101#endif
     102    };
    64103
    65104#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
    66     bb_applet_long_options = install_long_options;
    67 #endif
    68     bb_opt_complementally = "?:s--d:d--s";
    69     /* -c exists for backwards compatibility, its needed */
    70     flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */
     105    applet_long_options = install_longopts;
     106#endif
     107    opt_complementary = "s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z");
     108    /* -c exists for backwards compatibility, it's needed */
     109    /* -v is ignored ("print name of each created directory") */
     110    /* -b is ignored ("make a backup of each existing destination file") */
     111    flags = getopt32(argv, "cvb" "dpsg:m:o:" USE_SELINUX("Z:"),
     112            &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
     113    argc -= optind;
     114    argv += optind;
     115
     116#if ENABLE_SELINUX
     117    if (flags & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
     118        selinux_or_die();
     119        use_default_selinux_context = 0;
     120        if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
     121            copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
     122        }
     123        if (flags & OPT_SET_SECURITY_CONTEXT) {
     124            setfscreatecon_or_die(scontext);
     125            copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
     126        }
     127    }
     128#endif
    71129
    72130    /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
    73     if (flags & INSTALL_OPT_PRESERVE_TIME) {
     131    if (flags & OPT_PRESERVE_TIME) {
    74132        copy_flags |= FILEUTILS_PRESERVE_STATUS;
    75133    }
    76     bb_parse_mode(mode_str, &mode);
    77     gid = get_ug_id(gid_str, bb_xgetgrnam);
    78     uid = get_ug_id(uid_str, bb_xgetpwnam);
    79     umask(0);
     134    mode = 0666;
     135    if (flags & OPT_MODE)
     136        bb_parse_mode(mode_str, &mode);
     137    uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
     138    gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
     139    if (flags & (OPT_OWNER|OPT_GROUP))
     140        umask(0);
    80141
    81142    /* Create directories
    82      * dont use bb_make_directory() as it cant change uid or gid
     143     * don't use bb_make_directory() as it can't change uid or gid
    83144     * perhaps bb_make_directory() should be improved.
    84145     */
    85     if (flags & INSTALL_OPT_DIRECTORY) {
    86         for (argv += optind; *argv; argv++) {
    87             char *old_argv_ptr = *argv + 1;
    88             char *argv_ptr;
    89             do {
    90                 argv_ptr = strchr(old_argv_ptr, '/');
    91                 old_argv_ptr = argv_ptr;
    92                 if (argv_ptr) {
    93                     *argv_ptr = '\0';
    94                     old_argv_ptr++;
    95                 }
    96                 if (mkdir(*argv, mode) == -1) {
     146    if (flags & OPT_DIRECTORY) {
     147        while ((arg = *argv++) != NULL) {
     148            char *slash = arg;
     149            while (1) {
     150                slash = strchr(slash + 1, '/');
     151                if (slash)
     152                    *slash = '\0';
     153                if (mkdir(arg, mode | 0111) == -1) {
    97154                    if (errno != EEXIST) {
    98                         bb_perror_msg("coulnt create %s", *argv);
     155                        bb_perror_msg("cannot create %s", arg);
    99156                        ret = EXIT_FAILURE;
    100157                        break;
    101158                    }
    102                 }
    103                 else if (lchown(*argv, uid, gid) == -1) {
    104                     bb_perror_msg("cannot change ownership of %s", *argv);
     159                } /* dir was created, chown? */
     160                else if ((flags & (OPT_OWNER|OPT_GROUP))
     161                 && lchown(arg, uid, gid) == -1
     162                ) {
     163                    bb_perror_msg("cannot change ownership of %s", arg);
    105164                    ret = EXIT_FAILURE;
    106165                    break;
    107166                }
    108                 if (argv_ptr) {
    109                     *argv_ptr = '/';
    110                 }
    111             } while (old_argv_ptr);
    112         }
    113         return(ret);
    114     }
    115 
    116     {
    117         struct stat statbuf;
    118         isdir = lstat(argv[argc - 1], &statbuf)<0
    119                     ? 0 : S_ISDIR(statbuf.st_mode);
    120     }
    121     for (i = optind; i < argc - 1; i++) {
    122         char *dest;
    123 
    124         dest = argv[argc - 1];
    125         if (isdir) dest = concat_path_file(argv[argc - 1], basename(argv[i]));
    126         ret |= copy_file(argv[i], dest, copy_flags);
     167                if (!slash)
     168                    break;
     169                *slash = '/';
     170            }
     171        }
     172        return ret;
     173    }
     174
     175    if (argc < 2)
     176        bb_show_usage();
     177
     178    last = argv[argc - 1];
     179    argv[argc - 1] = NULL;
     180    /* coreutils install resolves link in this case, don't use lstat */
     181    isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
     182
     183    while ((arg = *argv++) != NULL) {
     184        char *dest = last;
     185        if (isdir)
     186            dest = concat_path_file(last, basename(arg));
     187        if (copy_file(arg, dest, copy_flags)) {
     188            /* copy is not made */
     189            ret = EXIT_FAILURE;
     190            goto next;
     191        }
    127192
    128193        /* Set the file mode */
    129         if (chmod(dest, mode) == -1) {
     194        if ((flags & OPT_MODE) && chmod(dest, mode) == -1) {
    130195            bb_perror_msg("cannot change permissions of %s", dest);
    131196            ret = EXIT_FAILURE;
    132197        }
    133 
     198#if ENABLE_SELINUX
     199        if (use_default_selinux_context)
     200            setdefaultfilecon(dest);
     201#endif
    134202        /* Set the user and group id */
    135         if (lchown(dest, uid, gid) == -1) {
     203        if ((flags & (OPT_OWNER|OPT_GROUP))
     204         && lchown(dest, uid, gid) == -1
     205        ) {
    136206            bb_perror_msg("cannot change ownership of %s", dest);
    137207            ret = EXIT_FAILURE;
    138208        }
    139         if (flags & INSTALL_OPT_STRIP) {
    140             if (execlp("strip", "strip", dest, NULL) == -1) {
    141                 bb_error_msg("strip failed");
     209        if (flags & OPT_STRIP) {
     210            char *args[3];
     211            args[0] = (char*)"strip";
     212            args[1] = dest;
     213            args[2] = NULL;
     214            if (spawn_and_wait(args)) {
     215                bb_perror_msg("strip");
    142216                ret = EXIT_FAILURE;
    143217            }
    144218        }
    145         if(ENABLE_FEATURE_CLEAN_UP && isdir) free(dest);
    146     }
    147 
    148     return(ret);
     219 next:
     220        if (ENABLE_FEATURE_CLEAN_UP && isdir)
     221            free(dest);
     222    }
     223
     224    return ret;
    149225}
Note: See TracChangeset for help on using the changeset viewer.