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> 28typedef 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 36static 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 */ 42U_CAPI UBool U_EXPORT2 43isFileModTimeLater(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. */ 102static 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. */ 129U_CAPI void U_EXPORT2 130swapFileSepChar(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