Annotation of win32/gnome/gmime-x.x.x/gmime-stream-mmap.c, revision 1.1
1.1 ! paf 1: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
! 2: /*
! 3: * Authors: Jeffrey Stedfast <fejj@ximian.com>
! 4: *
! 5: * Copyright 2001 Ximian, Inc. (www.ximian.com)
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify
! 8: * it under the terms of the GNU General Public License as published by
! 9: * the Free Software Foundation; either version 2 of the License, or
! 10: * (at your option) any later version.
! 11: *
! 12: * This program is distributed in the hope that it will be useful,
! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 15: * GNU General Public License for more details.
! 16: *
! 17: * You should have received a copy of the GNU General Public License
! 18: * along with this program; if not, write to the Free Software
! 19: * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
! 20: *
! 21: */
! 22:
! 23:
! 24: #ifdef HAVE_CONFIG_H
! 25: #include <config.h>
! 26: #endif
! 27:
! 28: #include <sys/types.h>
! 29: #include <sys/stat.h>
! 30: #include <string.h>
! 31: #ifdef HAVE_SYS_MMAN_H
! 32: #include <sys/mman.h>
! 33: #endif
! 34: #ifdef HAVE_UNISTD_H
! 35: #include <unistd.h>
! 36: #endif
! 37: #include <fcntl.h>
! 38: #include <errno.h>
! 39:
! 40: #include "gmime-stream-mmap.h"
! 41:
! 42:
! 43: static void stream_destroy (GMimeStream *stream);
! 44: static ssize_t stream_read (GMimeStream *stream, char *buf, size_t len);
! 45: static ssize_t stream_write (GMimeStream *stream, char *buf, size_t len);
! 46: static int stream_flush (GMimeStream *stream);
! 47: static int stream_close (GMimeStream *stream);
! 48: static gboolean stream_eos (GMimeStream *stream);
! 49: static int stream_reset (GMimeStream *stream);
! 50: static off_t stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence);
! 51: static off_t stream_tell (GMimeStream *stream);
! 52: static ssize_t stream_length (GMimeStream *stream);
! 53: static GMimeStream *stream_substream (GMimeStream *stream, off_t start, off_t end);
! 54:
! 55: static GMimeStream stream_template = {
! 56: NULL, 0,
! 57: 1, 0, 0, 0, stream_destroy,
! 58: stream_read, stream_write,
! 59: stream_flush, stream_close,
! 60: stream_eos, stream_reset,
! 61: stream_seek, stream_tell,
! 62: stream_length, stream_substream,
! 63: };
! 64:
! 65:
! 66: static void
! 67: stream_destroy (GMimeStream *stream)
! 68: {
! 69: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 70:
! 71: if (mstream->owner) {
! 72: #ifdef HAVE_MUNMAP
! 73: if (mstream->map)
! 74: munmap (mstream->map, mstream->maplen);
! 75: #endif
! 76:
! 77: if (mstream->fd != -1)
! 78: close (mstream->fd);
! 79: }
! 80:
! 81: g_free (mstream);
! 82: }
! 83:
! 84: static ssize_t
! 85: stream_read (GMimeStream *stream, char *buf, size_t len)
! 86: {
! 87: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 88: register char *mapptr;
! 89: ssize_t nread;
! 90:
! 91: if (stream->bound_end != -1 && stream->position >= stream->bound_end)
! 92: return -1;
! 93:
! 94: /* make sure we are at the right position */
! 95: mapptr = mstream->map + stream->position;
! 96:
! 97: if (stream->bound_end == -1)
! 98: nread = MIN ((mstream->map + mstream->maplen) - mapptr, len);
! 99: else
! 100: nread = MIN (stream->bound_end - stream->position, len);
! 101:
! 102: if (nread > 0) {
! 103: memcpy (buf, mapptr, nread);
! 104: stream->position += nread;
! 105: } else
! 106: mstream->eos = TRUE;
! 107:
! 108: return nread;
! 109: }
! 110:
! 111: static ssize_t
! 112: stream_write (GMimeStream *stream, char *buf, size_t len)
! 113: {
! 114: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 115: register char *mapptr;
! 116: ssize_t nwritten;
! 117:
! 118: if (stream->bound_end != -1 && stream->position >= stream->bound_end)
! 119: return -1;
! 120:
! 121: /* make sure we are at the right position */
! 122: mapptr = mstream->map + stream->position;
! 123:
! 124: if (stream->bound_end == -1)
! 125: nwritten = MIN ((mstream->map + mstream->maplen) - mapptr, len);
! 126: else
! 127: nwritten = MIN (stream->bound_end - stream->position, len);
! 128:
! 129: if (nwritten > 0) {
! 130: memcpy (mapptr, buf, nwritten);
! 131: stream->position += nwritten;
! 132: }
! 133:
! 134: return nwritten;
! 135: }
! 136:
! 137: static int
! 138: stream_flush (GMimeStream *stream)
! 139: {
! 140: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 141:
! 142: g_return_val_if_fail (mstream->fd != -1, -1);
! 143:
! 144: #ifdef HAVE_MSYNC
! 145: return msync (mstream->map, mstream->maplen, MS_SYNC /* | MS_INVALIDATE */);
! 146: #else
! 147: return 0;
! 148: #endif
! 149: }
! 150:
! 151: static int
! 152: stream_close (GMimeStream *stream)
! 153: {
! 154: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 155: int ret = 0;
! 156:
! 157: if (mstream->owner && mstream->map) {
! 158: #ifdef HAVE_MUNMAP
! 159: munmap (mstream->map, mstream->maplen);
! 160: mstream->map = NULL;
! 161: #endif
! 162: }
! 163:
! 164: if (mstream->owner && mstream->fd != -1) {
! 165: ret = close (mstream->fd);
! 166: if (ret != -1)
! 167: mstream->fd = -1;
! 168: }
! 169:
! 170: return ret;
! 171: }
! 172:
! 173: static gboolean
! 174: stream_eos (GMimeStream *stream)
! 175: {
! 176: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 177:
! 178: g_return_val_if_fail (mstream->fd != -1, TRUE);
! 179:
! 180: return mstream->eos;
! 181: }
! 182:
! 183: static int
! 184: stream_reset (GMimeStream *stream)
! 185: {
! 186: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 187:
! 188: g_return_val_if_fail (mstream->fd != -1, -1);
! 189:
! 190: stream->position = stream->bound_start;
! 191: mstream->eos = FALSE;
! 192:
! 193: return 0;
! 194: }
! 195:
! 196: static off_t
! 197: stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
! 198: {
! 199: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 200: off_t real = stream->position;
! 201:
! 202: g_return_val_if_fail (mstream->fd != -1, -1);
! 203:
! 204: switch (whence) {
! 205: case GMIME_STREAM_SEEK_SET:
! 206: real = offset;
! 207: break;
! 208: case GMIME_STREAM_SEEK_CUR:
! 209: real = stream->position + offset;
! 210: break;
! 211: case GMIME_STREAM_SEEK_END:
! 212: if (stream->bound_end == -1) {
! 213: real = offset <= 0 ? stream->bound_start + mstream->maplen + offset: -1;
! 214: if (real != -1) {
! 215: if (real < stream->bound_start)
! 216: real = stream->bound_start;
! 217: stream->position = real;
! 218: }
! 219:
! 220: return real;
! 221: }
! 222: real = stream->bound_end + offset;
! 223: break;
! 224: }
! 225:
! 226: if (stream->bound_end != -1)
! 227: real = MIN (real, stream->bound_end);
! 228: real = MAX (real, stream->bound_start);
! 229:
! 230: if (real != stream->position && mstream->eos)
! 231: mstream->eos = FALSE;
! 232:
! 233: stream->position = real;
! 234:
! 235: return real;
! 236: }
! 237:
! 238: static off_t
! 239: stream_tell (GMimeStream *stream)
! 240: {
! 241: return stream->position;
! 242: }
! 243:
! 244: static ssize_t
! 245: stream_length (GMimeStream *stream)
! 246: {
! 247: GMimeStreamMmap *mstream = (GMimeStreamMmap *) stream;
! 248:
! 249: if (stream->bound_start != -1 && stream->bound_end != -1)
! 250: return stream->bound_end - stream->bound_start;
! 251:
! 252: return mstream->maplen;
! 253: }
! 254:
! 255: static GMimeStream *
! 256: stream_substream (GMimeStream *stream, off_t start, off_t end)
! 257: {
! 258: /* FIXME: maybe we should return a GMimeStreamFs? */
! 259: GMimeStreamMmap *mstream;
! 260:
! 261: mstream = g_new (GMimeStreamMmap, 1);
! 262: mstream->owner = FALSE;
! 263: mstream->fd = GMIME_STREAM_MMAP (stream)->fd;
! 264:
! 265: mstream->map = GMIME_STREAM_MMAP (stream)->map;
! 266: mstream->maplen = GMIME_STREAM_MMAP (stream)->maplen;
! 267:
! 268: g_mime_stream_construct (GMIME_STREAM (mstream), &stream_template, GMIME_STREAM_MMAP_TYPE, start, end);
! 269:
! 270: return GMIME_STREAM (mstream);
! 271: }
! 272:
! 273:
! 274: /**
! 275: * g_mime_stream_mmap_new:
! 276: * @fd: file descriptor
! 277: * @prot: protection flags
! 278: * @flags: map flags
! 279: *
! 280: * Creates a new GMimeStreamMmap object around @fd.
! 281: *
! 282: * Returns a stream using @fd.
! 283: **/
! 284: GMimeStream *
! 285: g_mime_stream_mmap_new (int fd, int prot, int flags)
! 286: {
! 287: #ifdef HAVE_MMAP
! 288: GMimeStreamMmap *mstream;
! 289: struct stat st;
! 290: off_t start;
! 291: char *map;
! 292:
! 293: start = lseek (fd, 0, SEEK_CUR);
! 294: if (start == -1)
! 295: return NULL;
! 296:
! 297: if (fstat (fd, &st) == -1)
! 298: return NULL;
! 299:
! 300: map = mmap (NULL, st.st_size + getpagesize (), prot, flags, fd, 0);
! 301: if (map == MAP_FAILED)
! 302: return NULL;
! 303:
! 304: mstream = g_new (GMimeStreamMmap, 1);
! 305: mstream->owner = TRUE;
! 306: mstream->eos = FALSE;
! 307: mstream->fd = fd;
! 308: mstream->map = map;
! 309: mstream->maplen = st.st_size;
! 310:
! 311: g_mime_stream_construct (GMIME_STREAM (mstream), &stream_template, GMIME_STREAM_MMAP_TYPE, start, -1);
! 312:
! 313: return GMIME_STREAM (mstream);
! 314: #else
! 315: return NULL;
! 316: #endif /* HAVE_MMAP */
! 317: }
! 318:
! 319:
! 320: /**
! 321: * g_mime_stream_mmap_new_with_bounds:
! 322: * @fd: file descriptor
! 323: * @prot: protection flags
! 324: * @flags: map flags
! 325: * @start: start boundary
! 326: * @end: end boundary
! 327: *
! 328: * Creates a new GMimeStreamMmap object around @fd with bounds @start
! 329: * and @end.
! 330: *
! 331: * Returns a stream using @fd with bounds @start and @end.
! 332: **/
! 333: GMimeStream *
! 334: g_mime_stream_mmap_new_with_bounds (int fd, int prot, int flags, off_t start, off_t end)
! 335: {
! 336: #ifdef HAVE_MMAP
! 337: GMimeStreamMmap *mstream;
! 338: struct stat st;
! 339: char *map;
! 340:
! 341: if (end == -1) {
! 342: if (fstat (fd, &st) == -1)
! 343: return NULL;
! 344: } else
! 345: st.st_size = end /* - start */;
! 346:
! 347: map = mmap (NULL, st.st_size + getpagesize (), prot, flags, fd, 0);
! 348: if (map == MAP_FAILED)
! 349: return NULL;
! 350:
! 351: mstream = g_new (GMimeStreamMmap, 1);
! 352: mstream->owner = TRUE;
! 353: mstream->eos = FALSE;
! 354: mstream->fd = fd;
! 355: mstream->map = map;
! 356: mstream->maplen = st.st_size;
! 357:
! 358: g_mime_stream_construct (GMIME_STREAM (mstream), &stream_template, GMIME_STREAM_MMAP_TYPE, start, end);
! 359:
! 360: return GMIME_STREAM (mstream);
! 361: #else
! 362: return NULL;
! 363: #endif /* HAVE_MMAP */
! 364: }
E-mail: