Actual source code: ftest.c

      1: #include <petscsys.h>
      2: #include <errno.h>
      3: #if defined(PETSC_HAVE_PWD_H)
      4:   #include <pwd.h>
      5: #endif
      6: #include <ctype.h>
      7: #include <sys/stat.h>
      8: #if defined(PETSC_HAVE_UNISTD_H)
      9:   #include <unistd.h>
     10: #endif
     11: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
     12:   #include <sys/utsname.h>
     13: #endif
     14: #if defined(PETSC_HAVE_IO_H)
     15:   #include <io.h>
     16: #endif
     17: #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
     18:   #include <sys/systeminfo.h>
     19: #endif

     21: #if defined(PETSC_HAVE__ACCESS) || defined(PETSC_HAVE_ACCESS)

     23:   #include <errno.h>
     24: static PetscErrorCode PetscTestOwnership(const char fname[], char mode, uid_t fuid, gid_t fgid, int fmode, PetscBool *flg)
     25: {
     26:   int m = R_OK;

     28:   PetscFunctionBegin;
     29:   if (mode == 'r') m = R_OK;
     30:   else if (mode == 'w') m = W_OK;
     31:   else if (mode == 'x') m = X_OK;
     32:   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mode must be one of r, w, or x");
     33:   #if defined(PETSC_HAVE_ACCESS)
     34:   if (!access(fname, m)) {
     35:     PetscCall(PetscInfo(NULL, "System call access() succeeded on file %s\n", fname));
     36:     *flg = PETSC_TRUE;
     37:   } else {
     38:     PetscCall(PetscInfo(NULL, "System call access() failed on file %s due to \"%s\"\n", fname, strerror(errno)));
     39:     *flg = PETSC_FALSE;
     40:   }
     41:   #else
     42:   PetscCheck(m != X_OK, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unable to check execute permission for file %s", fname);
     43:   if (!_access(fname, m)) *flg = PETSC_TRUE;
     44:   #endif
     45:   PetscFunctionReturn(PETSC_SUCCESS);
     46: }

     48: #else /* PETSC_HAVE_ACCESS or PETSC_HAVE__ACCESS */

     50: static PetscErrorCode PetscTestOwnership(const char fname[], char mode, uid_t fuid, gid_t fgid, int fmode, PetscBool *flg)
     51: {
     52:   uid_t  uid;
     53:   gid_t *gid = NULL;
     54:   int    numGroups;
     55:   int    rbit = S_IROTH;
     56:   int    wbit = S_IWOTH;
     57:   int    ebit = S_IXOTH;
     58:   #if !defined(PETSC_MISSING_GETGROUPS)
     59:   int err;
     60:   #endif

     62:   PetscFunctionBegin;
     63:   /* Get the number of supplementary group IDs */
     64:   #if !defined(PETSC_MISSING_GETGROUPS)
     65:   numGroups = getgroups(0, gid);
     66:   PetscCheck(numGroups >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to count supplementary group IDs due to \"%s\"", strerror(errno));
     67:   PetscCall(PetscMalloc1(numGroups + 1, &gid));
     68:   #else
     69:   numGroups = 0;
     70:   #endif

     72:   /* Get the (effective) user and group of the caller */
     73:   uid    = geteuid();
     74:   gid[0] = getegid();

     76:   /* Get supplementary group IDs */
     77:   #if !defined(PETSC_MISSING_GETGROUPS)
     78:   err = getgroups(numGroups, gid + 1);
     79:   PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to obtain supplementary group IDs due to \"%s\"", strerror(errno));
     80:   #endif

     82:   /* Test for accessibility */
     83:   if (fuid == uid) {
     84:     rbit = S_IRUSR;
     85:     wbit = S_IWUSR;
     86:     ebit = S_IXUSR;
     87:   } else {
     88:     int g;

     90:     for (g = 0; g <= numGroups; g++) {
     91:       if (fgid == gid[g]) {
     92:         rbit = S_IRGRP;
     93:         wbit = S_IWGRP;
     94:         ebit = S_IXGRP;
     95:         break;
     96:       }
     97:     }
     98:   }
     99:   PetscCall(PetscFree(gid));

    101:   if (mode == 'r') {
    102:     if (fmode & rbit) *flg = PETSC_TRUE;
    103:   } else if (mode == 'w') {
    104:     if (fmode & wbit) *flg = PETSC_TRUE;
    105:   } else if (mode == 'x') {
    106:     if (fmode & ebit) *flg = PETSC_TRUE;
    107:   }
    108:   PetscFunctionReturn(PETSC_SUCCESS);
    109: }

    111: #endif /* PETSC_HAVE_ACCESS */

    113: static PetscErrorCode PetscGetFileStat(const char fname[], uid_t *fileUid, gid_t *fileGid, int *fileMode, PetscBool *exists)
    114: {
    115:   struct stat statbuf;
    116:   int         ierr;

    118:   PetscFunctionBegin;
    119:   *fileMode = 0;
    120:   *exists   = PETSC_FALSE;
    121: #if defined(PETSC_HAVE_STAT_NO_CONST)
    122:   ierr = stat((char *)fname, &statbuf);
    123: #else
    124:   ierr = stat(fname, &statbuf);
    125: #endif
    126:   if (ierr) {
    127: #if defined(EOVERFLOW)
    128:     PetscCheck(errno != EOVERFLOW, PETSC_COMM_SELF, PETSC_ERR_SYS, "EOVERFLOW in stat(), configure PETSc --with-large-file-io=1 to support files larger than 2GiB");
    129: #endif
    130:     PetscCall(PetscInfo(NULL, "System call stat() failed on file %s due to \"%s\"\n", fname, strerror(errno)));
    131:     *exists = PETSC_FALSE;
    132:   } else {
    133:     PetscCall(PetscInfo(NULL, "System call stat() succeeded on file %s\n", fname));
    134:     *exists   = PETSC_TRUE;
    135:     *fileUid  = statbuf.st_uid;
    136:     *fileGid  = statbuf.st_gid;
    137:     *fileMode = statbuf.st_mode;
    138:   }
    139:   PetscFunctionReturn(PETSC_SUCCESS);
    140: }

    142: /*@
    143:   PetscTestFile - checks for the existence of a file

    145:   Not Collective

    147:   Input Parameters:
    148: + fname - the filename
    149: - mode  - either 'r', 'w', 'x' or '\0'

    151:   Output Parameter:
    152: . flg - the file exists and satisfies the mode

    154:   Level: intermediate

    156:   Note:
    157:   If mode is '\0', no permissions checks are performed

    159: .seealso: `PetscTestDirectory()`, `PetscLs()`
    160: @*/
    161: PetscErrorCode PetscTestFile(const char fname[], char mode, PetscBool *flg)
    162: {
    163:   uid_t     fuid;
    164:   gid_t     fgid;
    165:   int       fmode;
    166:   PetscBool exists;

    168:   PetscFunctionBegin;
    169:   *flg = PETSC_FALSE;
    170:   if (!fname) PetscFunctionReturn(PETSC_SUCCESS);

    172:   PetscCall(PetscGetFileStat(fname, &fuid, &fgid, &fmode, &exists));
    173:   if (!exists) PetscFunctionReturn(PETSC_SUCCESS);
    174:   /* Except for systems that have this broken stat macros (rare), this is the correct way to check for a regular file */
    175:   if (!S_ISREG(fmode)) PetscFunctionReturn(PETSC_SUCCESS);
    176:   /* return if asked to check for existence only */
    177:   if (mode == '\0') {
    178:     *flg = exists;
    179:     PetscFunctionReturn(PETSC_SUCCESS);
    180:   }
    181:   PetscCall(PetscTestOwnership(fname, mode, fuid, fgid, fmode, flg));
    182:   PetscFunctionReturn(PETSC_SUCCESS);
    183: }

    185: /*@
    186:   PetscTestDirectory - checks for the existence of a directory

    188:   Not Collective

    190:   Input Parameters:
    191: + dirname - the directory name
    192: - mode    - either 'r', 'w', or 'x'

    194:   Output Parameter:
    195: . flg - the directory exists and satisfies the mode

    197:   Level: intermediate

    199: .seealso: `PetscTestFile()`, `PetscLs()`, `PetscRMTree()`
    200: @*/
    201: PetscErrorCode PetscTestDirectory(const char dirname[], char mode, PetscBool *flg)
    202: {
    203:   uid_t     fuid;
    204:   gid_t     fgid;
    205:   int       fmode;
    206:   PetscBool exists;

    208:   PetscFunctionBegin;
    209:   *flg = PETSC_FALSE;
    210:   if (!dirname) PetscFunctionReturn(PETSC_SUCCESS);

    212:   PetscCall(PetscGetFileStat(dirname, &fuid, &fgid, &fmode, &exists));
    213:   if (!exists) PetscFunctionReturn(PETSC_SUCCESS);
    214:   /* Except for systems that have this broken stat macros (rare), this
    215:      is the correct way to check for a directory */
    216:   if (!S_ISDIR(fmode)) PetscFunctionReturn(PETSC_SUCCESS);

    218:   PetscCall(PetscTestOwnership(dirname, mode, fuid, fgid, fmode, flg));
    219:   PetscFunctionReturn(PETSC_SUCCESS);
    220: }

    222: /*@C
    223:   PetscLs - produce a listing of the files in a directory

    225:   Collective

    227:   Input Parameters:
    228: + comm    - the MPI communicator
    229: . dirname - the directory name
    230: - tlen    - the length of the buffer `found`

    232:   Output Parameters:
    233: + found - listing of files
    234: - flg   - the directory exists

    236:   Level: intermediate

    238: .seealso: `PetscTestFile()`, `PetscRMTree()`, `PetscTestDirectory()`
    239: @*/
    240: PetscErrorCode PetscLs(MPI_Comm comm, const char dirname[], char found[], size_t tlen, PetscBool *flg)
    241: {
    242:   size_t len;
    243:   char  *f, program[PETSC_MAX_PATH_LEN];
    244:   FILE  *fp;

    246:   PetscFunctionBegin;
    247:   PetscCall(PetscStrncpy(program, "ls ", sizeof(program)));
    248:   PetscCall(PetscStrlcat(program, dirname, sizeof(program)));
    249: #if defined(PETSC_HAVE_POPEN)
    250:   PetscCall(PetscPOpen(comm, NULL, program, "r", &fp));
    251: #else
    252:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
    253: #endif
    254:   f = fgets(found, (int)tlen, fp);
    255:   if (f) *flg = PETSC_TRUE;
    256:   else *flg = PETSC_FALSE;
    257:   while (f) {
    258:     PetscCall(PetscStrlen(found, &len));
    259:     f = fgets(found + len, (int)(tlen - len), fp);
    260:   }
    261:   if (*flg) PetscCall(PetscInfo(NULL, "ls on %s gives \n%s\n", dirname, found));
    262: #if defined(PETSC_HAVE_POPEN)
    263:   PetscCall(PetscPClose(comm, fp));
    264: #else
    265:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
    266: #endif
    267:   PetscFunctionReturn(PETSC_SUCCESS);
    268: }