|
|
1.1 ! root 1: /* filewrap.c */ ! 2: ! 3: /* File-related system-call wrappers */ ! 4: ! 5: /* $Id: filewrap.c,v 1.29 2004/07/20 23:26:58 rswindell 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: ! 96: if(flags==O_RDONLY) ! 97: alock.l_type = F_RDLCK; /* set read lock to prevent writes */ ! 98: else ! 99: alock.l_type = F_WRLCK; /* set write lock to prevent all access */ ! 100: #else ! 101: alock.l_type = F_SANEWRLCKNO; ! 102: #endif ! 103: alock.l_whence = L_SET; /* SEEK_SET */ ! 104: alock.l_start = pos; ! 105: alock.l_len = (int)len; ! 106: ! 107: if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL) ! 108: return(-1); ! 109: #endif ! 110: ! 111: #if !defined(F_SANEWRLCKNO) && !defined(__QNX__) && !defined(__solaris__) ! 112: /* use flock (doesn't work over NFS) */ ! 113: if(flock(fd,LOCK_EX|LOCK_NB)!=0 && errno != EOPNOTSUPP) ! 114: return(-1); ! 115: #endif ! 116: ! 117: return(0); ! 118: } ! 119: ! 120: /* Removes a lock from a file record */ ! 121: int DLLCALL unlock(int fd, long pos, long len) ! 122: { ! 123: ! 124: #if defined(F_SANEUNLCK) || !defined(BSD) ! 125: struct flock alock; ! 126: #ifdef F_SANEUNLCK ! 127: alock.l_type = F_SANEUNLCK; /* remove the lock */ ! 128: #else ! 129: alock.l_type = F_UNLCK; /* remove the lock */ ! 130: #endif ! 131: alock.l_whence = L_SET; ! 132: alock.l_start = pos; ! 133: alock.l_len = (int)len; ! 134: if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL) ! 135: return(-1); ! 136: #endif ! 137: ! 138: #if !defined(F_SANEUNLCK) && !defined(__QNX__) && !defined(__solaris__) ! 139: /* use flock (doesn't work over NFS) */ ! 140: if(flock(fd,LOCK_UN|LOCK_NB)!=0 && errno != EOPNOTSUPP) ! 141: return(-1); ! 142: #endif ! 143: ! 144: return(0); ! 145: } ! 146: ! 147: /* Opens a file in specified sharing (file-locking) mode */ ! 148: #if !defined(__QNX__) ! 149: int DLLCALL sopen(const char *fn, int access, int share, ...) ! 150: { ! 151: int fd; ! 152: int pmode=S_IREAD; ! 153: #ifndef F_SANEWRLCKNO ! 154: int flock_op=LOCK_NB; /* non-blocking */ ! 155: #endif ! 156: #if defined(F_SANEWRLCKNO) || !defined(BSD) ! 157: struct flock alock; ! 158: #endif ! 159: va_list ap; ! 160: ! 161: if(access&O_CREAT) { ! 162: va_start(ap,share); ! 163: pmode = va_arg(ap,unsigned int); ! 164: va_end(ap); ! 165: } ! 166: ! 167: if ((fd = open(fn, access, pmode)) < 0) ! 168: return -1; ! 169: ! 170: if (share == SH_DENYNO) /* no lock needed */ ! 171: return fd; ! 172: #if defined(F_SANEWRLCKNO) || !defined(BSD) ! 173: /* use fcntl (doesn't work correctly with threads) */ ! 174: alock.l_type = share; ! 175: alock.l_whence = L_SET; ! 176: alock.l_start = 0; ! 177: alock.l_len = 0; /* lock to EOF */ ! 178: ! 179: if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL) { /* EINVAL means the file does not support locking */ ! 180: close(fd); ! 181: return -1; ! 182: } ! 183: #endif ! 184: ! 185: #if !defined(F_SANEWRLCKNO) && !defined(__QNX__) && !defined(__solaris__) ! 186: /* use flock (doesn't work over NFS) */ ! 187: if(share==SH_DENYRW) ! 188: flock_op|=LOCK_EX; ! 189: else /* SH_DENYWR */ ! 190: flock_op|=LOCK_SH; ! 191: if(flock(fd,flock_op)!=0 && errno != EOPNOTSUPP) { /* That object doesn't do locks */ ! 192: if(errno==EWOULDBLOCK) ! 193: errno=EAGAIN; ! 194: close(fd); ! 195: return(-1); ! 196: } ! 197: #endif ! 198: ! 199: return fd; ! 200: } ! 201: #endif /* !QNX */ ! 202: ! 203: #elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) ! 204: ! 205: #include <io.h> /* tell */ ! 206: #include <stdio.h> /* SEEK_SET */ ! 207: #include <sys/locking.h> /* _locking */ ! 208: ! 209: /* Fix MinGW locking.h typo */ ! 210: #if defined LK_UNLOCK && !defined LK_UNLCK ! 211: #define LK_UNLCK LK_UNLOCK ! 212: #endif ! 213: ! 214: int DLLCALL lock(int file, long offset, long size) ! 215: { ! 216: int i; ! 217: long pos; ! 218: ! 219: pos=tell(file); ! 220: if(offset!=pos) ! 221: lseek(file, offset, SEEK_SET); ! 222: i=_locking(file,LK_NBLCK,size); ! 223: if(offset!=pos) ! 224: lseek(file, pos, SEEK_SET); ! 225: return(i); ! 226: } ! 227: ! 228: int DLLCALL unlock(int file, long offset, long size) ! 229: { ! 230: int i; ! 231: long pos; ! 232: ! 233: pos=tell(file); ! 234: if(offset!=pos) ! 235: lseek(file, offset, SEEK_SET); ! 236: i=_locking(file,LK_UNLCK,size); ! 237: if(offset!=pos) ! 238: lseek(file, pos, SEEK_SET); ! 239: return(i); ! 240: } ! 241: ! 242: #endif /* !Unix && (MSVC || MinGW) */ ! 243: ! 244: #ifdef __unix__ ! 245: FILE *_fsopen(char *pszFilename, char *pszMode, int shmode) ! 246: { ! 247: int file; ! 248: int Mode=0; ! 249: char *p; ! 250: ! 251: for(p=pszMode;*p;p++) { ! 252: switch (*p) { ! 253: case 'r': ! 254: Mode |= 1; ! 255: break; ! 256: case 'w': ! 257: Mode |= 2; ! 258: break; ! 259: case 'a': ! 260: Mode |= 4; ! 261: break; ! 262: case '+': ! 263: Mode |= 8; ! 264: break; ! 265: case 'b': ! 266: case 't': ! 267: break; ! 268: default: ! 269: errno=EINVAL; ! 270: return(NULL); ! 271: } ! 272: } ! 273: switch(Mode) { ! 274: case 1: ! 275: Mode=O_RDONLY; ! 276: break; ! 277: case 2: ! 278: Mode=O_WRONLY|O_CREAT|O_TRUNC; ! 279: break; ! 280: case 4: ! 281: Mode=O_APPEND|O_WRONLY|O_CREAT; ! 282: break; ! 283: case 9: ! 284: Mode=O_RDWR|O_CREAT; ! 285: break; ! 286: case 10: ! 287: Mode=O_RDWR|O_CREAT|O_TRUNC; ! 288: break; ! 289: case 12: ! 290: Mode=O_RDWR|O_APPEND|O_CREAT; ! 291: break; ! 292: default: ! 293: errno=EINVAL; ! 294: return(NULL); ! 295: } ! 296: if(Mode&O_CREAT) ! 297: file=sopen(pszFilename,Mode,shmode,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); ! 298: else ! 299: file=sopen(pszFilename,Mode,shmode); ! 300: if(file==-1) ! 301: return(NULL); ! 302: return(fdopen(file,pszMode)); ! 303: } ! 304: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.