Skip to content

Commit 76bb695

Browse files
committed
#112 - extended shortcut/symlink support
1 parent 223a207 commit 76bb695

19 files changed

+1228
-780
lines changed

mcwin32/libw32/Makefile.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- mode: mak; indent-tabs-mode: t; tab-width: 8 -*-
2-
# $Id: Makefile.in,v 1.30 2025/03/30 17:16:02 cvsuser Exp $
2+
# $Id: Makefile.in,v 1.31 2025/04/01 16:15:14 cvsuser Exp $
33
# libwin32 makefile.
44
#
55
#
@@ -154,6 +154,7 @@ CSOURCES=\
154154
w32_gistrerror.c \
155155
w32_grp.c \
156156
w32_iconv.c \
157+
w32_fopen.c \
157158
w32_iconv_native.c \
158159
w32_ino.c \
159160
w32_io.c \
@@ -163,6 +164,7 @@ CSOURCES=\
163164
w32_mkstemp.c \
164165
w32_mmap.c \
165166
w32_neterr.c \
167+
w32_open.c \
166168
w32_pipe.c \
167169
w32_poll.c \
168170
w32_popen.c \

mcwin32/libw32/w32_access.c

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <edidentifier.h>
2-
__CIDENT_RCSID(gr_w32_access_c,"$Id: w32_access.c,v 1.7 2025/03/06 16:59:46 cvsuser Exp $")
2+
__CIDENT_RCSID(gr_w32_access_c,"$Id: w32_access.c,v 1.8 2025/04/01 16:15:14 cvsuser Exp $")
33

44
/* -*- mode: c; indent-width: 4; -*- */
55
/*
@@ -30,8 +30,14 @@ __CIDENT_RCSID(gr_w32_access_c,"$Id: w32_access.c,v 1.7 2025/03/06 16:59:46 cvsu
3030
*/
3131

3232
#include "win32_internal.h"
33+
#include "win32_io.h"
34+
3335
#include <unistd.h>
3436

