|
|
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.