#include "KinoSearch/Util/ToolSet.h"
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#define KINO_WANT_FSFILEDES_VTABLE
#include "KinoSearch/Store/FSFileDes.r"
#define CHECK_IO_OP(x) \
do { \
int check_val = (x); \
if (check_val == -1) { \
CONFESS("File operation failed: %s", strerror(errno)); \
} \
} while (0)
FSFileDes*
FSFileDes_new(const char *path, int oflags, int fdmode, const char *fmode)
{
int fd;
CREATE(self, FSFileDes, FSFILEDES);
/* open */
fd = open(path, oflags, fdmode);
if (fd == -1) {
free(self);
return NULL;
}
self->fhandle = fdopen(fd, fmode);
if (self->fhandle == NULL) {
free(self);
return NULL;
}
if (strcmp("ab", fmode) == 0) {
setvbuf(self->fhandle, NULL, _IONBF, 0);
}
/* init */
self->pos = 0;
self->stream_count = 0;
/* assign */
self->path = strdup(path);
/* track number of live FileDes released into the wild */
FileDes_object_count++;
FileDes_open_count++;
return self;
}
void
FSFileDes_destroy(FSFileDes *self)
{
if (self->fhandle != NULL) {
FileDes_FDClose(self);
}
free(self->path);
/* decrement count of FileDes structs in existence */
FileDes_object_count--;
free(self);
}
bool_t
FSFileDes_fdseek(FSFileDes *self, u64_t target)
{
CHECK_IO_OP( fseeko64(self->fhandle, target, SEEK_SET) );
self->pos = target;
return true;
}
bool_t
FSFileDes_fdread(FSFileDes *self, char *dest, u32_t dest_offset, u32_t len)
{
int check_val = fread(dest + dest_offset, sizeof(char), len,
self->fhandle);
if (check_val < 0 || (u32_t)check_val != len) {
Carp_set_kerror("Tried to read %lu bytes, got %d: %s",
(unsigned long)len, check_val, strerror(errno));
return false;
}
self->pos += len;
return true;
}
bool_t
FSFileDes_fdwrite(FSFileDes *self, const char* buf, u32_t len)
{
size_t check_val;
if (len == 0)
return true;
check_val = fwrite(buf, sizeof(char), len, self->fhandle);
if (check_val != len) {
Carp_set_kerror("Attempted to write %lu bytes, but wrote %lu",
(unsigned long)len, (unsigned long)check_val);
return false;
}
self->pos += len;
return true;
}
u64_t
FSFileDes_fdlength(FSFileDes *self)
{
/* save bookmark, seek to end, note length, return to bookmark */
u64_t len;
u64_t bookmark = ftello64(self->fhandle);
CHECK_IO_OP(bookmark);
CHECK_IO_OP( fseeko64(self->fhandle, 0, SEEK_END) );
len = ftello64(self->fhandle);
CHECK_IO_OP(len);
CHECK_IO_OP( fseeko64(self->fhandle, bookmark, SEEK_SET) );
return len;
}
bool_t
FSFileDes_fdclose(FSFileDes *self)
{
if (self->fhandle != NULL) {
if (fclose(self->fhandle)) {
Carp_set_kerror("Failed to close file: %s", strerror(errno));
return false;
}
FileDes_open_count--;
self->fhandle = NULL;
}
return true;
}
/* Copyright 2006-2007 Marvin Humphrey
*
* This program is free software; you can redistribute it and/or modify
* under the same terms as Perl itself.
*/