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: