Annotation of sbbs/src/xpdev/filewrap.c, revision 1.1.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.