1 /* path.h: path data structures
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #include "cygheap_malloc.h"
14 #include <sys/mount.h>
15 #include <sys/ioctl.h>
20 has_attribute (DWORD attributes
, DWORD attribs_to_test
)
22 return attributes
!= INVALID_FILE_ATTRIBUTES
23 && (attributes
& attribs_to_test
);
26 enum executable_states
29 dont_care_if_executable
,
30 not_executable
= dont_care_if_executable
,
31 dont_know_if_executable
38 suffix_info (const char *s
, int addit
= 0): name (s
), addon (addit
) {}
41 extern suffix_info stat_suffixes
[];
43 /* DO NOT copy any of these files into the same set of flags as the
44 below path_types. Ever. */
47 PC_SYM_FOLLOW
= _BIT ( 0), /* follow symlinks */
48 PC_SYM_NOFOLLOW
= _BIT ( 1), /* don't follow symlinks (but honor
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 */
56 PC_OPEN
= _BIT ( 9), /* use open semantics */
57 PC_CTTY
= _BIT (10), /* could later be used as ctty */
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 */
61 PC_SYM_NOFOLLOW_DIR
= _BIT (14), /* don't follow a trailing slash */
62 PC_DONT_USE
= _BIT (31) /* conversion to signed happens. */
67 PATH_CTTY
= _BIT ( 0), /* could later be used as ctty */
68 PATH_OPEN
= _BIT ( 1), /* use open semantics */
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 */
74 PATH_DONT_USE
= _BIT (31) /* conversion to signed happens. */
79 FFH_LINKAT
= (1 << 0),
82 NTSTATUS
file_get_fai (HANDLE
, PFILE_ALL_INFORMATION
);
83 int check_reparse_point_target (HANDLE
, bool, PREPARSE_DATA_BUFFER
,
88 class path_conv_handle
92 FILE_ALL_INFORMATION _fai
;
97 path_conv_handle () : hdl (NULL
) {}
98 inline void set (HANDLE h
) { hdl
= h
; }
105 inline void dup (const path_conv_handle
&pch
)
107 if (!DuplicateHandle (GetCurrentProcess (), pch
.handle (),
108 GetCurrentProcess (), &hdl
,
109 0, TRUE
, DUPLICATE_SAME_ACCESS
))
112 inline HANDLE
handle () const { return hdl
; }
113 inline PFILE_ALL_INFORMATION
fai () const
114 { return (PFILE_ALL_INFORMATION
) &attribs
._fai
; }
115 inline struct fattr3
*nfsattr () const
116 { return (struct fattr3
*) &attribs
._fattr3
; }
117 inline NTSTATUS
get_finfo (HANDLE h
, bool nfs
)
119 return nfs
? nfs_fetch_fattr3 (h
, nfsattr ()) : file_get_fai (h
, fai ());
121 inline ino_t
get_ino (bool nfs
) const
123 return nfs
? nfsattr ()->fileid
124 : fai ()->InternalInformation
.IndexNumber
.QuadPart
;
126 inline DWORD
get_dosattr (bool nfs
) const
129 return (nfsattr ()->type
& 7) == NF3DIR
? FILE_ATTRIBUTE_DIRECTORY
: 0;
130 return fai ()->BasicInformation
.FileAttributes
;
137 ULONG caseinsensitive
;
141 UNICODE_STRING uni_path
;
142 DWORD symlink_length
;
144 uint32_t mount_flags
;
147 const char *posix_path
;
148 path_conv_handle conv_handle
;
150 void add_ext_from_sym (symlink_info
&);
151 char *modifiable_path () {return (char *) path
;}
157 void *serialize (HANDLE
, unsigned int &) const;
158 HANDLE
deserialize (void *);
160 const char *known_suffix () { return suffix
; }
161 bool isremote () const {return fs
.is_remote_drive ();}
162 ULONG
objcaseinsensitive () const {return caseinsensitive
;}
163 bool has_acls () const {return !(mount_flags
& MOUNT_NOACL
)
165 bool hasgood_inode () const {return !(mount_flags
& MOUNT_IHASH
); }
166 bool isgood_inode (ino_t ino
) const;
167 bool support_sparse () const
169 return (mount_flags
& MOUNT_SPARSE
)
170 && (fs_flags () & FILE_SUPPORTS_SPARSE_FILES
);
172 int has_dos_filenames_only () const {return mount_flags
& MOUNT_DOS
;}
173 int has_buggy_reopen () const {return fs
.has_buggy_reopen ();}
174 int has_buggy_fileid_dirinfo () const {return fs
.has_buggy_fileid_dirinfo ();}
175 int has_buggy_basic_info () const {return fs
.has_buggy_basic_info ();}
178 return (mount_flags
& MOUNT_TEXT
) ? O_TEXT
: O_BINARY
;
180 int issymlink () const {return path_flags
& PATH_SYMLINK
;}
181 int is_lnk_symlink () const {return path_flags
& PATH_LNK
;}
182 int is_known_reparse_point () const {return path_flags
& PATH_REP
;}
183 int isdevice () const {return dev
.not_device (FH_FS
) && dev
.not_device (FH_FIFO
);}
184 int isfifo () const {return dev
.is_device (FH_FIFO
);}
185 int isspecial () const {return dev
.not_device (FH_FS
);}
186 int iscygdrive () const {return dev
.is_device (FH_CYGDRIVE
);}
187 int is_fs_special () const {return dev
.is_fs_special ();}
189 int is_lnk_special () const {return (isdevice () && is_fs_special ()
191 || isfifo () || is_lnk_symlink ();}
192 #ifdef __WITH_AF_UNIX
193 int issocket () const {return dev
.is_device (FH_LOCAL
)
194 || dev
.is_device (FH_UNIX
);}
196 int issocket () const {return dev
.is_device (FH_LOCAL
);}
197 #endif /* __WITH_AF_UNIX */
198 int iscygexec () const {return mount_flags
& MOUNT_CYGWIN_EXEC
;}
199 int isopen () const {return path_flags
& PATH_OPEN
;}
200 int isctty_capable () const {return path_flags
& PATH_CTTY
;}
201 int follow_fd_symlink () const {return path_flags
& PATH_RESOLVE_PROCFD
;}
202 void set_cygexec (bool isset
)
205 mount_flags
|= MOUNT_CYGWIN_EXEC
;
207 mount_flags
&= ~MOUNT_CYGWIN_EXEC
;
209 void set_cygexec (void *target
)
212 mount_flags
|= MOUNT_CYGWIN_EXEC
;
214 mount_flags
&= ~MOUNT_CYGWIN_EXEC
;
216 bool isro () const {return !!(mount_flags
& MOUNT_RO
);}
217 bool exists () const {return fileattr
!= INVALID_FILE_ATTRIBUTES
;}
218 bool has_attribute (DWORD x
) const {return exists () && (fileattr
& x
);}
219 int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY
);}
220 executable_states
exec_state ()
222 extern int _check_for_executable
;
223 if (mount_flags
& (MOUNT_CYGWIN_EXEC
| MOUNT_EXEC
))
224 return is_executable
;
225 if (mount_flags
& MOUNT_NOTEXEC
)
226 return not_executable
;
227 if (!_check_for_executable
)
228 return dont_care_if_executable
;
229 return dont_know_if_executable
;
232 void set_symlink (DWORD n
) {path_flags
|= PATH_SYMLINK
; symlink_length
= n
;}
233 void set_exec (int x
= 1) {mount_flags
|= x
? MOUNT_EXEC
: MOUNT_NOTEXEC
;}
235 void __reg3
check (const UNICODE_STRING
*upath
, uint32_t opt
= PC_SYM_FOLLOW
,
236 const suffix_info
*suffixes
= NULL
);
237 void __reg3
check (const char *src
, uint32_t opt
= PC_SYM_FOLLOW
,
238 const suffix_info
*suffixes
= NULL
);
240 path_conv (const device
& in_dev
)
241 : fileattr (INVALID_FILE_ATTRIBUTES
), wide_path (NULL
), path (NULL
),
242 mount_flags (0), path_flags (0), suffix (NULL
), posix_path (NULL
),
243 error (0), dev (in_dev
)
245 set_path (in_dev
.native ());
248 path_conv (const UNICODE_STRING
*src
, uint32_t opt
= PC_SYM_FOLLOW
,
249 const suffix_info
*suffixes
= NULL
)
250 : fileattr (INVALID_FILE_ATTRIBUTES
), wide_path (NULL
), path (NULL
),
251 mount_flags (0), path_flags (0), suffix (NULL
), posix_path (NULL
), error (0)
253 check (src
, opt
| ((opt
& PC_NONULLEMPTY
) ? 0 : PC_NULLEMPTY
), suffixes
);
256 path_conv (const char *src
, uint32_t opt
= PC_SYM_FOLLOW
,
257 const suffix_info
*suffixes
= NULL
)
258 : fileattr (INVALID_FILE_ATTRIBUTES
), wide_path (NULL
), path (NULL
),
259 mount_flags (0), path_flags (0), suffix (NULL
), posix_path (NULL
), error (0)
261 check (src
, opt
| ((opt
& PC_NONULLEMPTY
) ? 0 : PC_NULLEMPTY
), suffixes
);
265 : fileattr (INVALID_FILE_ATTRIBUTES
), wide_path (NULL
), path (NULL
),
266 mount_flags (0), path_flags (0), suffix (NULL
), posix_path (NULL
), error (0)
270 inline const char *get_win32 () const { return path
; }
271 void set_nt_native_path (PUNICODE_STRING
);
272 PUNICODE_STRING
get_nt_native_path ();
273 inline POBJECT_ATTRIBUTES
get_object_attr (OBJECT_ATTRIBUTES
&attr
,
274 SECURITY_ATTRIBUTES
&sa
)
276 if (!get_nt_native_path ())
278 InitializeObjectAttributes (&attr
, &uni_path
,
279 objcaseinsensitive ()
280 | (sa
.bInheritHandle
? OBJ_INHERIT
: 0),
281 NULL
, sa
.lpSecurityDescriptor
);
284 inline POBJECT_ATTRIBUTES
init_reopen_attr (OBJECT_ATTRIBUTES
&attr
, HANDLE h
)
286 if (has_buggy_reopen ())
287 InitializeObjectAttributes (&attr
, get_nt_native_path (),
288 objcaseinsensitive (), NULL
, NULL
)
290 InitializeObjectAttributes (&attr
, &ro_u_empty
, objcaseinsensitive (),
294 inline size_t get_wide_win32_path_len ()
296 get_nt_native_path ();
297 return uni_path
.Length
/ sizeof (WCHAR
);
300 PWCHAR
get_wide_win32_path (PWCHAR wc
);
301 operator DWORD
&() {return fileattr
;}
302 operator int () {return fileattr
; }
303 # define cfree_and_null(x) \
306 cfree ((void *) (x)); \
311 cfree_and_null (path
);
312 cfree_and_null (posix_path
);
313 cfree_and_null (wide_path
);
315 path_conv
& eq_worker (const path_conv
& pc
, const char *in_path
)
318 memcpy ((void *) this, &pc
, sizeof pc
);
319 /* The device info might contain pointers to allocated strings, in
320 contrast to statically allocated strings. Calling device::dup()
321 will duplicate the string if the source was allocated. */
324 path
= cstrdup (in_path
);
325 conv_handle
.dup (pc
.conv_handle
);
327 posix_path
= cstrdup(pc
.posix_path
);
330 wide_path
= cwcsdup (uni_path
.Buffer
);
332 api_fatal ("cwcsdup would have returned NULL");
333 uni_path
.Buffer
= wide_path
;
338 path_conv
&operator << (const path_conv
& pc
)
340 const char *save_path
;
346 save_path
= (char *) alloca (strlen (path
) + 1);
347 strcpy ((char *) save_path
, path
);
349 return eq_worker (pc
, save_path
);
352 path_conv
&operator =(const path_conv
& pc
)
354 return eq_worker (pc
, pc
.path
);
356 dev_t
get_device () {return dev
.get_device ();}
357 DWORD
file_attributes () const {return fileattr
;}
358 void file_attributes (DWORD new_attr
) {fileattr
= new_attr
;}
359 DWORD
fs_flags () const {return fs
.flags ();}
360 DWORD
fs_name_len () const {return fs
.name_len ();}
361 bool fs_got_fs () const { return fs
.got_fs (); }
362 bool fs_is_fat () const {return fs
.is_fat ();}
363 bool fs_is_exfat () const {return fs
.is_exfat ();}
364 bool fs_is_any_fat () const {return fs
.is_fat () || fs
.is_exfat ();}
365 bool fs_is_ntfs () const {return fs
.is_ntfs ();}
366 bool fs_is_refs () const {return fs
.is_refs ();}
367 bool fs_is_samba () const {return fs
.is_samba ();}
368 bool fs_is_nfs () const {return fs
.is_nfs ();}
369 bool fs_is_netapp () const {return fs
.is_netapp ();}
370 bool fs_is_cdrom () const {return fs
.is_cdrom ();}
371 bool fs_is_mvfs () const {return fs
.is_mvfs ();}
372 bool fs_is_cifs () const {return fs
.is_cifs ();}
373 bool fs_is_nwfs () const {return fs
.is_nwfs ();}
374 bool fs_is_ncfsd () const {return fs
.is_ncfsd ();}
375 bool fs_is_afs () const {return fs
.is_afs ();}
376 bool fs_is_prlfs () const {return fs
.is_prlfs ();}
377 fs_info_type
fs_type () const {return fs
.what_fs ();}
378 ULONG
fs_serial_number () const {return fs
.serial_number ();}
379 inline const char *set_path (const char *p
)
382 cfree (modifiable_path ());
383 char *new_path
= (char *) cmalloc_abort (HEAP_STR
, strlen (p
) + 7);
384 strcpy (new_path
, p
);
385 return path
= new_path
;
389 HANDLE
handle () const { return conv_handle
.handle (); }
390 PFILE_ALL_INFORMATION
fai () { return conv_handle
.fai (); }
391 struct fattr3
*nfsattr () { return conv_handle
.nfsattr (); }
392 inline NTSTATUS
get_finfo (HANDLE h
)
394 return conv_handle
.get_finfo (h
, fs
.is_nfs ());
396 inline ino_t
get_ino () const { return conv_handle
.get_ino (fs
.is_nfs ()); }
397 void reset_conv_handle () { conv_handle
.set (NULL
); }
398 void close_conv_handle () { conv_handle
.close (); }
400 ino_t
get_ino_by_handle (HANDLE h
);
401 inline const char *get_posix () const { return posix_path
; }
402 void __reg2
set_posix (const char *);
403 DWORD
get_symlink_length () { return symlink_length
; };
407 #define SYMLINK_COOKIE "!<symlink>"
410 #define SOCKET_COOKIE "!<socket >"
412 /* Interix symlink marker */
413 #define INTERIX_SYMLINK_COOKIE "IntxLNK\1"
417 FE_NADA
= 0, /* Nothing special */
418 FE_NNF
= 1, /* Return NULL if not found */
419 FE_CWD
= 4, /* Search CWD for program */
420 FE_DLL
= 8 /* Search for DLLs, not executables. */
422 const char *__reg3
find_exec (const char *name
, path_conv
& buf
,
423 const char *search
= "PATH",
424 unsigned opt
= FE_NADA
,
425 const char **known_suffix
= NULL
);
427 /* Common macros for checking for invalid path names */
428 #define isdrive(s) (isalpha (*(s)) && (s)[1] == ':')
429 #define iswdrive(s) (iswalpha (*(s)) && (s)[1] == L':')
432 has_exec_chars (const char *buf
, int len
)
435 ((buf
[0] == '#' && buf
[1] == '!') ||
436 (buf
[0] == ':' && buf
[1] == '\n') ||
437 (buf
[0] == 'M' && buf
[1] == 'Z'));
440 int __reg3
pathmatch (const char *path1
, const char *path2
, bool caseinsensitive
);
441 int __reg3
pathnmatch (const char *path1
, const char *path2
, int len
, bool caseinsensitive
);
442 bool __reg2
has_dot_last_component (const char *dir
, bool test_dot_dot
);
444 int __reg3
path_prefix_p (const char *path1
, const char *path2
, int len1
,
445 bool caseinsensitive
);
447 int normalize_win32_path (const char *, char *, char *&);
448 int normalize_posix_path (const char *, char *, char *&);
449 PUNICODE_STRING __reg3
get_nt_native_path (const char *, UNICODE_STRING
&, bool);
451 int __reg3
symlink_worker (const char *, path_conv
&, bool);