]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/path.h
Cygwin: add flag to indicate reparse points unknown to WinAPI
[newlib-cygwin.git] / winsup / cygwin / path.h
CommitLineData
1fd5e000
CF
1/* path.h: path data structures
2
1fd5e000
CF
3This file is part of Cygwin.
4
5This software is a copyrighted work licensed under the terms of the
6Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7details. */
8
7ac61736 9#include "devices.h"
58298328 10#include "mount.h"
fafbf755 11#include "cygheap_malloc.h"
2d355410 12#include "nfs.h"
7ac61736 13
c1023ee3 14#include <sys/mount.h>
7ac61736
CF
15#include <sys/ioctl.h>
16#include <fcntl.h>
6ae28c22 17#include <alloca.h>
7ac61736 18
c3a46349 19extern inline bool
f3810c72
CV
20has_attribute (DWORD attributes, DWORD attribs_to_test)
21{
22 return attributes != INVALID_FILE_ATTRIBUTES
23 && (attributes & attribs_to_test);
24}
25
7ac61736
CF
26enum executable_states
27{
28 is_executable,
29 dont_care_if_executable,
30 not_executable = dont_care_if_executable,
31 dont_know_if_executable
32};
33
1fd5e000
CF
34struct suffix_info
35{
36 const char *name;
37 int addon;
1dc16fc7 38 suffix_info (const char *s, int addit = 0): name (s), addon (addit) {}
1fd5e000
CF
39};
40
4a971ce4
CV
41extern suffix_info stat_suffixes[];
42
fde4eaa1
CV
43/* DO NOT copy any of these files into the same set of flags as the
44 below path_types. Ever. */
5bc584ba 45enum pathconv_arg
1fd5e000 46{
2caaa810
CV
47 PC_SYM_FOLLOW = _BIT ( 0), /* follow symlinks */
48 PC_SYM_NOFOLLOW = _BIT ( 1), /* don't follow symlinks (but honor
49 trailing slashes) */
50 PC_SYM_NOFOLLOW_REP = _BIT ( 2), /* don't follow dir reparse point */
51 PC_SYM_CONTENTS = _BIT ( 3), /* don't follow, return content only */
52 PC_NOFULL = _BIT ( 4), /* keep relative path */
53 PC_NULLEMPTY = _BIT ( 5), /* empty path is no error */
54 PC_NONULLEMPTY = _BIT ( 6), /* override PC_NULLEMPTY default */
55 PC_POSIX = _BIT ( 7), /* return normalized posix path */
c1023ee3
CV
56 PC_OPEN = _BIT ( 9), /* use open semantics */
57 PC_CTTY = _BIT (10), /* could later be used as ctty */
2caaa810
CV
58 PC_SYM_NOFOLLOW_PROCFD = _BIT (11), /* allow /proc/PID/fd redirection */
59 PC_KEEP_HANDLE = _BIT (12), /* keep handle for later stat calls */
60 PC_NO_ACCESS_CHECK = _BIT (13), /* helper flag for error check */
26425142 61 PC_SYM_NOFOLLOW_DIR = _BIT (14), /* don't follow a trailing slash */
c1023ee3 62 PC_DONT_USE = _BIT (31) /* conversion to signed happens. */
1fd5e000
CF
63};
64
5bc584ba 65enum path_types
1fd5e000 66{
c1023ee3
CV
67 PATH_CTTY = _BIT ( 0), /* could later be used as ctty */
68 PATH_OPEN = _BIT ( 1), /* use open semantics */
e9bc4ccc
CV
69 PATH_LNK = _BIT ( 2), /* *.lnk-type symlink */
70 PATH_REP = _BIT ( 3), /* reparse point known to Cygwin */
71 PATH_SYMLINK = _BIT ( 4), /* symlink understood by Cygwin */
72 PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */
73 PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */
aec64798 74 PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */
c1023ee3 75 PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
1fd5e000
CF
76};
77
9dae73ed
CV
78enum fetch_fh_flags
79{
80 FFH_LINKAT = (1 << 0),
81};
82
f91865c8 83NTSTATUS file_get_fai (HANDLE, PFILE_ALL_INFORMATION);
3e80cefb
CV
84int check_reparse_point_target (HANDLE, bool, PREPARSE_DATA_BUFFER,
85 PUNICODE_STRING);
f91865c8 86
c80480bf 87class symlink_info;
c80480bf 88
5a0d1edb
CV
89class path_conv_handle
90{
91 HANDLE hdl;
2d355410 92 union {
eed35efb 93 FILE_ALL_INFORMATION _fai;
2d355410
CV
94 /* For NFS. */
95 fattr3 _fattr3;
96 } attribs;
5a0d1edb 97public:
dd0821e3
CV
98 path_conv_handle () : hdl (NULL) {}
99 inline void set (HANDLE h) { hdl = h; }
5a0d1edb
CV
100 inline void close ()
101 {
102 if (hdl)
103 CloseHandle (hdl);
dd0821e3 104 set (NULL);
5a0d1edb 105 }
23771fa1 106 inline void dup (const path_conv_handle &pch)
5a0d1edb
CV
107 {
108 if (!DuplicateHandle (GetCurrentProcess (), pch.handle (),
109 GetCurrentProcess (), &hdl,
110 0, TRUE, DUPLICATE_SAME_ACCESS))
dd0821e3 111 hdl = NULL;
5a0d1edb
CV
112 }
113 inline HANDLE handle () const { return hdl; }
f91865c8 114 inline PFILE_ALL_INFORMATION fai () const
eed35efb 115 { return (PFILE_ALL_INFORMATION) &attribs._fai; }
f91865c8 116 inline struct fattr3 *nfsattr () const
2d355410 117 { return (struct fattr3 *) &attribs._fattr3; }
f91865c8
CV
118 inline NTSTATUS get_finfo (HANDLE h, bool nfs)
119 {
120 return nfs ? nfs_fetch_fattr3 (h, nfsattr ()) : file_get_fai (h, fai ());
121 }
122 inline ino_t get_ino (bool nfs) const
123 {
124 return nfs ? nfsattr ()->fileid
125 : fai ()->InternalInformation.IndexNumber.QuadPart;
126 }
127 inline DWORD get_dosattr (bool nfs) const
128 {
129 if (nfs)
130 return (nfsattr ()->type & 7) == NF3DIR ? FILE_ATTRIBUTE_DIRECTORY : 0;
131 return fai ()->BasicInformation.FileAttributes;
132 }
5a0d1edb
CV
133};
134
29ee580d
CF
135class path_conv
136{
99138976 137 DWORD fileattr;
e4b57503 138 ULONG caseinsensitive;
29ee580d 139 fs_info fs;
26d95368 140
91d2f6ee
CV
141 PWCHAR wide_path;
142 UNICODE_STRING uni_path;
fafbf755
CF
143 DWORD symlink_length;
144 const char *path;
c1023ee3
CV
145 uint32_t mount_flags;
146 uint32_t path_flags;
d2bd82aa
CV
147 const char *suffix;
148 const char *posix_path;
5a0d1edb 149 path_conv_handle conv_handle;
26d95368
CV
150
151 void add_ext_from_sym (symlink_info&);
152 char *modifiable_path () {return (char *) path;}
153
1fd5e000 154 public:
47063f00 155 int error;
7ac61736 156 device dev;
ecfb6f11 157
91b264c7
CV
158 void *serialize (HANDLE, unsigned int &) const;
159 HANDLE deserialize (void *);
160
d2bd82aa 161 const char *known_suffix () { return suffix; }
330a2fae 162 bool isremote () const {return fs.is_remote_drive ();}
e4b57503 163 ULONG objcaseinsensitive () const {return caseinsensitive;}
c1023ee3
CV
164 bool has_acls () const {return !(mount_flags & MOUNT_NOACL)
165 && fs.has_acls (); }
166 bool hasgood_inode () const {return !(mount_flags & MOUNT_IHASH); }
61522196 167 bool isgood_inode (ino_t ino) const;
05297cca
CV
168 bool support_sparse () const
169 {
c1023ee3 170 return (mount_flags & MOUNT_SPARSE)
05297cca
CV
171 && (fs_flags () & FILE_SUPPORTS_SPARSE_FILES);
172 }
c1023ee3 173 int has_dos_filenames_only () const {return mount_flags & MOUNT_DOS;}
4c9d01fd 174 int has_buggy_reopen () const {return fs.has_buggy_reopen ();}
d79a78e5 175 int has_buggy_fileid_dirinfo () const {return fs.has_buggy_fileid_dirinfo ();}
c04ed45d 176 int has_buggy_basic_info () const {return fs.has_buggy_basic_info ();}
e35f391f
CF
177 int binmode () const
178 {
367c1ae1 179 return (mount_flags & MOUNT_TEXT) ? O_TEXT : O_BINARY;
e35f391f 180 }
ecfb6f11 181 int issymlink () const {return path_flags & PATH_SYMLINK;}
762520f3 182 int is_lnk_symlink () const {return path_flags & PATH_LNK;}
aec64798 183 /* This indicates any known reparse point */
7ae89fe7 184 int is_known_reparse_point () const {return path_flags & PATH_REP;}
aec64798
CV
185 /* This indicates any known reparse point, handled sanely by WinAPI.
186 The difference is crucial: WSL symlinks, for instance, are known
187 reparse points, so we want to open them as reparse points usually.
188 However they are foreign to WinAPI and not handled sanely. If one
189 is part of $PATH, WinAPI functions may fail under the hood with
190 STATUS_IO_REPARSE_TAG_NOT_HANDLED. */
191 int is_winapi_reparse_point () const
192 {
193 return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP;
194 }
44d2fc0a
CF
195 int isdevice () const {return dev.not_device (FH_FS) && dev.not_device (FH_FIFO);}
196 int isfifo () const {return dev.is_device (FH_FIFO);}
197 int isspecial () const {return dev.not_device (FH_FS);}
198 int iscygdrive () const {return dev.is_device (FH_CYGDRIVE);}
c57b13f9 199 int is_fs_special () const {return dev.is_fs_special ();}
73f81953
KB
200
201 int is_lnk_special () const {return (isdevice () && is_fs_special ()
202 && !issocket ())
af4d29e1 203 || isfifo () || is_lnk_symlink ();}
6c55be9d 204#ifdef __WITH_AF_UNIX
aa467e6e
CV
205 int issocket () const {return dev.is_device (FH_LOCAL)
206 || dev.is_device (FH_UNIX);}
6c55be9d
CV
207#else
208 int issocket () const {return dev.is_device (FH_LOCAL);}
209#endif /* __WITH_AF_UNIX */
c1023ee3 210 int iscygexec () const {return mount_flags & MOUNT_CYGWIN_EXEC;}
23771fa1
CF
211 int isopen () const {return path_flags & PATH_OPEN;}
212 int isctty_capable () const {return path_flags & PATH_CTTY;}
ba12614f 213 int follow_fd_symlink () const {return path_flags & PATH_RESOLVE_PROCFD;}
70d0243c
CF
214 void set_cygexec (bool isset)
215 {
216 if (isset)
c1023ee3 217 mount_flags |= MOUNT_CYGWIN_EXEC;
70d0243c 218 else
c1023ee3 219 mount_flags &= ~MOUNT_CYGWIN_EXEC;
70d0243c 220 }
61522196
CV
221 void set_cygexec (void *target)
222 {
223 if (target)
c1023ee3 224 mount_flags |= MOUNT_CYGWIN_EXEC;
61522196 225 else
c1023ee3 226 mount_flags &= ~MOUNT_CYGWIN_EXEC;
61522196 227 }
c1023ee3 228 bool isro () const {return !!(mount_flags & MOUNT_RO);}
7eddac1b 229 bool exists () const {return fileattr != INVALID_FILE_ATTRIBUTES;}
47063f00
CF
230 bool has_attribute (DWORD x) const {return exists () && (fileattr & x);}
231 int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);}
95a8465b
CF
232 executable_states exec_state ()
233 {
234 extern int _check_for_executable;
c1023ee3 235 if (mount_flags & (MOUNT_CYGWIN_EXEC | MOUNT_EXEC))
95a8465b 236 return is_executable;
c1023ee3 237 if (mount_flags & MOUNT_NOTEXEC)
95a8465b
CF
238 return not_executable;
239 if (!_check_for_executable)
240 return dont_care_if_executable;
241 return dont_know_if_executable;
242 }
1fd5e000 243
b923181e 244 void set_symlink (DWORD n) {path_flags |= PATH_SYMLINK; symlink_length = n;}
c1023ee3 245 void set_exec (int x = 1) {mount_flags |= x ? MOUNT_EXEC : MOUNT_NOTEXEC;}
1fd5e000 246
c1023ee3 247 void __reg3 check (const UNICODE_STRING *upath, uint32_t opt = PC_SYM_FOLLOW,
6e75c72b 248 const suffix_info *suffixes = NULL);
c1023ee3 249 void __reg3 check (const char *src, uint32_t opt = PC_SYM_FOLLOW,
6e75c72b 250 const suffix_info *suffixes = NULL);
5bc584ba 251
c211f8eb 252 path_conv (const device& in_dev)
7f01964f 253 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
c1023ee3
CV
254 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL),
255 error (0), dev (in_dev)
c211f8eb 256 {
b2867a68 257 set_path (in_dev.native ());
c211f8eb 258 }
7ac61736 259
c1023ee3 260 path_conv (const UNICODE_STRING *src, uint32_t opt = PC_SYM_FOLLOW,
214c3a11 261 const suffix_info *suffixes = NULL)
6259826e 262 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
c1023ee3 263 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
214c3a11 264 {
c1023ee3 265 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
214c3a11
CV
266 }
267
c1023ee3 268 path_conv (const char *src, uint32_t opt = PC_SYM_FOLLOW,
5bc584ba 269 const suffix_info *suffixes = NULL)
6259826e 270 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
c1023ee3 271 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
55fc91b9 272 {
c1023ee3 273 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
55fc91b9
CF
274 }
275
c211f8eb 276 path_conv ()
fafbf755 277 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
c1023ee3 278 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
0986989f 279 {}
55fc91b9 280
720c33ae 281 ~path_conv ();
d2bd82aa 282 inline const char *get_win32 () const { return path; }
5abb0ed1 283 void set_nt_native_path (PUNICODE_STRING);
91d2f6ee 284 PUNICODE_STRING get_nt_native_path ();
4c9d01fd
CV
285 inline POBJECT_ATTRIBUTES get_object_attr (OBJECT_ATTRIBUTES &attr,
286 SECURITY_ATTRIBUTES &sa)
287 {
288 if (!get_nt_native_path ())
289 return NULL;
290 InitializeObjectAttributes (&attr, &uni_path,
291 objcaseinsensitive ()
292 | (sa.bInheritHandle ? OBJ_INHERIT : 0),
293 NULL, sa.lpSecurityDescriptor);
294 return &attr;
295 }
dc847e6b 296 inline POBJECT_ATTRIBUTES init_reopen_attr (OBJECT_ATTRIBUTES &attr, HANDLE h)
4c9d01fd
CV
297 {
298 if (has_buggy_reopen ())
dc847e6b 299 InitializeObjectAttributes (&attr, get_nt_native_path (),
4c9d01fd
CV
300 objcaseinsensitive (), NULL, NULL)
301 else
dc847e6b 302 InitializeObjectAttributes (&attr, &ro_u_empty, objcaseinsensitive (),
4c9d01fd 303 h, NULL);
dc847e6b 304 return &attr;
4c9d01fd 305 }
891b6e88
CV
306 inline size_t get_wide_win32_path_len ()
307 {
308 get_nt_native_path ();
309 return uni_path.Length / sizeof (WCHAR);
310 }
311
91d2f6ee 312 PWCHAR get_wide_win32_path (PWCHAR wc);
291be307 313 operator DWORD &() {return fileattr;}
9d1e72a1 314 operator int () {return fileattr; }
b2099ee7
CF
315# define cfree_and_null(x) \
316 if (x) \
317 { \
318 cfree ((void *) (x)); \
319 (x) = NULL; \
320 }
321 void free_strings ()
322 {
323 cfree_and_null (path);
d2bd82aa 324 cfree_and_null (posix_path);
b2099ee7
CF
325 cfree_and_null (wide_path);
326 }
1dfffe8e 327 path_conv& eq_worker (const path_conv& pc, const char *in_path)
19afaa1a 328 {
b2099ee7 329 free_strings ();
f0cf44dc 330 memcpy ((void *) this, &pc, sizeof pc);
b2867a68
CV
331 /* The device info might contain pointers to allocated strings, in
332 contrast to statically allocated strings. Calling device::dup()
333 will duplicate the string if the source was allocated. */
334 dev.dup ();
22d1ebac
KB
335 if (in_path)
336 path = cstrdup (in_path);
5a0d1edb 337 conv_handle.dup (pc.conv_handle);
22d1ebac
KB
338 if (pc.posix_path)
339 posix_path = cstrdup(pc.posix_path);
303dc023
CV
340 if (pc.wide_path)
341 {
342 wide_path = cwcsdup (uni_path.Buffer);
343 if (!wide_path)
344 api_fatal ("cwcsdup would have returned NULL");
345 uni_path.Buffer = wide_path;
346 }
19afaa1a
CV
347 return *this;
348 }
6ae28c22
CF
349
350 path_conv &operator << (const path_conv& pc)
351 {
352 const char *save_path;
1dfffe8e 353
6ae28c22
CF
354 if (!path)
355 save_path = pc.path;
356 else
357 {
358 save_path = (char *) alloca (strlen (path) + 1);
359 strcpy ((char *) save_path, path);
360 }
1dfffe8e 361 return eq_worker (pc, save_path);
6ae28c22
CF
362 }
363
364 path_conv &operator =(const path_conv& pc)
365 {
1dfffe8e 366 return eq_worker (pc, pc.path);
6ae28c22 367 }
61522196 368 dev_t get_device () {return dev.get_device ();}
330a2fae 369 DWORD file_attributes () const {return fileattr;}
0175b531 370 void file_attributes (DWORD new_attr) {fileattr = new_attr;}
05297cca
CV
371 DWORD fs_flags () const {return fs.flags ();}
372 DWORD fs_name_len () const {return fs.name_len ();}
da827464 373 bool fs_got_fs () const { return fs.got_fs (); }
330a2fae 374 bool fs_is_fat () const {return fs.is_fat ();}
0c25ca40
CV
375 bool fs_is_exfat () const {return fs.is_exfat ();}
376 bool fs_is_any_fat () const {return fs.is_fat () || fs.is_exfat ();}
330a2fae 377 bool fs_is_ntfs () const {return fs.is_ntfs ();}
115d74b9 378 bool fs_is_refs () const {return fs.is_refs ();}
330a2fae
CV
379 bool fs_is_samba () const {return fs.is_samba ();}
380 bool fs_is_nfs () const {return fs.is_nfs ();}
90c2ba78
CF
381 bool fs_is_netapp () const {return fs.is_netapp ();}
382 bool fs_is_cdrom () const {return fs.is_cdrom ();}
0fb0fb83 383 bool fs_is_mvfs () const {return fs.is_mvfs ();}
4a49c715
CV
384 bool fs_is_cifs () const {return fs.is_cifs ();}
385 bool fs_is_nwfs () const {return fs.is_nwfs ();}
69178ca0 386 bool fs_is_ncfsd () const {return fs.is_ncfsd ();}
9ecd475c 387 bool fs_is_afs () const {return fs.is_afs ();}
57d93beb 388 bool fs_is_prlfs () const {return fs.is_prlfs ();}
34ce8088 389 fs_info_type fs_type () const {return fs.what_fs ();}
636c94d8 390 ULONG fs_serial_number () const {return fs.serial_number ();}
fafbf755
CF
391 inline const char *set_path (const char *p)
392 {
393 if (path)
394 cfree (modifiable_path ());
395 char *new_path = (char *) cmalloc_abort (HEAP_STR, strlen (p) + 7);
396 strcpy (new_path, p);
397 return path = new_path;
398 }
9235f3ea 399 bool is_binary ();
7ac61736 400
5a0d1edb 401 HANDLE handle () const { return conv_handle.handle (); }
eed35efb 402 PFILE_ALL_INFORMATION fai () { return conv_handle.fai (); }
2d355410 403 struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
f91865c8
CV
404 inline NTSTATUS get_finfo (HANDLE h)
405 {
406 return conv_handle.get_finfo (h, fs.is_nfs ());
407 }
408 inline ino_t get_ino () const { return conv_handle.get_ino (fs.is_nfs ()); }
dd0821e3 409 void reset_conv_handle () { conv_handle.set (NULL); }
5a0d1edb
CV
410 void close_conv_handle () { conv_handle.close (); }
411
61522196 412 ino_t get_ino_by_handle (HANDLE h);
d2bd82aa
CV
413 inline const char *get_posix () const { return posix_path; }
414 void __reg2 set_posix (const char *);
b923181e 415 DWORD get_symlink_length () { return symlink_length; };
1fd5e000
CF
416};
417
418/* Symlink marker */
419#define SYMLINK_COOKIE "!<symlink>"
420
421/* Socket marker */
422#define SOCKET_COOKIE "!<socket >"
423
2671595b
CV
424/* Interix symlink marker */
425#define INTERIX_SYMLINK_COOKIE "IntxLNK\1"
426
6ea0c04e
CF
427enum fe_types
428{
429 FE_NADA = 0, /* Nothing special */
430 FE_NNF = 1, /* Return NULL if not found */
4b84e3dc
CV
431 FE_CWD = 4, /* Search CWD for program */
432 FE_DLL = 8 /* Search for DLLs, not executables. */
6ea0c04e 433};
6e75c72b 434const char *__reg3 find_exec (const char *name, path_conv& buf,
117b1b1e 435 const char *search = "PATH",
1ffe3e67 436 unsigned opt = FE_NADA,
6e75c72b 437 const char **known_suffix = NULL);
bccd5e0d 438
1fd5e000 439/* Common macros for checking for invalid path names */
ec50441f 440#define isdrive(s) (isalpha (*(s)) && (s)[1] == ':')
752b16ce 441#define iswdrive(s) (iswalpha (*(s)) && (s)[1] == L':')
7e24f1bf 442
b12796a0
CF
443static inline bool
444has_exec_chars (const char *buf, int len)
445{
446 return len >= 2 &&
447 ((buf[0] == '#' && buf[1] == '!') ||
448 (buf[0] == ':' && buf[1] == '\n') ||
449 (buf[0] == 'M' && buf[1] == 'Z'));
450}
451
6e75c72b
CF
452int __reg3 pathmatch (const char *path1, const char *path2, bool caseinsensitive);
453int __reg3 pathnmatch (const char *path1, const char *path2, int len, bool caseinsensitive);
454bool __reg2 has_dot_last_component (const char *dir, bool test_dot_dot);
291be307 455
6e75c72b
CF
456int __reg3 path_prefix_p (const char *path1, const char *path2, int len1,
457 bool caseinsensitive);
7905c4f1 458
ade47a34
CF
459int normalize_win32_path (const char *, char *, char *&);
460int normalize_posix_path (const char *, char *, char *&);
6e75c72b 461PUNICODE_STRING __reg3 get_nt_native_path (const char *, UNICODE_STRING&, bool);
db27ea41 462
4bfa93f1 463int __reg3 symlink_worker (const char *, path_conv &, bool);
This page took 1.014486 seconds and 5 git commands to generate.