summaryrefslogtreecommitdiff
path: root/protocols/Sametime/src/glib/gmappedfile.c
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2014-03-22 13:34:19 +0000
committerGeorge Hazan <george.hazan@gmail.com>2014-03-22 13:34:19 +0000
commit79b554fe05162550656da3c4e459fb717dc4dadf (patch)
tree34b5856bb397b145e2a6e6b317742b73ff53ec9f /protocols/Sametime/src/glib/gmappedfile.c
parent739fd4137010dc56881cf8328770b3175a2f2696 (diff)
glib inlined into SameTime
git-svn-id: http://svn.miranda-ng.org/main/trunk@8685 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Sametime/src/glib/gmappedfile.c')
-rw-r--r--protocols/Sametime/src/glib/gmappedfile.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/protocols/Sametime/src/glib/gmappedfile.c b/protocols/Sametime/src/glib/gmappedfile.c
new file mode 100644
index 0000000000..540ae5d91f
--- /dev/null
+++ b/protocols/Sametime/src/glib/gmappedfile.c
@@ -0,0 +1,344 @@
+/* GLIB - Library of useful routines for C programming
+ * gmappedfile.c: Simplified wrapper around the mmap() function.
+ *
+ * Copyright 2005 Matthias Clasen
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+#include "glibconfig.h"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#include <io.h>
+
+#define fstat(a,b) _fstati64(a,b)
+#define stat _stati64
+
+#endif
+
+#include "gconvert.h"
+#include "gerror.h"
+#include "gfileutils.h"
+#include "gmappedfile.h"
+#include "gmem.h"
+#include "gmessages.h"
+#include "gstdio.h"
+#include "gstrfuncs.h"
+#include "gatomic.h"
+#include "gbuffer.h"
+
+#include "glibintl.h"
+
+
+#ifndef _O_BINARY
+#define _O_BINARY 0
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+struct _GMappedFile
+{
+ gchar *contents;
+ gsize length;
+ gpointer free_func;
+ int ref_count;
+#ifdef G_OS_WIN32
+ HANDLE mapping;
+#endif
+};
+
+/* Make sure the layout of GMappedFile is the same as GBuffer's */
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GMappedFile, contents) ==
+ G_STRUCT_OFFSET (GBuffer, data));
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GMappedFile, length) ==
+ G_STRUCT_OFFSET (GBuffer, size));
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GMappedFile, ref_count) ==
+ G_STRUCT_OFFSET (GBuffer, ref_count));
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GMappedFile, free_func) ==
+ G_STRUCT_OFFSET (GBuffer, free_func));
+
+static void
+g_mapped_file_destroy (GMappedFile *file)
+{
+ if (file->length)
+ {
+#ifdef HAVE_MMAP
+ munmap (file->contents, file->length);
+#endif
+#ifdef G_OS_WIN32
+ UnmapViewOfFile (file->contents);
+ CloseHandle (file->mapping);
+#endif
+ }
+
+ g_slice_free (GMappedFile, file);
+}
+
+/**
+ * g_mapped_file_new:
+ * @filename: The path of the file to load, in the GLib filename encoding
+ * @writable: whether the mapping should be writable
+ * @error: return location for a #GError, or %NULL
+ *
+ * Maps a file into memory. On UNIX, this is using the mmap() function.
+ *
+ * If @writable is %TRUE, the mapped buffer may be modified, otherwise
+ * it is an error to modify the mapped buffer. Modifications to the buffer
+ * are not visible to other processes mapping the same file, and are not
+ * written back to the file.
+ *
+ * Note that modifications of the underlying file might affect the contents
+ * of the #GMappedFile. Therefore, mapping should only be used if the file
+ * will not be modified, or if all modifications of the file are done
+ * atomically (e.g. using g_file_set_contents()).
+ *
+ * Return value: a newly allocated #GMappedFile which must be unref'd
+ * with g_mapped_file_unref(), or %NULL if the mapping failed.
+ *
+ * Since: 2.8
+ */
+GMappedFile *
+g_mapped_file_new (const gchar *filename,
+ gboolean writable,
+ GError **error)
+{
+ GMappedFile *file;
+ int fd;
+ struct stat st;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (!error || *error == NULL, NULL);
+
+ fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
+ if (fd == -1)
+ {
+ int save_errno = errno;
+ gchar *display_filename = g_filename_display_name (filename);
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("Failed to open file '%s': open() failed: %s"),
+ display_filename,
+ g_strerror (save_errno));
+ g_free (display_filename);
+ return NULL;
+ }
+
+ file = g_slice_new0 (GMappedFile);
+ file->ref_count = 1;
+ file->free_func = g_mapped_file_destroy;
+
+ if (fstat (fd, &st) == -1)
+ {
+ int save_errno = errno;
+ gchar *display_filename = g_filename_display_name (filename);
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("Failed to get attributes of file '%s': fstat() failed: %s"),
+ display_filename,
+ g_strerror (save_errno));
+ g_free (display_filename);
+ goto out;
+ }
+
+ if (st.st_size == 0)
+ {
+ file->length = 0;
+ file->contents = NULL;
+ _close (fd);
+ return file;
+ }
+
+ file->contents = MAP_FAILED;
+
+#ifdef HAVE_MMAP
+ if (st.st_size > G_MAXSIZE)
+ {
+ errno = EINVAL;
+ }
+ else
+ {
+ file->length = (gsize) st.st_size;
+ file->contents = (gchar *) mmap (NULL, file->length,
+ writable ? PROT_READ|PROT_WRITE : PROT_READ,
+ MAP_PRIVATE, fd, 0);
+ }
+#endif
+#ifdef G_OS_WIN32
+ file->length = st.st_size;
+ file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL,
+ writable ? PAGE_WRITECOPY : PAGE_READONLY,
+ 0, 0,
+ NULL);
+ if (file->mapping != NULL)
+ {
+ file->contents = MapViewOfFile (file->mapping,
+ writable ? FILE_MAP_COPY : FILE_MAP_READ,
+ 0, 0,
+ 0);
+ if (file->contents == NULL)
+ {
+ file->contents = MAP_FAILED;
+ CloseHandle (file->mapping);
+ file->mapping = NULL;
+ }
+ }
+#endif
+
+
+ if (file->contents == MAP_FAILED)
+ {
+ int save_errno = errno;
+ gchar *display_filename = g_filename_display_name (filename);
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("Failed to map file '%s': mmap() failed: %s"),
+ display_filename,
+ g_strerror (save_errno));
+ g_free (display_filename);
+ goto out;
+ }
+
+ _close (fd);
+ return file;
+
+ out:
+ _close (fd);
+ g_slice_free (GMappedFile, file);
+
+ return NULL;
+}
+
+/**
+ * g_mapped_file_get_length:
+ * @file: a #GMappedFile
+ *
+ * Returns the length of the contents of a #GMappedFile.
+ *
+ * Returns: the length of the contents of @file.
+ *
+ * Since: 2.8
+ */
+gsize
+g_mapped_file_get_length (GMappedFile *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+
+ return file->length;
+}
+
+/**
+ * g_mapped_file_get_contents:
+ * @file: a #GMappedFile
+ *
+ * Returns the contents of a #GMappedFile.
+ *
+ * Note that the contents may not be zero-terminated,
+ * even if the #GMappedFile is backed by a text file.
+ *
+ * If the file is empty then %NULL is returned.
+ *
+ * Returns: the contents of @file, or %NULL.
+ *
+ * Since: 2.8
+ */
+gchar *
+g_mapped_file_get_contents (GMappedFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ return file->contents;
+}
+
+/**
+ * g_mapped_file_free:
+ * @file: a #GMappedFile
+ *
+ * This call existed before #GMappedFile had refcounting and is currently
+ * exactly the same as g_mapped_file_unref().
+ *
+ * Since: 2.8
+ * Deprecated:2.22: Use g_mapped_file_unref() instead.
+ */
+void
+g_mapped_file_free (GMappedFile *file)
+{
+ g_mapped_file_unref (file);
+}
+
+/**
+ * g_mapped_file_ref:
+ * @file: a #GMappedFile
+ *
+ * Increments the reference count of @file by one. It is safe to call
+ * this function from any thread.
+ *
+ * Return value: the passed in #GMappedFile.
+ *
+ * Since: 2.22
+ **/
+GMappedFile *
+g_mapped_file_ref (GMappedFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (file->ref_count > 0, file);
+
+ g_atomic_int_inc (&file->ref_count);
+
+ return file;
+}
+
+/**
+ * g_mapped_file_unref:
+ * @file: a #GMappedFile
+ *
+ * Decrements the reference count of @file by one. If the reference count
+ * drops to 0, unmaps the buffer of @file and frees it.
+ *
+ * It is safe to call this function from any thread.
+ *
+ * Since 2.22
+ **/
+void
+g_mapped_file_unref (GMappedFile *file)
+{
+ g_return_if_fail (file != NULL);
+ g_return_if_fail (file->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&file->ref_count))
+ g_mapped_file_destroy (file);
+}