tool_doswin.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 #include "tool_setup.h"
00023 
00024 #if defined(MSDOS) || defined(WIN32)
00025 
00026 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
00027 #  include <libgen.h>
00028 #endif
00029 
00030 #ifdef WIN32
00031 #  include "tool_cfgable.h"
00032 #  include "tool_libinfo.h"
00033 #endif
00034 
00035 #include "tool_bname.h"
00036 #include "tool_doswin.h"
00037 
00038 #include "memdebug.h" /* keep this as LAST include */
00039 
00040 /*
00041  * Macros ALWAYS_TRUE and ALWAYS_FALSE are used to avoid compiler warnings.
00042  */
00043 
00044 #define ALWAYS_TRUE   (1)
00045 #define ALWAYS_FALSE  (0)
00046 
00047 #if defined(_MSC_VER) && !defined(__POCC__)
00048 #  undef ALWAYS_TRUE
00049 #  undef ALWAYS_FALSE
00050 #  if (_MSC_VER < 1500)
00051 #    define ALWAYS_TRUE   (0, 1)
00052 #    define ALWAYS_FALSE  (1, 0)
00053 #  else
00054 #    define ALWAYS_TRUE \
00055 __pragma(warning(push)) \
00056 __pragma(warning(disable:4127)) \
00057 (1) \
00058 __pragma(warning(pop))
00059 #    define ALWAYS_FALSE \
00060 __pragma(warning(push)) \
00061 __pragma(warning(disable:4127)) \
00062 (0) \
00063 __pragma(warning(pop))
00064 #  endif
00065 #endif
00066 
00067 #ifdef WIN32
00068 #  undef  PATH_MAX
00069 #  define PATH_MAX MAX_PATH
00070 #endif
00071 
00072 #ifndef S_ISCHR
00073 #  ifdef S_IFCHR
00074 #    define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
00075 #  else
00076 #    define S_ISCHR(m) (0) /* cannot tell if file is a device */
00077 #  endif
00078 #endif
00079 
00080 #ifdef WIN32
00081 #  define _use_lfn(f) ALWAYS_TRUE   /* long file names always available */
00082 #elif !defined(__DJGPP__) || (__DJGPP__ < 2)  /* DJGPP 2.0 has _use_lfn() */
00083 #  define _use_lfn(f) ALWAYS_FALSE  /* long file names never available */
00084 #elif defined(__DJGPP__)
00085 #  include <fcntl.h>                /* _use_lfn(f) prototype */
00086 #endif
00087 
00088 #ifndef UNITTESTS
00089 static SANITIZEcode truncate_dryrun(const char *path,
00090                                     const size_t truncate_pos);
00091 #ifdef MSDOS
00092 static SANITIZEcode msdosify(char **const sanitized, const char *file_name,
00093                              int flags);
00094 #endif
00095 static SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
00096                                                        const char *file_name,
00097                                                        int flags);
00098 #endif /* !UNITTESTS (static declarations used if no unit tests) */
00099 
00100 
00101 /*
00102 Sanitize a file or path name.
00103 
00104 All banned characters are replaced by underscores, for example:
00105 f?*foo => f__foo
00106 f:foo::$DATA => f_foo__$DATA
00107 f:\foo:bar => f__foo_bar
00108 f:\foo:bar => f:\foo:bar   (flag SANITIZE_ALLOW_PATH)
00109 
00110 This function was implemented according to the guidelines in 'Naming Files,
00111 Paths, and Namespaces' section 'Naming Conventions'.
00112 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx
00113 
00114 Flags
00115 -----
00116 SANITIZE_ALLOW_COLONS:     Allow colons.
00117 Without this flag colons are sanitized.
00118 
00119 SANITIZE_ALLOW_PATH:       Allow path separators and colons.
00120 Without this flag path separators and colons are sanitized.
00121 
00122 SANITIZE_ALLOW_RESERVED:   Allow reserved device names.
00123 Without this flag a reserved device name is renamed (COM1 => _COM1) unless it's
00124 in a UNC prefixed path.
00125 
00126 SANITIZE_ALLOW_TRUNCATE:   Allow truncating a long filename.
00127 Without this flag if the sanitized filename or path will be too long an error
00128 occurs. With this flag the filename --and not any other parts of the path-- may
00129 be truncated to at least a single character. A filename followed by an
00130 alternate data stream (ADS) cannot be truncated in any case.
00131 
00132 Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
00133 Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
00134 */
00135 SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name,
00136                                 int flags)
00137 {
00138   char *p, *target;
00139   size_t len;
00140   SANITIZEcode sc;
00141   size_t max_sanitized_len;
00142 
00143   if(!sanitized)
00144     return SANITIZE_ERR_BAD_ARGUMENT;
00145 
00146   *sanitized = NULL;
00147 
00148   if(!file_name)
00149     return SANITIZE_ERR_BAD_ARGUMENT;
00150 
00151   if((flags & SANITIZE_ALLOW_PATH)) {
00152 #ifndef MSDOS
00153     if(file_name[0] == '\\' && file_name[1] == '\\')
00154       /* UNC prefixed path \\ (eg \\?\C:\foo) */
00155       max_sanitized_len = 32767-1;
00156     else
00157 #endif
00158       max_sanitized_len = PATH_MAX-1;
00159   }
00160   else
00161     /* The maximum length of a filename.
00162        FILENAME_MAX is often the same as PATH_MAX, in other words it is 260 and
00163        does not discount the path information therefore we shouldn't use it. */
00164     max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1;
00165 
00166   len = strlen(file_name);
00167   if(len > max_sanitized_len) {
00168     if(!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00169        truncate_dryrun(file_name, max_sanitized_len))
00170       return SANITIZE_ERR_INVALID_PATH;
00171 
00172     len = max_sanitized_len;
00173   }
00174 
00175   target = malloc(len + 1);
00176   if(!target)
00177     return SANITIZE_ERR_OUT_OF_MEMORY;
00178 
00179   strncpy(target, file_name, len);
00180   target[len] = '\0';
00181 
00182 #ifndef MSDOS
00183   if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4))
00184     /* Skip the literal path prefix \\?\ */
00185     p = target + 4;
00186   else
00187 #endif
00188     p = target;
00189 
00190   /* replace control characters and other banned characters */
00191   for(; *p; ++p) {
00192     const char *banned;
00193 
00194     if((1 <= *p && *p <= 31) ||
00195        (!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *p == ':') ||
00196        (!(flags & SANITIZE_ALLOW_PATH) && (*p == '/' || *p == '\\'))) {
00197       *p = '_';
00198       continue;
00199     }
00200 
00201     for(banned = "|<>\"?*"; *banned; ++banned) {
00202       if(*p == *banned) {
00203         *p = '_';
00204         break;
00205       }
00206     }
00207   }
00208 
00209   /* remove trailing spaces and periods if not allowing paths */
00210   if(!(flags & SANITIZE_ALLOW_PATH) && len) {
00211     char *clip = NULL;
00212 
00213     p = &target[len];
00214     do {
00215       --p;
00216       if(*p != ' ' && *p != '.')
00217         break;
00218       clip = p;
00219     } while(p != target);
00220 
00221     if(clip) {
00222       *clip = '\0';
00223       len = clip - target;
00224     }
00225   }
00226 
00227 #ifdef MSDOS
00228   sc = msdosify(&p, target, flags);
00229   free(target);
00230   if(sc)
00231     return sc;
00232   target = p;
00233   len = strlen(target);
00234 
00235   if(len > max_sanitized_len) {
00236     free(target);
00237     return SANITIZE_ERR_INVALID_PATH;
00238   }
00239 #endif
00240 
00241   if(!(flags & SANITIZE_ALLOW_RESERVED)) {
00242     sc = rename_if_reserved_dos_device_name(&p, target, flags);
00243     free(target);
00244     if(sc)
00245       return sc;
00246     target = p;
00247     len = strlen(target);
00248 
00249     if(len > max_sanitized_len) {
00250       free(target);
00251       return SANITIZE_ERR_INVALID_PATH;
00252     }
00253   }
00254 
00255   *sanitized = target;
00256   return SANITIZE_ERR_OK;
00257 }
00258 
00259 
00260 /*
00261 Test if truncating a path to a file will leave at least a single character in
00262 the filename. Filenames suffixed by an alternate data stream can't be
00263 truncated. This performs a dry run, nothing is modified.
00264 
00265 Good truncate_pos 9:    C:\foo\bar  =>  C:\foo\ba
00266 Good truncate_pos 6:    C:\foo      =>  C:\foo
00267 Good truncate_pos 5:    C:\foo      =>  C:\fo
00268 Bad* truncate_pos 5:    C:foo       =>  C:foo
00269 Bad truncate_pos 5:     C:\foo:ads  =>  C:\fo
00270 Bad truncate_pos 9:     C:\foo:ads  =>  C:\foo:ad
00271 Bad truncate_pos 5:     C:\foo\bar  =>  C:\fo
00272 Bad truncate_pos 5:     C:\foo\     =>  C:\fo
00273 Bad truncate_pos 7:     C:\foo\     =>  C:\foo\
00274 Error truncate_pos 7:   C:\foo      =>  (pos out of range)
00275 Bad truncate_pos 1:     C:\foo\     =>  C
00276 
00277 * C:foo is ambiguous, C could end up being a drive or file therefore something
00278   like C:superlongfilename can't be truncated.
00279 
00280 Returns
00281 SANITIZE_ERR_OK: Good -- 'path' can be truncated
00282 SANITIZE_ERR_INVALID_PATH: Bad -- 'path' cannot be truncated
00283 != SANITIZE_ERR_OK && != SANITIZE_ERR_INVALID_PATH: Error
00284 */
00285 SANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos)
00286 {
00287   size_t len;
00288 
00289   if(!path)
00290     return SANITIZE_ERR_BAD_ARGUMENT;
00291 
00292   len = strlen(path);
00293 
00294   if(truncate_pos > len)
00295     return SANITIZE_ERR_BAD_ARGUMENT;
00296 
00297   if(!len || !truncate_pos)
00298     return SANITIZE_ERR_INVALID_PATH;
00299 
00300   if(strpbrk(&path[truncate_pos - 1], "\\/:"))
00301     return SANITIZE_ERR_INVALID_PATH;
00302 
00303   /* C:\foo can be truncated but C:\foo:ads can't */
00304   if(truncate_pos > 1) {
00305     const char *p = &path[truncate_pos - 1];
00306     do {
00307       --p;
00308       if(*p == ':')
00309         return SANITIZE_ERR_INVALID_PATH;
00310     } while(p != path && *p != '\\' && *p != '/');
00311   }
00312 
00313   return SANITIZE_ERR_OK;
00314 }
00315 
00316 /* The functions msdosify, rename_if_dos_device_name and __crt0_glob_function
00317  * were taken with modification from the DJGPP port of tar 1.12. They use
00318  * algorithms originally from DJTAR.
00319  */
00320 
00321 /*
00322 Extra sanitization MSDOS for file_name.
00323 
00324 This is a supporting function for sanitize_file_name.
00325 
00326 Warning: This is an MSDOS legacy function and was purposely written in a way
00327 that some path information may pass through. For example drive letter names
00328 (C:, D:, etc) are allowed to pass through. For sanitizing a filename use
00329 sanitize_file_name.
00330 
00331 Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
00332 Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
00333 */
00334 #if defined(MSDOS) || defined(UNITTESTS)
00335 SANITIZEcode msdosify(char **const sanitized, const char *file_name,
00336                       int flags)
00337 {
00338   char dos_name[PATH_MAX];
00339   static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
00340     "|<>/\\\":?*"; /* illegal in DOS & W95 */
00341   static const char *illegal_chars_w95 = &illegal_chars_dos[8];
00342   int idx, dot_idx;
00343   const char *s = file_name;
00344   char *d = dos_name;
00345   const char *const dlimit = dos_name + sizeof(dos_name) - 1;
00346   const char *illegal_aliens = illegal_chars_dos;
00347   size_t len = sizeof(illegal_chars_dos) - 1;
00348 
00349   if(!sanitized)
00350     return SANITIZE_ERR_BAD_ARGUMENT;
00351 
00352   *sanitized = NULL;
00353 
00354   if(!file_name)
00355     return SANITIZE_ERR_BAD_ARGUMENT;
00356 
00357   if(strlen(file_name) > PATH_MAX-1 &&
00358      (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00359       truncate_dryrun(file_name, PATH_MAX-1)))
00360     return SANITIZE_ERR_INVALID_PATH;
00361 
00362   /* Support for Windows 9X VFAT systems, when available. */
00363   if(_use_lfn(file_name)) {
00364     illegal_aliens = illegal_chars_w95;
00365     len -= (illegal_chars_w95 - illegal_chars_dos);
00366   }
00367 
00368   /* Get past the drive letter, if any. */
00369   if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
00370     *d++ = *s++;
00371     *d = ((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) ? ':' : '_';
00372     ++d, ++s;
00373   }
00374 
00375   for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
00376     if(memchr(illegal_aliens, *s, len)) {
00377 
00378       if((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *s == ':')
00379         *d = ':';
00380       else if((flags & SANITIZE_ALLOW_PATH) && (*s == '/' || *s == '\\'))
00381         *d = *s;
00382       /* Dots are special: DOS doesn't allow them as the leading character,
00383          and a file name cannot have more than a single dot.  We leave the
00384          first non-leading dot alone, unless it comes too close to the
00385          beginning of the name: we want sh.lex.c to become sh_lex.c, not
00386          sh.lex-c.  */
00387       else if(*s == '.') {
00388         if((flags & SANITIZE_ALLOW_PATH) && idx == 0 &&
00389            (s[1] == '/' || s[1] == '\\' ||
00390             (s[1] == '.' && (s[2] == '/' || s[2] == '\\')))) {
00391           /* Copy "./" and "../" verbatim.  */
00392           *d++ = *s++;
00393           if(d == dlimit)
00394             break;
00395           if(*s == '.') {
00396             *d++ = *s++;
00397             if(d == dlimit)
00398               break;
00399           }
00400           *d = *s;
00401         }
00402         else if(idx == 0)
00403           *d = '_';
00404         else if(dot_idx >= 0) {
00405           if(dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */
00406             d[dot_idx - idx] = '_'; /* replace previous dot */
00407             *d = '.';
00408           }
00409           else
00410             *d = '-';
00411         }
00412         else
00413           *d = '.';
00414 
00415         if(*s == '.')
00416           dot_idx = idx;
00417       }
00418       else if(*s == '+' && s[1] == '+') {
00419         if(idx - 2 == dot_idx) { /* .c++, .h++ etc. */
00420           *d++ = 'x';
00421           if(d == dlimit)
00422             break;
00423           *d   = 'x';
00424         }
00425         else {
00426           /* libg++ etc.  */
00427           if(dlimit - d < 4) {
00428             *d++ = 'x';
00429             if(d == dlimit)
00430               break;
00431             *d   = 'x';
00432           }
00433           else {
00434             memcpy(d, "plus", 4);
00435             d += 3;
00436           }
00437         }
00438         s++;
00439         idx++;
00440       }
00441       else
00442         *d = '_';
00443     }
00444     else
00445       *d = *s;
00446     if(*s == '/' || *s == '\\') {
00447       idx = 0;
00448       dot_idx = -1;
00449     }
00450     else
00451       idx++;
00452   }
00453   *d = '\0';
00454 
00455   if(*s) {
00456     /* dos_name is truncated, check that truncation requirements are met,
00457        specifically truncating a filename suffixed by an alternate data stream
00458        or truncating the entire filename is not allowed. */
00459     if(!(flags & SANITIZE_ALLOW_TRUNCATE) || strpbrk(s, "\\/:") ||
00460        truncate_dryrun(dos_name, d - dos_name))
00461       return SANITIZE_ERR_INVALID_PATH;
00462   }
00463 
00464   *sanitized = strdup(dos_name);
00465   return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
00466 }
00467 #endif /* MSDOS || UNITTESTS */
00468 
00469 /*
00470 Rename file_name if it's a reserved dos device name.
00471 
00472 This is a supporting function for sanitize_file_name.
00473 
00474 Warning: This is an MSDOS legacy function and was purposely written in a way
00475 that some path information may pass through. For example drive letter names
00476 (C:, D:, etc) are allowed to pass through. For sanitizing a filename use
00477 sanitize_file_name.
00478 
00479 Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
00480 Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
00481 */
00482 SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
00483                                                 const char *file_name,
00484                                                 int flags)
00485 {
00486   /* We could have a file whose name is a device on MS-DOS.  Trying to
00487    * retrieve such a file would fail at best and wedge us at worst.  We need
00488    * to rename such files. */
00489   char *p, *base;
00490   char fname[PATH_MAX];
00491 #ifdef MSDOS
00492   struct_stat st_buf;
00493 #endif
00494 
00495   if(!sanitized)
00496     return SANITIZE_ERR_BAD_ARGUMENT;
00497 
00498   *sanitized = NULL;
00499 
00500   if(!file_name)
00501     return SANITIZE_ERR_BAD_ARGUMENT;
00502 
00503   /* Ignore UNC prefixed paths, they are allowed to contain a reserved name. */
00504 #ifndef MSDOS
00505   if((flags & SANITIZE_ALLOW_PATH) &&
00506      file_name[0] == '\\' && file_name[1] == '\\') {
00507     size_t len = strlen(file_name);
00508     *sanitized = malloc(len + 1);
00509     if(!*sanitized)
00510       return SANITIZE_ERR_OUT_OF_MEMORY;
00511     strncpy(*sanitized, file_name, len + 1);
00512     return SANITIZE_ERR_OK;
00513   }
00514 #endif
00515 
00516   if(strlen(file_name) > PATH_MAX-1 &&
00517      (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00518       truncate_dryrun(file_name, PATH_MAX-1)))
00519     return SANITIZE_ERR_INVALID_PATH;
00520 
00521   strncpy(fname, file_name, PATH_MAX-1);
00522   fname[PATH_MAX-1] = '\0';
00523   base = basename(fname);
00524 
00525   /* Rename reserved device names that are known to be accessible without \\.\
00526      Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS
00527      https://support.microsoft.com/en-us/kb/74496
00528      https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx
00529      */
00530   for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) {
00531     size_t p_len;
00532     int x = (curl_strnequal(p, "CON", 3) ||
00533              curl_strnequal(p, "PRN", 3) ||
00534              curl_strnequal(p, "AUX", 3) ||
00535              curl_strnequal(p, "NUL", 3)) ? 3 :
00536             (curl_strnequal(p, "CLOCK$", 6)) ? 6 :
00537             (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ?
00538               (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0;
00539 
00540     if(!x)
00541       continue;
00542 
00543     /* the devices may be accessible with an extension or ADS, for
00544        example CON.AIR and 'CON . AIR' and CON:AIR access console */
00545 
00546     for(; p[x] == ' '; ++x)
00547       ;
00548 
00549     if(p[x] == '.') {
00550       p[x] = '_';
00551       continue;
00552     }
00553     else if(p[x] == ':') {
00554       if(!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) {
00555         p[x] = '_';
00556         continue;
00557       }
00558       ++x;
00559     }
00560     else if(p[x]) /* no match */
00561       continue;
00562 
00563     /* p points to 'CON' or 'CON ' or 'CON:', etc */
00564     p_len = strlen(p);
00565 
00566     /* Prepend a '_' */
00567     if(strlen(fname) == PATH_MAX-1) {
00568       --p_len;
00569       if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(p, p_len))
00570         return SANITIZE_ERR_INVALID_PATH;
00571       p[p_len] = '\0';
00572     }
00573     memmove(p + 1, p, p_len + 1);
00574     p[0] = '_';
00575     ++p_len;
00576 
00577     /* if fname was just modified then the basename pointer must be updated */
00578     if(p == fname)
00579       base = basename(fname);
00580   }
00581 
00582   /* This is the legacy portion from rename_if_dos_device_name that checks for
00583      reserved device names. It only works on MSDOS. On Windows XP the stat
00584      check errors with EINVAL if the device name is reserved. On Windows
00585      Vista/7/8 it sets mode S_IFREG (regular file or device). According to MSDN
00586      stat doc the latter behavior is correct, but that doesn't help us identify
00587      whether it's a reserved device name and not a regular file name. */
00588 #ifdef MSDOS
00589   if(base && ((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
00590     /* Prepend a '_' */
00591     size_t blen = strlen(base);
00592     if(blen) {
00593       if(strlen(fname) == PATH_MAX-1) {
00594         --blen;
00595         if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(base, blen))
00596           return SANITIZE_ERR_INVALID_PATH;
00597         base[blen] = '\0';
00598       }
00599       memmove(base + 1, base, blen + 1);
00600       base[0] = '_';
00601       ++blen;
00602     }
00603   }
00604 #endif
00605 
00606   *sanitized = strdup(fname);
00607   return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
00608 }
00609 
00610 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
00611 
00612 /*
00613  * Disable program default argument globbing. We do it on our own.
00614  */
00615 char **__crt0_glob_function(char *arg)
00616 {
00617   (void)arg;
00618   return (char **)0;
00619 }
00620 
00621 #endif /* MSDOS && (__DJGPP__ || __GO32__) */
00622 
00623 #ifdef WIN32
00624 
00625 /*
00626  * Function to find CACert bundle on a Win32 platform using SearchPath.
00627  * (SearchPath is already declared via inclusions done in setup header file)
00628  * (Use the ASCII version instead of the unicode one!)
00629  * The order of the directories it searches is:
00630  *  1. application's directory
00631  *  2. current working directory
00632  *  3. Windows System directory (e.g. C:\windows\system32)
00633  *  4. Windows Directory (e.g. C:\windows)
00634  *  5. all directories along %PATH%
00635  *
00636  * For WinXP and later search order actually depends on registry value:
00637  * HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode
00638  */
00639 
00640 CURLcode FindWin32CACert(struct OperationConfig *config,
00641                          const char *bundle_file)
00642 {
00643   CURLcode result = CURLE_OK;
00644 
00645   /* search and set cert file only if libcurl supports SSL */
00646   if(curlinfo->features & CURL_VERSION_SSL) {
00647 
00648     DWORD res_len;
00649     DWORD buf_tchar_size = PATH_MAX + 1;
00650     DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size;
00651     char *ptr = NULL;
00652 
00653     char *buf = malloc(buf_bytes_size);
00654     if(!buf)
00655       return CURLE_OUT_OF_MEMORY;
00656     buf[0] = '\0';
00657 
00658     res_len = SearchPathA(NULL, bundle_file, NULL, buf_tchar_size, buf, &ptr);
00659     if(res_len > 0) {
00660       Curl_safefree(config->cacert);
00661       config->cacert = strdup(buf);
00662       if(!config->cacert)
00663         result = CURLE_OUT_OF_MEMORY;
00664     }
00665 
00666     Curl_safefree(buf);
00667   }
00668 
00669   return result;
00670 }
00671 
00672 #endif /* WIN32 */
00673 
00674 #endif /* MSDOS || WIN32 */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:07