"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-chmod.c" (15 Mar 2019, 4903 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-chmod.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.49_vs_0.09.50.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 static const mode_t modes[] = {
   28 #if defined(S_ISUID)
   29     S_ISUID,
   30 #endif
   31 #if defined(S_ISGID)
   32     S_ISGID,
   33 #endif
   34 #if defined(S_ISVTX)
   35     S_ISVTX,
   36 #endif
   37 #if defined(S_IRUSR)
   38     S_IRUSR,
   39 #endif
   40 #if defined(S_IWUSR)
   41     S_IWUSR,
   42 #endif
   43 #if defined(S_IXUSR)
   44     S_IXUSR,
   45 #endif
   46 #if defined(S_IRGRP)
   47     S_IRGRP,
   48 #endif
   49 #if defined(S_IWGRP)
   50     S_IWGRP,
   51 #endif
   52 #if defined(S_IXGRP)
   53     S_IXGRP,
   54 #endif
   55 #if defined(S_IROTH)
   56     S_IROTH,
   57 #endif
   58 #if defined(S_IWOTH)
   59     S_IWOTH,
   60 #endif
   61 #if defined( S_IXOTH)
   62     S_IXOTH,
   63 #endif
   64     0
   65 };
   66 
   67 /*
   68  *  BSD systems can return EFTYPE which we can ignore
   69  *  as a "known" error on invalid chmod mode bits
   70  */
   71 #if defined(EFTYPE)
   72 #define CHECK(x) if ((x) && (errno != EFTYPE)) return -1
   73 #else
   74 #define CHECK(x) if (x) return -1
   75 #endif
   76 
   77 /*
   78  *  do_fchmod()
   79  *  fchmod the 4 different masks from a mode flag, namely:
   80  *      mode flag
   81  *      all mode flags or'd together
   82  *      inverse mode flag
   83  *      inverse all mode flags or'd together
   84  */
   85 static int do_fchmod(
   86     const int fd,
   87     const int i,
   88     const mode_t mask,
   89     const mode_t all_mask)
   90 {
   91     CHECK(fchmod(fd, modes[i]) < 0);
   92     CHECK(fchmod(fd, mask) < 0);
   93     CHECK(fchmod(fd, modes[i] ^ all_mask) < 0);
   94     CHECK(fchmod(fd, mask ^ all_mask) < 0);
   95     return 0;
   96 }
   97 
   98 /*
   99  *  do_chmod()
  100  *  chmod the 4 different masks from a mode flag, namely:
  101  *      mode flag
  102  *      all mode flags or'd together
  103  *      inverse mode flag
  104  *      inverse all mode flags or'd together
  105  */
  106 static int do_chmod(
  107     const char *filename,
  108     const int i,
  109     const mode_t mask,
  110     const mode_t all_mask)
  111 {
  112     CHECK(chmod(filename, modes[i]) < 0);
  113     CHECK(chmod(filename, mask) < 0);
  114     CHECK(chmod(filename, modes[i] ^ all_mask) < 0);
  115     CHECK(chmod(filename, mask ^ all_mask) < 0);
  116     return 0;
  117 }
  118 
  119 /*
  120  *  stress_chmod
  121  *  stress chmod
  122  */
  123 static int stress_chmod(const args_t *args)
  124 {
  125     const pid_t ppid = getppid();
  126     int i, fd = -1, rc = EXIT_FAILURE, retries = 0;
  127     mode_t all_mask = 0;
  128     char filename[PATH_MAX], dirname[PATH_MAX];
  129 
  130     /*
  131      *  Allow for multiple workers to chmod the *same* file
  132      */
  133     stress_temp_dir(dirname, sizeof(dirname), args->name, ppid, 0);
  134     if (mkdir(dirname, S_IRUSR | S_IRWXU) < 0) {
  135         if (errno != EEXIST) {
  136             rc = exit_status(errno);
  137             pr_fail_err("mkdir");
  138             return rc;
  139         }
  140     }
  141     (void)stress_temp_filename(filename, sizeof(filename),
  142         args->name, ppid, 0, 0);
  143 
  144     if (args->instance == 0) {
  145         if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
  146             rc = exit_status(errno);
  147             pr_fail_err("creat");
  148             goto tidy;
  149         }
  150     } else {
  151         /* Other instances must try to open the file */
  152         for (;;) {
  153             if ((fd = open(filename, O_RDWR, S_IRUSR | S_IWUSR)) > - 1)
  154                 break;
  155 
  156 #if defined(__NetBSD__)
  157             /* For some reason usleep blocks */
  158             (void)shim_sched_yield();
  159 #else
  160             (void)shim_usleep(100000);
  161 #endif
  162             /* Timed out, then give up */
  163             if (!g_keep_stressing_flag) {
  164                 rc = EXIT_SUCCESS;
  165                 goto tidy;
  166             }
  167             /* Too many retries? */
  168             if (++retries >= 10000) {
  169                 pr_err("%s: chmod: file %s took %d "
  170                     "retries to open and gave up "
  171                     "(instance %" PRIu32 ")\n",
  172                     args->name, filename, retries, args->instance);
  173                 goto tidy;
  174             }
  175         }
  176     }
  177 
  178     for (i = 0; modes[i]; i++)
  179         all_mask |= modes[i];
  180 
  181     do {
  182         mode_t mask = 0;
  183 
  184         for (i = 0; modes[i]; i++) {
  185             mask |= modes[i];
  186             if (do_fchmod(fd, i, mask, all_mask) < 0) {
  187                 pr_fail_err("fchmod");
  188             }
  189             if (do_chmod(filename, i, mask, all_mask) < 0) {
  190                 if (errno == ENOENT || errno == ENOTDIR) {
  191                     /*
  192                      * File was removed during test by
  193                      * another worker
  194                      */
  195                     rc = EXIT_SUCCESS;
  196                     goto tidy;
  197                 }
  198                 pr_fail_err("chmod");
  199             }
  200         }
  201         inc_counter(args);
  202     } while (keep_stressing());
  203 
  204     rc = EXIT_SUCCESS;
  205 tidy:
  206     if (fd >= 0) {
  207         (void)fchmod(fd, 0666);
  208         (void)close(fd);
  209     }
  210     (void)unlink(filename);
  211     (void)rmdir(dirname);
  212 
  213     return rc;
  214 }
  215 
  216 stressor_info_t stress_chmod_info = {
  217     .stressor = stress_chmod,
  218     .class = CLASS_FILESYSTEM | CLASS_OS
  219 };