gstdio.c 22.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* gstdio.c - wrappers for C library functions
 *
 * Copyright 2004 Tor Lillqvist
 *
 * GLib is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * GLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GLib; see the file COPYING.LIB.  If not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "config.h"
22
#include "glibconfig.h"
23 24

#define G_STDIO_NO_WRAP_ON_UNIX
25 26 27 28 29 30 31 32 33 34

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef G_OS_WIN32
35
#include <windows.h>
36
#include <errno.h>
37
#include <wchar.h>
38
#include <direct.h>
39
#include <io.h>
40
#include <sys/utime.h>
41 42
#else
#include <utime.h>
43
#include <errno.h>
44 45 46 47
#endif

#include "gstdio.h"

48

49
#if !defined (G_OS_UNIX) && !defined (G_OS_WIN32) && !defined (G_OS_BEOS)
50 51 52
#error Please port this to your operating system
#endif

53 54 55 56
#if defined (_MSC_VER) && !defined(_WIN64)
#undef _wstat
#define _wstat _wstat32
#endif
57

58 59
/**
 * g_access:
60
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
61 62 63 64
 * @mode: as in access()
 *
 * A wrapper for the POSIX access() function. This function is used to
 * test a pathname for one or several of read, write or execute
65
 * permissions, or just existence.
66
 *
67 68 69 70 71 72 73 74
 * On Windows, the file protection mechanism is not at all POSIX-like,
 * and the underlying function in the C library only checks the
 * FAT-style READONLY attribute, and does not look at the ACL of a
 * file at all. This function is this in practise almost useless on
 * Windows. Software that needs to handle file permissions on Windows
 * more exactly should use the Win32 API.
 *
 * See your C library manual for more details about access().
75 76 77 78 79
 *
 * Returns: zero if the pathname refers to an existing file system
 * object that has all the tested permissions, or -1 otherwise or on
 * error.
 * 
Matthias Clasen's avatar
Matthias Clasen committed
80
 * Since: 2.8
81 82 83 84 85 86
 */
int
g_access (const gchar *filename,
	  int          mode)
{
#ifdef G_OS_WIN32
87 88 89 90 91
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
    
  if (wfilename == NULL)
92
    {
93 94
      errno = EINVAL;
      return -1;
95 96
    }

97 98 99 100
#ifndef X_OK
#define X_OK 1
#endif

101
  retval = _waccess (wfilename, mode & ~X_OK);
102
  save_errno = errno;
103

104
  g_free (wfilename);
105

106 107
  errno = save_errno;
  return retval;
108 109 110 111 112 113 114
#else
  return access (filename, mode);
#endif
}

/**
 * g_chmod:
115
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
116 117 118
 * @mode: as in chmod()
 *
 * A wrapper for the POSIX chmod() function. The chmod() function is
119 120 121 122 123 124 125
 * used to set the permissions of a file system object.
 * 
 * On Windows the file protection mechanism is not at all POSIX-like,
 * and the underlying chmod() function in the C library just sets or
 * clears the FAT-style READONLY attribute. It does not touch any
 * ACL. Software that needs to manage file permissions on Windows
 * exactly should use the Win32 API.
126
 *
127
 * See your C library manual for more details about chmod().
128
 *
Matthias Clasen's avatar
Matthias Clasen committed
129
 * Returns: zero if the operation succeeded, -1 on error.
130
 * 
Matthias Clasen's avatar
Matthias Clasen committed
131
 * Since: 2.8
132 133 134 135 136 137
 */
