Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / glib / gstdio.c
1 /* gstdio.c - wrappers for C library functions
2  *
3  * Copyright 2004 Tor Lillqvist
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "config.h"
22 #include "glibconfig.h"
23
24 /* Don’t redefine (for example) g_open() to open(), since we actually want to
25  * define g_open() in this file and export it as a symbol. See gstdio.h. */
26 #define G_STDIO_WRAP_ON_UNIX
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32 #ifdef G_OS_UNIX
33 #include <unistd.h>
34 #endif
35
36 #ifdef G_OS_WIN32
37 #include <windows.h>
38 #include <errno.h>
39 #include <wchar.h>
40 #include <direct.h>
41 #include <io.h>
42 #include <sys/utime.h>
43 #include <stdlib.h> /* for MB_CUR_MAX */
44 #else
45 #include <utime.h>
46 #include <errno.h>
47 #endif
48
49 #include "gstdio.h"
50 #include "gstdioprivate.h"
51
52 #if !defined (G_OS_UNIX) && !defined (G_OS_WIN32)
53 #error Please port this to your operating system
54 #endif
55
56 #if defined (_MSC_VER) && !defined(_WIN64)
57 #undef _wstat
58 #define _wstat _wstat32
59 #endif
60
61 #if defined (G_OS_WIN32)
62
63 /* We can't include Windows DDK and Windows SDK simultaneously,
64  * so let's copy this here from MinGW-w64 DDK.
65  * The structure is ultimately documented here:
66  * https://msdn.microsoft.com/en-us/library/ff552012(v=vs.85).aspx
67  */
68 typedef struct _REPARSE_DATA_BUFFER
69 {
70   ULONG  ReparseTag;
71   USHORT ReparseDataLength;
72   USHORT Reserved;
73   union
74   {
75     struct
76     {
77       USHORT SubstituteNameOffset;
78       USHORT SubstituteNameLength;
79       USHORT PrintNameOffset;
80       USHORT PrintNameLength;
81       ULONG  Flags;
82       WCHAR  PathBuffer[1];
83     } SymbolicLinkReparseBuffer;
84     struct
85     {
86       USHORT SubstituteNameOffset;
87       USHORT SubstituteNameLength;
88       USHORT PrintNameOffset;
89       USHORT PrintNameLength;
90       WCHAR  PathBuffer[1];
91     } MountPointReparseBuffer;
92     struct
93     {
94       UCHAR  DataBuffer[1];
95     } GenericReparseBuffer;
96   };
97 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
98
99 static int
100 w32_error_to_errno (DWORD error_code)
101 {
102   switch (error_code)
103     {
104     case ERROR_ACCESS_DENIED:
105       return EACCES;
106       break;
107     case ERROR_ALREADY_EXISTS:
108     case ERROR_FILE_EXISTS:
109       return EEXIST;
110     case ERROR_FILE_NOT_FOUND:
111       return ENOENT;
112       break;
113     case ERROR_INVALID_FUNCTION:
114       return EFAULT;
115       break;
116     case ERROR_INVALID_HANDLE:
117       return EBADF;
118       break;
119     case ERROR_INVALID_PARAMETER:
120       return EINVAL;
121       break;
122     case ERROR_LOCK_VIOLATION:
123     case ERROR_SHARING_VIOLATION:
124       return EACCES;
125       break;
126     case ERROR_NOT_ENOUGH_MEMORY:
127     case ERROR_OUTOFMEMORY:
128       return ENOMEM;
129       break;
130     case ERROR_NOT_SAME_DEVICE:
131       return EXDEV;
132       break;
133     case ERROR_PATH_NOT_FOUND:
134       return ENOENT; /* or ELOOP, or ENAMETOOLONG */
135       break;
136     default:
137       return EIO;
138       break;
139     }
140 }
141
142 #include "gstdio-private.c"
143
144 /* Windows implementation of fopen() does not accept modes such as
145  * "wb+". The 'b' needs to be appended to "w+", i.e. "w+b". Note
146  * that otherwise these 2 modes are supposed to be aliases, hence
147  * swappable at will. TODO: Is this still true?
148  */
149 static void
150 _g_win32_fix_mode (wchar_t *mode)
151 {
152   wchar_t *ptr;
153   wchar_t temp;
154
155   ptr = wcschr (mode, L'+');
156   if (ptr != NULL && (ptr - mode) > 1)
157     {
158       temp = mode[1];
159       mode[1] = *ptr;
160       *ptr = temp;
161     }
162 }
163
164 /* From
165  * https://support.microsoft.com/en-ca/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime
166  * FT = UT * 10000000 + 116444736000000000.
167  * Therefore:
168  * UT = (FT - 116444736000000000) / 10000000.
169  * Converts FILETIME to unix epoch time in form
170  * of a signed 64-bit integer (can be negative).
171  *
172  * The function that does the reverse can be found in
173  * gio/glocalfileinfo.c.
174  */
175 static gint64
176 _g_win32_filetime_to_unix_time (const FILETIME *ft,
177                                 gint32         *nsec)
178 {
179   gint64 result;
180   /* 1 unit of FILETIME is 100ns */
181   const gint64 hundreds_of_usec_per_sec = 10000000;
182   /* The difference between January 1, 1601 UTC (FILETIME epoch) and UNIX epoch
183    * in hundreds of nanoseconds.
184    */
185   const gint64 filetime_unix_epoch_offset = 116444736000000000;
186
187   result = ((gint64) ft->dwLowDateTime) | (((gint64) ft->dwHighDateTime) << 32);
188   result -= filetime_unix_epoch_offset;
189
190   if (nsec)
191     *nsec = (result % hundreds_of_usec_per_sec) * 100;
192
193   return result / hundreds_of_usec_per_sec;
194 }
195
196 #  ifdef _MSC_VER
197 #    ifndef S_IXUSR
198 #      define _S_IRUSR _S_IREAD
199 #      define _S_IWUSR _S_IWRITE
200 #      define _S_IXUSR _S_IEXEC
201 #      define S_IRUSR _S_IRUSR
202 #      define S_IWUSR _S_IWUSR
203 #      define S_IXUSR _S_IXUSR
204 #      define S_IRGRP (S_IRUSR >> 3)
205 #      define S_IWGRP (S_IWUSR >> 3)
206 #      define S_IXGRP (S_IXUSR >> 3)
207 #      define S_IROTH (S_IRGRP >> 3)
208 #      define S_IWOTH (S_IWGRP >> 3)
209 #      define S_IXOTH (S_IXGRP >> 3)
210 #    endif
211 #    ifndef S_ISDIR
212 #      define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
213 #    endif
214 #  endif
215
216 /* Uses filename and BHFI to fill a stat64 structure.
217  * Tries to reproduce the behaviour and quirks of MS C runtime stat().
218  */
219 static int
220 _g_win32_fill_statbuf_from_handle_info (const wchar_t                    *filename,
221                                         const wchar_t                    *filename_target,
222                                         const BY_HANDLE_FILE_INFORMATION *handle_info,
223                                         struct __stat64                  *statbuf)
224 {
225   wchar_t drive_letter_w = 0;
226   size_t drive_letter_size = MB_CUR_MAX;
227   char *drive_letter = _alloca (drive_letter_size);
228
229   /* If filename (target or link) is absolute,
230    * then use the drive letter from it as-is.
231    */
232   if (filename_target != NULL &&
233       filename_target[0] != L'\0' &&
234       filename_target[1] == L':')
235     drive_letter_w = filename_target[0];
236   else if (filename[0] != L'\0' &&
237            filename[1] == L':')
238     drive_letter_w = filename[0];
239
240   if (drive_letter_w > 0 &&
241       iswalpha (drive_letter_w) &&
242       iswascii (drive_letter_w) &&
243       wctomb (drive_letter, drive_letter_w) == 1)
244     statbuf->st_dev = toupper (drive_letter[0]) - 'A'; /* 0 means A: drive */
245   else
246     /* Otherwise use the PWD drive.
247      * Return value of 0 gives us 0 - 1 = -1,
248      * which is the "no idea" value for st_dev.
249      */
250     statbuf->st_dev = _getdrive () - 1;
251
252   statbuf->st_rdev = statbuf->st_dev;
253   /* Theoretically, it's possible to set it for ext-FS. No idea how.
254    * Meaningless for all filesystems that Windows normally uses.
255    */
256   statbuf->st_ino = 0;
257   statbuf->st_mode = 0;
258
259   if ((handle_info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
260     statbuf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
261   else
262     statbuf->st_mode |= S_IFREG;
263   /* No idea what S_IFCHR means here. */
264   /* S_IFIFO is not even mentioned in MSDN */
265   /* S_IFBLK is also not mentioned */
266
267   /* The aim here is to reproduce MS stat() behaviour,
268    * even if it's braindead.
269    */
270   statbuf->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
271   if ((handle_info->dwFileAttributes & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
272     statbuf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
273
274   if (!S_ISDIR (statbuf->st_mode))
275     {
276       const wchar_t *name;
277       const wchar_t *dot = NULL;
278
279       if (filename_target != NULL)
280         name = filename_target;
281       else
282         name = filename;
283
284       do
285         {
286           wchar_t *last_dot = wcschr (name, L'.');
287           if (last_dot == NULL)
288             break;
289           dot = last_dot;
290           name = &last_dot[1];
291         }
292       while (TRUE);
293
294       if ((dot != NULL &&
295           (wcsicmp (dot, L".exe") == 0 ||
296            wcsicmp (dot, L".com") == 0 ||
297            wcsicmp (dot, L".bat") == 0 ||
298            wcsicmp (dot, L".cmd") == 0)))
299         statbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
300     }
301
302   statbuf->st_nlink = handle_info->nNumberOfLinks;
303   statbuf->st_uid = statbuf->st_gid = 0;
304   statbuf->st_size = (((guint64) handle_info->nFileSizeHigh) << 32) | handle_info->nFileSizeLow;
305   statbuf->st_ctime = _g_win32_filetime_to_unix_time (&handle_info->ftCreationTime, NULL);
306   statbuf->st_mtime = _g_win32_filetime_to_unix_time (&handle_info->ftLastWriteTime, NULL);
307   statbuf->st_atime = _g_win32_filetime_to_unix_time (&handle_info->ftLastAccessTime, NULL);
308
309   return 0;
310 }
311
312 /* Fills our private stat-like structure using data from
313  * a normal stat64 struct, BHFI, FSI and a reparse tag.
314  */
315 static void
316 _g_win32_fill_privatestat (const struct __stat64            *statbuf,
317                            const BY_HANDLE_FILE_INFORMATION *handle_info,
318                            const FILE_STANDARD_INFO         *std_info,
319                            DWORD                             reparse_tag,
320                            GWin32PrivateStat                *buf)
321 {
322   gint32 nsec;
323
324   buf->st_dev = statbuf->st_dev;
325   buf->st_ino = statbuf->st_ino;
326   buf->st_mode = statbuf->st_mode;
327   buf->volume_serial = handle_info->dwVolumeSerialNumber;
328   buf->file_index = (((guint64) handle_info->nFileIndexHigh) << 32) | handle_info->nFileIndexLow;
329   buf->attributes = handle_info->dwFileAttributes;
330   buf->st_nlink = handle_info->nNumberOfLinks;
331   buf->st_size = (((guint64) handle_info->nFileSizeHigh) << 32) | handle_info->nFileSizeLow;
332   buf->allocated_size = std_info->AllocationSize.QuadPart;
333
334   buf->reparse_tag = reparse_tag;
335
336   buf->st_ctim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftCreationTime, &nsec);
337   buf->st_ctim.tv_nsec = nsec;
338   buf->st_mtim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftLastWriteTime, &nsec);
339   buf->st_mtim.tv_nsec = nsec;
340   buf->st_atim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftLastAccessTime, &nsec);
341   buf->st_atim.tv_nsec = nsec;
342 }
343
344 /* Read the link data from a symlink/mountpoint represented
345  * by the handle. Also reads reparse tag.
346  * @reparse_tag receives the tag. Can be %NULL if @buf or @alloc_buf
347  *              is non-NULL.
348  * @buf receives the link data. Can be %NULL if reparse_tag is non-%NULL.
349  *      Mutually-exclusive with @alloc_buf.
350  * @buf_size is the size of the @buf, in bytes.
351  * @alloc_buf points to a location where internally-allocated buffer
352  *            pointer will be written. That buffer receives the
353  *            link data. Mutually-exclusive with @buf.
354  * @terminate ensures that the buffer is NUL-terminated if
355  *            it isn't already. Note that this can erase useful
356  *            data if @buf is provided and @buf_size is too small.
357  *            Specifically, with @buf_size <= 2 the buffer will
358  *            receive an empty string, even if there is some
359  *            data in the reparse point.
360  * The contents of @buf or @alloc_buf are presented as-is - could
361  * be non-NUL-terminated (unless @terminate is %TRUE) or even malformed.
362  * Returns the number of bytes (!) placed into @buf or @alloc_buf,
363  * including NUL-terminator (if any).
364  *
365  * Returned value of 0 means that there's no recognizable data in the
366  * reparse point. @alloc_buf will not be allocated in that case,
367  * and @buf will be left unmodified.
368  *
369  * If @buf and @alloc_buf are %NULL, returns 0 to indicate success.
370  * Returns -1 to indicate an error, sets errno.
371  */
372 static int
373 _g_win32_readlink_handle_raw (HANDLE      h,
374                               DWORD      *reparse_tag,
375                               gunichar2  *buf,
376                               gsize       buf_size,
377                               gunichar2 **alloc_buf,
378                               gboolean    terminate)
379 {
380   DWORD error_code;
381   DWORD returned_bytes = 0;
382   BYTE *data = NULL;
383   gsize to_copy;
384   /* This is 16k. It's impossible to make DeviceIoControl() tell us
385    * the required size. NtFsControlFile() does have such a feature,
386    * but for some reason it doesn't work with CreateFile()-returned handles.
387    * The only alternative is to repeatedly call DeviceIoControl()
388    * with bigger and bigger buffers, until it succeeds.
389    * We choose to sacrifice stack space for speed.
390    */
391   BYTE max_buffer[sizeof (REPARSE_DATA_BUFFER) + MAXIMUM_REPARSE_DATA_BUFFER_SIZE] = {0,};
392   DWORD max_buffer_size = sizeof (REPARSE_DATA_BUFFER) + MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
393   REPARSE_DATA_BUFFER *rep_buf;
394
395   g_return_val_if_fail ((buf != NULL || alloc_buf != NULL || reparse_tag != NULL) &&
396                         (buf == NULL || alloc_buf == NULL),
397                         -1);
398
399   if (!DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, 0,
400                         max_buffer,
401                         max_buffer_size,
402                         &returned_bytes, NULL))
403     {
404       error_code = GetLastError ();
405       errno = w32_error_to_errno (error_code);
406       return -1;
407     }
408
409   rep_buf = (REPARSE_DATA_BUFFER *) max_buffer;
410
411   if (reparse_tag != NULL)
412     *reparse_tag = rep_buf->ReparseTag;
413
414   if (buf == NULL && alloc_buf == NULL)
415     return 0;
416
417   if (rep_buf->ReparseTag == IO_REPARSE_TAG_SYMLINK)
418     {
419       data = &((BYTE *) rep_buf->SymbolicLinkReparseBuffer.PathBuffer)[rep_buf->SymbolicLinkReparseBuffer.SubstituteNameOffset];
420
421       to_copy = rep_buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
422     }
423   else if (rep_buf->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
424     {
425       data = &((BYTE *) rep_buf->MountPointReparseBuffer.PathBuffer)[rep_buf->MountPointReparseBuffer.SubstituteNameOffset];
426
427       to_copy = rep_buf->MountPointReparseBuffer.SubstituteNameLength;
428     }
429   else
430     to_copy = 0;
431
432   return _g_win32_copy_and_maybe_terminate (data, to_copy, buf, buf_size, alloc_buf, terminate);
433 }
434
435 /* Read the link data from a symlink/mountpoint represented
436  * by the @filename.
437  * @filename is the name of the file.
438  * @reparse_tag receives the tag. Can be %NULL if @buf or @alloc_buf
439  *              is non-%NULL.
440  * @buf receives the link data. Mutually-exclusive with @alloc_buf.
441  * @buf_size is the size of the @buf, in bytes.
442  * @alloc_buf points to a location where internally-allocated buffer
443  *            pointer will be written. That buffer receives the
444  *            link data. Mutually-exclusive with @buf.
445  * @terminate ensures that the buffer is NUL-terminated if
446  *            it isn't already
447  * The contents of @buf or @alloc_buf are presented as-is - could
448  * be non-NUL-terminated (unless @terminate is TRUE) or even malformed.
449  * Returns the number of bytes (!) placed into @buf or @alloc_buf.
450  * Returned value of 0 means that there's no recognizable data in the
451  * reparse point. @alloc_buf will not be allocated in that case,
452  * and @buf will be left unmodified.
453  * If @buf and @alloc_buf are %NULL, returns 0 to indicate success.
454  * Returns -1 to indicate an error, sets errno.
455  */
456 static int
457 _g_win32_readlink_utf16_raw (const gunichar2  *filename,
458                              DWORD            *reparse_tag,
459                              gunichar2        *buf,
460                              gsize             buf_size,
461                              gunichar2       **alloc_buf,
462                              gboolean          terminate)
463 {
464   HANDLE h;
465   DWORD attributes;
466   DWORD to_copy;
467   DWORD error_code;
468
469   if ((attributes = GetFileAttributesW (filename)) == 0)
470     {
471       error_code = GetLastError ();
472       errno = w32_error_to_errno (error_code);
473       return -1;
474     }
475
476   if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
477     {
478       errno = EINVAL;
479       return -1;
480     }
481
482   /* To read symlink target we need to open the file as a reparse
483    * point and use DeviceIoControl() on it.
484    */
485   h = CreateFileW (filename,
486                    FILE_READ_EA,
487                    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
488                    NULL, OPEN_EXISTING,
489                    FILE_ATTRIBUTE_NORMAL
490                    | FILE_FLAG_OPEN_REPARSE_POINT
491                    | (attributes & FILE_ATTRIBUTE_DIRECTORY ? FILE_FLAG_BACKUP_SEMANTICS : 0),
492                    NULL);
493
494   if (h == INVALID_HANDLE_VALUE)
495     {
496       error_code = GetLastError ();
497       errno = w32_error_to_errno (error_code);
498       return -1;
499     }
500
501   to_copy = _g_win32_readlink_handle_raw (h, reparse_tag, buf, buf_size, alloc_buf, terminate);
502
503   CloseHandle (h);
504
505   return to_copy;
506 }
507
508 /* Read the link data from a symlink/mountpoint represented
509  * by a UTF-16 filename or a file handle.
510  * @filename is the name of the file. Mutually-exclusive with @file_handle.
511  * @file_handle is the handle of the file. Mutually-exclusive with @filename.
512  * @reparse_tag receives the tag. Can be %NULL if @buf or @alloc_buf
513  *              is non-%NULL.
514  * @buf receives the link data. Mutually-exclusive with @alloc_buf.
515  * @buf_size is the size of the @buf, in bytes.
516  * @alloc_buf points to a location where internally-allocated buffer
517  *            pointer will be written. That buffer receives the
518  *            link data. Mutually-exclusive with @buf.
519  * @terminate ensures that the buffer is NUL-terminated if
520  *            it isn't already
521  * The contents of @buf or @alloc_buf are adjusted
522  * (extended or nt object manager prefix is stripped),
523  * but otherwise they are presented as-is - could be non-NUL-terminated
524  * (unless @terminate is TRUE) or even malformed.
525  * Returns the number of bytes (!) placed into @buf or @alloc_buf.
526  * Returned value of 0 means that there's no recognizable data in the
527  * reparse point. @alloc_buf will not be allocated in that case,
528  * and @buf will be left unmodified.
529  * Returns -1 to indicate an error, sets errno.
530  */
531 static int
532 _g_win32_readlink_utf16_handle (const gunichar2  *filename,
533                                 HANDLE            file_handle,
534                                 DWORD            *reparse_tag,
535                                 gunichar2        *buf,
536                                 gsize             buf_size,
537                                 gunichar2       **alloc_buf,
538                                 gboolean          terminate)
539 {
540   int   result;
541   gsize string_size;
542
543   g_return_val_if_fail ((buf != NULL || alloc_buf != NULL || reparse_tag != NULL) &&
544                         (filename != NULL || file_handle != NULL) &&
545                         (buf == NULL || alloc_buf == NULL) &&
546                         (filename == NULL || file_handle == NULL),
547                         -1);
548
549   if (filename)
550     result = _g_win32_readlink_utf16_raw (filename, reparse_tag, buf, buf_size, alloc_buf, terminate);
551   else
552     result = _g_win32_readlink_handle_raw (file_handle, reparse_tag, buf, buf_size, alloc_buf, terminate);
553
554   if (result <= 0)
555     return result;
556
557   /* Ensure that output is a multiple of sizeof (gunichar2),
558    * cutting any trailing partial gunichar2, if present.
559    */
560   result -= result % sizeof (gunichar2);
561
562   if (result <= 0)
563     return result;
564
565   /* DeviceIoControl () tends to return filenames as NT Object Manager
566    * names , i.e. "\\??\\C:\\foo\\bar".
567    * Remove the leading 4-byte "\\??\\" prefix, as glib (as well as many W32 API
568    * functions) is unprepared to deal with it. Unless it has no 'x:' drive
569    * letter part after the prefix, in which case we leave everything
570    * as-is, because the path could be "\\??\\Volume{GUID}" - stripping
571    * the prefix will allow it to be confused with relative links
572    * targeting "Volume{GUID}".
573    */
574   string_size = result / sizeof (gunichar2);
575   _g_win32_strip_extended_ntobjm_prefix (buf ? buf : *alloc_buf, &string_size);
576
577   return string_size * sizeof (gunichar2);
578 }
579
580 /* Works like stat() or lstat(), depending on the value of @for_symlink,
581  * but accepts filename in UTF-16 and fills our custom stat structure.
582  * The @filename must not have trailing slashes.
583  */
584 static int
585 _g_win32_stat_utf16_no_trailing_slashes (const gunichar2    *filename,
586                                          GWin32PrivateStat  *buf,
587                                          gboolean            for_symlink)
588 {
589   struct __stat64 statbuf;
590   BY_HANDLE_FILE_INFORMATION handle_info;
591   FILE_STANDARD_INFO std_info;
592   gboolean is_symlink = FALSE;
593   wchar_t *filename_target = NULL;
594   DWORD immediate_attributes;
595   DWORD open_flags;
596   gboolean is_directory;
597   DWORD reparse_tag = 0;
598   DWORD error_code;
599   BOOL succeeded_so_far;
600   HANDLE file_handle;
601
602   immediate_attributes = GetFileAttributesW (filename);
603
604   if (immediate_attributes == INVALID_FILE_ATTRIBUTES)
605     {
606       error_code = GetLastError ();
607       errno = w32_error_to_errno (error_code);
608
609       return -1;
610     }
611
612   is_symlink = (immediate_attributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT;
613   is_directory = (immediate_attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
614
615   open_flags = FILE_ATTRIBUTE_NORMAL;
616
617   if (for_symlink && is_symlink)
618     open_flags |= FILE_FLAG_OPEN_REPARSE_POINT;
619
620   if (is_directory)
621     open_flags |= FILE_FLAG_BACKUP_SEMANTICS;
622
623   file_handle = CreateFileW (filename, FILE_READ_ATTRIBUTES | FILE_READ_EA,
624                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
625                              NULL, OPEN_EXISTING,
626                              open_flags,
627                              NULL);
628
629   if (file_handle == INVALID_HANDLE_VALUE)
630     {
631       error_code = GetLastError ();
632       errno = w32_error_to_errno (error_code);
633       return -1;
634     }
635
636   succeeded_so_far = GetFileInformationByHandle (file_handle,
637                                                  &handle_info);
638   error_code = GetLastError ();
639
640   if (succeeded_so_far)
641     {
642       succeeded_so_far = GetFileInformationByHandleEx (file_handle,
643                                                        FileStandardInfo,
644                                                        &std_info,
645                                                        sizeof (std_info));
646       error_code = GetLastError ();
647     }
648
649   if (!succeeded_so_far)
650     {
651       CloseHandle (file_handle);
652       errno = w32_error_to_errno (error_code);
653       return -1;
654     }
655
656   /* It's tempting to use GetFileInformationByHandleEx(FileAttributeTagInfo),
657    * but it always reports that the ReparseTag is 0.
658    * We already have a handle open for symlink, use that.
659    * For the target we have to specify a filename, and the function
660    * will open another handle internally.
661    */
662   if (is_symlink &&
663       _g_win32_readlink_utf16_handle (for_symlink ? NULL : filename,
664                                       for_symlink ? file_handle : NULL,
665                                       &reparse_tag,
666                                       NULL, 0,
667                                       for_symlink ? NULL : &filename_target,
668                                       TRUE) < 0)
669     {
670       CloseHandle (file_handle);
671       return -1;
672     }
673
674   CloseHandle (file_handle);
675
676   _g_win32_fill_statbuf_from_handle_info (filename,
677                                           filename_target,
678                                           &handle_info,
679                                           &statbuf);
680   g_free (filename_target);
681   _g_win32_fill_privatestat (&statbuf,
682                              &handle_info,
683                              &std_info,
684                              reparse_tag,
685                              buf);
686
687   return 0;
688 }
689
690 /* Works like fstat(), but fills our custom stat structure. */
691 static int
692 _g_win32_stat_fd (int                 fd,
693                   GWin32PrivateStat  *buf)
694 {
695   HANDLE file_handle;
696   gboolean succeeded_so_far;
697   DWORD error_code;
698   struct __stat64 statbuf;
699   BY_HANDLE_FILE_INFORMATION handle_info;
700   FILE_STANDARD_INFO std_info;
701   DWORD reparse_tag = 0;
702   gboolean is_symlink = FALSE;
703
704   file_handle = (HANDLE) _get_osfhandle (fd);
705
706   if (file_handle == INVALID_HANDLE_VALUE)
707     return -1;
708
709   succeeded_so_far = GetFileInformationByHandle (file_handle,
710                                                  &handle_info);
711   error_code = GetLastError ();
712
713   if (succeeded_so_far)
714     {
715       succeeded_so_far = GetFileInformationByHandleEx (file_handle,
716                                                        FileStandardInfo,
717                                                        &std_info,
718                                                        sizeof (std_info));
719       error_code = GetLastError ();
720     }
721
722   if (!succeeded_so_far)
723     {
724       errno = w32_error_to_errno (error_code);
725       return -1;
726     }
727
728   is_symlink = (handle_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT;
729
730   if (is_symlink &&
731       _g_win32_readlink_handle_raw (file_handle, &reparse_tag, NULL, 0, NULL, FALSE) < 0)
732     return -1;
733
734   if (_fstat64 (fd, &statbuf) != 0)
735     return -1;
736
737   _g_win32_fill_privatestat (&statbuf,
738                              &handle_info,
739                              &std_info,
740                              reparse_tag,
741                              buf);
742
743   return 0;
744 }
745
746 /* Works like stat() or lstat(), depending on the value of @for_symlink,
747  * but accepts filename in UTF-8 and fills our custom stat structure.
748  */
749 static int
750 _g_win32_stat_utf8 (const gchar       *filename,
751                     GWin32PrivateStat *buf,
752                     gboolean           for_symlink)
753 {
754   wchar_t *wfilename;
755   int result;
756   gsize len;
757
758   if (filename == NULL)
759     {
760       errno = EINVAL;
761       return -1;
762     }
763
764   len = strlen (filename);
765
766   while (len > 0 && G_IS_DIR_SEPARATOR (filename[len - 1]))
767     len--;
768
769   if (len <= 0 ||
770       (g_path_is_absolute (filename) && len <= (gsize) (g_path_skip_root (filename) - filename)))
771     len = strlen (filename);
772
773   wfilename = g_utf8_to_utf16 (filename, len, NULL, NULL, NULL);
774
775   if (wfilename == NULL)
776     {
777       errno = EINVAL;
778       return -1;
779     }
780
781   result = _g_win32_stat_utf16_no_trailing_slashes (wfilename, buf, for_symlink);
782
783   g_free (wfilename);
784
785   return result;
786 }
787
788 /* Works like stat(), but accepts filename in UTF-8
789  * and fills our custom stat structure.
790  */
791 int
792 g_win32_stat_utf8 (const gchar       *filename,
793                    GWin32PrivateStat *buf)
794 {
795   return _g_win32_stat_utf8 (filename, buf, FALSE);
796 }
797
798 /* Works like lstat(), but accepts filename in UTF-8
799  * and fills our custom stat structure.
800  */
801 int
802 g_win32_lstat_utf8 (const gchar       *filename,
803                     GWin32PrivateStat *buf)
804 {
805   return _g_win32_stat_utf8 (filename, buf, TRUE);
806 }
807
808 /* Works like fstat(), but accepts filename in UTF-8
809  * and fills our custom stat structure.
810  */
811 int
812 g_win32_fstat (int                fd,
813                GWin32PrivateStat *buf)
814 {
815   return _g_win32_stat_fd (fd, buf);
816 }
817
818 /**
819  * g_win32_readlink_utf8:
820  * @filename: (type filename): a pathname in UTF-8
821  * @buf: (array length=buf_size) : a buffer to receive the reparse point
822  *                                 target path. Mutually-exclusive
823  *                                 with @alloc_buf.
824  * @buf_size: size of the @buf, in bytes
825  * @alloc_buf: points to a location where internally-allocated buffer
826  *             pointer will be written. That buffer receives the
827  *             link data. Mutually-exclusive with @buf.
828  * @terminate: ensures that the buffer is NUL-terminated if
829  *             it isn't already. If %FALSE, the returned string
830  *             might not be NUL-terminated (depends entirely on
831  *             what the contents of the filesystem are).
832  *
833  * Tries to read the reparse point indicated by @filename, filling
834  * @buf or @alloc_buf with the path that the reparse point redirects to.
835  * The path will be UTF-8-encoded, and an extended path prefix
836  * or a NT object manager prefix will be removed from it, if
837  * possible, but otherwise the path is returned as-is. Specifically,
838  * it could be a "\\\\Volume{GUID}\\" path. It also might use
839  * backslashes as path separators.
840  *
841  * Returns: -1 on error (sets errno), 0 if there's no (recognizable)
842  * path in the reparse point (@alloc_buf will not be allocated in that case,
843  * and @buf will be left unmodified),
844  * or the number of bytes placed into @buf otherwise,
845  * including NUL-terminator (if present or if @terminate is TRUE).
846  * The buffer returned via @alloc_buf should be freed with g_free().
847  *
848  * Since: 2.60
849  */
850 int
851 g_win32_readlink_utf8 (const gchar  *filename,
852                        gchar        *buf,
853                        gsize         buf_size,
854                        gchar       **alloc_buf,
855                        gboolean      terminate)
856 {
857   wchar_t *wfilename;
858   int result;
859   wchar_t *buf_utf16;
860   glong tmp_len;
861   gchar *tmp;
862
863   g_return_val_if_fail ((buf != NULL || alloc_buf != NULL) &&
864                         (buf == NULL || alloc_buf == NULL),
865                         -1);
866
867   wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
868
869   if (wfilename == NULL)
870     {
871       errno = EINVAL;
872       return -1;
873     }
874
875   result = _g_win32_readlink_utf16_handle (wfilename, NULL, NULL,
876                                            NULL, 0, &buf_utf16, terminate);
877
878   g_free (wfilename);
879
880   if (result <= 0)
881     return result;
882
883   tmp = g_utf16_to_utf8 (buf_utf16,
884                          result / sizeof (gunichar2),
885                          NULL,
886                          &tmp_len,
887                          NULL);
888
889   g_free (buf_utf16);
890
891   if (tmp == NULL)
892     {
893       errno = EINVAL;
894       return -1;
895     }
896
897   if (alloc_buf)
898     {
899       *alloc_buf = tmp;
900       return tmp_len;
901     }
902
903   if ((gsize) tmp_len > buf_size)
904     tmp_len = buf_size;
905
906   memcpy (buf, tmp, tmp_len);
907   g_free (tmp);
908
909   return tmp_len;
910 }
911
912 #endif
913
914 /**
915  * g_access:
916  * @filename: (type filename): a pathname in the GLib file name encoding
917  *     (UTF-8 on Windows)
918  * @mode: as in access()
919  *
920  * A wrapper for the POSIX access() function. This function is used to
921  * test a pathname for one or several of read, write or execute
922  * permissions, or just existence.
923  *
924  * On Windows, the file protection mechanism is not at all POSIX-like,
925  * and the underlying function in the C library only checks the
926  * FAT-style READONLY attribute, and does not look at the ACL of a
927  * file at all. This function is this in practise almost useless on
928  * Windows. Software that needs to handle file permissions on Windows
929  * more exactly should use the Win32 API.
930  *
931  * See your C library manual for more details about access().
932  *
933  * Returns: zero if the pathname refers to an existing file system
934  *     object that has all the tested permissions, or -1 otherwise
935  *     or on error.
936  * 
937  * Since: 2.8
938  */
939 int
940 g_access (const gchar *filename,
941           int          mode)
942 {
943 #ifdef G_OS_WIN32
944   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
945   int retval;
946   int save_errno;
947     
948   if (wfilename == NULL)
949     {
950       errno = EINVAL;
951       return -1;
952     }
953
954 #ifndef X_OK
955 #define X_OK 1
956 #endif
957
958   retval = _waccess (wfilename, mode & ~X_OK);
959   save_errno = errno;
960
961   g_free (wfilename);
962
963   errno = save_errno;
964   return retval;
965 #else
966   return access (filename, mode);
967 #endif
968 }
969
970 /**
971  * g_chmod:
972  * @filename: (type filename): a pathname in the GLib file name encoding
973  *     (UTF-8 on Windows)
974  * @mode: as in chmod()
975  *
976  * A wrapper for the POSIX chmod() function. The chmod() function is
977  * used to set the permissions of a file system object.
978  * 
979  * On Windows the file protection mechanism is not at all POSIX-like,
980  * and the underlying chmod() function in the C library just sets or
981  * clears the FAT-style READONLY attribute. It does not touch any
982  * ACL. Software that needs to manage file permissions on Windows
983  * exactly should use the Win32 API.
984  *
985  * See your C library manual for more details about chmod().
986  *
987  * Returns: 0 if the operation succeeded, -1 on error
988  * 
989  * Since: 2.8
990  */
991 int
992 g_chmod (const gchar *filename,
993          int          mode)
994 {
995 #ifdef G_OS_WIN32
996   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
997   int retval;
998   int save_errno;
999     
1000   if (wfilename == NULL)
1001     {
1002       errno = EINVAL;
1003       return -1;
1004     }
1005
1006   retval = _wchmod (wfilename, mode);
1007   save_errno = errno;
1008
1009   g_free (wfilename);
1010
1011   errno = save_errno;
1012   return retval;
1013 #else
1014   return chmod (filename, mode);
1015 #endif
1016 }
1017 /**
1018  * g_open:
1019  * @filename: (type filename): a pathname in the GLib file name encoding
1020  *     (UTF-8 on Windows)
1021  * @flags: as in open()
1022  * @mode: as in open()
1023  *
1024  * A wrapper for the POSIX open() function. The open() function is
1025  * used to convert a pathname into a file descriptor.
1026  *
1027  * On POSIX systems file descriptors are implemented by the operating
1028  * system. On Windows, it's the C library that implements open() and
1029  * file descriptors. The actual Win32 API for opening files is quite
1030  * different, see MSDN documentation for CreateFile(). The Win32 API
1031  * uses file handles, which are more randomish integers, not small
1032  * integers like file descriptors.
1033  *
1034  * Because file descriptors are specific to the C library on Windows,
1035  * the file descriptor returned by this function makes sense only to
1036  * functions in the same C library. Thus if the GLib-using code uses a
1037  * different C library than GLib does, the file descriptor returned by
1038  * this function cannot be passed to C library functions like write()
1039  * or read().
1040  *
1041  * See your C library manual for more details about open().
1042  *
1043  * Returns: a new file descriptor, or -1 if an error occurred.
1044  *     The return value can be used exactly like the return value
1045  *     from open().
1046  * 
1047  * Since: 2.6
1048  */
1049 int
1050 g_open (const gchar *filename,
1051         int          flags,
1052         int          mode)
1053 {
1054 #ifdef G_OS_WIN32
1055   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1056   int retval;
1057   int save_errno;
1058     
1059   if (wfilename == NULL)
1060     {
1061       errno = EINVAL;
1062       return -1;
1063     }
1064
1065   retval = _wopen (wfilename, flags, mode);
1066   save_errno = errno;
1067
1068   g_free (wfilename);
1069
1070   errno = save_errno;
1071   return retval;
1072 #else
1073   int fd;
1074   do
1075     fd = open (filename, flags, mode);
1076   while (G_UNLIKELY (fd == -1 && errno == EINTR));
1077   return fd;
1078 #endif
1079 }
1080
1081 /**
1082  * g_creat:
1083  * @filename: (type filename): a pathname in the GLib file name encoding
1084  *     (UTF-8 on Windows)
1085  * @mode: as in creat()
1086  *
1087  * A wrapper for the POSIX creat() function. The creat() function is
1088  * used to convert a pathname into a file descriptor, creating a file
1089  * if necessary.
1090  *
1091  * On POSIX systems file descriptors are implemented by the operating
1092  * system. On Windows, it's the C library that implements creat() and
1093  * file descriptors. The actual Windows API for opening files is
1094  * different, see MSDN documentation for CreateFile(). The Win32 API
1095  * uses file handles, which are more randomish integers, not small
1096  * integers like file descriptors.
1097  *
1098  * Because file descriptors are specific to the C library on Windows,
1099  * the file descriptor returned by this function makes sense only to
1100  * functions in the same C library. Thus if the GLib-using code uses a
1101  * different C library than GLib does, the file descriptor returned by
1102  * this function cannot be passed to C library functions like write()
1103  * or read().
1104  *
1105  * See your C library manual for more details about creat().
1106  *
1107  * Returns: a new file descriptor, or -1 if an error occurred.
1108  *     The return value can be used exactly like the return value
1109  *     from creat().
1110  * 
1111  * Since: 2.8
1112  */
1113 int
1114 g_creat (const gchar *filename,
1115          int          mode)
1116 {
1117 #ifdef G_OS_WIN32
1118   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1119   int retval;
1120   int save_errno;
1121     
1122   if (wfilename == NULL)
1123     {
1124       errno = EINVAL;
1125       return -1;
1126     }
1127
1128   retval = _wcreat (wfilename, mode);
1129   save_errno = errno;
1130
1131   g_free (wfilename);
1132
1133   errno = save_errno;
1134   return retval;
1135 #else
1136   return creat (filename, mode);
1137 #endif
1138 }
1139
1140 /**
1141  * g_rename:
1142  * @oldfilename: (type filename): a pathname in the GLib file name encoding
1143  *     (UTF-8 on Windows)
1144  * @newfilename: (type filename): a pathname in the GLib file name encoding
1145  *
1146  * A wrapper for the POSIX rename() function. The rename() function 
1147  * renames a file, moving it between directories if required.
1148  * 
1149  * See your C library manual for more details about how rename() works
1150  * on your system. It is not possible in general on Windows to rename
1151  * a file that is open to some process.
1152  *
1153  * Returns: 0 if the renaming succeeded, -1 if an error occurred
1154  * 
1155  * Since: 2.6
1156  */
1157 int
1158 g_rename (const gchar *oldfilename,
1159           const gchar *newfilename)
1160 {
1161 #ifdef G_OS_WIN32
1162   wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
1163   wchar_t *wnewfilename;
1164   int retval;
1165   int save_errno = 0;
1166
1167   if (woldfilename == NULL)
1168     {
1169       errno = EINVAL;
1170       return -1;
1171     }
1172
1173   wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
1174
1175   if (wnewfilename == NULL)
1176     {
1177       g_free (woldfilename);
1178       errno = EINVAL;
1179       return -1;
1180     }
1181
1182   if (MoveFileExW (woldfilename, wnewfilename, MOVEFILE_REPLACE_EXISTING))
1183     retval = 0;
1184   else
1185     {
1186       retval = -1;
1187       save_errno = w32_error_to_errno (GetLastError ());
1188     }
1189
1190   g_free (woldfilename);
1191   g_free (wnewfilename);
1192     
1193   errno = save_errno;
1194   return retval;
1195 #else
1196   return rename (oldfilename, newfilename);
1197 #endif
1198 }
1199
1200 /**
1201  * g_mkdir: 
1202  * @filename: (type filename): a pathname in the GLib file name encoding
1203  *     (UTF-8 on Windows)
1204  * @mode: permissions to use for the newly created directory
1205  *
1206  * A wrapper for the POSIX mkdir() function. The mkdir() function 
1207  * attempts to create a directory with the given name and permissions.
1208  * The mode argument is ignored on Windows.
1209  * 
1210  * See your C library manual for more details about mkdir().
1211  *
1212  * Returns: 0 if the directory was successfully created, -1 if an error 
1213  *    occurred
1214  * 
1215  * Since: 2.6
1216  */
1217 int
1218 g_mkdir (const gchar *filename,
1219          int          mode)
1220 {
1221 #ifdef G_OS_WIN32
1222   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1223   int retval;
1224   int save_errno;
1225
1226   if (wfilename == NULL)
1227     {
1228       errno = EINVAL;
1229       return -1;
1230     }
1231
1232   retval = _wmkdir (wfilename);
1233   save_errno = errno;
1234
1235   g_free (wfilename);
1236     
1237   errno = save_errno;
1238   return retval;
1239 #else
1240   return mkdir (filename, mode);
1241 #endif
1242 }
1243
1244 /**
1245  * g_chdir: 
1246  * @path: (type filename): a pathname in the GLib file name encoding
1247  *     (UTF-8 on Windows)
1248  *
1249  * A wrapper for the POSIX chdir() function. The function changes the
1250  * current directory of the process to @path.
1251  * 
1252  * See your C library manual for more details about chdir().
1253  *
1254  * Returns: 0 on success, -1 if an error occurred.
1255  * 
1256  * Since: 2.8
1257  */
1258 int
1259 g_chdir (const gchar *path)
1260 {
1261 #ifdef G_OS_WIN32
1262   wchar_t *wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
1263   int retval;
1264   int save_errno;
1265
1266   if (wpath == NULL)
1267     {
1268       errno = EINVAL;
1269       return -1;
1270     }
1271
1272   retval = _wchdir (wpath);
1273   save_errno = errno;
1274
1275   g_free (wpath);
1276     
1277   errno = save_errno;
1278   return retval;
1279 #else
1280   return chdir (path);
1281 #endif
1282 }
1283
1284 /**
1285  * GStatBuf:
1286  *
1287  * A type corresponding to the appropriate struct type for the stat()
1288  * system call, depending on the platform and/or compiler being used.
1289  *
1290  * See g_stat() for more information.
1291  */
1292 /**
1293  * g_stat: 
1294  * @filename: (type filename): a pathname in the GLib file name encoding
1295  *     (UTF-8 on Windows)
1296  * @buf: a pointer to a stat struct, which will be filled with the file
1297  *     information
1298  *
1299  * A wrapper for the POSIX stat() function. The stat() function
1300  * returns information about a file. On Windows the stat() function in
1301  * the C library checks only the FAT-style READONLY attribute and does
1302  * not look at the ACL at all. Thus on Windows the protection bits in
1303  * the @st_mode field are a fabrication of little use.
1304  * 
1305  * On Windows the Microsoft C libraries have several variants of the
1306  * stat struct and stat() function with names like _stat(), _stat32(),
1307  * _stat32i64() and _stat64i32(). The one used here is for 32-bit code
1308  * the one with 32-bit size and time fields, specifically called _stat32().
1309  *
1310  * In Microsoft's compiler, by default struct stat means one with
1311  * 64-bit time fields while in MinGW struct stat is the legacy one
1312  * with 32-bit fields. To hopefully clear up this messs, the gstdio.h
1313  * header defines a type #GStatBuf which is the appropriate struct type
1314  * depending on the platform and/or compiler being used. On POSIX it
1315  * is just struct stat, but note that even on POSIX platforms, stat()
1316  * might be a macro.
1317  *
1318  * See your C library manual for more details about stat().
1319  *
1320  * Returns: 0 if the information was successfully retrieved,
1321  *     -1 if an error occurred
1322  * 
1323  * Since: 2.6
1324  */
1325 int
1326 g_stat (const gchar *filename,
1327         GStatBuf    *buf)
1328 {
1329 #ifdef G_OS_WIN32
1330   GWin32PrivateStat w32_buf;
1331   int retval = g_win32_stat_utf8 (filename, &w32_buf);
1332
1333   buf->st_dev = w32_buf.st_dev;
1334   buf->st_ino = w32_buf.st_ino;
1335   buf->st_mode = w32_buf.st_mode;
1336   buf->st_nlink = w32_buf.st_nlink;
1337   buf->st_uid = w32_buf.st_uid;
1338   buf->st_gid = w32_buf.st_gid;
1339   buf->st_rdev = w32_buf.st_dev;
1340   buf->st_size = w32_buf.st_size;
1341   buf->st_atime = w32_buf.st_atim.tv_sec;
1342   buf->st_mtime = w32_buf.st_mtim.tv_sec;
1343   buf->st_ctime = w32_buf.st_ctim.tv_sec;
1344
1345   return retval;
1346 #else
1347   return stat (filename, buf);
1348 #endif
1349 }
1350
1351 /**
1352  * g_lstat: 
1353  * @filename: (type filename): a pathname in the GLib file name encoding
1354  *     (UTF-8 on Windows)
1355  * @buf: a pointer to a stat struct, which will be filled with the file
1356  *     information
1357  *
1358  * A wrapper for the POSIX lstat() function. The lstat() function is
1359  * like stat() except that in the case of symbolic links, it returns
1360  * information about the symbolic link itself and not the file that it
1361  * refers to. If the system does not support symbolic links g_lstat()
1362  * is identical to g_stat().
1363  * 
1364  * See your C library manual for more details about lstat().
1365  *
1366  * Returns: 0 if the information was successfully retrieved,
1367  *     -1 if an error occurred
1368  * 
1369  * Since: 2.6
1370  */
1371 int
1372 g_lstat (const gchar *filename,
1373          GStatBuf    *buf)
1374 {
1375 #ifdef HAVE_LSTAT
1376   /* This can't be Win32, so don't do the widechar dance. */
1377   return lstat (filename, buf);
1378 #elif defined (G_OS_WIN32)
1379   GWin32PrivateStat w32_buf;
1380   int retval = g_win32_lstat_utf8 (filename, &w32_buf);
1381
1382   buf->st_dev = w32_buf.st_dev;
1383   buf->st_ino = w32_buf.st_ino;
1384   buf->st_mode = w32_buf.st_mode;
1385   buf->st_nlink = w32_buf.st_nlink;
1386   buf->st_uid = w32_buf.st_uid;
1387   buf->st_gid = w32_buf.st_gid;
1388   buf->st_rdev = w32_buf.st_dev;
1389   buf->st_size = w32_buf.st_size;
1390   buf->st_atime = w32_buf.st_atim.tv_sec;
1391   buf->st_mtime = w32_buf.st_mtim.tv_sec;
1392   buf->st_ctime = w32_buf.st_ctim.tv_sec;
1393
1394   return retval;
1395 #else
1396   return g_stat (filename, buf);
1397 #endif
1398 }
1399
1400 /**
1401  * g_unlink:
1402  * @filename: (type filename): a pathname in the GLib file name encoding
1403  *     (UTF-8 on Windows)
1404  *
1405  * A wrapper for the POSIX unlink() function. The unlink() function 
1406  * deletes a name from the filesystem. If this was the last link to the 
1407  * file and no processes have it opened, the diskspace occupied by the
1408  * file is freed.
1409  * 
1410  * See your C library manual for more details about unlink(). Note
1411  * that on Windows, it is in general not possible to delete files that
1412  * are open to some process, or mapped into memory.
1413  *
1414  * Returns: 0 if the name was successfully deleted, -1 if an error 
1415  *    occurred
1416  * 
1417  * Since: 2.6
1418  */
1419 int
1420 g_unlink (const gchar *filename)
1421 {
1422 #ifdef G_OS_WIN32
1423   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1424   int retval;
1425   int save_errno;
1426
1427   if (wfilename == NULL)
1428     {
1429       errno = EINVAL;
1430       return -1;
1431     }
1432
1433   retval = _wunlink (wfilename);
1434   save_errno = errno;
1435
1436   g_free (wfilename);
1437
1438   errno = save_errno;
1439   return retval;
1440 #else
1441   return unlink (filename);
1442 #endif
1443 }
1444
1445 /**
1446  * g_remove:
1447  * @filename: (type filename): a pathname in the GLib file name encoding
1448  *     (UTF-8 on Windows)
1449  *
1450  * A wrapper for the POSIX remove() function. The remove() function
1451  * deletes a name from the filesystem.
1452  * 
1453  * See your C library manual for more details about how remove() works
1454  * on your system. On Unix, remove() removes also directories, as it
1455  * calls unlink() for files and rmdir() for directories. On Windows,
1456  * although remove() in the C library only works for files, this
1457  * function tries first remove() and then if that fails rmdir(), and
1458  * thus works for both files and directories. Note however, that on
1459  * Windows, it is in general not possible to remove a file that is
1460  * open to some process, or mapped into memory.
1461  *
1462  * If this function fails on Windows you can't infer too much from the
1463  * errno value. rmdir() is tried regardless of what caused remove() to
1464  * fail. Any errno value set by remove() will be overwritten by that
1465  * set by rmdir().
1466  *
1467  * Returns: 0 if the file was successfully removed, -1 if an error 
1468  *    occurred
1469  * 
1470  * Since: 2.6
1471  */
1472 int
1473 g_remove (const gchar *filename)
1474 {
1475 #ifdef G_OS_WIN32
1476   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1477   int retval;
1478   int save_errno;
1479
1480   if (wfilename == NULL)
1481     {
1482       errno = EINVAL;
1483       return -1;
1484     }
1485
1486   retval = _wremove (wfilename);
1487   if (retval == -1)
1488     retval = _wrmdir (wfilename);
1489   save_errno = errno;
1490
1491   g_free (wfilename);
1492
1493   errno = save_errno;
1494   return retval;
1495 #else
1496   return remove (filename);
1497 #endif
1498 }
1499
1500 /**
1501  * g_rmdir:
1502  * @filename: (type filename): a pathname in the GLib file name encoding
1503  *     (UTF-8 on Windows)
1504  *
1505  * A wrapper for the POSIX rmdir() function. The rmdir() function
1506  * deletes a directory from the filesystem.
1507  * 
1508  * See your C library manual for more details about how rmdir() works
1509  * on your system.
1510  *
1511  * Returns: 0 if the directory was successfully removed, -1 if an error 
1512  *    occurred
1513  * 
1514  * Since: 2.6
1515  */
1516 int
1517 g_rmdir (const gchar *filename)
1518 {
1519 #ifdef G_OS_WIN32
1520   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1521   int retval;
1522   int save_errno;
1523
1524   if (wfilename == NULL)
1525     {
1526       errno = EINVAL;
1527       return -1;
1528     }
1529   
1530   retval = _wrmdir (wfilename);
1531   save_errno = errno;
1532
1533   g_free (wfilename);
1534
1535   errno = save_errno;
1536   return retval;
1537 #else
1538   return rmdir (filename);
1539 #endif
1540 }
1541
1542 /**
1543  * g_fopen:
1544  * @filename: (type filename): a pathname in the GLib file name encoding
1545  *     (UTF-8 on Windows)
1546  * @mode: a string describing the mode in which the file should be opened
1547  *
1548  * A wrapper for the stdio `fopen()` function. The `fopen()` function
1549  * opens a file and associates a new stream with it.
1550  * 
1551  * Because file descriptors are specific to the C library on Windows,
1552  * and a file descriptor is part of the `FILE` struct, the `FILE*` returned
1553  * by this function makes sense only to functions in the same C library.
1554  * Thus if the GLib-using code uses a different C library than GLib does,
1555  * the FILE* returned by this function cannot be passed to C library
1556  * functions like `fprintf()` or `fread()`.
1557  *
1558  * See your C library manual for more details about `fopen()`.
1559  *
1560  * As `close()` and `fclose()` are part of the C library, this implies that it is
1561  * currently impossible to close a file if the application C library and the C library
1562  * used by GLib are different. Convenience functions like g_file_set_contents_full()
1563  * avoid this problem.
1564  *
1565  * Returns: A `FILE*` if the file was successfully opened, or %NULL if
1566  *     an error occurred
1567  * 
1568  * Since: 2.6
1569  */
1570 FILE *
1571 g_fopen (const gchar *filename,
1572          const gchar *mode)
1573 {
1574 #ifdef G_OS_WIN32
1575   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1576   wchar_t *wmode;
1577   FILE *retval;
1578   int save_errno;
1579
1580   if (wfilename == NULL)
1581     {
1582       errno = EINVAL;
1583       return NULL;
1584     }
1585
1586   wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
1587
1588   if (wmode == NULL)
1589     {
1590       g_free (wfilename);
1591       errno = EINVAL;
1592       return NULL;
1593     }
1594
1595   _g_win32_fix_mode (wmode);
1596   retval = _wfopen (wfilename, wmode);
1597   save_errno = errno;
1598
1599   g_free (wfilename);
1600   g_free (wmode);
1601
1602   errno = save_errno;
1603   return retval;
1604 #else
1605   return fopen (filename, mode);
1606 #endif
1607 }
1608
1609 /**
1610  * g_freopen:
1611  * @filename: (type filename): a pathname in the GLib file name encoding
1612  *     (UTF-8 on Windows)
1613  * @mode: a string describing the mode in which the file should be  opened
1614  * @stream: (nullable): an existing stream which will be reused, or %NULL
1615  *
1616  * A wrapper for the POSIX freopen() function. The freopen() function
1617  * opens a file and associates it with an existing stream.
1618  * 
1619  * See your C library manual for more details about freopen().
1620  *
1621  * Returns: A FILE* if the file was successfully opened, or %NULL if
1622  *     an error occurred.
1623  * 
1624  * Since: 2.6
1625  */
1626 FILE *
1627 g_freopen (const gchar *filename,
1628            const gchar *mode,
1629            FILE        *stream)
1630 {
1631 #ifdef G_OS_WIN32
1632   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1633   wchar_t *wmode;
1634   FILE *retval;
1635   int save_errno;
1636
1637   if (wfilename == NULL)
1638     {
1639       errno = EINVAL;
1640       return NULL;
1641     }
1642
1643   wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
1644
1645   if (wmode == NULL)
1646     {
1647       g_free (wfilename);
1648       errno = EINVAL;
1649       return NULL;
1650     }
1651
1652   _g_win32_fix_mode (wmode);
1653   retval = _wfreopen (wfilename, wmode, stream);
1654   save_errno = errno;
1655
1656   g_free (wfilename);
1657   g_free (wmode);
1658
1659   errno = save_errno;
1660   return retval;
1661 #else
1662   return freopen (filename, mode, stream);
1663 #endif
1664 }
1665
1666 /**
1667  * g_fsync:
1668  * @fd: a file descriptor
1669  *
1670  * A wrapper for the POSIX `fsync()` function. On Windows, `_commit()` will be
1671  * used. On macOS, `fcntl(F_FULLFSYNC)` will be used.
1672  * The `fsync()` function is used to synchronize a file's in-core
1673  * state with that of the disk.
1674  *
1675  * This wrapper will handle retrying on `EINTR`.
1676  *
1677  * See the C library manual for more details about fsync().
1678  *
1679  * Returns: 0 on success, or -1 if an error occurred.
1680  * The return value can be used exactly like the return value from fsync().
1681  *
1682  * Since: 2.64
1683  */
1684 gint
1685 g_fsync (gint fd)
1686 {
1687 #ifdef G_OS_WIN32
1688   return _commit (fd);
1689 #elif defined(HAVE_FSYNC) || defined(HAVE_FCNTL_F_FULLFSYNC)
1690   int retval;
1691   do
1692 #ifdef HAVE_FCNTL_F_FULLFSYNC
1693     retval = fcntl (fd, F_FULLFSYNC, 0);
1694 #else
1695     retval = fsync (fd);
1696 #endif
1697   while (G_UNLIKELY (retval < 0 && errno == EINTR));
1698   return retval;
1699 #else
1700   return 0;
1701 #endif
1702 }
1703
1704 /**
1705  * g_utime:
1706  * @filename: (type filename): a pathname in the GLib file name encoding
1707  *     (UTF-8 on Windows)
1708  * @utb: a pointer to a struct utimbuf.
1709  *
1710  * A wrapper for the POSIX utime() function. The utime() function
1711  * sets the access and modification timestamps of a file.
1712  * 
1713  * See your C library manual for more details about how utime() works
1714  * on your system.
1715  *
1716  * Returns: 0 if the operation was successful, -1 if an error occurred
1717  * 
1718  * Since: 2.18
1719  */
1720 int
1721 g_utime (const gchar    *filename,
1722          struct utimbuf *utb)
1723 {
1724 #ifdef G_OS_WIN32
1725   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1726   int retval;
1727   int save_errno;
1728
1729   if (wfilename == NULL)
1730     {
1731       errno = EINVAL;
1732       return -1;
1733     }
1734   
1735   retval = _wutime (wfilename, (struct _utimbuf*) utb);
1736   save_errno = errno;
1737
1738   g_free (wfilename);
1739
1740   errno = save_errno;
1741   return retval;
1742 #else
1743   return utime (filename, utb);
1744 #endif
1745 }
1746
1747 /**
1748  * g_close:
1749  * @fd: A file descriptor
1750  * @error: a #GError
1751  *
1752  * This wraps the close() call. In case of error, %errno will be
1753  * preserved, but the error will also be stored as a #GError in @error.
1754  * In case of success, %errno is undefined.
1755  *
1756  * Besides using #GError, there is another major reason to prefer this
1757  * function over the call provided by the system; on Unix, it will
1758  * attempt to correctly handle %EINTR, which has platform-specific
1759  * semantics.
1760  *
1761  * It is a bug to call this function with an invalid file descriptor.
1762  *
1763  * On POSIX platforms since GLib 2.76, this function is async-signal safe
1764  * if (and only if) @error is %NULL and @fd is a valid open file descriptor.
1765  * This makes it safe to call from a signal handler or a #GSpawnChildSetupFunc
1766  * under those conditions.
1767  * See [`signal(7)`](man:signal(7)) and
1768  * [`signal-safety(7)`](man:signal-safety(7)) for more details.
1769  *
1770  * Returns: %TRUE on success, %FALSE if there was an error.
1771  *
1772  * Since: 2.36
1773  */
1774 gboolean
1775 g_close (gint       fd,
1776          GError   **error)
1777 {
1778   int res;
1779
1780   /* Important: if @error is NULL, we must not do anything that is
1781    * not async-signal-safe.
1782    */
1783   res = close (fd);
1784
1785   if (res == -1)
1786     {
1787       int errsv = errno;
1788
1789       if (errsv == EINTR)
1790         {
1791           /* Just ignore EINTR for now; a retry loop is the wrong thing to do
1792            * on Linux at least.  Anyone who wants to add a conditional check
1793            * for e.g. HP-UX is welcome to do so later...
1794            *
1795            * close_func_with_invalid_fds() in gspawn.c has similar logic.
1796            *
1797            * https://lwn.net/Articles/576478/
1798            * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
1799            * https://bugzilla.gnome.org/show_bug.cgi?id=682819
1800            * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
1801            * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
1802            *
1803            * `close$NOCANCEL()` in gstdioprivate.h, on macOS, ensures that the fd is
1804            * closed even if it did return EINTR.
1805            */
1806           return TRUE;
1807         }
1808
1809       if (error)
1810         {
1811           g_set_error_literal (error, G_FILE_ERROR,
1812                                g_file_error_from_errno (errsv),
1813                                g_strerror (errsv));
1814         }
1815
1816       if (errsv == EBADF)
1817         {
1818           /* There is a bug. Fail an assertion. Note that this function is supposed to be
1819            * async-signal-safe, but in case an assertion fails, all bets are already off. */
1820           if (fd >= 0)
1821             {
1822               /* Closing an non-negative, invalid file descriptor is a bug. The bug is
1823                * not necessarily in the caller of g_close(), but somebody else
1824                * might have wrongly closed fd. In any case, there is a serious bug
1825                * somewhere. */
1826               g_critical ("g_close(fd:%d) failed with EBADF. The tracking of file descriptors got messed up", fd);
1827             }
1828           else
1829             {
1830               /* Closing a negative "file descriptor" is less problematic. It's still a nonsensical action
1831                * from the caller. Assert against that too. */
1832               g_critical ("g_close(fd:%d) failed with EBADF. This is not a valid file descriptor", fd);
1833             }
1834         }
1835
1836       errno = errsv;
1837
1838       return FALSE;
1839     }
1840
1841   return TRUE;
1842 }
1843
1844 /**
1845  * g_clear_fd: (skip)
1846  * @fd_ptr: (not optional) (inout) (transfer full): a pointer to a file descriptor
1847  * @error: Used to return an error on failure
1848  *
1849  * If @fd_ptr points to a file descriptor, close it and return
1850  * whether closing it was successful, like g_close().
1851  * If @fd_ptr points to a negative number, return %TRUE without closing
1852  * anything.
1853  * In both cases, set @fd_ptr to `-1` before returning.
1854  *
1855  * Like g_close(), if closing the file descriptor fails, the error is
1856  * stored in both %errno and @error. If this function succeeds,
1857  * %errno is undefined.
1858  *
1859  * On POSIX platforms, this function is async-signal safe
1860  * if @error is %NULL and @fd_ptr points to either a negative number or a
1861  * valid open file descriptor.
1862  * This makes it safe to call from a signal handler or a #GSpawnChildSetupFunc
1863  * under those conditions.
1864  * See [`signal(7)`](man:signal(7)) and
1865  * [`signal-safety(7)`](man:signal-safety(7)) for more details.
1866  *
1867  * It is a programming error for @fd_ptr to point to a non-negative
1868  * number that is not a valid file descriptor.
1869  *
1870  * A typical use of this function is to clean up a file descriptor at
1871  * the end of its scope, whether it has been set successfully or not:
1872  *
1873  * |[
1874  * gboolean
1875  * operate_on_fd (GError **error)
1876  * {
1877  *   gboolean ret = FALSE;
1878  *   int fd = -1;
1879  *
1880  *   fd = open_a_fd (error);
1881  *
1882  *   if (fd < 0)
1883  *     goto out;
1884  *
1885  *   if (!do_something (fd, error))
1886  *     goto out;
1887  *
1888  *   if (!g_clear_fd (&fd, error))
1889  *     goto out;
1890  *
1891  *   ret = TRUE;
1892  *
1893  * out:
1894  *   // OK to call even if fd was never opened or was already closed
1895  *   g_clear_fd (&fd, NULL);
1896  *   return ret;
1897  * }
1898  * ]|
1899  *
1900  * This function is also useful in conjunction with #g_autofd.
1901  *
1902  * Returns: %TRUE on success
1903  * Since: 2.76
1904  */
1905
1906 /**
1907  * g_autofd: (skip)
1908  *
1909  * Macro to add an attribute to a file descriptor variable to ensure
1910  * automatic cleanup using g_clear_fd().
1911  *
1912  * This macro behaves like #g_autofree rather than g_autoptr(): it is
1913  * an attribute supplied before the type name, rather than wrapping the
1914  * type definition.
1915  *
1916  * Otherwise, this macro has similar constraints as g_autoptr(): it is
1917  * only supported on GCC and clang, and the variable must be initialized
1918  * (to either a valid file descriptor or a negative number).
1919  *
1920  * Using this macro is async-signal-safe if the constraints described above
1921  * are met, so it can be used in a signal handler or after `fork()`.
1922  *
1923  * Any error from closing the file descriptor when it goes out of scope
1924  * is ignored. Use g_clear_fd() if error-checking is required.
1925  *
1926  * |[
1927  * gboolean
1928  * operate_on_fds (GError **error)
1929  * {
1930  *   g_autofd int fd1 = open_a_fd (..., error);
1931  *   g_autofd int fd2 = -1;
1932  *
1933  *   // it is safe to return early here, nothing will be closed
1934  *   if (fd1 < 0)
1935  *     return FALSE;
1936  *
1937  *   fd2 = open_a_fd (..., error);
1938  *
1939  *   // fd1 will be closed automatically if we return here
1940  *   if (fd2 < 0)
1941  *     return FALSE;
1942  *
1943  *   // fd1 and fd2 will be closed automatically if we return here
1944  *   if (!do_something_useful (fd1, fd2, error))
1945  *     return FALSE;
1946  *
1947  *   // fd2 will be closed automatically if we return here
1948  *   if (!g_clear_fd (&fd1, error))
1949  *     return FALSE;
1950  *
1951  *   // fd2 will be automatically closed here if still open
1952  *   return TRUE;
1953  * }
1954  * ]|
1955  *
1956  * Since: 2.76
1957  */