Cygwin: sched_setscheduler: allow changes of the priority
[newlib-cygwin.git] / winsup / cygwin / local_includes / path.h
blob3dd21d975abf4b9b8621520f1753a78dc64131fe
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 extern inline bool
27 isoffline (DWORD attributes)
29 return has_attribute (attributes, FILE_ATTRIBUTE_OFFLINE
30 | FILE_ATTRIBUTE_RECALL_ON_OPEN
31 | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS);
34 enum executable_states
36 is_executable,
37 dont_care_if_executable,
38 not_executable = dont_care_if_executable,
39 dont_know_if_executable
42 struct suffix_info
44 const char *name;
45 suffix_info (const char *s): name (s) {}
48 extern suffix_info stat_suffixes[];
50 /* DO NOT copy any of these files into the same set of flags as the
51 below path_types. Ever. */
52 enum pathconv_arg
54 PC_SYM_FOLLOW = _BIT ( 0), /* follow symlinks */
55 PC_SYM_NOFOLLOW = _BIT ( 1), /* don't follow symlinks (but honor
56 trailing slashes) */
57 PC_SYM_NOFOLLOW_REP = _BIT ( 2), /* don't follow dir reparse point */
58 PC_SYM_CONTENTS = _BIT ( 3), /* don't follow, return content only */
59 PC_NOFULL = _BIT ( 4), /* keep relative path */
60 PC_NULLEMPTY = _BIT ( 5), /* empty path is no error */
61 PC_NONULLEMPTY = _BIT ( 6), /* override PC_NULLEMPTY default */
62 PC_POSIX = _BIT ( 7), /* return normalized posix path */
63 PC_OPEN = _BIT ( 9), /* use open semantics */
64 PC_CTTY = _BIT (10), /* could later be used as ctty */
65 PC_SYM_NOFOLLOW_PROCFD = _BIT (11), /* allow /proc/PID/fd redirection */
66 PC_KEEP_HANDLE = _BIT (12), /* keep handle for later stat calls */
67 PC_NO_ACCESS_CHECK = _BIT (13), /* helper flag for error check */
68 PC_SYM_NOFOLLOW_DIR = _BIT (14), /* don't follow a trailing slash */
69 PC_DONT_USE = _BIT (31) /* conversion to signed happens. */
72 enum path_types
74 PATH_CTTY = _BIT ( 0), /* could later be used as ctty */
75 PATH_OPEN = _BIT ( 1), /* use open semantics */
76 PATH_LNK = _BIT ( 2), /* *.lnk-type symlink */
77 PATH_REP = _BIT ( 3), /* reparse point known to Cygwin */
78 PATH_SYMLINK = _BIT ( 4), /* symlink understood by Cygwin */
79 PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */
80 PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */
81 PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */
82 PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
85 enum fetch_fh_flags
87 FFH_LINKAT = (1 << 0),
90 NTSTATUS file_get_fai (HANDLE, PFILE_ALL_INFORMATION);
91 int check_reparse_point_target (HANDLE, bool, PREPARSE_DATA_BUFFER,
92 PUNICODE_STRING);
94 class symlink_info;
96 class path_conv_handle
98 HANDLE hdl;
99 union {
100 FILE_ALL_INFORMATION _fai;
101 /* For NFS. */
102 fattr3 _fattr3;
103 } attribs;
104 public:
105 path_conv_handle () : hdl (NULL) {}
106 inline void set (HANDLE h) { hdl = h; }
107 inline void close ()
109 if (hdl)
110 CloseHandle (hdl);
111 set (NULL);
113 inline void dup (const path_conv_handle &pch)
115 if (pch.handle ()
116 && !DuplicateHandle (GetCurrentProcess (), pch.handle (),
117 GetCurrentProcess (), &hdl,
118 0, TRUE, DUPLICATE_SAME_ACCESS))
119 hdl = NULL;
121 inline HANDLE handle () const { return hdl; }
122 inline PFILE_ALL_INFORMATION fai () const
123 { return (PFILE_ALL_INFORMATION) &attribs._fai; }
124 inline struct fattr3 *nfsattr () const
125 { return (struct fattr3 *) &attribs._fattr3; }
126 inline NTSTATUS get_finfo (HANDLE h, bool nfs)
128 return nfs ? nfs_fetch_fattr3 (h, nfsattr ()) : file_get_fai (h, fai ());
130 inline ino_t get_ino (bool nfs) const
132 return nfs ? nfsattr ()->fileid
133 : fai ()->InternalInformation.IndexNumber.QuadPart;
135 inline DWORD get_dosattr (HANDLE h, bool nfs) const
137 if (nfs)
139 IO_STATUS_BLOCK io;
140 FILE_BASIC_INFORMATION fbi;
142 NtQueryInformationFile (h, &io, &fbi, sizeof fbi, FileBasicInformation);
143 return fbi.FileAttributes;
145 return fai ()->BasicInformation.FileAttributes;
149 class path_conv
151 DWORD fileattr;
152 ULONG caseinsensitive;
153 fs_info fs;
155 PWCHAR wide_path;
156 UNICODE_STRING uni_path;
157 DWORD symlink_length;
158 const char *path;
159 uint32_t mount_flags;
160 uint32_t path_flags;
161 const char *suffix;
162 const char *posix_path;
163 path_conv_handle conv_handle;
164 /* virt_fileid is used by and unique within each fhandler_virtual class.
165 We need it here to avoid calling the exists() method too often, in
166 case the derived class has a costly exists() operation.
167 virt_fileid is evaluated by the fhandler_virtual::exists() call in
168 path_conv::check and propageted to the caller's path_conv. */
169 int _virt_fileid;
171 void add_ext_from_sym (symlink_info&);
172 char *modifiable_path () {return (char *) path;}
174 public:
175 int error;
176 device dev;
178 int &virt_fileid() { return _virt_fileid; }
180 void *serialize (HANDLE, unsigned int &) const;
181 HANDLE deserialize (void *);
183 const char *known_suffix () { return suffix; }
184 bool isremote () const {return fs.is_remote_drive ();}
185 ULONG objcaseinsensitive () const {return caseinsensitive;}
186 bool has_acls () const {return !(mount_flags & MOUNT_NOACL)
187 && fs.has_acls (); }
188 bool hasgood_inode () const {return !(mount_flags & MOUNT_IHASH); }
189 bool isgood_inode (ino_t ino) const;
190 bool support_sparse () const
192 return (fs_flags () & FILE_SUPPORTS_SPARSE_FILES)
193 && (fs.is_ssd () || (mount_flags & MOUNT_SPARSE));
195 int has_dos_filenames_only () const {return mount_flags & MOUNT_DOS;}
196 int has_buggy_reopen () const {return fs.has_buggy_reopen ();}
197 int has_buggy_fileid_dirinfo () const {return fs.has_buggy_fileid_dirinfo ();}
198 int has_buggy_basic_info () const {return fs.has_buggy_basic_info ();}
199 int binmode () const
201 return (mount_flags & MOUNT_TEXT) ? O_TEXT : O_BINARY;
203 int issymlink () const {return path_flags & PATH_SYMLINK;}
204 int is_lnk_symlink () const {return path_flags & PATH_LNK;}
205 /* This indicates any known reparse point */
206 int is_known_reparse_point () const {return path_flags & PATH_REP;}
207 /* This indicates any known reparse point, handled sanely by WinAPI.
208 The difference is crucial: WSL symlinks, for instance, are known
209 reparse points, so we want to open them as reparse points usually.
210 However they are foreign to WinAPI and not handled sanely. If one
211 is part of $PATH, WinAPI functions may fail under the hood with
212 STATUS_IO_REPARSE_TAG_NOT_HANDLED. */
213 int is_winapi_reparse_point () const
215 return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP;
217 int isdevice () const {return dev.not_device (FH_FS) && dev.not_device (FH_FIFO);}
218 int isfifo () const {return dev.is_device (FH_FIFO);}
219 int isspecial () const {return dev.not_device (FH_FS);}
220 int iscygdrive () const {return dev.is_device (FH_CYGDRIVE);}
221 int is_fs_special () const {return dev.is_fs_special ();}
223 int is_lnk_special () const {return (isdevice () && is_fs_special ()
224 && !issocket ())
225 || isfifo () || is_lnk_symlink ();}
226 #ifdef __WITH_AF_UNIX
227 int issocket () const {return dev.is_device (FH_LOCAL)
228 || dev.is_device (FH_UNIX);}
229 #else
230 int issocket () const {return dev.is_device (FH_LOCAL);}
231 #endif /* __WITH_AF_UNIX */
232 int iscygexec () const {return mount_flags & MOUNT_CYGWIN_EXEC;}
233 int isopen () const {return path_flags & PATH_OPEN;}
234 int isctty_capable () const {return path_flags & PATH_CTTY;}
235 int follow_fd_symlink () const {return path_flags & PATH_RESOLVE_PROCFD;}
236 void set_cygexec (bool isset)
238 if (isset)
239 mount_flags |= MOUNT_CYGWIN_EXEC;
240 else
241 mount_flags &= ~MOUNT_CYGWIN_EXEC;
243 void set_cygexec (void *target)
245 if (target)
246 mount_flags |= MOUNT_CYGWIN_EXEC;
247 else
248 mount_flags &= ~MOUNT_CYGWIN_EXEC;
250 bool isro () const {return !!(mount_flags & MOUNT_RO);}
251 bool exists () const {return fileattr != INVALID_FILE_ATTRIBUTES;}
252 bool has_attribute (DWORD x) const {return exists () && (fileattr & x);}
253 int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);}
254 bool isoffline () const
256 return has_attribute (FILE_ATTRIBUTE_OFFLINE
257 | FILE_ATTRIBUTE_RECALL_ON_OPEN
258 | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS);
260 executable_states exec_state ()
262 extern int _check_for_executable;
263 if (mount_flags & (MOUNT_CYGWIN_EXEC | MOUNT_EXEC))
264 return is_executable;
265 if (mount_flags & MOUNT_NOTEXEC)
266 return not_executable;
267 if (isoffline () || !_check_for_executable)
268 return dont_care_if_executable;
269 return dont_know_if_executable;
272 void set_symlink (DWORD n) {path_flags |= PATH_SYMLINK; symlink_length = n;}
273 void set_exec (int x = 1) {mount_flags |= x ? MOUNT_EXEC : MOUNT_NOTEXEC;}
275 void check (const UNICODE_STRING *upath, uint32_t opt = PC_SYM_FOLLOW,
276 const suffix_info *suffixes = NULL);
277 void check (const char *src, uint32_t opt = PC_SYM_FOLLOW,
278 const suffix_info *suffixes = NULL);
280 path_conv (const device& in_dev)
281 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
282 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL),
283 error (0), dev (in_dev)
285 set_path (in_dev.native ());
288 path_conv (const UNICODE_STRING *src, uint32_t opt = PC_SYM_FOLLOW,
289 const suffix_info *suffixes = NULL)
290 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
291 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
293 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
296 path_conv (const char *src, uint32_t opt = PC_SYM_FOLLOW,
297 const suffix_info *suffixes = NULL)
298 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
299 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
301 check (src, opt | ((opt & PC_NONULLEMPTY) ? 0 : PC_NULLEMPTY), suffixes);
304 path_conv ()
305 : fileattr (INVALID_FILE_ATTRIBUTES), wide_path (NULL), path (NULL),
306 mount_flags (0), path_flags (0), suffix (NULL), posix_path (NULL), error (0)
309 ~path_conv ();
310 inline const char *get_win32 () const { return path; }
311 void set_nt_native_path (PUNICODE_STRING);
312 PUNICODE_STRING get_nt_native_path (PUNICODE_STRING = NULL);
313 inline POBJECT_ATTRIBUTES get_object_attr (OBJECT_ATTRIBUTES &attr,
314 SECURITY_ATTRIBUTES &sa)
316 if (!get_nt_native_path ())
317 return NULL;
318 InitializeObjectAttributes (&attr, &uni_path,
319 objcaseinsensitive ()
320 | (sa.bInheritHandle ? OBJ_INHERIT : 0),
321 NULL, sa.lpSecurityDescriptor);
322 return &attr;
324 inline POBJECT_ATTRIBUTES init_reopen_attr (OBJECT_ATTRIBUTES &attr, HANDLE h)
326 if (has_buggy_reopen ())
327 InitializeObjectAttributes (&attr, get_nt_native_path (),
328 objcaseinsensitive (), NULL, NULL)
329 else
330 InitializeObjectAttributes (&attr, &ro_u_empty, objcaseinsensitive (),
331 h, NULL);
332 return &attr;
334 inline size_t get_wide_win32_path_len ()
336 get_nt_native_path ();
337 return uni_path.Length / sizeof (WCHAR);
340 PWCHAR get_wide_win32_path (PWCHAR wc);
341 operator DWORD &() {return fileattr;}
342 operator int () {return fileattr; }
343 # define cfree_and_null(x) \
344 if (x) \
346 cfree ((void *) (x)); \
347 (x) = NULL; \
349 void free_strings ()
351 cfree_and_null (path);
352 cfree_and_null (posix_path);
353 cfree_and_null (wide_path);
355 path_conv& eq_worker (const path_conv& pc, const char *in_path)
357 free_strings ();
358 memcpy ((void *) this, &pc, sizeof pc);
359 /* The device info might contain pointers to allocated strings, in
360 contrast to statically allocated strings. Calling device::dup()
361 will duplicate the string if the source was allocated. */
362 dev.dup ();
363 if (in_path)
364 path = cstrdup (in_path);
365 conv_handle.dup (pc.conv_handle);
366 if (pc.posix_path)
367 posix_path = cstrdup(pc.posix_path);
368 if (pc.wide_path)
370 wide_path = cwcsdup (uni_path.Buffer);
371 if (!wide_path)
372 api_fatal ("cwcsdup would have returned NULL");
373 uni_path.Buffer = wide_path;
375 return *this;
378 path_conv &operator << (const path_conv& pc)
380 const char *save_path;
382 if (!path)
383 save_path = pc.path;
384 else
386 save_path = (char *) alloca (strlen (path) + 1);
387 strcpy ((char *) save_path, path);
389 return eq_worker (pc, save_path);
392 path_conv &operator =(const path_conv& pc)
394 return eq_worker (pc, pc.path);
396 dev_t get_device () {return dev.get_device ();}
397 DWORD file_attributes () const {return fileattr;}
398 void file_attributes (DWORD new_attr) {fileattr = new_attr;}
399 DWORD fs_flags () const {return fs.flags ();}
400 DWORD fs_name_len () const {return fs.name_len ();}
401 bool fs_got_fs () const { return fs.got_fs (); }
402 bool fs_is_fat () const {return fs.is_fat ();}
403 bool fs_is_exfat () const {return fs.is_exfat ();}
404 bool fs_is_any_fat () const {return fs.is_fat () || fs.is_exfat ();}
405 bool fs_is_ntfs () const {return fs.is_ntfs ();}
406 bool fs_is_refs () const {return fs.is_refs ();}
407 bool fs_is_samba () const {return fs.is_samba ();}
408 bool fs_is_nfs () const {return fs.is_nfs ();}
409 bool fs_is_netapp () const {return fs.is_netapp ();}
410 bool fs_is_cdrom () const {return fs.is_cdrom ();}
411 bool fs_is_mvfs () const {return fs.is_mvfs ();}
412 bool fs_is_cifs () const {return fs.is_cifs ();}
413 bool fs_is_nwfs () const {return fs.is_nwfs ();}
414 bool fs_is_ncfsd () const {return fs.is_ncfsd ();}
415 bool fs_is_afs () const {return fs.is_afs ();}
416 bool fs_is_prlfs () const {return fs.is_prlfs ();}
417 fs_info_type fs_type () const {return fs.what_fs ();}
418 ULONG fs_serial_number () const {return fs.serial_number ();}
419 inline const char *set_path (const char *p)
421 if (path)
422 cfree (modifiable_path ());
423 char *new_path = (char *) cmalloc_abort (HEAP_STR, strlen (p) + 7);
424 strcpy (new_path, p);
425 return path = new_path;
427 bool is_binary ();
429 HANDLE handle () const { return conv_handle.handle (); }
430 PFILE_ALL_INFORMATION fai () { return conv_handle.fai (); }
431 struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
432 inline NTSTATUS get_finfo (HANDLE h)
434 return conv_handle.get_finfo (h, fs.is_nfs ());
436 inline ino_t get_ino () const { return conv_handle.get_ino (fs.is_nfs ()); }
437 void close_conv_handle () { conv_handle.close (); }
439 ino_t get_ino_by_handle (HANDLE h);
440 inline const char *get_posix () const { return posix_path; }
441 void set_posix (const char *);
442 DWORD get_symlink_length () { return symlink_length; };
445 /* Symlink marker */
446 #define SYMLINK_COOKIE "!<symlink>"
448 /* Socket marker */
449 #define SOCKET_COOKIE "!<socket >"
451 /* Interix symlink marker */
452 #define INTERIX_SYMLINK_COOKIE "IntxLNK\1"
454 enum fe_types
456 FE_NADA = 0, /* Nothing special */
457 FE_NNF = 1, /* Return NULL if not found */
458 FE_CWD = 4, /* Search CWD for program */
459 FE_DLL = 8 /* Search for DLLs, not executables. */
461 const char *find_exec (const char *name, path_conv& buf,
462 const char *search = "PATH",
463 unsigned opt = FE_NADA,
464 const char **known_suffix = NULL);
466 /* Common macros for checking for invalid path names */
467 #define isdrive(s) (isalpha (*(s)) && (s)[1] == ':')
468 #define iswdrive(s) (iswalpha (*(s)) && (s)[1] == L':')
470 static inline bool
471 has_exec_chars (const char *buf, int len)
473 return len >= 2 &&
474 ((buf[0] == '#' && buf[1] == '!') ||
475 (buf[0] == ':' && buf[1] == '\n') ||
476 (buf[0] == 'M' && buf[1] == 'Z'));
479 int pathmatch (const char *path1, const char *path2, bool caseinsensitive);
480 int pathnmatch (const char *path1, const char *path2, int len, bool caseinsensitive);
481 bool has_dot_last_component (const char *dir, bool test_dot_dot);
483 int path_prefix_p (const char *path1, const char *path2, int len1,
484 bool caseinsensitive);
486 int normalize_win32_path (const char *, char *, char *&);
487 int normalize_posix_path (const char *, char *, char *&);
488 PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&, bool);
490 int symlink_worker (const char *, path_conv &, bool);