_fpopen.c (1350B)
1 #include <errno.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <wchar.h> 6 7 #include <sys.h> 8 9 #include "../syscall.h" 10 #include "../libc.h" 11 12 FILE * 13 _fpopen(const char *restrict fname, 14 const char *restrict mode, 15 FILE * restrict fp) 16 { 17 int i, flags, fd, rw, bin, rights; 18 19 flags = rw = bin = 0; 20 rights = 0666; 21 22 if (mode[0] == '\0') 23 goto einval; 24 25 for (i = 1; mode[i]; ++i) { 26 switch (mode[i]) { 27 case '+': 28 if (rw) 29 goto einval; 30 rw = 1; 31 break; 32 case 'b': 33 if (bin) 34 goto einval; 35 bin = 1; 36 break; 37 case 't': 38 flags |= O_EXCL | O_CLOEXEC; 39 rights = 0600; 40 break; 41 default: 42 goto einval; 43 } 44 } 45 46 switch (mode[0]) { 47 case 'a': 48 flags |= O_APPEND | O_CREAT; 49 goto wrflags; 50 case 'w': 51 flags |= O_TRUNC | O_CREAT; 52 wrflags: 53 flags |= (rw) ? O_RDWR : O_WRONLY; 54 break; 55 case 'r': 56 flags |= (rw) ? O_RDWR : O_RDONLY; 57 break; 58 default: 59 einval: 60 errno = EINVAL; 61 return NULL; 62 } 63 64 if ((fd = _open(fname, flags, rights)) < 0) 65 return NULL; 66 67 memset(&fp->mbs, 0, sizeof(mbstate_t)); 68 fp->buf = NULL; 69 fp->fd = fd; 70 71 if (!bin) 72 fp->flags |= _IOTXT; 73 74 switch (flags & O_ACCMODE) { 75 case O_RDWR: 76 fp->flags |= _IORW; 77 break; 78 case O_RDONLY: 79 fp->flags |= _IOREAD; 80 break; 81 case O_WRONLY: 82 fp->flags |= _IOWRITE; 83 break; 84 } 85 86 fp->lp = fp->rp = fp->wp = NULL; 87 88 return fp; 89 }