Browse Source

Unify the write and read structs. There was no good reason to keep them

separate. Improve the bts_seek so that it only calls close or lseek if
necessary. Otherwise it's a nop. Hide bts_seek and instead make the offset
explicit in calls to bts_get or bts_put.
master
Richard Nyberg 18 years ago
parent
commit
a3933c0761
2 changed files with 119 additions and 154 deletions
  1. +97
    -123
      misc/stream.c
  2. +22
    -31
      misc/stream.h

+ 97
- 123
misc/stream.c View File

@@ -11,61 +11,77 @@
#include "subr.h"
#include "stream.h"

struct bt_stream_ro *
bts_open_ro(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
int
bts_open(struct bt_stream **res, struct metainfo *meta, fdcb_t fd_cb,
void *fd_arg)
{
struct bt_stream_ro *bts = malloc(sizeof(*bts));
struct bt_stream *bts = calloc(1, sizeof(*bts));
if (bts == NULL)
return NULL;
return ENOMEM;

bts->meta = meta;
bts->fd_cb = fd_cb;
bts->fd_arg = fd_arg;
bts->t_off = 0;
bts->f_off = 0;
bts->index = 0;
bts->fd = -1;
bts_seek_ro(bts, off);
return bts;

*res = bts;
return 0;
}

void
bts_seek_ro(struct bt_stream_ro *bts, off_t off)
int
bts_close(struct bt_stream *bts)
{
struct fileinfo *files = bts->meta->files;

assert(off >= 0 && off <= bts->meta->total_length);
int err = 0;
if (bts->fd != -1 && close(bts->fd) == -1)
err = errno;
free(bts);
return err;
}

if (bts->fd != -1) {
close(bts->fd);
bts->fd = -1;
}
int
bts_seek(struct bt_stream *bts, off_t off)
{
if (bts->t_off == off)
return 0;

bts->t_off = off;
bts->index = 0;

while (off >= files[bts->index].length) {
off -= files[bts->index].length;
bts->index++;
}
struct fileinfo *files = bts->meta->files;
unsigned i;
for (i = 0; off >= files[i].length; i++)
off -= files[i].length;

if (i != bts->index) {
if (bts->fd != -1) {
if (close(bts->fd) == -1)
return errno;
bts->fd = -1;
}
} else if (bts->fd != -1)
lseek(bts->fd, off, SEEK_SET);
bts->index = i;
bts->f_off = off;

return 0;
}

int
bts_read_ro(struct bt_stream_ro *bts, char *buf, size_t len)
bts_get(struct bt_stream *bts, off_t off, uint8_t *buf, size_t len)
{
struct fileinfo *files = bts->meta->files;
size_t boff, wantread;
ssize_t didread;
int err;

assert(bts->t_off + len <= bts->meta->total_length);
assert(off + len <= bts->meta->total_length);
if ((err = bts_seek(bts, off)) != 0)
return err;

boff = 0;
while (boff < len) {
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
err = bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
@@ -92,104 +108,22 @@ bts_read_ro(struct bt_stream_ro *bts, char *buf, size_t len)
return 0;
}

void
bts_close_ro(struct bt_stream_ro *bts)
{
if (bts->fd != -1)
close(bts->fd);
free(bts);
}

#define SHAFILEBUF (1 << 15)

int
bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash)
{
SHA_CTX ctx;
char buf[SHAFILEBUF];
size_t wantread;
int err = 0;

SHA1_Init(&ctx);
while (length > 0) {
wantread = min(length, SHAFILEBUF);
if ((err = bts_read_ro(bts, buf, wantread)) != 0)
break;
length -= wantread;
SHA1_Update(&ctx, buf, wantread);
}
SHA1_Final(hash, &ctx);
return err;
}

int
bts_hashes(struct metainfo *meta,
F_fdcb fd_cb,
void (*cb)(uint32_t, uint8_t *, void *),
void *arg)
{
int err = 0;
uint8_t hash[SHA_DIGEST_LENGTH];
uint32_t piece;
struct bt_stream_ro *bts;
off_t plen = meta->piece_length;
off_t llen = meta->total_length % plen;

if ((bts = bts_open_ro(meta, 0, fd_cb, arg)) == NULL)
return ENOMEM;

for (piece = 0; piece < meta->npieces; piece++) {
if (piece < meta->npieces - 1)
err = bts_sha(bts, plen, hash);
else
err = bts_sha(bts, llen, hash);

if (err == 0)
cb(piece, hash, arg);
else if (err == ENOENT) {
cb(piece, NULL, arg);
if (piece < meta->npieces - 1)
bts_seek_ro(bts, (piece + 1) * plen);
err = 0;
} else
break;
}
bts_close_ro(bts);
return err;
}

struct bt_stream_wo *
bts_open_wo(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
{
struct bt_stream_wo *bts = malloc(sizeof(*bts));
if (bts == NULL)
return NULL;

bts->meta = meta;
bts->fd_cb = fd_cb;
bts->fd_arg = fd_arg;
bts->t_off = 0;
bts->f_off = 0;
bts->index = 0;
bts->fd = -1;
bts_seek_ro((struct bt_stream_ro *)bts, off);
return bts;
}

int
bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)
bts_put(struct bt_stream *bts, off_t off, const uint8_t *buf, size_t len)
{
struct fileinfo *files = bts->meta->files;
size_t boff, wantwrite;
ssize_t didwrite;
int err;

assert(bts->t_off + len <= bts->meta->total_length);
assert(off + len <= bts->meta->total_length);
if ((err = bts_seek(bts, off)) != 0)
return err;

boff = 0;
while (boff < len) {
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
err = bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
@@ -220,17 +154,57 @@ bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)
return 0;
}

#define SHAFILEBUF (1 << 15)

int
bts_close_wo(struct bt_stream_wo *bts)
bts_sha(struct bt_stream *bts, off_t start, off_t length, uint8_t *hash)
{
SHA_CTX ctx;
char buf[SHAFILEBUF];
size_t wantread;
int err = 0;
if (bts->fd != -1) {
if (fsync(bts->fd) == -1) {
err = errno;
close(bts->fd);
} else if (close(bts->fd) == -1)
err = errno;

SHA1_Init(&ctx);
while (length > 0) {
wantread = min(length, SHAFILEBUF);
if ((err = bts_get(bts, start, buf, wantread)) != 0)
break;
length -= wantread;
start += wantread;
SHA1_Update(&ctx, buf, wantread);
}
free(bts);
SHA1_Final(hash, &ctx);
return err;
}

int
bts_hashes(struct metainfo *meta, fdcb_t fd_cb, hashcb_t cb, void *arg)
{
int err = 0;
uint8_t hash[SHA_DIGEST_LENGTH];
uint32_t piece;
struct bt_stream *bts;
off_t plen = meta->piece_length;
off_t llen = meta->total_length % plen;

if ((err = bts_open(&bts, meta, fd_cb, arg)) != 0)
return err;

for (piece = 0; piece < meta->npieces; piece++) {
off_t start = piece * plen;
if (piece < meta->npieces - 1)
err = bts_sha(bts, start, plen, hash);
else
err = bts_sha(bts, start, llen, hash);

if (err == 0)
cb(piece, hash, arg);
else if (err == ENOENT) {
cb(piece, NULL, arg);
err = 0;
} else
break;
}
bts_close(bts);
return err;
}

+ 22
- 31
misc/stream.h View File

@@ -1,36 +1,27 @@
#ifndef BTPD_STREAM_H
#define BTPD_STREAM_H

typedef int (*F_fdcb)(const char *, int *, void *);

#define def_stream(name) \
struct name {\
struct metainfo *meta;\
F_fdcb fd_cb;\
void *fd_arg;\
unsigned index;\
off_t t_off;\
off_t f_off;\
int fd;\
}

def_stream(bt_stream_ro);

struct bt_stream_ro *
bts_open_ro(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg);
int bts_read_ro(struct bt_stream_ro *bts, char *buf, size_t len);
void bts_seek_ro(struct bt_stream_ro *bts, off_t nbytes);
void bts_close_ro(struct bt_stream_ro *bts);

def_stream(bt_stream_wo);

struct bt_stream_wo *
bts_open_wo(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg);
int bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len);
int bts_close_wo(struct bt_stream_wo *bts);

int bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash);
int bts_hashes(struct metainfo *, F_fdcb fd_cb,
void (*cb)(uint32_t, uint8_t *, void *), void *arg);
typedef int (*fdcb_t)(const char *, int *, void *);
typedef void (*hashcb_t)(uint32_t, uint8_t *, void *);

struct bt_stream {
struct metainfo *meta;
fdcb_t fd_cb;
void *fd_arg;
unsigned index;
off_t t_off;
off_t f_off;
int fd;
};

int bts_open(struct bt_stream **res, struct metainfo *meta, fdcb_t fd_cb,
void *fd_arg);
int bts_get(struct bt_stream *bts, off_t off, uint8_t *buf, size_t len);
int bts_put(struct bt_stream *bts, off_t off, const uint8_t *buf, size_t len);
int bts_close(struct bt_stream *bts);

int bts_sha(struct bt_stream *bts, off_t start, off_t length, uint8_t *hash);
int bts_hashes(struct metainfo *meta, fdcb_t fd_cb, hashcb_t hash_cb,
void *arg);

#endif

Loading…
Cancel
Save