37+
static int W32AccessA(const char *path, int amode);
38+
static int W32AccessW(const wchar_t *path, int amode);
39+
40+
3541
/*
3642
// NAME
3743
// access - determine accessibility of a file.
@@ -127,7 +133,7 @@ w32_access(const char *path, int amode)
127133
int
128134
w32_accessA(const char *path, int amode)
129135
{
130-
int ret = -1;
136+
int ret = -1; // success=0, otherwise=-1
131137

132138
if (NULL == path) {
133139
errno = EFAULT;
@@ -136,16 +142,21 @@ w32_accessA(const char *path, int amode)
136142
errno = ENOENT;
137143

138144
} else {
139-
const char *expath;
145+
char symbuf[WIN32_PATH_MAX];
140146

141-
if (NULL != (expath = w32_extendedpathA(path))) {
142-
path = expath; // abs-path to expanded
147+
if (w32_resolvelinkA(path, symbuf, _countof(symbuf), NULL) != NULL) {
148+
path = symbuf; // symlink
143149
}
144150

145-
#undef _access
146-
ret = _access(path, amode);
147-
148-
free((void*)expath);
151+
if ((ret = W32AccessA(path, amode)) == -1) {
152+
if (ENOTDIR == errno || ENOENT == errno) {
153+
if (path != symbuf) { // component error, expand embedded shortcut
154+
if (w32_expandlinkA(path, symbuf, _countof(symbuf), SHORTCUT_COMPONENT)) {
155+
ret = W32AccessA(symbuf, amode);
156+
}
157+
}
158+
}
159+
}
149160
}
150161
return ret;
151162
}
@@ -154,7 +165,7 @@ w32_accessA(const char *path, int amode)
154165
int
155166
w32_accessW(const wchar_t *path, int amode)
156167
{
157-
int ret = -1;
168+
int ret = -1; // success=0, otherwise=-1
158169

159170
if (NULL == path) {
160171
errno = EFAULT;
@@ -163,17 +174,58 @@ w32_accessW(const wchar_t *path, int amode)
163174
errno = ENOENT;
164175

165176
} else {
166-
const wchar_t *expath;
177+
wchar_t symbuf[WIN32_PATH_MAX];
167178

168-
if (NULL != (expath = w32_extendedpathW(path))) {
169-
path = expath; // abs-path to expanded
179+
if (w32_resolvelinkW(path, symbuf, _countof(symbuf), NULL) != NULL) {
180+
path = symbuf; // symlink
170181
}
171182

172-
#undef _waccess
173-
ret = _waccess(path, amode);
183+
if ((ret = W32AccessW(path, amode)) == -1) {
184+
if (ENOTDIR == errno || ENOENT == errno) {
185+
if (path != symbuf) { // component error, expand embedded shortcut
186+
if (w32_expandlinkW(path, symbuf, _countof(symbuf), SHORTCUT_COMPONENT)) {
187+
ret = W32AccessW(symbuf, amode);
188+
}
189+
}
190+
}
191+
}
192+
}
193+
return ret;
194+
}
195+
174196

175-
free((void*)expath);
197+
static int
198+
W32AccessA(const char *path, int amode)
199+
{
200+
const char *expath;
201+
int ret;
202+
203+
if (NULL != (expath = w32_extendedpathA(path))) {
204+
path = expath; // extended abs-path
205+
}
206+
207+
#undef _access
208+
ret = _access(path, amode);
209+
210+
free((void*)expath);
211+
return ret;
212+
}
213+
214+
215+
static int
216+
W32AccessW(const wchar_t *path, int amode)
217+
{
218+
const wchar_t *expath;
219+
int ret;
220+
221+
if (NULL != (expath = w32_extendedpathW(path))) {
222+
path = expath; // extended abs-path
176223
}
224+
225+
#undef _waccess
226+
ret = _waccess(path, amode);
227+
228+
free((void*)expath);
177229
return ret;
178230
}
179231

mcwin32/libw32/w32_chmod.c

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <edidentifier.h>
2-
__CIDENT_RCSID(gr_w32_chmod_c,"$Id: w32_chmod.c,v 1.9 2025/03/06 16:59:46 cvsuser Exp $")
2+
__CIDENT_RCSID(gr_w32_chmod_c,"$Id: w32_chmod.c,v 1.10 2025/04/01 16:15:14 cvsuser Exp $")
33

44
/* -*- mode: c; indent-width: 4; -*- */
55
/*
@@ -33,8 +33,12 @@ __CIDENT_RCSID(gr_w32_chmod_c,"$Id: w32_chmod.c,v 1.9 2025/03/06 16:59:46 cvsuse
3333
#endif
3434

3535
#include "win32_internal.h"
36+
#include "win32_io.h"
37+
3638
#include <unistd.h>
3739

40+
static int W32ChmodA(const char *path, mode_t mode);
41+
static int W32ChmodW(const wchar_t *path, mode_t mode);
3842

3943
/*
4044
// NAME
@@ -105,32 +109,99 @@ w32_chmod(const char *pathname, mode_t mode)
105109

106110
LIBW32_API int
107111
w32_chmodA(const char *pathname, mode_t mode)
112+
{
113+
int ret = -1; // success=0, otherwise=-1
114+
115+
if (NULL == pathname) {
116+
errno = EFAULT;
117+
118+
} else if (!*pathname) {
119+
errno = ENOENT;
120+
121+
} else {
122+
char symbuf[WIN32_PATH_MAX];
123+
124+
if (w32_resolvelinkA(pathname, symbuf, _countof(symbuf), NULL) != NULL) {
125+
pathname = symbuf; // symlink
126+
}
127+
128+
if ((ret = W32ChmodA(pathname, mode)) == -1) {
129+
if (ENOTDIR == errno || ENOENT == errno) {
130+
if (pathname != symbuf) { // component error, expand embedded shortcut
131+
if (w32_expandlinkA(pathname, symbuf, _countof(symbuf), SHORTCUT_COMPONENT)) {
132+
ret = W32ChmodA(symbuf, mode);
133+
}
134+
}
135+
}
136+
}
137+
}
138+
return ret;
139+
}
140+
141+
142+
LIBW32_API int
143+
w32_chmodW(const wchar_t *pathname, mode_t mode)
144+
{
145+
int ret = -1; // success=0, otherwise=-1
146+
147+
if (NULL == pathname) {
148+
errno = EFAULT;
149+
150+
} else if (!*pathname) {
151+
errno = ENOENT;
152+
153+
} else {
154+
wchar_t symbuf[WIN32_PATH_MAX];
155+
156+
if (w32_resolvelinkW(pathname, symbuf, _countof(symbuf), NULL) != NULL) {
157+
pathname = symbuf; // symlink
158+
}
159+
160+
if ((ret = W32ChmodW(pathname, mode)) == -1) {
161+
if (ENOTDIR == errno || ENOENT == errno) {
162+
if (pathname != symbuf) { // component error, expand embedded shortcut
163+
if (w32_expandlinkW(pathname, symbuf, _countof(symbuf), SHORTCUT_COMPONENT)) {
164+
ret = W32ChmodW(symbuf, mode);
165+
}
166+
}
167+
}
168+
}
169+
}
170+
return ret;
171+
}
172+
173+
174+
static int
175+
W32ChmodA(const char *pathname, mode_t mode)
108176
{
109177
const char *expath;
110178
int ret;
111179

112180
if (NULL != (expath = w32_extendedpathA(pathname))) {
113-
pathname = expath; // abs-path to expanded
181+
pathname = expath; // extended abs-path
114182
}
115183

116184
#undef chmod
117185
ret = chmod(pathname, mode);
186+
118187
free((void*)expath);
119188
return ret;
120189
}
121190

122191

123-
LIBW32_API int
124-
w32_chmodW(const wchar_t *pathname, mode_t mode)
192+
static int
193+
W32ChmodW(const wchar_t *pathname, mode_t mode)
125194
{
126195
const wchar_t *expath;
127196
int ret;
128197

129198
if (NULL != (expath = w32_extendedpathW(pathname))) {
130-
pathname = expath; // abs-path to expanded
199+
pathname = expath; // extended abs-path
131200
}
201+
132202
#undef _wchmod
133203
ret = _wchmod(pathname, mode);
204+
134205
free((void*)expath);
135206
return ret;
136207
}

mcwin32/libw32/w32_dir.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <edidentifier.h>
2-
__CIDENT_RCSID(gr_w32_dir_c, "$Id: w32_dir.c,v 1.29 2025/03/30 17:16:02 cvsuser Exp $")
2+
__CIDENT_RCSID(gr_w32_dir_c, "$Id: w32_dir.c,v 1.30 2025/04/01 16:15:14 cvsuser Exp $")
33

44
/* -*- mode: c; indent-width: 4; -*- */
55
/*
@@ -171,7 +171,7 @@ w32_mkdirA(const char *path, int mode)
171171
int ret = 0;
172172

173173
if (NULL != (expath = w32_extendedpathA(path))) {
174-
path = expath; // abs-path to expanded
174+
path = expath; // extended abs-path
175175
}
176176

177177
(void) mode;
@@ -191,7 +191,7 @@ w32_mkdirW(const wchar_t *path, int mode)
191191
int ret = 0;
192192

193193
if (NULL != (expath = w32_extendedpathW(path))) {
194-
path = expath; // abs-path to expanded
194+
path = expath; // extended abs-path
195195
}
196196

197197
(void) mode;
@@ -587,7 +587,7 @@ cache_directory()
587587
* =C:=C:\Program and Settings\users\
588588
*/
589589
env_var[1] = toupper(cwd[0]);
590-
w32_unix2dos(cwd);
590+
w32_unix2dosA(cwd);
591591

