VirtualBox

Changeset 1551 in kBuild for trunk/src/kmk/kmkbuiltin/rm.c


Ignore:
Timestamp:
Apr 23, 2008 12:40:15 AM (17 years ago)
Author:
bird
Message:

Full protection, depth argument and environment overrides.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/rm.c

    r1550 r1551  
    7171# define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
    7272# define HAVE_DOS_PATHS 1
    73 # define DEFAULT_REQUIRED_R_DEPTH 2
     73# define DEFAULT_PROTECTION_DEPTH 1
    7474#else
    7575# define IS_SLASH(ch)   ( (ch) == '/' )
    7676# undef HAVE_DOS_PATHS
    77 # define DEFAULT_REQUIRED_R_DEPTH 3
     77# define DEFAULT_PROTECTION_DEPTH 2
    7878#endif
    7979
     
    9292#endif
    9393
    94 static int protectionflag;
     94static int protectionflag, fullprotectionflag, protectiondepth;
    9595static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
    9696static uid_t uid;
     
    103103    { "version",                                        no_argument, 0, 262 },
    104104    { "disable-protection",                             no_argument, 0, 263 },
     105    { "enable-protection",                              no_argument, 0, 264 },
     106    { "enable-full-protection",                         no_argument, 0, 265 },
     107    { "disable-full-protection",                        no_argument, 0, 266 },
     108    { "protection-depth",                               required_argument, 0, 267 },
    105109    { 0, 0,     0, 0 },
    106110};
     
    111115static void     rm_file(char **);
    112116static int      rm_overwrite(char *, struct stat *);
    113 static void     rm_tree(char **, int);
     117static void     rm_tree(char **);
    114118static int      count_path_components(const char *);
     119static int  set_protection_depth(const char *);
    115120static int      usage(FILE *);
    116121
     
    128133{
    129134        int ch, rflag;
     135        int i;
    130136
    131137        /* reinitialize globals */
    132138        argv0 = argv[0];
    133139        dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0;
     140        fullprotectionflag = 0;
    134141        protectionflag = 1;
     142        protectiondepth = DEFAULT_PROTECTION_DEPTH;
    135143        uid = 0;
    136144
     
    143151
    144152        Pflag = rflag = 0;
    145         while ((ch = getopt_long(argc, argv, "dfiPRrvW", long_options, NULL)) != -1)
     153        while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1)
    146154                switch(ch) {
    147155                case 'd':
     
    162170#if 0
    163171                case 'r':                       /* Compatibility. */
    164 #endif 
     172#endif
    165173                        rflag = 1;
    166174                        break;
     
    181189                        protectionflag = 0;
    182190                        break;
     191                case 264:
     192                        protectionflag = 1;
     193                        break;
     194                case 265:
     195                        fullprotectionflag = 1;
     196                        break;
     197                case 266:
     198                        fullprotectionflag = 0;
     199                        break;
     200                case 267:
     201                        set_protection_depth(optarg);
     202                        break;
    183203                case '?':
    184204                default:
     
    194214        }
    195215
     216        /* Search the environment for option overrides (protection). */
     217#define STR_SIZE_PAIR(str) str, sizeof(str) - 1
     218        for (i = 0; envp[i]; i++) {
     219                if (!strncmp(envp[i], "KMK_RM_", sizeof("KMK_RM_") - 1)) {
     220                        if (!strncmp(envp[i], STR_SIZE_PAIR("KMK_RM_PROTECTION_DEPTH="))) {
     221                                const char *val = envp[i] + sizeof("KMK_RM_PROTECTION_DEPTH=") - 1;
     222                                if (set_protection_depth(val))
     223                                        return eval;
     224                        } else if (!strncmp(envp[i], STR_SIZE_PAIR("KMK_RM_DISABLE_PROTECTION="))) {
     225                                if (protectionflag >= 0)
     226                                        protectionflag = 0;
     227                        } else if (!strncmp(envp[i], STR_SIZE_PAIR("KMK_RM_ENABLE_PROTECTION="))) {
     228                                protectionflag = -1;
     229                        } else if (!strncmp(envp[i], STR_SIZE_PAIR("KMK_RM_DISABLE_FULL_PROTECTION="))) {
     230                                if (fullprotectionflag >= 0)
     231                                        fullprotectionflag = 0;
     232                        } else if (!strncmp(envp[i], STR_SIZE_PAIR("KMK_RM_ENABLE_FULL_PROTECTION="))) {
     233                                fullprotectionflag = protectionflag = -1;
     234                        }
     235                }
     236        }
     237        if (fullprotectionflag)
     238                protectionflag = 1;
     239#undef STR_SIZE_PAIR
     240
    196241        checkdot(argv);
    197242        uid = geteuid();
     
    199244        if (*argv) {
    200245                stdin_ok = isatty(STDIN_FILENO);
    201                 if (rflag) {
    202                         /*
    203                          * Get options from the environment before doing rm_tree().
    204                          */
    205                         int required_r_depth = DEFAULT_REQUIRED_R_DEPTH;
    206                         int i;
    207                         for (i = 0; envp[i]; i++) {
    208                                 if (!strncmp(envp[i], "KMK_RM_=", sizeof("KMK_RM_=") - 1)) {
    209                                         if (!strncmp(envp[i], "KMK_RM_PROTECTION_DEPTH=", sizeof("KMK_RM_PROTECTION_DEPTH=") - 1)) {
    210                                                 char *ignore;
    211                                                 const char *val = envp[i] + sizeof("KMK_RM_PROTECTION_DEPTH=") - 1;
    212                                                 required_r_depth = isdigit(*val) ? strtol(val, &ignore, 0) : count_path_components(val);
    213                                                 if (required_r_depth < 1)
    214                                                         required_r_depth = DEFAULT_REQUIRED_R_DEPTH;
    215                                         } else if (!strcmp(envp[i], "KMK_RM_DISABLE_PROTECTION=1")) {
    216                                                 protectionflag = 0;
    217                                         }
    218                                 }
    219                         }
    220 
    221                         if (!eval)
    222                                 rm_tree(argv, required_r_depth);
    223                 } else {
     246                if (rflag)
     247                        rm_tree(argv);
     248                else
    224249                        rm_file(argv);
    225                 }
    226         }
    227 
     250        }
     251
     252        return eval;
     253}
     254
     255/**
     256 * Sets protectiondepth according to the option argument.
     257 *
     258 * @returns eval, that is 0 on success and non-zero on failure
     259 *
     260 * @param   val         The value.
     261 */
     262static int
     263set_protection_depth(const char *val)
     264{
     265        /* skip leading blanks, they don't count either way. */
     266        while (isspace(*val))
     267                val++;
     268
     269        /* number or path? */
     270        if (!isdigit(*val) || strpbrk(val, ":/\\")) {
     271                protectiondepth = count_path_components(val);
     272        } else {
     273                char *more = 0;
     274                protectiondepth = strtol(val, &more, 0);
     275                if (protectiondepth != 0 && more) {
     276                        /* trailing space is harmless. */
     277                        while (isspace(*more))
     278                                more++;
     279                }
     280                if (!protectiondepth || val == more || *more)
     281                        return eval = errx(1, "bogus protection depth: %s", val);
     282        }
     283
     284        if (protectiondepth < 1)
     285                return eval = errx(1, "bogus protection depth: %s", val);
    228286        return eval;
    229287}
     
    235293 * etc = 1
    236294 * etc/ = 1
    237  * etc/x11 = 2 
     295 * etc/x11 = 2
    238296 * and so and and so forth.
    239297 */
     
    274332
    275333/**
    276  * Parses the specified path counting the number of components 
     334 * Parses the specified path counting the number of components
    277335 * relative to root.
    278336 *
    279  * We don't check symbolic links and such, just some simple and cheap 
     337 * We don't check symbolic links and such, just some simple and cheap
    280338 * path parsing.
    281339 *
     
    296354    if (IS_SLASH(path[0]) && IS_SLASH(path[1]) && !IS_SLASH(path[2])) {
    297355                /* skip the root - UNC */
    298                 path += 3; 
     356                path += 3;
    299357                while (!IS_SLASH(*path) && *path) /* server name */
    300358                        path++;
     
    314372
    315373                if (IS_SLASH(path[drive_letter ? 2 : 0])) {
    316                         /* 
     374                        /*
    317375                         * Relative path, must count cwd depth first.
    318376                         */
     
    357415#endif
    358416
    359         /* 
     417        /*
    360418         * We're now past any UNC or drive letter crap, possibly positioned
    361419         * at the root slash or at the start of a path component at the
     
    367425
    368426/**
    369  * Protect the upper layers of the file system against accidental 
     427 * Protect the upper layers of the file system against accidental
    370428 * or malicious deletetion attempt from within a makefile.
    371429 *
    372430 * @param   path                The path to check.
    373  * @param   required_depth      The minimum number of components in the 
     431 * @param   required_depth      The minimum number of components in the
    374432 *                              path counting from the root.
    375433 *
    376  * @returns 0 on success. 
     434 * @returns 0 on success.
    377435 *          On failure an error is printed, eval is set and -1 is returned.
    378436 */
     
    396454
    397455static void
    398 rm_tree(char **argv, int required_r_depth)
     456rm_tree(char **argv)
    399457{
    400458        FTS *fts;
     
    405463
    406464        /*
    407          * Check up front before anything is deleted. This will not catch 
     465         * Check up front before anything is deleted. This will not catch
    408466         * everything, but we'll check the individual items later.
    409467         */
     
    411469                int i;
    412470                for (i = 0; argv[i]; i++) {
    413                         if (enforce_protection(argv[i], required_r_depth))
     471                        if (enforce_protection(argv[i], protectiondepth + 1))
    414472                                return;
    415473                }
     
    492550                }
    493551
    494                 /* 
     552                /*
    495553                 * Protect against deleting root files and directories.
    496554                 */
    497                 if (protectionflag && enforce_protection(p->fts_accpath, required_r_depth)) {
     555                if (protectionflag && enforce_protection(p->fts_accpath, protectiondepth + 1)) {
    498556                        fts_close(fts);
    499557                        return;
     
    583641        int rval;
    584642        char *f;
     643
     644        /*
     645         * Check up front before anything is deleted.
     646         */
     647        if (fullprotectionflag) {
     648                int i;
     649                for (i = 0; argv[i]; i++) {
     650                        if (enforce_protection(argv[i], protectiondepth + 1))
     651                                return;
     652                }
     653        }
    585654
    586655        /*
     
    824893usage(FILE *pf)
    825894{
    826         fprintf(pf, 
    827                 "usage: %s [-f | -i] [-dPRvW] [--disable-protection] file ...\n"
     895        fprintf(pf,
     896                "usage: %s [options] file ...\n"
    828897                "   or: %s --help\n"
    829898                "   or: %s --version\n"
     
    847916                "       Undelete without files.\n"
    848917                "   --disable-protection\n"
    849                 "       Will disable the protection file protection applied by -R.\n"
     918                "       Will disable the protection file protection applied with -R.\n"
     919                "   --enable-protection\n"
     920                "       Will enable the protection file protection applied with -R.\n"
     921                "   --enable-full-protection\n"
     922                "       Will enable the protection file protection for all operations.\n"
     923                "   --disable-full-protection\n"
     924                "       Will disable the protection file protection for all operations.\n"
     925                "   --protection-depth\n"
     926                "       Number or path indicating the file protection depth. Default: %d\n"
    850927                "\n"
    851928                "Environment:\n"
    852929                "    KMK_RM_DISABLE_PROTECTION\n"
    853                 "       Same as --disable-protection.\n"
     930                "       Same as --disable-protection. Overrides command line.\n"
     931                "    KMK_RM_ENABLE_PROTECTION\n"
     932                "       Same as --enable-protection. Overrides everyone else.\n"
     933                "    KMK_RM_ENABLE_FULL_PROTECTION\n"
     934                "       Same as --enable-full-protection. Overrides everyone else.\n"
     935                "    KMK_RM_DISABLE_FULL_PROTECTION\n"
     936                "       Same as --disable-full-protection. Overrides command line.\n"
    854937                "    KMK_RM_PROTECTION_DEPTH\n"
    855                 "       Changes the protection depth, path or number. Default: %d\n"
     938                "       Same as --protection-depth. Overrides command line.\n"
    856939                "\n"
    857940                "The file protection of the top %d layers of the file hierarchy is there\n"
    858941                "to try prevent makefiles from doing bad things to your system. This\n"
    859942                "protection is not bulletproof, but should help prevent you from shooting\n"
    860                 "yourself in the foot. Not that it does NOT apply to normal file removal.\n"
     943                "yourself in the foot.\n"
    861944                ,
    862                 g_progname, g_progname, g_progname, 
    863                 DEFAULT_REQUIRED_R_DEPTH, DEFAULT_REQUIRED_R_DEPTH);
     945                g_progname, g_progname, g_progname,
     946                DEFAULT_PROTECTION_DEPTH, DEFAULT_PROTECTION_DEPTH);
    864947        return EX_USAGE;
    865948}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette