/* * filer.c - open, seeks in and reads from a file * * Copyright (C) 2006 Thorsten Zitterell */ #include #include #include #include #include #include #include #include #include #include "filer.h" /* * function filer_getcapacity() * returns: size/capacity of file/device */ unsigned long long filer_getcapacity(filer_info_t * filer_info) { return filer_info->size; } /* * function filer_seekblock(): seek to position in file/block device * returns: 1 on success, otherwise 0 */ static inline int filer_seekblock(filer_info_t * filer_info, off_t newpos) { if (lseek(filer_info->fd, newpos, SEEK_SET) == (off_t) -1) { return 0; } filer_info->pos = newpos; return 1; } /* * function filer_readblock(): read bytes at specific position * returns: 1 on success, otherwise 0 */ inline int filer_readblock(filer_info_t * filer_info, void *buf, size_t size, off_t pos) { size_t remain = size; int result = 0; int numblocks = 0; if (!filer_seekblock(filer_info, pos)) goto leave; while (remain > 0) { if ((numblocks = read(filer_info->fd, buf, remain)) <= 0) { if (errno == EINTR) continue; goto leave; } if (numblocks == 0) { goto leave; } remain -= numblocks; buf += numblocks; } result = 1; leave: filer_info->pos += (size - remain); return result; } /* * function filer_init(): open file to be served * returns: data structure with file information */ filer_info_t *filer_init(const char *filename) { filer_info_t *filer_info; struct stat64 stbuf; filer_info = (filer_info_t *) malloc(sizeof(filer_info_t)); if (!filer_info) return NULL; filer_info->filename = strdup(filename); if ((filer_info->fd = open(filename, O_RDONLY | O_LARGEFILE)) < 0) { fprintf(stderr, "ERROR: Cannot open filename \"%s\"\n", filename); goto out_free; } stbuf.st_size = 0; if (fstat64(filer_info->fd, &stbuf) < 0) { fprintf(stderr, "ERROR: Cannot stat file \"%s\"\n", filename); goto out_free; } /* get file/device size */ if ((filer_info->size = stbuf.st_size) == 0) { filer_info->size = lseek64(filer_info->fd, (off_t) 0, SEEK_END); } if (filer_info->size == 0) { fprintf(stderr, "ERROR: File/device has zero size\n"); goto out_free; } goto out; out_free: if (filer_info) free(filer_info); filer_info = NULL; out: return filer_info; }