fopen.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * fopen.c - open a stream
  3. */
  4. /* $Header$ */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include "loc_incl.h"
  8. #define PMODE 0666
  9. /* The next 3 defines are true in all UNIX systems known to me.
  10. */
  11. #define O_RDONLY 0
  12. #define O_WRONLY 1
  13. #define O_RDWR 2
  14. /* Since the O_CREAT flag is not available on all systems, we can't get it
  15. * from the standard library. Furthermore, even if we know that <fcntl.h>
  16. * contains such a flag, it's not sure whether it can be used, since we
  17. * might be cross-compiling for another system, which may use an entirely
  18. * different value for O_CREAT (or not support such a mode). The safest
  19. * thing is to just use the Version 7 semantics for open, and use creat()
  20. * whenever necessary.
  21. *
  22. * Another problem is O_APPEND, for which the same holds. When "a"
  23. * open-mode is used, an lseek() to the end is done before every write()
  24. * system-call.
  25. *
  26. * The O_CREAT, O_TRUNC and O_APPEND given here, are only for convenience.
  27. * They are not passed to open(), so the values don't have to match a value
  28. * from the real world. It is enough when they are unique.
  29. */
  30. #define O_CREAT 0x010
  31. #define O_TRUNC 0x020
  32. #define O_APPEND 0x040
  33. int open(const char *path, int flags);
  34. int creat(const char *path, int mode);
  35. int close(int d);
  36. FILE *
  37. fopen(const char *name, const char *mode)
  38. {
  39. register int i;
  40. int rwmode = 0, rwflags = 0;
  41. FILE *stream;
  42. int fd, flags = 0;
  43. for (i = 0; __iotab[i] != 0 ; i++)
  44. if ( i >= FOPEN_MAX )
  45. return (FILE *)NULL;
  46. switch(*mode++) {
  47. case 'r':
  48. flags |= _IOREAD | _IOREADING;
  49. rwmode = O_RDONLY;
  50. break;
  51. case 'w':
  52. flags |= _IOWRITE | _IOWRITING;
  53. rwmode = O_WRONLY;
  54. rwflags = O_CREAT | O_TRUNC;
  55. break;
  56. case 'a':
  57. flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
  58. rwmode = O_WRONLY;
  59. rwflags |= O_APPEND | O_CREAT;
  60. break;
  61. default:
  62. return (FILE *)NULL;
  63. }
  64. while (*mode) {
  65. switch(*mode++) {
  66. case 'b':
  67. break;
  68. case '+':
  69. rwmode = O_RDWR;
  70. flags |= _IOREAD | _IOWRITE;
  71. break;
  72. default:
  73. return (FILE *)NULL;
  74. }
  75. }
  76. /* Perform a creat() when the file should be truncated or when
  77. * the file is opened for writing and the open() failed.
  78. */
  79. if ((rwflags & O_TRUNC)
  80. || (((fd = open(name, rwmode)) < 0)
  81. && (flags & _IOWRITE)))
  82. fd = creat(name, PMODE);
  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. }