int
g_chmod (const gchar *filename,
	 int          mode)
{
#ifdef G_OS_WIN32
138 139 140 141 142
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
    
  if (wfilename == NULL)
143
    {
144 145
      errno = EINVAL;
      return -1;
146 147
    }

148 149
  retval = _wchmod (wfilename, mode);
  save_errno = errno;
150

151
  g_free (wfilename);
152

153 154
  errno = save_errno;
  return retval;
155 156 157 158
#else
  return chmod (filename, mode);
#endif
}
159 160
/**
 * g_open:
161
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
162 163 164
 * @flags: as in open()
 * @mode: as in open()
 *
165
 * A wrapper for the POSIX open() function. The open() function is
166 167 168
 * used to convert a pathname into a file descriptor.
 *
 * On POSIX systems file descriptors are implemented by the operating
169
 * system. On Windows, it's the C library that implements open() and
170 171 172 173
 * file descriptors. The actual Win32 API for opening files is quite
 * different, see MSDN documentation for CreateFile(). The Win32 API
 * uses file handles, which are more randomish integers, not small
 * integers like file descriptors.
174
 *
175 176 177 178 179 180 181 182
 * Because file descriptors are specific to the C library on Windows,
 * the file descriptor returned by this function makes sense only to
 * functions in the same C library. Thus if the GLib-using code uses a
 * different C library than GLib does, the file descriptor returned by
 * this function cannot be passed to C library functions like write()
 * or read().
 *
 * See your C library manual for more details about open().
183
 *
184 185
 * Returns: a new file descriptor, or -1 if an error occurred. The
 * return value can be used exactly like the return value from open().
186 187 188 189 190 191 192 193 194
 * 
 * Since: 2.6
 */
int
g_open (const gchar *filename,
	int          flags,
	int          mode)
{
#ifdef G_OS_WIN32
195 196 197 198 199
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
    
  if (wfilename == NULL)
200
    {
201 202
      errno = EINVAL;
      return -1;
203
    }
204

205 206
  retval = _wopen (wfilename, flags, mode);
  save_errno = errno;
207

208
  g_free (wfilename);
209

210 211
  errno = save_errno;
  return retval;
212
#else
213 214 215 216 217
  int fd;
  do
    fd = open (filename, flags, mode);
  while (G_UNLIKELY (fd == -1 && errno == EINTR));
  return fd;
218 219 220
#endif
}

221 222
/**
 * g_creat:
223
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
224 225 226 227
 * @mode: as in creat()
 *
 * A wrapper for the POSIX creat() function. The creat() function is
 * used to convert a pathname into a file descriptor, creating a file
228 229 230 231 232 233 234 235
 * if necessary.

 * On POSIX systems file descriptors are implemented by the operating
 * system. On Windows, it's the C library that implements creat() and
 * file descriptors. The actual Windows API for opening files is
 * different, see MSDN documentation for CreateFile(). The Win32 API
 * uses file handles, which are more randomish integers, not small
 * integers like file descriptors.
236
 *
237 238 239 240 241 242 243 244
 * Because file descriptors are specific to the C library on Windows,
 * the file descriptor returned by this function makes sense only to
 * functions in the same C library. Thus if the GLib-using code uses a
 * different C library than GLib does, the file descriptor returned by
 * this function cannot be passed to C library functions like write()
 * or read().
 *
 * See your C library manual for more details about creat().
245 246 247 248
 *
 * Returns: a new file descriptor, or -1 if an error occurred. The
 * return value can be used exactly like the return value from creat().
 * 
Matthias Clasen's avatar
Matthias Clasen committed
249
 * Since: 2.8
250 251 252 253 254 255
 */
int
g_creat (const gchar *filename,
	 int          mode)
{
#ifdef G_OS_WIN32
256 257 258 259 260
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
    
  if (wfilename == NULL)
261
    {
262 263
      errno = EINVAL;
      return -1;
264 265
    }

266 267
  retval = _wcreat (wfilename, mode);
  save_errno = errno;
268

269
  g_free (wfilename);
270

271 272
  errno = save_errno;
  return retval;
273 274 275 276 277
#else
  return creat (filename, mode);
#endif
}

278 279
/**
 * g_rename:
280
 * @oldfilename: a pathname in the GLib file name encoding (UTF-8 on Windows)
281 282 283 284 285
 * @newfilename: a pathname in the GLib file name encoding
 *
 * A wrapper for the POSIX rename() function. The rename() function 
 * renames a file, moving it between directories if required.
 * 
286
 * See your C library manual for more details about how rename() works
287 288
 * on your system. It is not possible in general on Windows to rename
 * a file that is open to some process.
289 290 291 292 293 294 295 296 297 298
 *
 * Returns: 0 if the renaming succeeded, -1 if an error occurred
 * 
 * Since: 2.6
 */
