/* $Id$ */ #include #include #include #include #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; }