source: trunk/third/sendmail/libsm/stdio.c @ 19204

Revision 19204, 9.4 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 * Copyright (c) 1990, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
9 *
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
13 */
14
15#include <sm/gen.h>
16SM_RCSID("@(#)$Id: stdio.c,v 1.1.1.1 2003-04-08 15:08:46 zacheiss Exp $")
17#include <unistd.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <string.h>     /* FreeBSD: FD_ZERO needs <string.h> */
21#include <sys/stat.h>
22#include <sys/time.h>
23#include <sm/heap.h>
24#include <sm/assert.h>
25#include <sm/varargs.h>
26#include <sm/io.h>
27#include <sm/setjmp.h>
28#include <sm/conf.h>
29#include <sm/fdset.h>
30#include "local.h"
31
32/*
33**  Overall:
34**  Small standard I/O/seek/close functions.
35**  These maintain the `known seek offset' for seek optimization.
36*/
37
38/*
39**  SM_STDOPEN -- open a file with stdio behavior
40**
41**  Not associated with the system's stdio in libc.
42**
43**      Parameters:
44**              fp -- file pointer to be associated with the open
45**              info -- pathname of the file to be opened
46**              flags -- indicates type of access methods
47**              rpool -- ignored
48**
49**      Returns:
50**              Failure: -1 and set errno
51**              Success: 0 or greater (fd of file from open(2)).
52**
53*/
54
55/* ARGSUSED3 */
56int
57sm_stdopen(fp, info, flags, rpool)
58        SM_FILE_T *fp;
59        const void *info;
60        int flags;
61        const void *rpool;
62{
63        char *path = (char *) info;
64        int oflags;
65
66        switch (flags)
67        {
68          case SM_IO_RDWR:
69                oflags = O_RDWR;
70                break;
71          case SM_IO_RDWRTR:
72                oflags = O_RDWR | O_CREAT | O_TRUNC;
73                break;
74          case SM_IO_RDONLY:
75                oflags = O_RDONLY;
76                break;
77          case SM_IO_WRONLY:
78                oflags = O_WRONLY | O_CREAT | O_TRUNC;
79                break;
80          case SM_IO_APPEND:
81                oflags = O_APPEND | O_WRONLY | O_CREAT;
82                break;
83          case SM_IO_APPENDRW:
84                oflags = O_APPEND | O_RDWR | O_CREAT;
85                break;
86          default:
87                errno = EINVAL;
88                return -1;
89        }
90        fp->f_file = open(path, oflags,
91                          S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
92        if (fp->f_file < 0)
93                return -1; /* errno set by open() */
94
95        if (oflags & O_APPEND)
96                (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
97
98        return fp->f_file;
99}
100
101/*
102**  SM_STDREAD -- read from the file
103**
104**      Parameters:
105**              fp -- file pointer to read from
106**              buf -- location to place read data
107**              n -- number of bytes to read
108**
109**      Returns:
110**              Failure: -1 and sets errno
111**              Success: number of bytes read
112**
113**      Side Effects:
114**              Updates internal offset into file.
115*/
116
117ssize_t
118sm_stdread(fp, buf, n)
119        SM_FILE_T *fp;
120        char *buf;
121        size_t n;
122{
123        register int ret;
124
125        ret = read(fp->f_file, buf, n);
126
127        /* if the read succeeded, update the current offset */
128        if (ret > 0)
129                fp->f_lseekoff += ret;
130        return ret;
131}
132
133/*
134**  SM_STDWRITE -- write to the file
135**
136**      Parameters:
137**              fp -- file pointer ro write to
138**              buf -- location of data to be written
139**              n - number of bytes to write
140**
141**      Returns:
142**              Failure: -1 and sets errno
143**              Success: number of bytes written
144*/
145
146ssize_t
147sm_stdwrite(fp, buf, n)
148        SM_FILE_T *fp;
149        char const *buf;
150        size_t n;
151{
152        return write(fp->f_file, buf, n);
153}
154
155/*
156**  SM_STDSEEK -- set the file offset position
157**
158**      Parmeters:
159**              fp -- file pointer to position
160**              offset -- how far to position from "base" (set by 'whence')
161**              whence -- indicates where the "base" of the 'offset' to start
162**
163**      Results:
164**              Failure: -1 and sets errno
165**              Success: the current offset
166**
167**      Side Effects:
168**              Updates the internal value of the offset.
169*/
170
171off_t
172sm_stdseek(fp, offset, whence)
173        SM_FILE_T *fp;
174        off_t offset;
175        int whence;
176{
177        register off_t ret;
178
179        ret = lseek(fp->f_file, (off_t) offset, whence);
180        if (ret != (off_t) -1)
181                fp->f_lseekoff = ret;
182        return ret;
183}
184
185/*
186**  SM_STDCLOSE -- close the file
187**
188**      Parameters:
189**              fp -- the file pointer to close
190**
191**      Returns:
192**              Success: 0 (zero)
193**              Failure: -1 and sets errno
194*/
195
196int
197sm_stdclose(fp)
198        SM_FILE_T *fp;
199{
200        return close(fp->f_file);
201}
202
203/*
204**  SM_STDSETMODE -- set the access mode for the file
205**
206**  Called by sm_stdsetinfo().
207**
208**      Parameters:
209**              fp -- file pointer
210**              mode -- new mode to set the file access to
211**
212**      Results:
213**              Success: 0 (zero);
214**              Failure: -1 and sets errno
215*/
216
217int
218sm_stdsetmode(fp, mode)
219        SM_FILE_T *fp;
220        const int *mode;
221{
222        int flags = 0;
223
224        switch (*mode)
225        {
226          case SM_IO_RDWR:
227                flags |= SMRW;
228                break;
229          case SM_IO_RDONLY:
230                flags |= SMRD;
231                break;
232          case SM_IO_WRONLY:
233                flags |= SMWR;
234                break;
235          case SM_IO_APPEND:
236          default:
237                errno = EINVAL;
238                return -1;
239        }
240        fp->f_flags = fp->f_flags & ~SMMODEMASK;
241        fp->f_flags |= flags;
242        return 0;
243}
244
245/*
246**  SM_STDGETMODE -- for getinfo determine open mode
247**
248**  Called by sm_stdgetinfo().
249**
250**      Parameters:
251**              fp -- the file mode being determined
252**              mode -- internal mode to map to external value
253**
254**      Results:
255**              Failure: -1 and sets errno
256**              Success: external mode value
257*/
258
259int
260sm_stdgetmode(fp, mode)
261        SM_FILE_T *fp;
262        int *mode;
263{
264        switch (fp->f_flags & SMMODEMASK)
265        {
266          case SMRW:
267                *mode = SM_IO_RDWR;
268                break;
269          case SMRD:
270                *mode = SM_IO_RDONLY;
271                break;
272          case SMWR:
273                *mode = SM_IO_WRONLY;
274                break;
275          default:
276                errno = EINVAL;
277                return -1;
278        }
279        return 0;
280}
281
282/*
283**  SM_STDSETINFO -- set/modify information for a file
284**
285**      Parameters:
286**              fp -- file to set info for
287**              what -- type of info to set
288**              valp -- location of data used for setting
289**
290**      Returns:
291**              Failure: -1 and sets errno
292**              Success: >=0
293*/
294
295int
296sm_stdsetinfo(fp, what, valp)
297        SM_FILE_T *fp;
298        int what;
299        void *valp;
300{
301        switch (what)
302        {
303          case SM_IO_WHAT_MODE:
304                return sm_stdsetmode(fp, (const int *)valp);
305
306          default:
307                errno = EINVAL;
308                return -1;
309        }
310}
311
312/*
313**  SM_GETINFO -- get information about the open file
314**
315**      Parameters:
316**              fp -- file to get info for
317**              what -- type of info to get
318**              valp -- location to place found info
319**
320**      Returns:
321**              Success: may or may not place info in 'valp' depending
322**                      on 'what' value, and returns values >=0. Return
323**                      value may be the obtained info
324**              Failure: -1 and sets errno
325*/
326
327int
328sm_stdgetinfo(fp, what, valp)
329        SM_FILE_T *fp;
330        int what;
331        void *valp;
332{
333        switch (what)
334        {
335          case SM_IO_WHAT_MODE:
336                return sm_stdgetmode(fp, (int *)valp);
337
338          case SM_IO_WHAT_FD:
339                return fp->f_file;
340
341          case SM_IO_WHAT_SIZE:
342          {
343                  struct stat st;
344
345                  if (fstat(fp->f_file, &st) == 0)
346                          return st.st_size;
347                  else
348                          return -1;
349          }
350
351          case SM_IO_IS_READABLE:
352          {
353                  fd_set readfds;
354                  struct timeval timeout;
355
356                  if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
357                  {
358                          errno = EINVAL;
359                          return -1;
360                  }
361                  FD_ZERO(&readfds);
362                  SM_FD_SET(fp->f_file, &readfds);
363                  timeout.tv_sec = 0;
364                  timeout.tv_usec = 0;
365                  if (select(fp->f_file + 1, FDSET_CAST &readfds,
366                             NULL, NULL, &timeout) > 0 &&
367                      SM_FD_ISSET(fp->f_file, &readfds))
368                          return 1;
369                  return 0;
370          }
371
372          default:
373                errno = EINVAL;
374                return -1;
375        }
376}
377
378/*
379**  SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
380**
381**      I/O function to handle fdopen() stdio equivalence. The rest of
382**      the functions are the same as the sm_stdopen() above.
383**
384**      Parameters:
385**              fp -- the file pointer to be associated with the open
386**              name -- the primitive file descriptor for association
387**              flags -- indicates type of access methods
388**              rpool -- ignored
389**
390**      Results:
391**              Success: primitive file descriptor value
392**              Failure: -1 and sets errno
393*/
394
395/* ARGSUSED3 */
396int
397sm_stdfdopen(fp, info, flags, rpool)
398        SM_FILE_T *fp;
399        const void *info;
400        int flags;
401        const void *rpool;
402{
403        int oflags, tmp, fdflags, fd = *((int *) info);
404
405        switch (flags)
406        {
407          case SM_IO_RDWR:
408                oflags = O_RDWR | O_CREAT;
409                break;
410          case SM_IO_RDONLY:
411                oflags = O_RDONLY;
412                break;
413          case SM_IO_WRONLY:
414                oflags = O_WRONLY | O_CREAT | O_TRUNC;
415                break;
416          case SM_IO_APPEND:
417                oflags = O_APPEND | O_WRONLY | O_CREAT;
418                break;
419          case SM_IO_APPENDRW:
420                oflags = O_APPEND | O_RDWR | O_CREAT;
421                break;
422          default:
423                errno = EINVAL;
424                return -1;
425        }
426
427        /* Make sure the mode the user wants is a subset of the actual mode. */
428        if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
429                return -1;
430        tmp = fdflags & O_ACCMODE;
431        if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
432        {
433                errno = EINVAL;
434                return -1;
435        }
436        fp->f_file = fd;
437        if (oflags & O_APPEND)
438                (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
439        return fp->f_file;
440}
441
442/*
443**  SM_IO_FOPEN -- open a file
444**
445**      Same interface and semantics as the open() system call,
446**      except that it returns SM_FILE_T* instead of a file descriptor.
447**
448**      Parameters:
449**              pathname -- path of file to open
450**              flags -- flags controlling the open
451**              ...  -- option "mode" for opening the file
452**
453**      Returns:
454**              Raises an exception on heap exhaustion.
455**              Returns NULL and sets errno if open() fails.
456**              Returns an SM_FILE_T pointer on success.
457*/
458
459SM_FILE_T *
460#if SM_VA_STD
461sm_io_fopen(char *pathname, int flags, ...)
462#else /* SM_VA_STD */
463sm_io_fopen(pathname, flags, va_alist)
464        char *pathname;
465        int flags;
466        va_dcl
467#endif /* SM_VA_STD */
468{
469        MODE_T mode;
470        SM_FILE_T *fp;
471        int ioflags;
472
473        if (flags & O_CREAT)
474        {
475                SM_VA_LOCAL_DECL
476
477                SM_VA_START(ap, flags);
478                mode = (MODE_T) SM_VA_ARG(ap, int);
479                SM_VA_END(ap);
480        }
481        else
482                mode = 0;
483
484        switch (flags & O_ACCMODE)
485        {
486          case O_RDONLY:
487                ioflags = SMRD;
488                break;
489          case O_WRONLY:
490                ioflags = SMWR;
491                break;
492          case O_RDWR:
493                ioflags = SMRW;
494                break;
495          default:
496                sm_abort("sm_io_fopen: bad flags 0%o", flags);
497        }
498
499        fp = sm_fp(SmFtStdio, ioflags, NULL);
500        fp->f_file = open(pathname, flags, mode);
501        if (fp->f_file == -1)
502        {
503                fp->f_flags = 0;
504                fp->sm_magic = NULL;
505                return NULL;
506        }
507        return fp;
508}
Note: See TracBrowser for help on using the repository browser.