off_t hseek(hFILE *fp, off_t offset, int whence) { off_t pos; if (writebuffer_is_nonempty(fp)) { int ret = flush_buffer(fp); if (ret < 0) return ret; } else { // Convert relative offsets from being relative to the hFILE's stream // position (at begin) to being relative to the backend's physical // stream position (at end, due to the buffering read-ahead). if (whence == SEEK_CUR) offset -= fp->end - fp->begin; } pos = fp->backend->seek(fp, offset, whence); if (pos < 0) { fp->has_errno = errno; return pos; } // Seeking succeeded, so discard any non-empty read buffer fp->begin = fp->end = fp->buffer; fp->at_eof = 0; fp->offset = pos; return pos; }
off_t hseek(hFILE *fp, off_t offset, int whence) { off_t curpos, pos; if (writebuffer_is_nonempty(fp) && fp->mobile) { int ret = flush_buffer(fp); if (ret < 0) return ret; } curpos = htell(fp); // Relative offsets are given relative to the hFILE's stream position, // which may differ from the backend's physical position due to buffering // read-ahead. Correct for this by converting to an absolute position. if (whence == SEEK_CUR) { if (curpos + offset < 0) { // Either a negative offset resulted in a position before the // start of the file, or we overflowed when given a positive offset fp->has_errno = errno = (offset < 0)? EINVAL : EOVERFLOW; return -1; } whence = SEEK_SET; offset = curpos + offset; } // For fixed immobile buffers, convert everything else to SEEK_SET too // so that seeking can be avoided for all (within range) requests. else if (! fp->mobile && whence == SEEK_END) { size_t length = fp->end - fp->buffer; if (offset > 0 || -offset > length) { fp->has_errno = errno = EINVAL; return -1; } whence = SEEK_SET; offset = length + offset; } // Avoid seeking if the desired position is within our read buffer. // (But not when the next operation may be a write on a mobile buffer.) if (whence == SEEK_SET && (! fp->mobile || fp->readonly) && offset >= fp->offset && offset - fp->offset <= fp->end - fp->buffer) { fp->begin = &fp->buffer[offset - fp->offset]; return offset; } pos = fp->backend->seek(fp, offset, whence); if (pos < 0) { fp->has_errno = errno; return pos; } // Seeking succeeded, so discard any non-empty read buffer fp->begin = fp->end = fp->buffer; fp->at_eof = 0; fp->offset = pos; return pos; }
int hclose(hFILE *fp) { int err = fp->has_errno; if (writebuffer_is_nonempty(fp) && hflush(fp) < 0) err = fp->has_errno; if (fp->backend->close(fp) < 0) err = errno; hfile_destroy(fp); if (err) { errno = err; return EOF; } else return 0; }
ssize_t hgetdelim(char *buffer, size_t size, int delim, hFILE *fp) { char *found; size_t n, copied = 0; ssize_t got; if (size < 1 || size > SSIZE_MAX) { fp->has_errno = errno = EINVAL; return -1; } if (writebuffer_is_nonempty(fp)) { fp->has_errno = errno = EBADF; return -1; } --size; /* to allow space for the NUL terminator */ do { n = fp->end - fp->begin; if (n > size - copied) n = size - copied; /* Look in the hFILE buffer for the delimiter */ found = memchr(fp->begin, delim, n); if (found != NULL) { n = found - fp->begin + 1; memcpy(buffer + copied, fp->begin, n); buffer[n + copied] = '\0'; fp->begin += n; return n + copied; } /* No delimiter yet, copy as much as we can and refill if necessary */ memcpy(buffer + copied, fp->begin, n); fp->begin += n; copied += n; if (copied == size) { /* Output buffer full */ buffer[copied] = '\0'; return copied; } got = refill_buffer(fp); } while (got > 0); if (got < 0) return -1; /* Error on refill. */ buffer[copied] = '\0'; /* EOF, return anything that was copied. */ return copied; }
off_t hseek(hFILE *fp, off_t offset, int whence) { off_t pos; if (writebuffer_is_nonempty(fp)) { int ret = flush_buffer(fp); if (ret < 0) return ret; } pos = fp->backend->seek(fp, offset, whence); if (pos < 0) { fp->has_errno = errno; return pos; } // Seeking succeeded, so discard any non-empty read buffer fp->begin = fp->end = fp->buffer; fp->at_eof = 0; fp->offset = pos; return pos; }