|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.