592592
(void) SetEnvironmentVariableA(env_var, cwd);
593593
}
@@ -721,7 +721,7 @@ w32_rmdirA(const char *path)
721721
int ret = 0;
722722

723723
if (NULL != (expath = w32_extendedpathA(path))) {
724-
path = expath; // abs-path to expanded
724+
path = expath; // extended abs-path
725725
}
726726

727727
if (! RemoveDirectoryA(path)) {
@@ -740,7 +740,7 @@ w32_rmdirW(const wchar_t *path)
740740
int ret = 0;
741741

742742
if (NULL != (expath = w32_extendedpathW(path))) {
743-
path = expath; // abs-path to expanded
743+
path = expath; // extended abs-path
744744
}
745745

746746
if (! RemoveDirectoryW(path)) {
@@ -772,7 +772,7 @@ w32_expandlinkA(const char *name, char *buf, size_t buflen, unsigned flags)
772772
for (cursor = t_name + length, end = cursor; --cursor >= t_name;) {
773773
if ('.' == *cursor) { // extension
774774
if (1 == ++dots) { // last/trailing
775-
if (0 == w32_iostrnicmp(cursor, ".lnk", 4) && (cursor + 4) == end) {
775+
if (0 == w32_iostrnicmpA(cursor, ".lnk", 4) && (cursor + 4) == end) {
776776
//
777777
// <shortcut>.lnk
778778
// - attempt expansion, allowing one within any given path.
@@ -830,7 +830,7 @@ w32_expandlinkW(const wchar_t *name, wchar_t *buf, size_t buflen, unsigned flags
830830
for (cursor = t_name + length, end = cursor; --cursor >= t_name;) {
831831
if ('.' == *cursor) { // extension
832832
if (1 == ++dots) { // last/trailing
833-
if (0 == w32_iowstrnicmp(cursor, ".lnk", 4) && (cursor + 4) == end) {
833+
if (0 == w32_iostrnicmpW(cursor, ".lnk", 4) && (cursor + 4) == end) {
834834
//
835835
// <shortcut>.lnk
836836
// - attempt expansion, allowing one within any given path.

mcwin32/libw32/w32_dirent.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <edidentifier.h>
2-
__CIDENT_RCSID(gr_w32_dirent_c,"$Id: w32_dirent.c,v 1.33 2025/03/30 17:16:02 cvsuser Exp $")
2+
__CIDENT_RCSID(gr_w32_dirent_c,"$Id: w32_dirent.c,v 1.34 2025/04/01 16:15:14 cvsuser Exp $")
33

44
/* -*- mode: c; indent-width: 4; -*- */
55
/*
@@ -464,7 +464,7 @@ IsShortcutA(const char *name)
464464

465465
for (cursor = name + len; --cursor >= name;) {
466466
if (*cursor == '.') { // extension
467-
return (*++cursor && 0 == w32_iostricmp(cursor, "lnk"));
467+
return (*++cursor && 0 == w32_iostricmpA(cursor, "lnk"));
468468
}
469469
if (*cursor == '/' || *cursor == '\\') {
470470
break; // delimiter
@@ -482,7 +482,7 @@ IsShortcutW(const wchar_t *name)
482482

483483
for (cursor = name + len; --cursor >= name;) {
484484
if (*cursor == '.') { // extension
485-
return (*++cursor && 0 == w32_iowstricmp(cursor, "lnk"));
485+
return (*++cursor && 0 == w32_iostricmpW(cursor, "lnk"));
486486
}
487487
if (*cursor == '/' || *cursor == '\\') {
488488
break; // delimiter

0 commit comments

Comments
 (0)