📄 gfileutils.c
字号:
filename, g_strerror (errno)); return FALSE; } /* I don't think this will ever fail, aside from ENOMEM, but. */ if (fstat (fd, &stat_buf) < 0) { close (fd); g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to get attributes of file '%s': fstat() failed: %s"), filename, g_strerror (errno)); return FALSE; } if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode)) { return get_contents_regfile (filename, &stat_buf, fd, contents, length, error); } else { FILE *f; f = fdopen (fd, "r"); if (f == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to open file '%s': fdopen() failed: %s"), filename, g_strerror (errno)); return FALSE; } return get_contents_stdio (filename, f, contents, length, error); }}#else /* G_OS_WIN32 */static gbooleanget_contents_win32 (const gchar *filename, gchar **contents, gsize *length, GError **error){ FILE *f; /* I guess you want binary mode; maybe you want text sometimes? */ f = fopen (filename, "rb"); if (f == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to open file '%s': %s"), filename, g_strerror (errno)); return FALSE; } return get_contents_stdio (filename, f, contents, length, error);}#endif/** * g_file_get_contents: * @filename: a file to read contents from * @contents: location to store an allocated string * @length: location to store length in bytes of the contents * @error: return location for a #GError * * Reads an entire file into allocated memory, with good error * checking. If @error is set, %FALSE is returned, and @contents is set * to %NULL. If %TRUE is returned, @error will not be set, and @contents * will be set to the file contents. The string stored in @contents * will be nul-terminated, so for text files you can pass %NULL for the * @length argument. The error domain is #G_FILE_ERROR. Possible * error codes are those in the #GFileError enumeration. * * Return value: %TRUE on success, %FALSE if error is set **/gbooleang_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **error){ g_return_val_if_fail (filename != NULL, FALSE); g_return_val_if_fail (contents != NULL, FALSE); *contents = NULL; if (length) *length = 0;#ifdef G_OS_WIN32 return get_contents_win32 (filename, contents, length, error);#else return get_contents_posix (filename, contents, length, error);#endif}/* * mkstemp() implementation is from the GNU C library. * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. *//** * g_mkstemp: * @tmpl: template filename * * Opens a temporary file. See the <function>mkstemp()</function> documentation * on most UNIX-like systems. This is a portability wrapper, which simply calls * <function>mkstemp()</function> on systems that have it, and implements * it in GLib otherwise. * * The parameter is a string that should match the rules for * <function>mkstemp()</function>, i.e. end in "XXXXXX". The X string will * be modified to form the name of a file that didn't exist. * * Return value: A file handle (as from <function>open()</function>) to the file * opened for reading and writing. The file is opened in binary mode * on platforms where there is a difference. The file handle should be * closed with <function>close()</function>. In case of errors, -1 is returned. */intg_mkstemp (char *tmpl){#ifdef HAVE_MKSTEMP return mkstemp (tmpl);#else int len; char *XXXXXX; int count, fd; static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const int NLETTERS = sizeof (letters) - 1; glong value; GTimeVal tv; static int counter = 0; len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) return -1; /* This is where the Xs start. */ XXXXXX = &tmpl[len - 6]; /* Get some more or less random data. */ g_get_current_time (&tv); value = (tv.tv_usec ^ tv.tv_sec) + counter++; for (count = 0; count < 100; value += 7777, ++count) { glong v = value; /* Fill in the random bits. */ XXXXXX[0] = letters[v % NLETTERS]; v /= NLETTERS; XXXXXX[1] = letters[v % NLETTERS]; v /= NLETTERS; XXXXXX[2] = letters[v % NLETTERS]; v /= NLETTERS; XXXXXX[3] = letters[v % NLETTERS]; v /= NLETTERS; XXXXXX[4] = letters[v % NLETTERS]; v /= NLETTERS; XXXXXX[5] = letters[v % NLETTERS]; fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); if (fd >= 0) return fd; else if (errno != EEXIST) /* Any other error will apply also to other names we might * try, and there are 2^32 or so of them, so give up now. */ return -1; } /* We got out of the loop because we ran out of combinations to try. */ return -1;#endif}/** * g_file_open_tmp: * @tmpl: Template for file name, as in g_mkstemp(), basename only * @name_used: location to store actual name used * @error: return location for a #GError * * Opens a file for writing in the preferred directory for temporary * files (as returned by g_get_tmp_dir()). * * @tmpl should be a string ending with six 'X' characters, as the * parameter to g_mkstemp() (or <function>mkstemp()</function>). * However, unlike these functions, the template should only be a * basename, no directory components are allowed. If template is %NULL, * a default template is used. * * Note that in contrast to g_mkstemp() (and <function>mkstemp()</function>) * @tmpl is not modified, and might thus be a read-only literal string. * * The actual name used is returned in @name_used if non-%NULL. This * string should be freed with g_free() when not needed any longer. * * Return value: A file handle (as from <function>open()</function>) to * the file opened for reading and writing. The file is opened in binary * mode on platforms where there is a difference. The file handle should be * closed with <function>close()</function>. In case of errors, -1 is returned * and @error will be set. **/intg_file_open_tmp (const char *tmpl, char **name_used, GError **error){ int retval; const char *tmpdir; char *sep; char *fulltemplate; if (tmpl == NULL) tmpl = ".XXXXXX"; if (strchr (tmpl, G_DIR_SEPARATOR)#ifdef G_OS_WIN32 || strchr (tmpl, '/')#endif ) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Template '%s' invalid, should not contain a '%s'"), tmpl, G_DIR_SEPARATOR_S); return -1; } if (strlen (tmpl) < 6 || strcmp (tmpl + strlen (tmpl) - 6, "XXXXXX") != 0) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Template '%s' doesn't end with XXXXXX"), tmpl); return -1; } tmpdir = g_get_tmp_dir (); if (tmpdir [strlen (tmpdir) - 1] == G_DIR_SEPARATOR) sep = ""; else sep = G_DIR_SEPARATOR_S; fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL); retval = g_mkstemp (fulltemplate); if (retval == -1) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to create file '%s': %s"), fulltemplate, g_strerror (errno)); g_free (fulltemplate); return -1; } if (name_used) *name_used = fulltemplate; else g_free (fulltemplate); return retval;}static gchar *g_build_pathv (const gchar *separator, const gchar *first_element, va_list args){ GString *result; gint separator_len = strlen (separator); gboolean is_first = TRUE; gboolean have_leading = FALSE; const gchar *single_element = NULL; const gchar *next_element; const gchar *last_trailing = NULL; result = g_string_new (NULL); next_element = first_element; while (TRUE) { const gchar *element; const gchar *start; const gchar *end; if (next_element) { element = next_element; next_element = va_arg (args, gchar *); } else break; /* Ignore empty elements */ if (!*element) continue; start = element; if (separator_len) { while (start && strncmp (start, separator, separator_len) == 0) start += separator_len; } end = start + strlen (start); if (separator_len) { while (end >= start + separator_len && strncmp (end - separator_len, separator, separator_len) == 0) end -= separator_len; last_trailing = end; while (last_trailing >= element + separator_len && strncmp (last_trailing - separator_len, separator, separator_len) == 0) last_trailing -= separator_len; if (!have_leading) { /* If the leading and trailing separator strings are in the * same element and overlap, the result is exactly that element */ if (last_trailing <= start) single_element = element; g_string_append_len (result, element, start - element); have_leading = TRUE; } else single_element = NULL; } if (end == start) continue; if (!is_first) g_string_append (result, separator); g_string_append_len (result, start, end - start); is_first = FALSE; } if (single_element) { g_string_free (result, TRUE); return g_strdup (single_element); } else { if (last_trailing) g_string_append (result, last_trailing); return g_string_free (result, FALSE); }}/** * g_build_path: * @separator: a string used to separator the elements of the path. * @first_element: the first element in the path * @Varargs: remaining elements in path * * Creates a path from a series of elements using @separator as the * separator between elements. At the boundary between two elements, * any trailing occurrences of separator in the first element, or * leading occurrences of separator in the second element are removed * and exactly one copy of the separator is inserted. * * Empty elements are ignored. * * The number of leading copies of the separator on the result is * the same as the number of leading copies of the separator on * the first non-empty element. * * The number of trailing copies of the separator on the result is * the same as the number of trailing copies of the separator on * the last non-empty element. (Determination of the number of * trailing copies is done without stripping leading copies, so * if the separator is <literal>ABA</literal>, <literal>ABABA</literal> * has 1 trailing copy.) * * However, if there is only a single non-empty element, and there * are no characters in that element not part of the leading or * trailing separators, then the result is exactly the original value * of that element. * * Other than for determination of the number of leading and trailing * copies of the separator, elements consisting only of copies * of the separator are ignored. * * Return value: a newly-allocated string that must be freed with g_free(). **/gchar *g_build_path (const gchar *separator, const gchar *first_element, ...){ gchar *str; va_list args; g_return_val_if_fail (separator != NULL, NULL); va_start (args, first_element); str = g_build_pathv (separator, first_element, args); va_end (args); return str;}/** * g_build_filename: * @first_element: the first element in the path * @Varargs: remaining elements in path * * Creates a filename from a series of elements using the correct * separator for filenames. This function behaves identically * to <literal>g_build_path (G_DIR_SEPARATOR_S, first_element, ....)</literal>. * * No attempt is made to force the resulting filename to be an absolute * path. If the first element is a relative path, the result will * be a relative path. * * Return value: a newly-allocated string that must be freed with g_free(). **/gchar *g_build_filename (const gchar *first_element, ...){ gchar *str; va_list args; va_start (args, first_element); str = g_build_pathv (G_DIR_SEPARATOR_S, first_element, args); va_end (args); return str;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -