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