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