int
g_rename (const gchar *oldfilename,
	  const gchar *newfilename)
{
#ifdef G_OS_WIN32
299 300 301
  wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
  wchar_t *wnewfilename;
  int retval;
302
  int save_errno = 0;
303

304 305 306 307 308
  if (woldfilename == NULL)
    {
      errno = EINVAL;
      return -1;
    }
309

310
  wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
311

312 313
  if (wnewfilename == NULL)
    {
314
      g_free (woldfilename);
315 316
      errno = EINVAL;
      return -1;
317
    }
318 319 320

  if (MoveFileExW (woldfilename, wnewfilename, MOVEFILE_REPLACE_EXISTING))
    retval = 0;
321 322
  else
    {
323 324
      retval = -1;
      switch (GetLastError ())
325
	{
326 327 328 329 330 331 332 333 334 335 336
#define CASE(a,b) case ERROR_##a: save_errno = b; break
	  CASE (FILE_NOT_FOUND, ENOENT);
	  CASE (PATH_NOT_FOUND, ENOENT);
	  CASE (ACCESS_DENIED, EACCES);
	  CASE (NOT_SAME_DEVICE, EXDEV);
	  CASE (LOCK_VIOLATION, EACCES);
	  CASE (SHARING_VIOLATION, EACCES);
	  CASE (FILE_EXISTS, EEXIST);
	  CASE (ALREADY_EXISTS, EEXIST);
#undef CASE
	default: save_errno = EIO;
337
	}
338
    }
339 340 341 342 343 344

  g_free (woldfilename);
  g_free (wnewfilename);
    
  errno = save_errno;
  return retval;
345 346 347 348 349 350 351
#else
  return rename (oldfilename, newfilename);
#endif
}

/**
 * g_mkdir: 
352
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
353 354 355 356
 * @mode: permissions to use for the newly created directory
 *
 * A wrapper for the POSIX mkdir() function. The mkdir() function 
 * attempts to create a directory with the given name and permissions.
357
 * The mode argument is ignored on Windows.
358
 * 
359
 * See your C library manual for more details about mkdir().
360 361 362 363 364 365 366 367 368 369 370
 *
 * Returns: 0 if the directory was successfully created, -1 if an error 
 *    occurred
 * 
 * Since: 2.6
 */
int
g_mkdir (const gchar *filename,
	 int          mode)
{
#ifdef G_OS_WIN32
371 372 373
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
374

375
  if (wfilename == NULL)
376
    {
377 378 379
      errno = EINVAL;
      return -1;
    }
380

381 382
  retval = _wmkdir (wfilename);
  save_errno = errno;
383

384 385 386 387
  g_free (wfilename);
    
  errno = save_errno;
  return retval;
388 389 390 391 392
#else
  return mkdir (filename, mode);
#endif
}

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/**
 * g_chdir: 
 * @path: a pathname in the GLib file name encoding (UTF-8 on Windows)
 *
 * A wrapper for the POSIX chdir() function. The function changes the
 * current directory of the process to @path.
 * 
 * See your C library manual for more details about chdir().
 *
 * Returns: 0 on success, -1 if an error occurred.
 * 
 * Since: 2.8
 */
int
g_chdir (const gchar *path)
{
#ifdef G_OS_WIN32
410 411 412
  wchar_t *wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
413

414
  if (wpath == NULL)
415
    {
416 417 418
      errno = EINVAL;
      return -1;
    }
419

420 421
  retval = _wchdir (wpath);
  save_errno = errno;
422

423 424 425 426
  g_free (wpath);
    
  errno = save_errno;
  return retval;
427 428 429 430 431
#else
  return chdir (path);
#endif
}

432 433 434 435 436 437 438 439
/**
 * GStatBuf:
 *
 * A type corresponding to the appropriate struct type for the stat
 * system call, depending on the platform and/or compiler being used.
 *
 * See g_stat() for more information.
 **/
