ICU-12779 merge r39468 r39469 from #12798 into maint-58

X-SVN-Rev: 39471
diff --git a/source/common/putil.cpp b/source/common/putil.cpp
index ca1dd44..03f6548 100644
--- a/source/common/putil.cpp
+++ b/source/common/putil.cpp
@@ -834,7 +834,6 @@
 #endif
 
 #ifdef SEARCH_TZFILE
-#define MAX_PATH_SIZE PATH_MAX /* Set the limit for the size of the path. */
 #define MAX_READ_SIZE 512
 
 typedef struct DefaultTZInfo {
@@ -910,15 +909,19 @@
 
     return result;
 }
-/*
- * This method recursively traverses the directory given for a matching TZ file and returns the first match.
- */
+
+
 /* dirent also lists two entries: "." and ".." that we can safely ignore. */
 #define SKIP1 "."
 #define SKIP2 ".."
-static char SEARCH_TZFILE_RESULT[MAX_PATH_SIZE] = "";
+static UBool U_CALLCONV putil_cleanup(void);
+static CharString *gSearchTZFileResult = NULL;
+
+/*
+ * This method recursively traverses the directory given for a matching TZ file and returns the first match.
+ * This function is not thread safe - it uses a global, gSearchTZFileResult, to hold its results.
+ */
 static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
-    char curpath[MAX_PATH_SIZE];
     DIR* dirp = opendir(path);
     DIR* subDirp = NULL;
     struct dirent* dirEntry = NULL;
@@ -928,24 +931,40 @@
         return result;
     }
 
+    if (gSearchTZFileResult == NULL) {
+        gSearchTZFileResult = new CharString;
+        if (gSearchTZFileResult == NULL) {
+            return NULL;
+        }
+        ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
+    }
+
     /* Save the current path */
-    uprv_memset(curpath, 0, MAX_PATH_SIZE);
-    uprv_strcpy(curpath, path);
+    UErrorCode status = U_ZERO_ERROR;
+    CharString curpath(path, -1, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
 
     /* Check each entry in the directory. */
     while((dirEntry = readdir(dirp)) != NULL) {
         const char* dirName = dirEntry->d_name;
         if (uprv_strcmp(dirName, SKIP1) != 0 && uprv_strcmp(dirName, SKIP2) != 0) {
             /* Create a newpath with the new entry to test each entry in the directory. */
-            char newpath[MAX_PATH_SIZE];
-            uprv_strcpy(newpath, curpath);
-            uprv_strcat(newpath, dirName);
+            CharString newpath(curpath, status);
+            newpath.append(dirName, -1, status);
+            if (U_FAILURE(status)) {
+                return NULL;
+            }
 
-            if ((subDirp = opendir(newpath)) != NULL) {
+            if ((subDirp = opendir(newpath.data())) != NULL) {
                 /* If this new path is a directory, make a recursive call with the newpath. */
                 closedir(subDirp);
-                uprv_strcat(newpath, "/");
-                result = searchForTZFile(newpath, tzInfo);
+                newpath.append('/', status);
+                if (U_FAILURE(status)) {
+                    return NULL;
+                }
+                result = searchForTZFile(newpath.data(), tzInfo);
                 /*
                  Have to get out here. Otherwise, we'd keep looking
                  and return the first match in the top-level directory
@@ -957,11 +976,19 @@
                 if (result != NULL)
                     break;
             } else if (uprv_strcmp(TZFILE_SKIP, dirName) != 0 && uprv_strcmp(TZFILE_SKIP2, dirName) != 0) {
-                if(compareBinaryFiles(TZDEFAULT, newpath, tzInfo)) {
-                    const char* zoneid = newpath + (sizeof(TZZONEINFO)) - 1;
+                if(compareBinaryFiles(TZDEFAULT, newpath.data(), tzInfo)) {
+                    int32_t amountToSkip = sizeof(TZZONEINFO) - 1;
+                    if (amountToSkip > newpath.length()) {
+                        amountToSkip = newpath.length();
+                    }
+                    const char* zoneid = newpath.data() + amountToSkip;
                     skipZoneIDPrefix(&zoneid);
-                    uprv_strcpy(SEARCH_TZFILE_RESULT, zoneid);
-                    result = SEARCH_TZFILE_RESULT;
+                    gSearchTZFileResult->clear();
+                    gSearchTZFileResult->append(zoneid, -1, status);
+                    if (U_FAILURE(status)) {
+                        return NULL;
+                    }
+                    result = gSearchTZFileResult->data();
                     /* Get out after the first one found. */
                     break;
                 }
@@ -1150,6 +1177,11 @@
     gTimeZoneFilesDirectory = NULL;
     gTimeZoneFilesInitOnce.reset();
 
+#ifdef SEARCH_TZFILE
+    delete gSearchTZFileResult;
+    gSearchTZFileResult = NULL;
+#endif
+
 #if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
     if (gCorrectedPOSIXLocale) {
         uprv_free(gCorrectedPOSIXLocale);
diff --git a/source/tools/toolutil/filetools.cpp b/source/tools/toolutil/filetools.cpp
index 28a9b34..b0d4ed8 100644
--- a/source/tools/toolutil/filetools.cpp
+++ b/source/tools/toolutil/filetools.cpp
@@ -6,6 +6,7 @@
  *******************************************************************************
  */
 
+#include "unicode/platform.h"
 #if U_PLATFORM == U_PF_MINGW
 // *cough* - for struct stat
 #ifdef __STRICT_ANSI__
@@ -15,6 +16,7 @@
 
 #include "filetools.h"
 #include "filestrm.h"
+#include "charstr.h"
 #include "cstring.h"
 #include "unicode/putil.h"
 #include "putilimp.h"
@@ -29,8 +31,6 @@
 #include <dirent.h>
 typedef struct dirent DIRENT;
 
-#define MAX_PATH_SIZE 4096 /* Set the limit for the size of the path. */
-
 #define SKIP1 "."
 #define SKIP2 ".."
 #endif
@@ -58,20 +58,24 @@
 
             while ((dirEntry = readdir(pDir)) != NULL) {
                 if (uprv_strcmp(dirEntry->d_name, SKIP1) != 0 && uprv_strcmp(dirEntry->d_name, SKIP2) != 0) {
-                    char newpath[MAX_PATH_SIZE] = "";
-                    uprv_strcpy(newpath, checkAgainst);
-                    uprv_strcat(newpath, U_FILE_SEP_STRING);
-                    uprv_strcat(newpath, dirEntry->d_name);
+                    UErrorCode status = U_ZERO_ERROR;
+                    icu::CharString newpath(checkAgainst, -1, status);
+                    newpath.append(U_FILE_SEP_STRING, -1, status);
+                    newpath.append(dirEntry->d_name, -1, status);
+                    if (U_FAILURE(status)) {
+                        fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, u_errorName(status));
+                        return FALSE;
+                    };
 
-                    if ((subDirp = opendir(newpath)) != NULL) {
+                    if ((subDirp = opendir(newpath.data())) != NULL) {
                         /* If this new path is a directory, make a recursive call with the newpath. */
                         closedir(subDirp);
-                        isLatest = isFileModTimeLater(filePath, newpath, isDir);
+                        isLatest = isFileModTimeLater(filePath, newpath.data(), isDir);
                         if (!isLatest) {
                             break;
                         }
                     } else {
-                        int32_t latest = whichFileModTimeIsLater(filePath, newpath);
+                        int32_t latest = whichFileModTimeIsLater(filePath, newpath.data());
                         if (latest < 0 || latest == 2) {
                             isLatest = FALSE;
                             break;