Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / local_includes / path.h
blob4e62287f6a6e38c5c64e938ac828e808643656c2
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
7 details. */
9 #include "devices.h"
10 #include "mount.h"
11 #include "cygheap_malloc.h"
12 #include "nfs.h"
14 #include <sys/mount.h>
15 #include <sys/ioctl.h>
16 #include <fcntl.h>
17 #include <alloca.h>
19 extern inline bool
20 has_attribute (DWORD attributes, DWORD attribs_to_test)
22 return attributes != INVALID_FILE_ATTRIBUTES
23 && (attributes & attribs_to_test);
26 enum executable_states
28 is_executable,
29 dont_care_if_executable,
30 not_executable = dont_care_if_executable,
31 dont_know_if_executable
34 struct suffix_info
36 const char *name;
37 suffix_info (const char *s): name (s) {}
40 extern suffix_info stat_suffixes[];
42 /* DO NOT copy any of these files into the same set of flags as the
43 below path_types. Ever. */
44 enum pathconv_arg
46 PC_SYM_FOLLOW = _BIT ( 0), /* follow symlinks */
47 PC_SYM_NOFOLLOW = _BIT ( 1), /* don't follow symlinks (but honor
48 trailing slashes) */
49 PC_SYM_NOFOLLOW_REP = _BIT ( 2), /* don't follow dir reparse point */
50 PC_SYM_CONTENTS = _BIT ( 3), /* don't follow, return content only */
51 PC_NOFULL = _BIT ( 4), /* keep relative path */
52 PC_NULLEMPTY = _BIT ( 5), /* empty path is no error */
53 PC_NONULLEMPTY = _BIT ( 6), /* override PC_NULLEMPTY default */
54 PC_POSIX = _BIT ( 7), /* return normalized posix path */
55 PC_OPEN = _BIT ( 9), /* use open semantics */
56 PC_CTTY = _BIT (10), /* could later be used as ctty */
57 PC_SYM_NOFOLLOW_PROCFD = _BIT (11), /* allow /proc/PID/fd redirection */
58 PC_KEEP_HANDLE = _BIT (12), /* keep handle for later stat calls */
59 PC_NO_ACCESS_CHECK = _BIT (13), /* helper flag for error check */
60 PC_SYM_NOFOLLOW_DIR = _BIT (14), /* don't follow a trailing slash */
61 PC_DONT_USE = _BIT (31) /* conversion to signed happens. */
64 enum path_types
66 PATH_CTTY = _BIT ( 0), /* could later be used as ctty */
67 PATH_OPEN = _BIT ( 1), /* use open semantics */
68 PATH_LNK = _BIT ( 2), /* *.lnk-type symlink */
69 PATH_REP = _BIT ( 3), /* reparse point known to Cygwin */
70 PATH_SYMLINK = _BIT ( 4), /* symlink understood by Cygwin */
71 PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */
72 PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */
73 PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */
74 PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
77 enum fetch_fh_flags
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,
84 PUNICODE_STRING);
86 class symlink_info;
88 class path_conv_handle
90 HANDLE hdl;
91 union {
92 FILE_ALL_INFORMATION _fai;
93 /* For NFS. */
94 fattr3 _fattr3;
95 } attribs;
96 public:
97 path_conv_handle () : hdl (NULL) {}
98 inline void set (HANDLE h) { hdl = h; }
99 inline void close ()
101 if (hdl)
102 CloseHandle (hdl);
103 set (NULL);
105 inline void dup (const path_conv_handle &pch)
107 if (pch.handle ()
108 && !DuplicateHandle (GetCurrentProcess (), pch.handle (),
109 GetCurrentProcess (), &hdl,
110 0, TRUE, DUPLICATE_SAME_ACCESS))
111 hdl = NULL;
113 inline HANDLE handle () const { return hdl; }
114 inline PFILE_ALL_INFORMATION fai () const
115 { return (PFILE_ALL_INFORMATION) &attribs._fai; }
116 inline struct fattr3 *nfsattr () const
117 { return (struct fattr3 *) &attribs._fattr3; }
118 inline NTSTATUS get_finfo (HANDLE h, bool nfs)
120 return nfs ? nfs_fetch_fattr3 (h, nfsattr ()) : file_get_fai (h, fai ());
122 inline ino_t get_ino (bool nfs) const
124 return nfs ? nfsattr ()->fileid
125 : fai ()->InternalInformation.IndexNumber.QuadPart;
127 inline DWORD get_dosattr (HANDLE h, bool nfs) const
129 if (nfs)
131 IO_STATUS_BLOCK io;
132 FILE_BASIC_INFORMATION fbi;
134 NtQueryInformationFile (h, &io, &fbi, sizeof fbi, FileBasicInformation);
135 return fbi.FileAttributes;
137 return fai ()->BasicInformation.FileAttributes;
141 class path_conv
143 DWORD fileattr;
144 ULONG caseinsensitive;
145 fs_info fs;
147 PWCHAR wide_path;
148 UNICODE_STRING uni_path;
149 DWORD symlink_length;
150 const char *path;
151 uint32_t mount_flags;
152 uint32_t path_flags;
153 const char *suffix;
154 const char *posix_path;
155 path_conv_handle conv_handle;
157 void add_ext_from_sym (symlink_info&);
158 char *modifiable_path () {return (char *) path;}
160 public:
161 int error;
162 device dev;
164 void *serialize (HANDLE, unsigned int &) const;
165 HANDLE deserialize (void *);
167 const char *known_suffix () { return suffix; }
168 bool isremote () const {return fs.is_remote_drive ();}
169 ULONG objcaseinsensitive () const {return caseinsensitive;}
170 bool has_acls () const {return !(mount_flags & MOUNT_NOACL)
171 && fs.has_acls (); }
172 bool hasgood_inode () const {return !(mount_flags & MOUNT_IHASH); }
173 bool isgood_inode (ino_t ino) const;
174 bool support_sparse () const
176 return (fs_flags () & FILE_SUPPORTS_SPARSE_FILES)
177 && (fs.is_ssd () || (mount_flags & MOUNT_SPARSE));
179 int has_dos_filenames_only () const {return mount_flags & MOUNT_DOS;}
180 int has_buggy_reopen () const {return fs.has_buggy_reopen ();}
181 int has_buggy_fileid_dirinfo () const {return fs.has_buggy_fileid_dirinfo ();}
182 int has_buggy_basic_info () const {return fs.has_buggy_basic_info ();}
183 int binmode () const
185 return (mount_flags & MOUNT_TEXT) ? O_TEXT : O_BINARY;
187 int issymlink () const {return path_flags & PATH_SYMLINK;}
188 int is_lnk_symlink () const {return path_flags & PATH_LNK;}
189 /* This indicates any known reparse point */
190 int is_known_reparse_point () const {return path_flags & PATH_REP;}
191 /* This indicates any known reparse point, handled sanely by WinAPI.
192 The difference is crucial: WSL symlinks, for instance, are known
193 reparse points, so we want to open them as reparse points usually.
194 However they are foreign to WinAPI and not handled sanely. If one
195 is part of $PATH, WinAPI functions may fail under the hood with
196 STATUS_IO_REPARSE_TAG_NOT_HANDLED. */
197 int is_winapi_reparse_point () const
199 return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP;
201 int isdevice () const {return dev.not_device (FH_FS) && dev.not_device (FH_FIFO);}
202 int isfifo () const {return dev.is_device (FH_FIFO);}
203 int isspecial () const {return dev.not_device (FH_FS);}
204 int iscygdrive () const {return dev.is_device (FH_CYGDRIVE);}
205 int is_fs_special () const {return dev.is_fs_special ();}
207 int is_lnk_special () const {return (isdevice () && is_fs_special ()
208 && !issocket ())
209 || isfifo () || is_lnk_symlink ();}
210 #ifdef __WITH_AF_UNIX
211 int issocket () const {return dev.is_device (FH_LOCAL)
212 || dev.is_device (FH_UNIX);}
213 #else
214 int issocket () const {return dev.is_device (FH_LOCAL);}
215 #endif /* __WITH_AF_UNIX */
216 int iscygexec () const {return mount_flags & MOUNT_CYGWIN_EXEC;}
217 int isopen () const {return path_flags & PATH_OPEN;}
218 int isctty_capable () const {return path_flags & PATH_CTTY;}
219 int follow_fd_symlink () const {return path_flags & PATH_RESOLVE_PROCFD;}
220 void set_cygexec (bool isset)
222 if (isset)
223 mount_flags |= MOUNT_CYGWIN_EXEC;
224 else
225 mount_flags &= ~MOUNT_CYGWIN_EXEC;
227 void set_cygexec (void *target)
229 if (target)
230 mount_flags |= MOUNT_CYGWIN_EXEC;
231 else
232 mount_flags &= ~MOUNT_CYGWIN_EXEC;
234 bool isro () const {return !!(mount_flags & MOUNT_RO);}
235 bool exists () const {return fileattr != INVALID_FILE_ATTRIBUTES;}
236 bool has_attribute (DWORD x) const {return exists () && (fileattr & x);}
237 int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);}
238 executable_states exec_state ()
240 extern int _check_for_executable;
241 if (mount_flags & (MOUNT_CYGWIN_EXEC | MOUNT_EXEC))
242 return is_executable;
243 if (mount_flags & MOUNT_NOTEXEC)
244 return not_executable;
245 if (!_check_for_executable)
246 return dont_care_if_executable;
247 return dont_know_if_executable;
250 void set_symlink (DWORD n) {path_flags |= PATH_SYMLINK; symlink_length = n;}
251 void set_exec (int x = 1) {mount_flags |= x ? MOUNT_EXEC : MOUNT_NOTEXEC;}
253 void check (const UNICODE_STRING *upath, uint32_t opt = PC_SYM_FOLLOW,
254 const suffix_info *suffixes = NULL);
255 void check (const char *src, uint32_t opt = PC_SYM_FOLLOW,
256 const suffix_info *suffixes = NULL);
258 path_conv (const device& in_dev)
259 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
260 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL),
261 error (0), dev (in_dev)
263 set_path (in_dev.native ());
266 path_conv (const UNICODE_STRING *src, uint32_t opt = PC_SYM_FOLLOW,
267 const suffix_info *suffixes = NULL)
268 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
269 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
271 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
274 path_conv (const char *src, uint32_t opt = PC_SYM_FOLLOW,
275 const suffix_info *suffixes = NULL)
276 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
277 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
279 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
282 path_conv ()
283 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
284 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
287 ~path_conv ();
288 inline const char *get_win32 () const { return path; }
289 void set_nt_native_path (PUNICODE_STRING);
290 PUNICODE_STRING get_nt_native_path (PUNICODE_STRING = NULL);
291 inline POBJECT_ATTRIBUTES get_object_attr (OBJECT_ATTRIBUTES &attr,
292 SECURITY_ATTRIBUTES &sa)
294 if (!get_nt_native_path ())
295 return NULL;
296 InitializeObjectAttributes (&attr, &uni_path,
297 objcaseinsensitive ()
298 | (sa.bInheritHandle ? OBJ_INHERIT : 0),
299 NULL, sa.lpSecurityDescriptor);
300 return &attr;
302 inline POBJECT_ATTRIBUTES init_reopen_attr (OBJECT_ATTRIBUTES &attr, HANDLE h)
304 if (has_buggy_reopen ())
305 InitializeObjectAttributes (&attr, get_nt_native_path (),
306 objcaseinsensitive (), NULL, NULL)
307 else
308 InitializeObjectAttributes (&attr, &ro_u_empty, objcaseinsensitive (),
309 h, NULL);
310 return &attr;
312 inline size_t get_wide_win32_path_len ()
314 get_nt_native_path ();
315 return uni_path.Length / sizeof (WCHAR);
318 PWCHAR get_wide_win32_path (PWCHAR wc);
319 operator DWORD &() {return fileattr;}
320 operator int () {return fileattr; }
321 # define cfree_and_null(x) \
322 if (x) \
324 cfree ((void *) (x)); \
325 (x) = NULL; \
327 void free_strings ()
329 cfree_and_null (path);
330 cfree_and_null (posix_path);
331 cfree_and_null (wide_path);
333 path_conv& eq_worker (const path_conv& pc, const char *in_path)
335 free_strings ();
336 memcpy ((void *) this, &pc, sizeof pc);
337 /* The device info might contain pointers to allocated strings, in
338 contrast to statically allocated strings. Calling device::dup()
339 will duplicate the string if the source was allocated. */
340 dev.dup ();
341 if (in_path)
342 path = cstrdup (in_path);
343 conv_handle.dup (pc.conv_handle);
344 if (pc.posix_path)
345 posix_path = cstrdup(pc.posix_path);
346 if (pc.wide_path)
348 wide_path = cwcsdup (uni_path.Buffer);
349 if (!wide_path)
350 api_fatal ("cwcsdup would have returned NULL");
351 uni_path.Buffer = wide_path;
353 return *this;
356 path_conv &operator << (const path_conv& pc)
358 const char *save_path;
360 if (!path)
361 save_path = pc.path;
362 else
364 save_path = (char *) alloca (strlen (path) + 1);
365 strcpy ((char *) save_path, path);
367 return eq_worker (pc, save_path);
370 path_conv &operator =(const path_conv& pc)
372 return eq_worker (pc, pc.path);
374 dev_t get_device () {return dev.get_device ();}
375 DWORD file_attributes () const {return fileattr;}
376 void file_attributes (DWORD new_attr) {fileattr = new_attr;}
377 DWORD fs_flags () const {return fs.flags ();}
378 DWORD fs_name_len () const {return fs.name_len ();}
379 bool fs_got_fs () const { return fs.got_fs (); }
380 bool fs_is_fat () const {return fs.is_fat ();}
381 bool fs_is_exfat () const {return fs.is_exfat ();}
382 bool fs_is_any_fat () const {return fs.is_fat () || fs.is_exfat ();}
383 bool fs_is_ntfs () const {return fs.is_ntfs ();}
384 bool fs_is_refs () const {return fs.is_refs ();}
385 bool fs_is_samba () const {return fs.is_samba ();}
386 bool fs_is_nfs () const {return fs.is_nfs ();}
387 bool fs_is_netapp () const {return fs.is_netapp ();}
388 bool fs_is_cdrom () const {return fs.is_cdrom ();}
389 bool fs_is_mvfs () const {return fs.is_mvfs ();}
390 bool fs_is_cifs () const {return fs.is_cifs ();}
391 bool fs_is_nwfs () const {return fs.is_nwfs ();}
392 bool fs_is_ncfsd () const {return fs.is_ncfsd ();}
393 bool fs_is_afs () const {return fs.is_afs ();}
394 bool fs_is_prlfs () const {return fs.is_prlfs ();}
395 fs_info_type fs_type () const {return fs.what_fs ();}
396 ULONG fs_serial_number () const {return fs.serial_number ();}
397 inline const char *set_path (const char *p)
399 if (path)
400 cfree (modifiable_path ());
401 char *new_path = (char *) cmalloc_abort (HEAP_STR, strlen (p) + 7);
402 strcpy (new_path, p);
403 return path = new_path;
405 bool is_binary ();
407 HANDLE handle () const { return conv_handle.handle (); }
408 PFILE_ALL_INFORMATION fai () { return conv_handle.fai (); }
409 struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
410 inline NTSTATUS get_finfo (HANDLE h)
412 return conv_handle.get_finfo (h, fs.is_nfs ());
414 inline ino_t get_ino () const { return conv_handle.get_ino (fs.is_nfs ()); }
415 void close_conv_handle () { conv_handle.close (); }
417 ino_t get_ino_by_handle (HANDLE h);
418 inline const char *get_posix () const { return posix_path; }
419 void set_posix (const char *);
420 DWORD get_symlink_length () { return symlink_length; };
423 /* Symlink marker */
424 #define SYMLINK_COOKIE "!<symlink>"
426 /* Socket marker */
427 #define SOCKET_COOKIE "!<socket >"
429 /* Interix symlink marker */
430 #define INTERIX_SYMLINK_COOKIE "IntxLNK\1"
432 enum fe_types
434 FE_NADA = 0, /* Nothing special */
435 FE_NNF = 1, /* Return NULL if not found */
436 FE_CWD = 4, /* Search CWD for program */
437 FE_DLL = 8 /* Search for DLLs, not executables. */
439 const char *find_exec (const char *name, path_conv& buf,
440 const char *search = "PATH",
441 unsigned opt = FE_NADA,
442 const char **known_suffix = NULL);
444 /* Common macros for checking for invalid path names */
445 #define isdrive(s) (isalpha (*(s)) && (s)[1] == ':')
446 #define iswdrive(s) (iswalpha (*(s)) && (s)[1] == L':')
448 static inline bool
449 has_exec_chars (const char *buf, int len)
451 return len >= 2 &&
452 ((buf[0] == '#' && buf[1] == '!') ||
453 (buf[0] == ':' && buf[1] == '\n') ||
454 (buf[0] == 'M' && buf[1] == 'Z'));
457 int pathmatch (const char *path1, const char *path2, bool caseinsensitive);
458 int pathnmatch (const char *path1, const char *path2, int len, bool caseinsensitive);
459 bool has_dot_last_component (const char *dir, bool test_dot_dot);
461 int path_prefix_p (const char *path1, const char *path2, int len1,
462 bool caseinsensitive);
464 int normalize_win32_path (const char *, char *, char *&);
465 int normalize_posix_path (const char *, char *, char *&);
466 PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&, bool);
468 int symlink_worker (const char *, path_conv &, bool);