440 441
/**
 * g_stat: 
442
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
443 444 445
 * @buf: a pointer to a <structname>stat</structname> struct, which
 *    will be filled with the file information
 *
446 447
 * A wrapper for the POSIX stat() function. The stat() function
 * returns information about a file. On Windows the stat() function in
448 449 450
 * the C library checks only the FAT-style READONLY attribute and does
 * not look at the ACL at all. Thus on Windows the protection bits in
 * the st_mode field are a fabrication of little use.
451
 * 
452 453 454 455 456 457 458 459 460 461 462 463 464 465
 * On Windows the Microsoft C libraries have several variants of the
 * <structname>stat</structname> struct and stat() function with names
 * like "_stat", "_stat32", "_stat32i64" and "_stat64i32". The one
 * used here is for 32-bit code the one with 32-bit size and time
 * fields, specifically called "_stat32".
 *
 * In Microsoft's compiler, by default "struct stat" means one with
 * 64-bit time fields while in MinGW "struct stat" is the legacy one
 * with 32-bit fields. To hopefully clear up this messs, the gstdio.h
 * header defines a type GStatBuf which is the appropriate struct type
 * depending on the platform and/or compiler being used. On POSIX it
 * is just "struct stat", but note that even on POSIX platforms,
 * "stat" might be a macro.
 *
466
 * See your C library manual for more details about stat().
467
 *
Tor Lillqvist's avatar
Tor Lillqvist committed
468
 * Returns: 0 if the information was successfully retrieved, -1 if an error 
469 470 471 472 473
 *    occurred
 * 
 * Since: 2.6
 */
int
474 475
g_stat (const gchar *filename,
	GStatBuf    *buf)
476 477
{
#ifdef G_OS_WIN32
478 479 480 481
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
  int len;
482

483
  if (wfilename == NULL)
484
    {
485 486 487
      errno = EINVAL;
      return -1;
    }
488

489 490 491 492 493 494
  len = wcslen (wfilename);
  while (len > 0 && G_IS_DIR_SEPARATOR (wfilename[len-1]))
    len--;
  if (len > 0 &&
      (!g_path_is_absolute (filename) || len > g_path_skip_root (filename) - filename))
    wfilename[len] = '\0';
495

496
  retval = _wstat (wfilename, buf);
497
  save_errno = errno;
498

499
  g_free (wfilename);
500

501 502
  errno = save_errno;
  return retval;
503 504 505 506 507
#else
  return stat (filename, buf);
#endif
}

Tor Lillqvist's avatar
Tor Lillqvist committed
508 509
/**
 * g_lstat: 
510
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
Tor Lillqvist's avatar
Tor Lillqvist committed
511 512 513 514 515 516
 * @buf: a pointer to a <structname>stat</structname> struct, which
 *    will be filled with the file information
 *
 * A wrapper for the POSIX lstat() function. The lstat() function is
 * like stat() except that in the case of symbolic links, it returns
 * information about the symbolic link itself and not the file that it
517
 * refers to. If the system does not support symbolic links g_lstat()
Tor Lillqvist's avatar
Tor Lillqvist committed
518 519
 * is identical to g_stat().
 * 
520
 * See your C library manual for more details about lstat().
Tor Lillqvist's avatar
Tor Lillqvist committed
521 522 523 524 525 526 527
 *
 * Returns: 0 if the information was successfully retrieved, -1 if an error 
 *    occurred
 * 
 * Since: 2.6
 */
int
528 529
g_lstat (const gchar *filename,
	 GStatBuf    *buf)
Tor Lillqvist's avatar
Tor Lillqvist committed
530
{
531 532
#ifdef HAVE_LSTAT
  /* This can't be Win32, so don't do the widechar dance. */
Tor Lillqvist's avatar
Tor Lillqvist committed
533
  return lstat (filename, buf);
534 535
#else
  return g_stat (filename, buf);
Tor Lillqvist's avatar
Tor Lillqvist committed
536 537 538
#endif
}

539 540
/**
 * g_unlink:
541
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
542 543 544 545 546 547
 *
 * A wrapper for the POSIX unlink() function. The unlink() function 
 * deletes a name from the filesystem. If this was the last link to the 
 * file and no processes have it opened, the diskspace occupied by the
 * file is freed.
 * 
548 549 550
 * See your C library manual for more details about unlink(). Note
 * that on Windows, it is in general not possible to delete files that
 * are open to some process, or mapped into memory.
551
 *
552
 * Returns: 0 if the name was successfully deleted, -1 if an error 
553 554 555 556 557 558 559 560
 *    occurred
 * 
 * Since: 2.6
 */
int
g_unlink (const gchar *filename)
{
#ifdef G_OS_WIN32
561 562 563
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
564

565
  if (wfilename == NULL)
566
    {
567 568 569
      errno = EINVAL;
      return -1;
    }
570

571 572
  retval = _wunlink (wfilename);
  save_errno = errno;
573

574
  g_free (wfilename);
575

576 577
  errno = save_errno;
  return retval;
578 579 580 581 582 583 584
#else
  return unlink (filename);
#endif
}

