/* * Set up a file stream on an OS file. The caller has allocated the * stream and buffer. */ void file_init_stream(stream *s, FILE *file, const char *fmode, byte *buffer, uint buffer_size) { switch (fmode[0]) { case 'a': sappend_file(s, file, buffer, buffer_size); break; case 'r': /* Defeat buffering for terminals. */ { struct stat rstat; fstat(fileno(file), &rstat); sread_file(s, file, buffer, (S_ISCHR(rstat.st_mode) ? 1 : buffer_size)); } break; case 'w': swrite_file(s, file, buffer, buffer_size); } if (fmode[1] == '+') s->file_modes |= s_mode_read | s_mode_write; s->save_close = s->procs.close; s->procs.close = file_close_file; }
/* Switch a file stream to reading or writing. */ static int s_fileno_switch(stream * s, bool writing) { uint modes = s->file_modes; int fd = sfileno(s); long pos; if (writing) { if (!(s->file_modes & s_mode_write)) return ERRC; pos = stell(s); if_debug2('s', "[s]switch 0x%lx to write at %ld\n", (ulong) s, pos); lseek(fd, pos, SEEK_SET); /* pacify OS */ if (modes & s_mode_append) { sappend_file(s, s->file, s->cbuf, s->cbsize); /* sets position */ } else { swrite_file(s, s->file, s->cbuf, s->cbsize); s->position = pos; } s->modes = modes; } else { if (!(s->file_modes & s_mode_read)) return ERRC; pos = stell(s); if_debug2('s', "[s]switch 0x%lx to read at %ld\n", (ulong) s, pos); if (sflush(s) < 0) return ERRC; lseek(fd, 0L, SEEK_CUR); /* pacify OS */ sread_file(s, s->file, s->cbuf, s->cbsize); s->modes |= modes & s_mode_append; /* don't lose append info */ s->position = pos; } s->file_modes = modes; return 0; }