Home | History | Annotate | Download | only in toolutil
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /******************************************************************************
      4  *   Copyright (C) 2009-2013, International Business Machines
      5  *   Corporation and others.  All Rights Reserved.
      6  *******************************************************************************
      7  */
      8 
      9 #include "unicode/platform.h"
     10 #if U_PLATFORM == U_PF_MINGW
     11 // *cough* - for struct stat
     12 #ifdef __STRICT_ANSI__
     13 #undef __STRICT_ANSI__
     14 #endif
     15 #endif
     16 
     17 #include "filetools.h"
     18 #include "filestrm.h"
     19 #include "charstr.h"
     20 #include "cstring.h"
     21 #include "unicode/putil.h"
     22 #include "putilimp.h"
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <sys/stat.h>
     27 #include <time.h>
     28 #include <string.h>
     29 
     30 #if U_HAVE_DIRENT_H
     31 #include <dirent.h>
     32 typedef struct dirent DIRENT;
     33 
     34 #define SKIP1 "."
     35 #define SKIP2 ".."
     36 #endif
     37 
     38 static int32_t whichFileModTimeIsLater(const char *file1, const char *file2);
     39 
     40 /*
     41  * Goes through the given directory recursive to compare each file's modification time with that of the file given.
     42  * Also can be given just one file to check against. Default value for isDir is FALSE.
     43  */
     44 U_CAPI UBool U_EXPORT2
     45 isFileModTimeLater(const char *filePath, const char *checkAgainst, UBool isDir) {
     46     UBool isLatest = TRUE;
     47 
     48     if (filePath == NULL || checkAgainst == NULL) {
     49         return FALSE;
     50     }
     51 
     52     if (isDir == TRUE) {
     53 #if U_HAVE_DIRENT_H
     54         DIR *pDir = NULL;
     55         if ((pDir= opendir(checkAgainst)) != NULL) {
     56             DIR *subDirp = NULL;
     57             DIRENT *dirEntry = NULL;
     58 
     59             while ((dirEntry = readdir(pDir)) != NULL) {
     60                 if (uprv_strcmp(dirEntry->d_name, SKIP1) != 0 && uprv_strcmp(dirEntry->d_name, SKIP2) != 0) {
     61                     UErrorCode status = U_ZERO_ERROR;
     62                     icu::CharString newpath(checkAgainst, -1, status);
     63                     newpath.append(U_FILE_SEP_STRING, -1, status);
     64                     newpath.append(dirEntry->d_name, -1, status);
     65                     if (U_FAILURE(status)) {
     66                         fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, u_errorName(status));
     67                         return FALSE;
     68                     };
     69 
     70                     if ((subDirp = opendir(newpath.data())) != NULL) {
     71                         /* If this new path is a directory, make a recursive call with the newpath. */
     72                         closedir(subDirp);
     73                         isLatest = isFileModTimeLater(filePath, newpath.data(), isDir);
     74                         if (!isLatest) {
     75                             break;
     76                         }
     77                     } else {
     78                         int32_t latest = whichFileModTimeIsLater(filePath, newpath.data());
     79                         if (latest < 0 || latest == 2) {
     80                             isLatest = FALSE;
     81                             break;
     82                         }
     83                     }
     84 
     85                 }
     86             }
     87             closedir(pDir);
     88         } else {
     89             fprintf(stderr, "Unable to open directory: %s\n", checkAgainst);
     90             return FALSE;
     91         }
     92 #endif
     93     } else {
     94         if (T_FileStream_file_exists(checkAgainst)) {
     95             int32_t latest = whichFileModTimeIsLater(filePath, checkAgainst);
     96             if (latest < 0 || latest == 2) {
     97                 isLatest = FALSE;
     98             }
     99         } else {
    100             isLatest = FALSE;
    101         }
    102     }
    103 
    104     return isLatest;
    105 }
    106 
    107 /* Compares the mod time of both files returning a number indicating which one is later. -1 if error ocurs. */
    108 static int32_t whichFileModTimeIsLater(const char *file1, const char *file2) {
    109     int32_t result = 0;
    110     struct stat stbuf1, stbuf2;
    111 
    112     if (stat(file1, &stbuf1) == 0 && stat(file2, &stbuf2) == 0) {
    113         time_t modtime1, modtime2;
    114         double diff;
    115 
    116         modtime1 = stbuf1.st_mtime;
    117         modtime2 = stbuf2.st_mtime;
    118 
    119         diff = difftime(modtime1, modtime2);
    120         if (diff < 0.0) {
    121             result = 2;
    122         } else if (diff > 0.0) {
    123             result = 1;
    124         }
    125 
    126     } else {
    127         fprintf(stderr, "Unable to get stats from file: %s or %s\n", file1, file2);
    128         result = -1;
    129     }
    130 
    131     return result;
    132 }
    133 
    134 /* Swap the file separater character given with the new one in the file path. */
    135 U_CAPI void U_EXPORT2
    136 swapFileSepChar(char *filePath, const char oldFileSepChar, const char newFileSepChar) {
    137     for (int32_t i = 0, length = uprv_strlen(filePath); i < length; i++) {
    138         filePath[i] = (filePath[i] == oldFileSepChar ) ? newFileSepChar : filePath[i];
    139     }
    140 }
    141