This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perlform: Revise link
[perl5.git] / cpan / Win32 / longpath.inc
CommitLineData
8883bb5a
JV
1#ifndef isSLASH\r
2#define isSLASH(c) ((c) == '/' || (c) == '\\')\r
3#define SKIP_SLASHES(s) \\r
4 STMT_START { \\r
5 while (*(s) && isSLASH(*(s))) \\r
6 ++(s); \\r
7 } STMT_END\r
8#define COPY_NONSLASHES(d,s) \\r
9 STMT_START { \\r
10 while (*(s) && !isSLASH(*(s))) \\r
11 *(d)++ = *(s)++; \\r
12 } STMT_END\r
13#endif\r
14\r
15/* Find the longname of a given path. path is destructively modified.\r
16 * It should have space for at least MAX_PATH characters. */\r
17\r
18CHAR_T *\r
19LONGPATH(CHAR_T *path)\r
20{\r
21 WIN32_FIND_DATA_T fdata;\r
22 HANDLE fhand;\r
23 CHAR_T tmpbuf[MAX_PATH+1];\r
24 CHAR_T *tmpstart = tmpbuf;\r
25 CHAR_T *start = path;\r
26 CHAR_T sep;\r
27 if (!path)\r
28 return NULL;\r
29\r
30 /* drive prefix */\r
31 if (isALPHA(path[0]) && path[1] == ':') {\r
32 start = path + 2;\r
33 *tmpstart++ = toupper(path[0]);\r
34 *tmpstart++ = ':';\r
35 }\r
36 /* UNC prefix */\r
37 else if (isSLASH(path[0]) && isSLASH(path[1])) {\r
38 start = path + 2;\r
39 *tmpstart++ = path[0];\r
40 *tmpstart++ = path[1];\r
41 SKIP_SLASHES(start);\r
42 COPY_NONSLASHES(tmpstart,start); /* copy machine name */\r
43 if (*start) {\r
44 *tmpstart++ = *start++;\r
45 SKIP_SLASHES(start);\r
46 COPY_NONSLASHES(tmpstart,start); /* copy share name */\r
47 }\r
48 }\r
49 *tmpstart = '\0';\r
50 while (*start) {\r
51 /* copy initial slash, if any */\r
52 if (isSLASH(*start)) {\r
53 *tmpstart++ = *start++;\r
54 *tmpstart = '\0';\r
55 SKIP_SLASHES(start);\r
56 }\r
57\r
58 /* FindFirstFile() expands "." and "..", so we need to pass\r
59 * those through unmolested */\r
60 if (*start == '.'\r
61 && (!start[1] || isSLASH(start[1])\r
62 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))\r
63 {\r
64 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */\r
65 *tmpstart = '\0';\r
66 continue;\r
67 }\r
68\r
69 /* if this is the end, bust outta here */\r
70 if (!*start)\r
71 break;\r
72\r
73 /* now we're at a non-slash; walk up to next slash */\r
74 while (*start && !isSLASH(*start))\r
75 ++start;\r
76\r
77 /* stop and find full name of component */\r
78 sep = *start;\r
79 *start = '\0';\r
80 fhand = FN_FINDFIRSTFILE(path,&fdata);\r
81 *start = sep;\r
82 if (fhand != INVALID_HANDLE_VALUE) {\r
83 STRLEN len = FN_STRLEN(fdata.cFileName);\r
84 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {\r
85 FN_STRCPY(tmpstart, fdata.cFileName);\r
86 tmpstart += len;\r
87 FindClose(fhand);\r
88 }\r
89 else {\r
90 FindClose(fhand);\r
91 errno = ERANGE;\r
92 return NULL;\r
93 }\r
94 }\r
95 else {\r
96 /* failed a step, just return without side effects */\r
97 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/\r
98 errno = EINVAL;\r
99 return NULL;\r
100 }\r
101 }\r
102 FN_STRCPY(path,tmpbuf);\r
103 return path;\r
104}\r
105\r
106#undef CHAR_T\r
107#undef WIN32_FIND_DATA_T\r
108#undef FN_FINDFIRSTFILE\r
109#undef FN_STRLEN\r
110#undef FN_STRCPY\r
111#undef LONGPATH\r