glib/libglib/src/gmappedfile.c
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/libglib/src/gmappedfile.c	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,282 @@
+/* GLIB - Library of useful routines for C programming
+ * gmappedfile.c: Simplified wrapper around the mmap() function.
+ *
+ * Copyright 2005 Matthias Clasen
+ * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
+ *
+ * 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>
+#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 "glibintl.h"
+
+#include "galias.h"
+
+#ifdef __SYMBIAN32__
+#include "glib.h"
+#endif /* __SYMBIAN32__ */
+
+#ifndef _O_BINARY
+#define _O_BINARY 0
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+struct _GMappedFile 
+{
+  gsize  length;
+  gchar *contents;
+#ifdef G_OS_WIN32
+  HANDLE mapping;
+#endif
+};
+
+/**
+ * g_mapped_file_new:
+ * @filename: The path of the file to load, in the GLib filename encoding
+ * @writable: wether 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 freed
+ *    with g_mapped_file_free(), or %NULL if the mapping failed. 
+ *
+ * Since: 2.8
+ */
+EXPORT_C 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_new0 (GMappedFile, 1);
+
+  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 = "";
+      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_free (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
+ */
+EXPORT_C 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.
+ *
+ * Returns: the contents of @file.
+ *
+ * Since: 2.8
+ */
+EXPORT_C 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
+ *
+ * Unmaps the buffer of @file and frees it. 
+ *
+ * Since: 2.8
+ */
+EXPORT_C void
+g_mapped_file_free (GMappedFile *file)
+{
+  g_return_if_fail (file != NULL);
+
+  if (file->length)
+  {
+#ifdef HAVE_MMAP
+    munmap (file->contents, file->length);
+#endif
+#ifdef G_OS_WIN32
+    UnmapViewOfFile (file->contents);
+    CloseHandle (file->mapping);
+#endif
+  }
+
+  g_free (file);
+}
+
+
+#define __G_MAPPED_FILE_C__
+#include "galiasdef.c"