root/opal/util/os_dirpath.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_os_dirpath_create
  2. opal_os_dirpath_destroy
  3. opal_os_dirpath_is_empty
  4. opal_os_dirpath_access

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2015-2017 Research Organization for Information Science
  13  *                         and Technology (RIST). All rights reserved.
  14  * Copyright (c) 2016-2017 Intel, Inc. All rights reserved.
  15  * $COPYRIGHT$
  16  *
  17  * Additional copyrights may follow
  18  *
  19  * $HEADER$
  20  */
  21 
  22 
  23 #include "opal_config.h"
  24 
  25 #include <errno.h>
  26 #include <string.h>
  27 #ifdef HAVE_UNISTD_H
  28 #include <unistd.h>
  29 #endif  /* HAVE_UNISTD_H */
  30 #include <stdlib.h>
  31 #if HAVE_SYS_STAT_H
  32 #include <sys/stat.h>
  33 #endif /* HAVE_SYS_STAT_H */
  34 #ifdef HAVE_SYS_TYPES_H
  35 #include <sys/types.h>
  36 #endif  /* HAVE_SYS_TYPES_H */
  37 #ifdef HAVE_DIRENT_H
  38 #include <dirent.h>
  39 #endif  /* HAVE_DIRENT_H */
  40 
  41 #include "opal/util/output.h"
  42 #include "opal/util/os_dirpath.h"
  43 #include "opal/util/show_help.h"
  44 #include "opal/util/argv.h"
  45 #include "opal/util/os_path.h"
  46 #include "opal/constants.h"
  47 
  48 static const char path_sep[] = OPAL_PATH_SEP;
  49 
  50 int opal_os_dirpath_create(const char *path, const mode_t mode)
  51 {
  52     struct stat buf;
  53     char **parts, *tmp;
  54     int i, len;
  55     int ret;
  56 
  57     if (NULL == path) { /* protect ourselves from errors */
  58         return(OPAL_ERR_BAD_PARAM);
  59     }
  60 
  61     if (0 == (ret = stat(path, &buf))) { /* already exists */
  62         if (mode == (mode & buf.st_mode)) { /* has correct mode */
  63             return(OPAL_SUCCESS);
  64         }
  65         if (0 == (ret = chmod(path, (buf.st_mode | mode)))) { /* successfully change mode */
  66             return(OPAL_SUCCESS);
  67         }
  68         opal_show_help("help-opal-util.txt", "dir-mode", true,
  69                     path, mode, strerror(errno));
  70         return(OPAL_ERR_PERM); /* can't set correct mode */
  71     }
  72 
  73     /* quick -- try to make directory */
  74     if (0 == mkdir(path, mode)) {
  75         return(OPAL_SUCCESS);
  76     }
  77 
  78     /* didnt work, so now have to build our way down the tree */
  79     /* Split the requested path up into its individual parts */
  80 
  81     parts = opal_argv_split(path, path_sep[0]);
  82 
  83     /* Ensure to allocate enough space for tmp: the strlen of the
  84        incoming path + 1 (for \0) */
  85 
  86     tmp = (char*)malloc(strlen(path) + 1);
  87     tmp[0] = '\0';
  88 
  89     /* Iterate through all the subdirectory names in the path,
  90        building up a directory name.  Check to see if that dirname
  91        exists.  If it doesn't, create it. */
  92 
  93     len = opal_argv_count(parts);
  94     for (i = 0; i < len; ++i) {
  95         if (i == 0) {
  96             /* If in POSIX-land, ensure that we never end a directory
  97                name with path_sep */
  98 
  99             if ('/' == path[0]) {
 100                 strcat(tmp, path_sep);
 101             }
 102             strcat(tmp, parts[i]);
 103         }
 104 
 105         /* If it's not the first part, ensure that there's a
 106            preceeding path_sep and then append this part */
 107 
 108         else {
 109             if (path_sep[0] != tmp[strlen(tmp) - 1]) {
 110                 strcat(tmp, path_sep);
 111             }
 112             strcat(tmp, parts[i]);
 113         }
 114 
 115         /* Now that we have the name, try to create it */
 116         mkdir(tmp, mode);
 117         ret = errno;  // save the errno for an error msg, if needed
 118         if (0 != stat(tmp, &buf)) {
 119             opal_show_help("help-opal-util.txt", "mkdir-failed", true,
 120                         tmp, strerror(ret));
 121             opal_argv_free(parts);
 122             free(tmp);
 123             return OPAL_ERROR;
 124         } else if (i == (len-1) && (mode != (mode & buf.st_mode)) && (0 > chmod(tmp, (buf.st_mode | mode)))) {
 125             opal_show_help("help-opal-util.txt", "dir-mode", true,
 126                            tmp, mode, strerror(errno));
 127             opal_argv_free(parts);
 128             free(tmp);
 129             return(OPAL_ERR_PERM); /* can't set correct mode */
 130         }
 131     }
 132 
 133     /* All done */
 134 
 135     opal_argv_free(parts);
 136     free(tmp);
 137     return OPAL_SUCCESS;
 138 }
 139 
 140 /**
 141  * This function attempts to remove a directory along with all the
 142  * files in it.  If the recursive variable is non-zero, then it will
 143  * try to recursively remove all directories.  If provided, the
 144  * callback function is executed prior to the directory or file being
 145  * removed.  If the callback returns non-zero, then no removal is
 146  * done.
 147  */
 148 int opal_os_dirpath_destroy(const char *path,
 149                             bool recursive,
 150                             opal_os_dirpath_destroy_callback_fn_t cbfunc)
 151 {
 152     int rc, exit_status = OPAL_SUCCESS;
 153     bool is_dir = false;
 154     DIR *dp;
 155     struct dirent *ep;
 156     char *filenm;
 157     struct stat buf;
 158 
 159     if (NULL == path) {  /* protect against error */
 160         return OPAL_ERROR;
 161     }
 162 
 163     /*
 164      * Make sure we have access to the the base directory
 165      */
 166     if (OPAL_SUCCESS != (rc = opal_os_dirpath_access(path, 0))) {
 167         exit_status = rc;
 168         goto cleanup;
 169     }
 170 
 171     /* Open up the directory */
 172     dp = opendir(path);
 173     if (NULL == dp) {
 174         return OPAL_ERROR;
 175     }
 176 
 177     while (NULL != (ep = readdir(dp))) {
 178         /* skip:
 179          *  - . and ..
 180          */
 181         if ((0 == strcmp(ep->d_name, ".")) ||
 182             (0 == strcmp(ep->d_name, ".."))) {
 183             continue;
 184         }
 185 
 186         /* Check to see if it is a directory */
 187         is_dir = false;
 188 
 189         /* Create a pathname.  This is not always needed, but it makes
 190          * for cleaner code just to create it here.  Note that we are
 191          * allocating memory here, so we need to free it later on.
 192          */
 193         filenm = opal_os_path(false, path, ep->d_name, NULL);
 194 
 195         rc = stat(filenm, &buf);
 196         if (0 > rc) {
 197             /* Handle a race condition. filenm might have been deleted by an
 198              * other process running on the same node. That typically occurs
 199              * when one task is removing the job_session_dir and an other task
 200              * is still removing its proc_session_dir.
 201              */
 202             free(filenm);
 203             continue;
 204         }
 205         if (S_ISDIR(buf.st_mode)) {
 206             is_dir = true;
 207         }
 208 
 209         /*
 210          * If not recursively decending, then if we find a directory then fail
 211          * since we were not told to remove it.
 212          */
 213         if (is_dir && !recursive) {
 214             /* Set the error indicating that we found a directory,
 215              * but continue removing files
 216              */
 217             exit_status = OPAL_ERROR;
 218             free(filenm);
 219             continue;
 220         }
 221 
 222         /* Will the caller allow us to remove this file/directory? */
 223         if (NULL != cbfunc) {
 224             /*
 225              * Caller does not wish to remove this file/directory,
 226              * continue with the rest of the entries
 227              */
 228             if (!(cbfunc(path, ep->d_name))) {
 229                 free(filenm);
 230                 continue;
 231             }
 232         }
 233         /* Directories are recursively destroyed */
 234         if (is_dir) {
 235             rc = opal_os_dirpath_destroy(filenm, recursive, cbfunc);
 236             free(filenm);
 237             if (OPAL_SUCCESS != rc) {
 238                 exit_status = rc;
 239                 closedir(dp);
 240                 goto cleanup;
 241             }
 242         } else {
 243             /* Files are removed right here */
 244             if (0 != (rc = unlink(filenm))) {
 245                 exit_status = OPAL_ERROR;
 246             }
 247             free(filenm);
 248         }
 249     }
 250 
 251     /* Done with this directory */
 252     closedir(dp);
 253 
 254  cleanup:
 255 
 256     /*
 257      * If the directory is empty, them remove it
 258      */
 259     if(opal_os_dirpath_is_empty(path)) {
 260         rmdir(path);
 261     }
 262 
 263     return exit_status;
 264 }
 265 
 266 bool opal_os_dirpath_is_empty(const char *path ) {
 267     DIR *dp;
 268     struct dirent *ep;
 269 
 270     if (NULL != path) {  /* protect against error */
 271         dp = opendir(path);
 272         if (NULL != dp) {
 273             while ((ep = readdir(dp))) {
 274                         if ((0 != strcmp(ep->d_name, ".")) &&
 275                             (0 != strcmp(ep->d_name, ".."))) {
 276                             closedir(dp);
 277                             return false;
 278                         }
 279             }
 280             closedir(dp);
 281             return true;
 282         }
 283         return false;
 284     }
 285 
 286     return true;
 287 }
 288 
 289 int opal_os_dirpath_access(const char *path, const mode_t in_mode ) {
 290     struct stat buf;
 291     mode_t loc_mode = S_IRWXU;  /* looking for full rights */
 292 
 293     /*
 294      * If there was no mode specified, use the default mode
 295      */
 296     if (0 != in_mode) {
 297         loc_mode = in_mode;
 298     }
 299 
 300     if (0 == stat(path, &buf)) { /* exists - check access */
 301         if ((buf.st_mode & loc_mode) == loc_mode) { /* okay, I can work here */
 302             return(OPAL_SUCCESS);
 303         } else {
 304             /* Don't have access rights to the existing path */
 305             return(OPAL_ERROR);
 306         }
 307     } else {
 308         /* We could not find the path */
 309         return( OPAL_ERR_NOT_FOUND );
 310     }
 311 }

/* [<][>][^][v][top][bottom][index][help] */