/**
 * g_remove:
585
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
586
 *
587 588
 * A wrapper for the POSIX remove() function. The remove() function
 * deletes a name from the filesystem.
589
 * 
590 591 592 593
 * See your C library manual for more details about how remove() works
 * on your system. On Unix, remove() removes also directories, as it
 * calls unlink() for files and rmdir() for directories. On Windows,
 * although remove() in the C library only works for files, this
Tor Lillqvist's avatar
Tor Lillqvist committed
594 595 596 597
 * function tries first remove() and then if that fails rmdir(), and
 * thus works for both files and directories. Note however, that on
 * Windows, it is in general not possible to remove a file that is
 * open to some process, or mapped into memory.
598
 *
599 600 601 602 603
 * If this function fails on Windows you can't infer too much from the
 * errno value. rmdir() is tried regardless of what caused remove() to
 * fail. Any errno value set by remove() will be overwritten by that
 * set by rmdir().
 *
604
 * Returns: 0 if the file was successfully removed, -1 if an error 
605 606 607 608 609 610 611 612
 *    occurred
 * 
 * Since: 2.6
 */
int
g_remove (const gchar *filename)
{
#ifdef G_OS_WIN32
613 614 615
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
616

617
  if (wfilename == NULL)
618
    {
619 620 621
      errno = EINVAL;
      return -1;
    }
622

623 624 625 626
  retval = _wremove (wfilename);
  if (retval == -1)
    retval = _wrmdir (wfilename);
  save_errno = errno;
627

628
  g_free (wfilename);
629

630 631
  errno = save_errno;
  return retval;
632 633 634 635 636
#else
  return remove (filename);
#endif
}

Tor Lillqvist's avatar
Tor Lillqvist committed
637 638
/**
 * g_rmdir:
639
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
Tor Lillqvist's avatar
Tor Lillqvist committed
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
 *
 * A wrapper for the POSIX rmdir() function. The rmdir() function
 * deletes a directory from the filesystem.
 * 
 * See your C library manual for more details about how rmdir() works
 * on your system.
 *
 * Returns: 0 if the directory was successfully removed, -1 if an error 
 *    occurred
 * 
 * Since: 2.6
 */
int
g_rmdir (const gchar *filename)
{
#ifdef G_OS_WIN32
656 657 658
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;
659

660
  if (wfilename == NULL)
Tor Lillqvist's avatar
Tor Lillqvist committed
661
    {
662 663 664 665 666 667
      errno = EINVAL;
      return -1;
    }
  
  retval = _wrmdir (wfilename);
  save_errno = errno;
Tor Lillqvist's avatar
Tor Lillqvist committed
668

669
  g_free (wfilename);
Tor Lillqvist's avatar
Tor Lillqvist committed
670

671 672
  errno = save_errno;
  return retval;
Tor Lillqvist's avatar
Tor Lillqvist committed
673 674 675 676 677
#else
  return rmdir (filename);
#endif
}

678 679
/**
 * g_fopen:
680
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
681 682 683
 * @mode: a string describing the mode in which the file should be 
 *   opened
 *
684 685
 * A wrapper for the stdio fopen() function. The fopen() function
 * opens a file and associates a new stream with it.
686
 * 
687 688 689 690 691 692 693 694 695
 * Because file descriptors are specific to the C library on Windows,
 * and a file descriptor is partof the <type>FILE</type> struct, the
 * <type>FILE</type> pointer returned by this function makes sense
 * only to functions in the same C library. Thus if the GLib-using
 * code uses a different C library than GLib does, the
 * <type>FILE</type> pointer returned by this function cannot be
 * passed to C library functions like fprintf() or fread().
 *
 * See your C library manual for more details about fopen().
696
 *
Ross Burton's avatar
Ross Burton committed
697
 * Returns: A <type>FILE</type> pointer if the file was successfully
698 699 700 701 702 703 704 705 706
 *    opened, or %NULL if an error occurred
 * 
 * Since: 2.6
 */
FILE *
g_fopen (const gchar *filename,
	 const gchar *mode)
{
#ifdef G_OS_WIN32
707 708 709 710
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  wchar_t *wmode;
  FILE *retval;
  int save_errno;
711

712 713 714 715 716
  if (wfilename == NULL)
    {
      errno = EINVAL;
      return NULL;
    }
717

718
  wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
719

720 721
  if (wmode == NULL)
    {
722
      g_free (wfilename);
723 724
      errno = EINVAL;
      return NULL;
725
    }
726

727 728
  retval = _wfopen (wfilename, wmode);
  save_errno = errno;
729

730 731
  g_free (wfilename);
  g_free (wmode);
732

733 734
  errno = save_errno;
  return retval;
735 736 737 738 739 740 741
#else
  return fopen (filename, mode);
#endif
}

/**
 * g_freopen:
742
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
743 744
 * @mode: a string describing the mode in which the file should be 
 *   opened
745
 * @stream: (allow-none): an existing stream which will be reused, or %NULL
746 747 748 749
 *
 * A wrapper for the POSIX freopen() function. The freopen() function
 * opens a file and associates it with an existing stream.
 * 
750
 * See your C library manual for more details about freopen().
751
 *
Stef Walter's avatar
Stef Walter committed
752
 * Returns: A <literal>FILE</literal> pointer if the file was successfully
753 754 755 756 757 758 759 760 761 762
 *    opened, or %NULL if an error occurred.
 * 
 * Since: 2.6
 */
FILE *
g_freopen (const gchar *filename,
	   const gchar *mode,
	   FILE        *stream)
{
#ifdef G_OS_WIN32
763 764 765 766
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  wchar_t *wmode;
  FILE *retval;
  int save_errno;
767

768 769 770 771 772 773 774
  if (wfilename == NULL)
    {
      errno = EINVAL;
      return NULL;
    }
  
  wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
775

776 777
  if (wmode == NULL)
    {
778
      g_free (wfilename);
779 780
      errno = EINVAL;
      return NULL;
781
    }
782 783 784
  
  retval = _wfreopen (wfilename, wmode, stream);
  save_errno = errno;
785

786 787
  g_free (wfilename);
  g_free (wmode);
788

789 790
  errno = save_errno;
  return retval;
791 792 793 794
#else
  return freopen (filename, mode, stream);
#endif
}
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
/**
 * g_utime:
 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
 * @utb: a pointer to a struct utimbuf.
 *
 * A wrapper for the POSIX utime() function. The utime() function
 * sets the access and modification timestamps of a file.
 * 
 * See your C library manual for more details about how utime() works
 * on your system.
 *
 * Returns: 0 if the operation was successful, -1 if an error 
 *    occurred
 * 
 * Since: 2.18
 */
int
g_utime (const gchar    *filename,
	 struct utimbuf *utb)
{
#ifdef G_OS_WIN32
  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
  int retval;
  int save_errno;

  if (wfilename == NULL)
    {
      errno = EINVAL;
      return -1;
    }
  
  retval = _wutime (wfilename, (struct _utimbuf*) utb);
  save_errno = errno;

  g_free (wfilename);

  errno = save_errno;
  return retval;
#else
  return utime (filename, utb);
#endif
}
Colin Walters's avatar
Colin Walters committed
838 839 840 841 842 843 844 845 846 847 848 849 850

/**
 * g_close:
 * @fd: A file descriptor
 * @error: a #GError
 *
 * This wraps the close() call; in case of error, %errno will be
 * preserved, but the error will also be stored as a #GError in @error.
 *
 * Besides using #GError, there is another major reason to prefer this
 * function over the call provided by the system; on Unix, it will
 * attempt to correctly handle %EINTR, which has platform-specific
 * semantics.
851 852
 *
 * Since: 2.36
Colin Walters's avatar
Colin Walters committed
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
 */
gboolean
g_close (gint       fd,
         GError   **error)
{
  int res;
  res = close (fd);
  /* Just ignore EINTR for now; a retry loop is the wrong thing to do
   * on Linux at least.  Anyone who wants to add a conditional check
   * for e.g. HP-UX is welcome to do so later...
   *
   * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
   * https://bugzilla.gnome.org/show_bug.cgi?id=682819
   * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
   * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
   */
  if (G_UNLIKELY (res == -1 && errno == EINTR))
    return TRUE;
  else if (res == -1)
    {
      int errsv = errno;
      g_set_error_literal (error, G_FILE_ERROR,
                           g_file_error_from_errno (errsv),
                           g_strerror (errsv));
      errno = errsv;
      return FALSE;
    }
  return TRUE;
}