diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/sys/Makefile | 2 | ||||
-rw-r--r-- | common/sys/record.c | 194 |
2 files changed, 195 insertions, 1 deletions
diff --git a/common/sys/Makefile b/common/sys/Makefile index 39598f86..e0fec71f 100644 --- a/common/sys/Makefile +++ b/common/sys/Makefile @@ -5,7 +5,7 @@ MKPIC:=no SRCROOT= ../.. .include "$(SRCROOT)/pttbbs.mk" -SRCS:= file.c lock.c log.c net.c sort.c string.c time.c crypt.c osdep.c +SRCS:= file.c lock.c log.c net.c sort.c string.c time.c crypt.c record.c osdep.c LIB:= cmsys install: diff --git a/common/sys/record.c b/common/sys/record.c new file mode 100644 index 00000000..e1b74402 --- /dev/null +++ b/common/sys/record.c @@ -0,0 +1,194 @@ +/* $Id$ */ + +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <assert.h> +#include "cmsys.h" + +#define BUFSIZE 512 + +/* Functions for fixed size record operations */ + +int +get_num_records(const char *fpath, size_t size) +{ + struct stat st; + + if (stat(fpath, &st) == -1) + return 0; + + return st.st_size / size; +} + +int +get_records_keep(const char *fpath, void *rptr, size_t size, int id, size_t number, int *fd) +{ + assert(fpath); + assert(fd); + + if (id < 1) + return -1; + + if (*fd < 0 && (*fd = open(fpath, O_RDONLY, 0)) == -1) + return -1; + + if (lseek(*fd, (off_t) (size * (id - 1)), SEEK_SET) == -1) + return 0; + + if ((id = read(*fd, rptr, size * number)) == -1) + return -1; + + return id / size; +} + +int +get_records(const char *fpath, void *rptr, size_t size, int id, size_t number) +{ + int res, fd = -1; + + res = get_records_keep(fpath, rptr, size, id, number, &fd); + close(fd); + + return res; +} + +#ifndef get_record +int +get_record(const char *fpath, void *rptr, size_t size, int id) +{ + return get_records(fpath, rptr, size, id, 1); +} +#endif + +#ifndef get_record_keep +int +get_record_keep(const char *fpath, void *rptr, size_t size, int id, int *fd) +{ + return get_records_keep(fpath, rptr, size, id, 1, fd); +} +#endif + +int +substitute_record(const char *fpath, const void *rptr, size_t size, int id) +{ + int fd; + off_t offset = size * (id - 1); + + if (id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) + return -1; + + lseek(fd, offset, SEEK_SET); + PttLock(fd, offset, size, F_WRLCK); + write(fd, rptr, size); + PttLock(fd, offset, size, F_UNLCK); + close(fd); + + return 0; +} + +int +append_record(const char *fpath, const void *record, size_t size) +{ + int fd, index = -2, fsize = 0; + + if ((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) + return -1; + + flock(fd, LOCK_EX); + + if ((fsize = lseek(fd, 0, SEEK_END)) < 0) + goto out; + + index = fsize / size; + lseek(fd, index * size, SEEK_SET); // avoid offset + + write(fd, record, size); + +out: + flock(fd, LOCK_UN); + close(fd); + + return index + 1; +} + +int +delete_records(const char *fpath, size_t size, int id, size_t num) +{ + char buf[BUFSIZE]; + int fi, fo, locksize, readsize, c, d=0; + struct stat st; + off_t offset = size * (id - 1); + + if ((fi=open(fpath, O_RDONLY, 0)) == -1) + return -1; + + if ((fo=open(fpath, O_WRONLY, 0)) == -1) { + close(fi); + return -1; + } + + if (fstat(fi, &st)==-1) { + close(fo); + close(fi); + return -1; + } + + locksize = st.st_size - offset; + readsize = locksize - size*num; + + if (locksize < 0 ) { + close(fo); + close(fi); + return -1; + } + + PttLock(fo, offset, locksize, F_WRLCK); + + if (readsize > 0) { + lseek(fi, offset+size, SEEK_SET); + lseek(fo, offset, SEEK_SET); + while (d < readsize && (c = read(fi, buf, BUFSIZE)) > 0) { + write(fo, buf, c); + d += c; + } + } + close(fi); + + ftruncate(fo, st.st_size - size*num); + + PttLock(fo, offset, locksize, F_UNLCK); + + close(fo); + + return 0; +} + +#ifndef delete_record +int delete_record(const char *fpath, size_t size, int id) +{ + return delete_records(fpath, size, id, 1); +} +#endif + +int +apply_record(const char *fpath, int (*fptr) (void *item, void *optarg), size_t size, void *arg) +{ + char buf[BUFSIZE]; + int fd; + + assert(size <= sizeof(buf)); + + if ((fd = open(fpath, O_RDONLY, 0)) == -1) + return -1; + + while (read(fd, buf, size) == size) + if ((*fptr) (buf, arg) == 1) { + close(fd); + return 1; + } + + close(fd); + + return 0; +} |