2 * Copyright (c) 2000-2005 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
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.
16 SM_RCSID("@(#)$Id: stdio.c,v 1.71 2005/06/14 23:07:20 ca Exp $")
20 #include <string.h> /* FreeBSD: FD_ZERO needs <string.h> */
24 #include <sm/assert.h>
25 #include <sm/varargs.h>
27 #include <sm/setjmp.h>
32 static int sm_stdsetmode
__P((SM_FILE_T
*, const int *));
33 static int sm_stdgetmode
__P((SM_FILE_T
*, int *));
37 ** Small standard I/O/seek/close functions.
38 ** These maintain the `known seek offset' for seek optimization.
42 ** SM_STDOPEN -- open a file with stdio behavior
44 ** Not associated with the system's stdio in libc.
47 ** fp -- file pointer to be associated with the open
48 ** info -- pathname of the file to be opened
49 ** flags -- indicates type of access methods
53 ** Failure: -1 and set errno
54 ** Success: 0 or greater (fd of file from open(2)).
60 sm_stdopen(fp
, info
, flags
, rpool
)
66 char *path
= (char *) info
;
69 switch (SM_IO_MODE(flags
))
75 oflags
= O_RDWR
| O_CREAT
| O_TRUNC
;
81 oflags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
84 oflags
= O_APPEND
| O_WRONLY
| O_CREAT
;
87 oflags
= O_APPEND
| O_RDWR
| O_CREAT
;
94 if (SM_IS_BINARY(flags
))
97 fp
->f_file
= open(path
, oflags
,
98 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
);
100 return -1; /* errno set by open() */
102 if (oflags
& O_APPEND
)
103 (void) (*fp
->f_seek
)((void *)fp
, (off_t
)0, SEEK_END
);
109 ** SM_STDREAD -- read from the file
112 ** fp -- file pointer to read from
113 ** buf -- location to place read data
114 ** n -- number of bytes to read
117 ** Failure: -1 and sets errno
118 ** Success: number of bytes read
121 ** Updates internal offset into file.
125 sm_stdread(fp
, buf
, n
)
132 ret
= read(fp
->f_file
, buf
, n
);
134 /* if the read succeeded, update the current offset */
136 fp
->f_lseekoff
+= ret
;
141 ** SM_STDWRITE -- write to the file
144 ** fp -- file pointer ro write to
145 ** buf -- location of data to be written
146 ** n - number of bytes to write
149 ** Failure: -1 and sets errno
150 ** Success: number of bytes written
154 sm_stdwrite(fp
, buf
, n
)
159 return write(fp
->f_file
, buf
, n
);
163 ** SM_STDSEEK -- set the file offset position
166 ** fp -- file pointer to position
167 ** offset -- how far to position from "base" (set by 'whence')
168 ** whence -- indicates where the "base" of the 'offset' to start
171 ** Failure: -1 and sets errno
172 ** Success: the current offset
175 ** Updates the internal value of the offset.
179 sm_stdseek(fp
, offset
, whence
)
186 ret
= lseek(fp
->f_file
, (off_t
) offset
, whence
);
187 if (ret
!= (off_t
) -1)
188 fp
->f_lseekoff
= ret
;
193 ** SM_STDCLOSE -- close the file
196 ** fp -- the file pointer to close
200 ** Failure: -1 and sets errno
207 return close(fp
->f_file
);
211 ** SM_STDSETMODE -- set the access mode for the file
213 ** Called by sm_stdsetinfo().
216 ** fp -- file pointer
217 ** mode -- new mode to set the file access to
220 ** Success: 0 (zero);
221 ** Failure: -1 and sets errno
225 sm_stdsetmode(fp
, mode
)
231 switch (SM_IO_MODE(*mode
))
247 fp
->f_flags
= fp
->f_flags
& ~SMMODEMASK
;
248 fp
->f_flags
|= flags
;
253 ** SM_STDGETMODE -- for getinfo determine open mode
255 ** Called by sm_stdgetinfo().
258 ** fp -- the file mode being determined
259 ** mode -- internal mode to map to external value
262 ** Failure: -1 and sets errno
263 ** Success: external mode value
267 sm_stdgetmode(fp
, mode
)
271 switch (fp
->f_flags
& SMMODEMASK
)
277 *mode
= SM_IO_RDONLY
;
280 *mode
= SM_IO_WRONLY
;
290 ** SM_STDSETINFO -- set/modify information for a file
293 ** fp -- file to set info for
294 ** what -- type of info to set
295 ** valp -- location of data used for setting
298 ** Failure: -1 and sets errno
303 sm_stdsetinfo(fp
, what
, valp
)
310 case SM_IO_WHAT_MODE
:
311 return sm_stdsetmode(fp
, (const int *)valp
);
320 ** SM_GETINFO -- get information about the open file
323 ** fp -- file to get info for
324 ** what -- type of info to get
325 ** valp -- location to place found info
328 ** Success: may or may not place info in 'valp' depending
329 ** on 'what' value, and returns values >=0. Return
330 ** value may be the obtained info
331 ** Failure: -1 and sets errno
335 sm_stdgetinfo(fp
, what
, valp
)
342 case SM_IO_WHAT_MODE
:
343 return sm_stdgetmode(fp
, (int *)valp
);
348 case SM_IO_WHAT_SIZE
:
352 if (fstat(fp
->f_file
, &st
) == 0)
358 case SM_IO_IS_READABLE
:
361 struct timeval timeout
;
363 if (SM_FD_SETSIZE
> 0 && fp
->f_file
>= SM_FD_SETSIZE
)
369 SM_FD_SET(fp
->f_file
, &readfds
);
372 if (select(fp
->f_file
+ 1, FDSET_CAST
&readfds
,
373 NULL
, NULL
, &timeout
) > 0 &&
374 SM_FD_ISSET(fp
->f_file
, &readfds
))
386 ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
388 ** I/O function to handle fdopen() stdio equivalence. The rest of
389 ** the functions are the same as the sm_stdopen() above.
392 ** fp -- the file pointer to be associated with the open
393 ** name -- the primitive file descriptor for association
394 ** flags -- indicates type of access methods
398 ** Success: primitive file descriptor value
399 ** Failure: -1 and sets errno
404 sm_stdfdopen(fp
, info
, flags
, rpool
)
410 int oflags
, tmp
, fdflags
, fd
= *((int *) info
);
412 switch (SM_IO_MODE(flags
))
415 oflags
= O_RDWR
| O_CREAT
;
421 oflags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
424 oflags
= O_APPEND
| O_WRONLY
| O_CREAT
;
427 oflags
= O_APPEND
| O_RDWR
| O_CREAT
;
434 if (SM_IS_BINARY(flags
))
436 #endif /* O_BINARY */
438 /* Make sure the mode the user wants is a subset of the actual mode. */
439 if ((fdflags
= fcntl(fd
, F_GETFL
, 0)) < 0)
441 tmp
= fdflags
& O_ACCMODE
;
442 if (tmp
!= O_RDWR
&& (tmp
!= (oflags
& O_ACCMODE
)))
448 if (oflags
& O_APPEND
)
449 (void) (*fp
->f_seek
)(fp
, (off_t
)0, SEEK_END
);
454 ** SM_IO_FOPEN -- open a file
456 ** Same interface and semantics as the open() system call,
457 ** except that it returns SM_FILE_T* instead of a file descriptor.
460 ** pathname -- path of file to open
461 ** flags -- flags controlling the open
462 ** ... -- option "mode" for opening the file
465 ** Raises an exception on heap exhaustion.
466 ** Returns NULL and sets errno if open() fails.
467 ** Returns an SM_FILE_T pointer on success.
472 sm_io_fopen(char *pathname
, int flags
, ...)
473 #else /* SM_VA_STD */
474 sm_io_fopen(pathname
, flags
, va_alist
)
478 #endif /* SM_VA_STD */
488 SM_VA_START(ap
, flags
);
489 mode
= (MODE_T
) SM_VA_ARG(ap
, int);
495 switch (flags
& O_ACCMODE
)
507 sm_abort("sm_io_fopen: bad flags 0%o", flags
);
510 fp
= sm_fp(SmFtStdio
, ioflags
, NULL
);
511 fp
->f_file
= open(pathname
, flags
, mode
);
512 if (fp
->f_file
== -1)