LCOV - code coverage report
Current view: top level - glib/glib - gstdio.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 46 52 88.5 %
Date: 2024-04-23 05:16:05 Functions: 16 17 94.1 %
Branches: 10 18 55.6 %

           Branch data     Line data    Source code
       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                 :       2937 : 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                 :       2937 :   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                 :         33 : 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                 :         33 :   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                 :          9 : 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                 :          9 :     fd = open (filename, flags, mode);
    1076   [ -  +  -  - ]:          9 :   while (G_UNLIKELY (fd == -1 && errno == EINTR));
    1077                 :          9 :   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                 :          1 : 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                 :          1 :   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                 :          1 : 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                 :          1 :   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                 :          2 : 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                 :          2 :   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                 :         33 : 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                 :         33 :   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                 :          4 : 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                 :          4 :   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                 :         36 : 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                 :         36 :   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                 :        237 : 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                 :        237 :   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                 :        102 : 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                 :        102 :   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                 :       2008 : 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                 :       2008 :   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                 :         19 : 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                 :         19 :   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                 :          0 : 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                 :          0 :   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                 :         29 : 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                 :         29 :     retval = fsync (fd);
    1696                 :            : #endif
    1697   [ +  +  -  + ]:         29 :   while (G_UNLIKELY (retval < 0 && errno == EINTR));
    1698                 :         29 :   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                 :          1 : 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                 :          1 :   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                 :       8299 : 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                 :       8299 :   res = close (fd);
    1784                 :            : 
    1785         [ +  + ]:       8299 :   if (res == -1)
    1786                 :            :     {
    1787                 :          3 :       int errsv = errno;
    1788                 :            : 
    1789         [ -  + ]:          3 :       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                 :          0 :           return TRUE;
    1807                 :            :         }
    1808                 :            : 
    1809         [ -  + ]:          3 :       if (error)
    1810                 :            :         {
    1811                 :          0 :           g_set_error_literal (error, G_FILE_ERROR,
    1812                 :          0 :                                g_file_error_from_errno (errsv),
    1813                 :            :                                g_strerror (errsv));
    1814                 :            :         }
    1815                 :            : 
    1816         [ +  - ]:          3 :       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         [ +  - ]:          3 :           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                 :          3 :               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                 :          0 :               g_critical ("g_close(fd:%d) failed with EBADF. This is not a valid file descriptor", fd);
    1833                 :            :             }
    1834                 :            :         }
    1835                 :            : 
    1836                 :          3 :       errno = errsv;
    1837                 :            : 
    1838                 :          3 :       return FALSE;
    1839                 :            :     }
    1840                 :            : 
    1841                 :       8296 :   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                 :            :  */

Generated by: LCOV version 1.14