From 642b5fb0007b64c77d186fcb018d571152ee1d47 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 14 Aug 2023 18:51:07 +0200 Subject: reorganization: first steps --- src/libc/fs/dir.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/libc/fs/dir.c (limited to 'src/libc/fs/dir.c') diff --git a/src/libc/fs/dir.c b/src/libc/fs/dir.c new file mode 100644 index 0000000..b7f840d --- /dev/null +++ b/src/libc/fs/dir.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +void dir_start(struct dirbuild *db, long offset, char *buf, size_t buflen) { + db->offset = offset; + db->buf = buf; + db->bpos = 0; + db->blen = buflen; + db->error = 0; + + // TODO decide how negative directory offsets should be handled + if (offset < 0) db->error = -ENOSYS; +} + +bool dir_append(struct dirbuild *db, const char *name) { + return dir_appendl(db, name, strlen(name)); +} + +bool dir_appendl(struct dirbuild *db, const char *name, size_t len) { + if (db->error) return true; + if (len > (size_t)LONG_MAX) { + db->error = -1; + return true; + } + + len++; // account for the null byte + + if (db->offset < (long)len) { + name += db->offset; + len -= db->offset; + db->offset = 0; + + if (db->buf) { + // TODO no buffer overrun check + memcpy(db->buf + db->bpos, name, len - 1); + db->buf[db->bpos + len - 1] = '\0'; + } + db->bpos += len; + } else { + db->offset -= len; + } + return false; +} + +bool dir_append_from(struct dirbuild *db, hid_t h) { + if (db->error) return true; + if (db->buf && db->bpos == db->blen) return false; + + int ret; + if (db->buf) { + ret = _sys_read(h, db->buf + db->bpos, db->blen - db->bpos, db->offset); + if (ret < 0) { + db->error = ret; + return true; + } else if (ret > 0) { + /* not eof */ + db->offset = 0; + db->bpos += ret; + return false; + } /* else ret == 0, EOF, need getsize */ + } + + ret = _sys_getsize(h); + if (ret < 0) { + db->error = ret; + return true; + } + if (db->offset < ret) { + /* should only occur when !buf, otherwise leaks previous data from buf. + * TODO consider impact */ + db->bpos += ret - db->offset; + db->offset = 0; + } else { + db->offset -= ret; + } + return false; +} + +long dir_finish(struct dirbuild *db) { + return db->error ? db->error : db->bpos; +} -- cgit v1.2.3