1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7#ifndef WIN32_LEAN_AND_MEAN
8#define WIN32_LEAN_AND_MEAN
9#endif
10#include <sys/stat.h>
11#include <stdlib.h>
12#include <locale.h>
13#include <windows.h>
14#include "__mingw_fix_stat.h"
15
16static const char* next_char (unsigned int cp, const char* p)
17{
18 /* If it is a lead byte, skip the next byte except if it is \0.
19 * If it is \0, it's not a valid DBCS string. */
20 return (__mingw_isleadbyte_cp (*p, cp) && p[1] != '\0') ? p + 2 : p + 1;
21}
22
23/**
24 * Returns _path without trailing slash if any
25 *
26 * - if _path has no trailing slash, the function returns it
27 * - if _path has a trailing slash, but is of the form C:/, then it returns it
28 * - otherwise, the function creates a new string, which is a copy of _path
29 * without the trailing slash. It is then the responsibility of the caller
30 * to free it.
31 */
32
33char* __mingw_fix_stat_path (const char* _path)
34{
35 const unsigned int cp = __mingw_filename_cp ();
36 size_t len;
37 char *p;
38
39 p = (char*)_path;
40
41 if (_path && *_path) {
42 len = strlen (_path);
43
44 /* Ignore X:\
45 * No ANSI or OEM code page uses ':' as a trail byte. (The code page 1361
46 * cannot be used as ANSI or OEM code page.) */
47 if (len <= 1 || ((len == 2 || len == 3) && _path[1] == ':'))
48 return p;
49
50 const char *r = _path;
51
52 /* Check UNC \\abc\<name>\ */
53 if ((_path[0] == '\\' || _path[0] == '/')
54 && (_path[1] == '\\' || _path[1] == '/'))
55 {
56 r = &_path[2];
57 while (*r != 0 && *r != '\\' && *r != '/')
58 r = next_char (cp, r);
59 if (*r != 0)
60 ++r;
61 if (*r == 0)
62 return p;
63 while (*r != 0 && *r != '\\' && *r != '/')
64 r = next_char (cp, r);
65 if (*r != 0)
66 ++r;
67 if (*r == 0)
68 return p;
69 }
70
71 if (_path[len - 1] == '/' || _path[len - 1] == '\\')
72 {
73 /* Return if the last character is a double-byte character.
74 * Its trail byte could be a '\' which must not be interpret
75 * as a directory separator. */
76 while (r[1] != '\0')
77 {
78 r = next_char (cp, r);
79 if (*r == '\0')
80 return p;
81 }
82
83 p = (char*)malloc (len);
84 if (p == NULL)
85 return NULL; /* malloc has set errno. */
86 memcpy (p, _path, len - 1);
87 p[len - 1] = '\0';
88 }
89 }
90
91 return p;
92}