Annotation of sbbs/src/xpdev/filewrap.c, revision 1.1

1.1     ! root        1: /* filewrap.c */
        !             2: 
        !             3: /* File-related system-call wrappers */
        !             4: 
        !             5: /* $Id: filewrap.c,v 1.33 2006/05/18 04:09:35 deuce Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This library is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU Lesser General Public License          *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
        !            18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: /* OS-specific */
        !            39: #if defined(__unix__)
        !            40: 
        !            41: #include <stdarg.h>            /* va_list */
        !            42: #include <string.h>     /* strlen() */
        !            43: #include <unistd.h>     /* getpid() */
        !            44: #include <fcntl.h>      /* fcntl() file/record locking */
        !            45: #include <sys/file.h>  /* L_SET for Solaris */
        !            46: #include <errno.h>
        !            47: #include <sys/param.h> /* BSD */
        !            48: 
        !            49: #endif
        !            50: 
        !            51: /* ANSI */
        !            52: #include <sys/types.h> /* _dev_t */
        !            53: #include <sys/stat.h>  /* struct stat */
        !            54: 
        !            55: #include "filewrap.h"  /* Verify prototypes */
        !            56: 
        !            57: /****************************************************************************/
        !            58: /* Returns the modification time of the file in 'fd'                                           */
        !            59: /****************************************************************************/
        !            60: time_t DLLCALL filetime(int fd)
        !            61: {
        !            62:        struct stat st;
        !            63: 
        !            64:        if(fstat(fd, &st)!=0)
        !            65:                return(-1);
        !            66: 
        !            67:        return(st.st_mtime);
        !            68: }
        !            69: 
        !            70: #if defined(__unix__) && !defined(__BORLANDC__)
        !            71: 
        !            72: /****************************************************************************/
        !            73: /* Returns the length of the file in 'fd'                                                                      */
        !            74: /****************************************************************************/
        !            75: long DLLCALL filelength(int fd)
        !            76: {
        !            77:        struct stat st;
        !            78: 
        !            79:        if(fstat(fd, &st)!=0)
        !            80:                return(-1L);
        !            81: 
        !            82:        return(st.st_size);
        !            83: }
        !            84: 
        !            85: /* Sets a lock on a portion of a file */
        !            86: int DLLCALL lock(int fd, long pos, long len)
        !            87: {
        !            88:        #if defined(F_SANERDLCKNO) || !defined(BSD)
        !            89:                struct flock alock;
        !            90: 
        !            91:        #ifndef F_SANEWRLCKNO
        !            92:                int     flags;
        !            93:                if((flags=fcntl(fd,F_GETFL))==-1)
        !            94:                        return -1;
        !            95:                if(flags==O_RDONLY)
        !            96:                        alock.l_type = F_RDLCK; /* set read lock to prevent writes */
        !            97:                else
        !            98:                        alock.l_type = F_WRLCK; /* set write lock to prevent all access */
        !            99:        #else
        !           100:                alock.l_type = F_SANEWRLCKNO;
        !           101:        #endif
        !           102:                alock.l_whence = L_SET;         /* SEEK_SET */
        !           103:                alock.l_start = pos;
        !           104:                alock.l_len = (int)len;
        !           105: 
        !           106:                if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL)
        !           107:                        return(-1);
        !           108:        #endif
        !           109: 
        !           110:        #if !defined(F_SANEWRLCKNO) && !defined(__QNX__) && !defined(__solaris__)
        !           111:                /* use flock (doesn't work over NFS) */
        !           112:                if(flock(fd,LOCK_EX|LOCK_NB)!=0 && errno != EOPNOTSUPP)
        !           113:                        return(-1);
        !           114:        #endif
        !           115: 
        !           116:                return(0);
        !           117: }
        !           118: 
        !           119: /* Removes a lock from a file record */
        !           120: int DLLCALL unlock(int fd, long pos, long len)
        !           121: {
        !           122: 
        !           123: #if defined(F_SANEUNLCK) || !defined(BSD)
        !           124:        struct flock alock;
        !           125: #ifdef F_SANEUNLCK
        !           126:        alock.l_type = F_SANEUNLCK;   /* remove the lock */
        !           127: #else
        !           128:        alock.l_type = F_UNLCK;   /* remove the lock */
        !           129: #endif
        !           130:        alock.l_whence = L_SET;
        !           131:        alock.l_start = pos;
        !           132:        alock.l_len = (int)len;
        !           133:        if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL)
        !           134:                return(-1);
        !           135: #endif
        !           136: 
        !           137: #if !defined(F_SANEUNLCK) && !defined(__QNX__) && !defined(__solaris__)
        !           138:        /* use flock (doesn't work over NFS) */
        !           139:        if(flock(fd,LOCK_UN|LOCK_NB)!=0 && errno != EOPNOTSUPP)
        !           140:                return(-1);
        !           141: #endif
        !           142: 
        !           143:        return(0);
        !           144: }
        !           145: 
        !           146: /* Opens a file in specified sharing (file-locking) mode */
        !           147: /*
        !           148:  * This is how it *SHOULD* work:
        !           149:  * Values of DOS 2-6.22 file sharing behavior: 
        !           150:  *          | Second and subsequent Opens 
        !           151:  * First    |Compat Deny   Deny   Deny   Deny 
        !           152:  * Open     |       All    Write  Read   None 
        !           153:  *          |R W RW R W RW R W RW R W RW R W RW
        !           154:  * - - - - -| - - - - - - - - - - - - - - - - -
        !           155:  * Compat R |Y Y Y  N N N  1 N N  N N N  1 N N
        !           156:  *        W |Y Y Y  N N N  N N N  N N N  N N N
        !           157:  *        RW|Y Y Y  N N N  N N N  N N N  N N N
        !           158:  * - - - - -|
        !           159:  * Deny   R |C C C  N N N  N N N  N N N  N N N
        !           160:  * All    W |C C C  N N N  N N N  N N N  N N N
        !           161:  *        RW|C C C  N N N  N N N  N N N  N N N
        !           162:  * - - - - -|
        !           163:  * Deny   R |2 C C  N N N  Y N N  N N N  Y N N
        !           164:  * Write  W |C C C  N N N  N N N  Y N N  Y N N
        !           165:  *        RW|C C C  N N N  N N N  N N N  Y N N
        !           166:  * - - - - -| 
        !           167:  * Deny   R |C C C  N N N  N Y N  N N N  N Y N
        !           168:  * Read   W |C C C  N N N  N N N  N Y N  N Y N
        !           169:  *        RW|C C C  N N N  N N N  N N N  N Y N
        !           170:  * - - - - -| 
        !           171:  * Deny   R |2 C C  N N N  Y Y Y  N N N  Y Y Y
        !           172:  * None   W |C C C  N N N  N N N  Y Y Y  Y Y Y
        !           173:  *        RW|C C C  N N N  N N N  N N N  Y Y Y
        !           174:  * 
        !           175:  * Legend:
        !           176:  * Y = open succeeds, 
        !           177:  * N = open fails with error code 05h. 
        !           178:  * C = open fails, INT 24 generated. 
        !           179:  * 1 = open succeeds if file read-only, else fails with error code. 
        !           180:  * 2 = open succeeds if file read-only, else fails with INT 24 
        !           181:  */
        !           182: #if !defined(__QNX__)
        !           183: int DLLCALL sopen(const char *fn, int sh_access, int share, ...)
        !           184: {
        !           185:        int fd;
        !           186:        int pmode=S_IREAD;
        !           187: #ifndef F_SANEWRLCKNO
        !           188:        int     flock_op=LOCK_NB;       /* non-blocking */
        !           189: #endif
        !           190: #if defined(F_SANEWRLCKNO) || !defined(BSD)
        !           191:        struct flock alock;
        !           192: #endif
        !           193:     va_list ap;
        !           194: 
        !           195:     if(sh_access&O_CREAT) {
        !           196:         va_start(ap,share);
        !           197:         pmode = va_arg(ap,unsigned int);
        !           198:         va_end(ap);
        !           199:     }
        !           200: 
        !           201:        if ((fd = open(fn, sh_access, pmode)) < 0)
        !           202:                return -1;
        !           203: 
        !           204:        if (share == SH_DENYNO || share == SH_COMPAT) /* no lock needed */
        !           205:                return fd;
        !           206: #if defined(F_SANEWRLCKNO) || !defined(BSD)
        !           207:        /* use fcntl (doesn't work correctly with threads) */
        !           208:        alock.l_type = share;
        !           209:        alock.l_whence = L_SET;
        !           210:        alock.l_start = 0;
        !           211:        alock.l_len = 0;       /* lock to EOF */
        !           212: 
        !           213:        if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL) { /* EINVAL means the file does not support locking */
        !           214:                close(fd);
        !           215:                return -1;
        !           216:        }
        !           217: #endif
        !           218: 
        !           219: #if !defined(F_SANEWRLCKNO) && !defined(__QNX__) && !defined(__solaris__)
        !           220:        /* use flock (doesn't work over NFS) */
        !           221:        if(share==SH_DENYRW)
        !           222:                flock_op|=LOCK_EX;
        !           223:        else   /* SH_DENYWR */
        !           224:                flock_op|=LOCK_SH;
        !           225:        if(flock(fd,flock_op)!=0 && errno != EOPNOTSUPP) { /* That object doesn't do locks */
        !           226:                if(errno==EWOULDBLOCK) 
        !           227:                        errno=EAGAIN;
        !           228:                close(fd);
        !           229:                return(-1);
        !           230:        }
        !           231: #endif
        !           232: 
        !           233:        return fd;
        !           234: }
        !           235: #endif /* !QNX */
        !           236: 
        !           237: #elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__)
        !           238: 
        !           239: #include <io.h>                                /* tell */
        !           240: #include <stdio.h>                     /* SEEK_SET */
        !           241: #include <sys/locking.h>       /* _locking */
        !           242: 
        !           243: /* Fix MinGW locking.h typo */
        !           244: #if defined LK_UNLOCK && !defined LK_UNLCK
        !           245:        #define LK_UNLCK LK_UNLOCK
        !           246: #endif
        !           247: 
        !           248: int DLLCALL lock(int file, long offset, long size) 
        !           249: {
        !           250:        int     i;
        !           251:        long    pos;
        !           252:    
        !           253:        pos=tell(file);
        !           254:        if(offset!=pos)
        !           255:                lseek(file, offset, SEEK_SET);
        !           256:        i=_locking(file,LK_NBLCK,size);
        !           257:        if(offset!=pos)
        !           258:                lseek(file, pos, SEEK_SET);
        !           259:        return(i);
        !           260: }
        !           261: 
        !           262: int DLLCALL unlock(int file, long offset, long size)
        !           263: {
        !           264:        int     i;
        !           265:        long    pos;
        !           266:    
        !           267:        pos=tell(file);
        !           268:        if(offset!=pos)
        !           269:                lseek(file, offset, SEEK_SET);
        !           270:        i=_locking(file,LK_UNLCK,size);
        !           271:        if(offset!=pos)
        !           272:                lseek(file, pos, SEEK_SET);
        !           273:        return(i);
        !           274: }
        !           275: 
        !           276: #endif /* !Unix && (MSVC || MinGW) */
        !           277: 
        !           278: #ifdef __unix__
        !           279: FILE *_fsopen(char *pszFilename, char *pszMode, int shmode)
        !           280: {
        !           281:        int file;
        !           282:        int Mode=0;
        !           283:        char *p;
        !           284:        
        !           285:        for(p=pszMode;*p;p++)  {
        !           286:                switch (*p)  {
        !           287:                        case 'r':
        !           288:                                Mode |= 1;
        !           289:                                break;
        !           290:                        case 'w':
        !           291:                                Mode |= 2;
        !           292:                                break;
        !           293:                        case 'a':
        !           294:                                Mode |= 4;
        !           295:                                break;
        !           296:                        case '+':
        !           297:                                Mode |= 8;
        !           298:                                break;
        !           299:                        case 'b':
        !           300:                        case 't':
        !           301:                                break;
        !           302:                        default:
        !           303:                                errno=EINVAL;
        !           304:                        return(NULL);
        !           305:                }
        !           306:        }
        !           307:        switch(Mode)  {
        !           308:                case 1:
        !           309:                        Mode=O_RDONLY;
        !           310:                        break;
        !           311:                case 2:
        !           312:                        Mode=O_WRONLY|O_CREAT|O_TRUNC;
        !           313:                        break;
        !           314:                case 4:
        !           315:                        Mode=O_APPEND|O_WRONLY|O_CREAT;
        !           316:                        break;
        !           317:                case 9:
        !           318:                        Mode=O_RDWR|O_CREAT;
        !           319:                        break;
        !           320:                case 10:
        !           321:                        Mode=O_RDWR|O_CREAT|O_TRUNC;
        !           322:                        break;
        !           323:                case 12:
        !           324:                        Mode=O_RDWR|O_APPEND|O_CREAT;
        !           325:                        break;
        !           326:                default:
        !           327:                        errno=EINVAL;
        !           328:                        return(NULL);
        !           329:        }
        !           330:        if(Mode&O_CREAT)
        !           331:                file=sopen(pszFilename,Mode,shmode,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        !           332:        else
        !           333:                file=sopen(pszFilename,Mode,shmode);
        !           334:        if(file==-1)
        !           335:                return(NULL);
        !           336:        return(fdopen(file,pszMode));
        !           337: }
        !           338: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.