📄 gfileutils.c
字号:
/* gfileutils.c - File utility functions * * Copyright 2000 Red Hat, Inc. * * 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 "glibconfig.h"#include "glib.h"#include <sys/stat.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#ifdef G_OS_WIN32#include <io.h>#ifndef F_OK#define F_OK 0#define X_OK 1#define W_OK 2#define R_OK 4#endif /* !F_OK */#ifndef S_ISREG#define S_ISREG(mode) ((mode)&_S_IFREG)#endif#ifndef S_ISDIR#define S_ISDIR(mode) ((mode)&_S_IFDIR)#endif#endif /* G_OS_WIN32 */#ifndef S_ISLNK#define S_ISLNK(x) 0#endif#ifndef O_BINARY#define O_BINARY 0#endif#include "glibintl.h"/** * g_file_test: * @filename: a filename to test * @test: bitfield of #GFileTest flags * * Returns %TRUE if any of the tests in the bitfield @test are * %TRUE. For example, <literal>(G_FILE_TEST_EXISTS | * G_FILE_TEST_IS_DIR)</literal> will return %TRUE if the file exists; * the check whether it's a directory doesn't matter since the existence * test is %TRUE. With the current set of available tests, there's no point * passing in more than one test at a time. * * Apart from #G_FILE_TEST_IS_SYMLINK all tests follow symbolic links, * so for a symbolic link to a regular file g_file_test() will return * %TRUE for both #G_FILE_TEST_IS_SYMLINK and #G_FILE_TEST_IS_REGULAR. * * Note, that for a dangling symbolic link g_file_test() will return * %TRUE for #G_FILE_TEST_IS_SYMLINK and %FALSE for all other flags. * * Return value: whether a test was %TRUE **/gbooleang_file_test (const gchar *filename, GFileTest test){ if ((test & G_FILE_TEST_EXISTS) && (access (filename, F_OK) == 0)) return TRUE; if ((test & G_FILE_TEST_IS_EXECUTABLE) && (access (filename, X_OK) == 0)) return TRUE; if (test & G_FILE_TEST_IS_SYMLINK) {#ifdef G_OS_WIN32 /* no sym links on win32, no lstat in msvcrt */#else struct stat s; if ((lstat (filename, &s) == 0) && S_ISLNK (s.st_mode)) return TRUE;#endif } if (test & (G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR)) { struct stat s; if (stat (filename, &s) == 0) { if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode)) return TRUE; if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode)) return TRUE; } } return FALSE;}GQuarkg_file_error_quark (void){ static GQuark q = 0; if (q == 0) q = g_quark_from_static_string ("g-file-error-quark"); return q;}/** * g_file_error_from_errno: * @err_no: an "errno" value * * Gets a #GFileError constant based on the passed-in @errno. * For example, if you pass in %EEXIST this function returns * #G_FILE_ERROR_EXIST. Unlike @errno values, you can portably * assume that all #GFileError values will exist. * * Normally a #GFileError value goes into a #GError returned * from a function that manipulates files. So you would use * g_file_error_from_errno() when constructing a #GError. * * Return value: #GFileError corresponding to the given @errno **/GFileErrorg_file_error_from_errno (gint err_no){ switch (err_no) {#ifdef EEXIST case EEXIST: return G_FILE_ERROR_EXIST; break;#endif#ifdef EISDIR case EISDIR: return G_FILE_ERROR_ISDIR; break;#endif#ifdef EACCES case EACCES: return G_FILE_ERROR_ACCES; break;#endif#ifdef ENAMETOOLONG case ENAMETOOLONG: return G_FILE_ERROR_NAMETOOLONG; break;#endif#ifdef ENOENT case ENOENT: return G_FILE_ERROR_NOENT; break;#endif#ifdef ENOTDIR case ENOTDIR: return G_FILE_ERROR_NOTDIR; break;#endif#ifdef ENXIO case ENXIO: return G_FILE_ERROR_NXIO; break;#endif#ifdef ENODEV case ENODEV: return G_FILE_ERROR_NODEV; break;#endif#ifdef EROFS case EROFS: return G_FILE_ERROR_ROFS; break;#endif#ifdef ETXTBSY case ETXTBSY: return G_FILE_ERROR_TXTBSY; break;#endif#ifdef EFAULT case EFAULT: return G_FILE_ERROR_FAULT; break;#endif#ifdef ELOOP case ELOOP: return G_FILE_ERROR_LOOP; break;#endif#ifdef ENOSPC case ENOSPC: return G_FILE_ERROR_NOSPC; break;#endif#ifdef ENOMEM case ENOMEM: return G_FILE_ERROR_NOMEM; break;#endif#ifdef EMFILE case EMFILE: return G_FILE_ERROR_MFILE; break;#endif#ifdef ENFILE case ENFILE: return G_FILE_ERROR_NFILE; break;#endif#ifdef EBADF case EBADF: return G_FILE_ERROR_BADF; break;#endif#ifdef EINVAL case EINVAL: return G_FILE_ERROR_INVAL; break;#endif#ifdef EPIPE case EPIPE: return G_FILE_ERROR_PIPE; break;#endif#ifdef EAGAIN case EAGAIN: return G_FILE_ERROR_AGAIN; break;#endif#ifdef EINTR case EINTR: return G_FILE_ERROR_INTR; break;#endif#ifdef EIO case EIO: return G_FILE_ERROR_IO; break;#endif#ifdef EPERM case EPERM: return G_FILE_ERROR_PERM; break;#endif default: return G_FILE_ERROR_FAILED; break; }}static gbooleanget_contents_stdio (const gchar *filename, FILE *f, gchar **contents, gsize *length, GError **error){ gchar buf[2048]; size_t bytes; char *str; size_t total_bytes; size_t total_allocated; g_assert (f != NULL);#define STARTING_ALLOC 64 total_bytes = 0; total_allocated = STARTING_ALLOC; str = g_malloc (STARTING_ALLOC); while (!feof (f)) { bytes = fread (buf, 1, 2048, f); while ((total_bytes + bytes + 1) > total_allocated) { total_allocated *= 2; str = g_try_realloc (str, total_allocated); if (str == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOMEM, _("Could not allocate %lu bytes to read file \"%s\""), (gulong) total_allocated, filename); goto error; } } if (ferror (f)) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Error reading file '%s': %s"), filename, g_strerror (errno)); goto error; } memcpy (str + total_bytes, buf, bytes); total_bytes += bytes; } fclose (f); str[total_bytes] = '\0'; if (length) *length = total_bytes; *contents = str; return TRUE; error: g_free (str); fclose (f); return FALSE; }#ifndef G_OS_WIN32static gbooleanget_contents_regfile (const gchar *filename, struct stat *stat_buf, gint fd, gchar **contents, gsize *length, GError **error){ gchar *buf; size_t bytes_read; size_t size; size_t alloc_size; size = stat_buf->st_size; alloc_size = size + 1; buf = g_try_malloc (alloc_size); if (buf == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOMEM, _("Could not allocate %lu bytes to read file \"%s\""), (gulong) alloc_size, filename); goto error; } bytes_read = 0; while (bytes_read < size) { gssize rc; rc = read (fd, buf + bytes_read, size - bytes_read); if (rc < 0) { if (errno != EINTR) { g_free (buf); g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to read from file '%s': %s"), filename, g_strerror (errno)); goto error; } } else if (rc == 0) break; else bytes_read += rc; } buf[bytes_read] = '\0'; if (length) *length = bytes_read; *contents = buf; close (fd); return TRUE; error: close (fd); return FALSE;}static gbooleanget_contents_posix (const gchar *filename, gchar **contents, gsize *length, GError **error){ struct stat stat_buf; gint fd; /* O_BINARY useful on Cygwin */ fd = open (filename, O_RDONLY|O_BINARY); if (fd < 0) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to open file '%s': %s"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -