#include "fileutil.h" #include #include #include #include int __fp_open(FILE *fp, int fd, bool use_buffering) { /* We initialize fdpos to 0 even in append mode (7.19.3§1) */ fp->fd = fd; fp->fdpos = 0; /* We assume all files in the filesystem are non-interactive in order to conform to (7.19.5.3§7) TODO: Vhex might want something more elaborate here */ if(use_buffering && setvbuf(fp, NULL, _IOFBF, BUFSIZ)) return -1; return 0; } void __fp_close(FILE *fp, bool free_fp) { if(!fp) return; if(fp->fd >= 0) { fflush(fp); close(fp->fd); } if(fp->bufowned) free(fp->buf); if(free_fp) free(fp); } void __fp_buffer_mode_read(FILE *fp) { if(fp->bufmode != _IONBF && fp->bufdir == __FILE_BUF_WRITE && fp->bufpos > 0) fflush(fp); fp->bufdir = __FILE_BUF_READ; } void __fp_buffer_mode_write(FILE *fp) { if(fp->bufmode != _IONBF && fp->bufdir == __FILE_BUF_READ && fp->bufpos < fp->bufread) fflush(fp); fp->bufdir = __FILE_BUF_WRITE; } ssize_t __fp_read(FILE *fp, void *data, size_t size) { size_t read_ = 0; while(read_ < size) { ssize_t rc = read(fp->fd, data + read_, size - read_); if(rc < 0) { fp->error = 1; return EOF; } if(rc == 0) { fp->eof = 1; break; } fp->fdpos += rc; read_ += rc; } return read_; } ssize_t __fp_write(FILE *fp, void const *data, size_t size) { size_t written = 0; while(written < size) { ssize_t rc = write(fp->fd, data + written, size - written); if(rc < 0) { fp->error = 1; return EOF; } if(rc == 0) break; fp->fdpos += rc; written += rc; } return written; } int __fp_parse_mode(char const *mode, FILE *fp) { int base = 0; bool binary = false; bool update = false; for(int i = 0; mode[i]; i++) { if(mode[i] == 'r' || mode[i] == 'w' || mode[i] == 'a') { if(base) goto err; base = mode[i]; } else if(mode[i] == 'b') binary = true; else if(mode[i] == '+') update = true; } if(!base) goto err; if(fp) { fp->readable = (base == 'r' || update); fp->writable = (base == 'w' || base == 'a' || update); fp->append = (base == 'a'); fp->text = !binary; } if(base == 'r') return (update ? O_RDWR : O_RDONLY); if(base == 'w') return (update ? O_RDWR : O_WRONLY) | O_CREAT | O_TRUNC; if(base == 'a') return (update ? O_RDWR : O_WRONLY) | O_CREAT; /* Fallthrough */ err: errno = EINVAL; return -1; }