static int fill_buffer(stream_t *s, char *buffer, int max_len) { struct priv *p = s->priv; if (s->pos < 0) return -1; if (s->pos >= p->max_size) { if (stream_seek(p->original, s->pos) < 1) return -1; return stream_read(p->original, buffer, max_len); } // Size of file changes -> invalidate last block if (s->pos >= p->size - BLOCK_SIZE) { int64_t new_size = -1; stream_control(s, STREAM_CTRL_GET_SIZE, &new_size); if (new_size != p->size) set_bit(p, BLOCK_ALIGN(p->size), 0); p->size = MPMIN(p->max_size, new_size); } int64_t aligned = BLOCK_ALIGN(s->pos); if (!test_bit(p, aligned)) { char tmp[BLOCK_SIZE]; stream_seek(p->original, aligned); int r = stream_read(p->original, tmp, BLOCK_SIZE); if (r < BLOCK_SIZE) { if (p->size < 0) { MP_WARN(s, "suspected EOF\n"); } else if (aligned + r < p->size) { MP_ERR(s, "unexpected EOF\n"); return -1; } } if (fseeko(p->cache_file, aligned, SEEK_SET)) return -1; if (fwrite(tmp, r, 1, p->cache_file) != 1) return -1; set_bit(p, aligned, 1); } if (fseeko(p->cache_file, s->pos, SEEK_SET)) return -1; // align/limit to blocks max_len = MPMIN(max_len, BLOCK_SIZE - (s->pos % BLOCK_SIZE)); // Limit to max. known file size max_len = MPMIN(max_len, p->size - s->pos); return fread(buffer, 1, max_len, p->cache_file); }
void* malloc(size_t nbytes) { if (nbytes == 0) return NULL; /* round number of units up to block size */ size_t nunits = BLOCK_ALIGN(nbytes); Header *prevp; if ((prevp = freep) == NULL) { /* initialize free segment */ Header *e = (Header *) MEMLOC; e->next = freep = prevp = &base; e->size = ALLOCSIZ; base.next = e; base.size = 0; } Header *p; for (p = prevp->next; ; prevp = p, p = p->next) { /* check block size */ if (p->size >= nunits) { if (p->size == nunits) { /* exact */ prevp->next = p->next; } else { /* allocate tail end */ p->size -= nunits; p += p->size; p->size = nunits; } /* move free pointer */ freep = prevp; return BLOCK_PTR(p); } if (p == freep) { /* wrapped around free list; no blocks left */ return NULL; } } }
static int copy_blocks(int ifd, int ofd, unsigned long *offset, unsigned long *size) { off_t cur; int amt; unsigned long len = 0; char buffer[SIZE]; cur = lseek(ofd, 0, SEEK_CUR); if (cur % SIZE) { cur = BLOCK_ALIGN(cur); cur = lseek(ofd, cur, SEEK_SET); } *offset = (unsigned long) cur; while((amt = read(ifd, buffer, SIZE)) > 0) { write(ofd, buffer, amt); len += amt; } *size = len; return 0; }