fopen.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * fopen.c - open a stream
  3. */
  4. /* $Id$ */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <unistd.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include "loc_incl.h"
  11. #define PMODE 0666
  12. /* Since the O_CREAT flag is not available on all systems, we can't get it
  13. * from the standard library. Furthermore, even if we know that <fcntl.h>
  14. * contains such a flag, it's not sure whether it can be used, since we
  15. * might be cross-compiling for another system, which may use an entirely
  16. * different value for O_CREAT (or not support such a mode). The safest
  17. * thing is to just use the Version 7 semantics for open, and use creat()
  18. * whenever necessary.
  19. *
  20. * Another problem is O_APPEND, for which the same holds. When "a"
  21. * open-mode is used, an lseek() to the end is done before every write()
  22. * system-call.
  23. *
  24. * FIXME dtrg: I'm not sure this is relevant any more. Implementing O_CREAT
  25. * and O_APPEND ought to be the job of the syscall library, no? Besides, the
  26. * code requires valid definitions.
  27. *
  28. * Remember to fix freopen.c if changing this.
  29. */
  30. FILE *
  31. fopen(const char *name, const char *mode)
  32. {
  33. register int i;
  34. int rwmode = 0, rwflags = 0;
  35. FILE *stream;
  36. int fd, flags = 0;
  37. for (i = 0; __iotab[i] != 0 ; i++)
  38. if ( i >= FOPEN_MAX-1 )
  39. return (FILE *)NULL;
  40. switch(*mode++) {
  41. case 'r':
  42. flags |= _IOREAD | _IOREADING;
  43. rwmode = O_RDONLY;
  44. break;
  45. case 'w':
  46. flags |= _IOWRITE | _IOWRITING;
  47. rwmode = O_WRONLY;
  48. rwflags = O_CREAT | O_TRUNC;
  49. break;
  50. case 'a':
  51. flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
  52. rwmode = O_WRONLY;
  53. rwflags |= O_APPEND | O_CREAT;
  54. break;
  55. default:
  56. return (FILE *)NULL;
  57. }
  58. while (*mode) {
  59. switch(*mode++) {
  60. case 'b':
  61. continue;
  62. case '+':
  63. rwmode = O_RDWR;
  64. flags |= _IOREAD | _IOWRITE;
  65. continue;
  66. /* The sequence may be followed by additional characters */
  67. default:
  68. break;
  69. }
  70. break;
  71. }
  72. /* Perform a creat() when the file should be truncated or when
  73. * the file is opened for writing and the open() failed.
  74. */
  75. if ((rwflags & O_TRUNC)
  76. || (((fd = open(name, rwmode)) < 0)
  77. && (rwflags & O_CREAT))) {
  78. if (((fd = creat(name, PMODE)) > 0) && flags | _IOREAD) {
  79. (void) close(fd);
  80. fd = open(name, rwmode);
  81. }
  82. }
  83. if (fd < 0) return (FILE *)NULL;
  84. if (( stream = (FILE *) malloc(sizeof(FILE))) == NULL ) {
  85. close(fd);
  86. return (FILE *)NULL;
  87. }
  88. if ((flags & (_IOREAD | _IOWRITE)) == (_IOREAD | _IOWRITE))
  89. flags &= ~(_IOREADING | _IOWRITING);
  90. stream->_count = 0;
  91. stream->_fd = fd;
  92. stream->_flags = flags;
  93. stream->_buf = NULL;
  94. __iotab[i] = stream;
  95. return stream;
  96. }