/*************************************************************************** * Copyright (c) 2007-2010, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: bfile_util.c $ * $brcm_Revision: 2 $ * $brcm_Date: 6/23/10 2:22p $ * * Module Description: * * Block based cached file I/O * * Revision History: * * $brcm_Log: /BSEAV/lib/bfile/bfile_util.c $ * * 2 6/23/10 2:22p gmohile * SW3548-2975 : Return correct offset in b_file_correct_offset * * 1 6/21/10 1:32p vsilyaev * SW3548-2975: File utilities * * *******************************************************************************/ #include "bstd.h" #include "bkni.h" #include "bfile_util.h" BDBG_MODULE(bfile_util); BDBG_OBJECT_ID(bfile_read_offset); struct bfile_read_offset { struct bfile_io_read ops; /* shall be the first member */ off_t source_offset; bfile_io_read_t source; BDBG_OBJECT(bfile_read_offset) }; static ssize_t b_file_read_offset_read(bfile_io_read_t fd, void *buf, size_t length) { struct bfile_read_offset *f=(void *)fd; BDBG_OBJECT_ASSERT(f, bfile_read_offset); BDBG_MSG(("b_file_read_offset_read: %#lx %u", (unsigned long)fd, (unsigned)length)); return f->source->read(f->source, buf, length); } static off_t b_file_correct_offset(const struct bfile_read_offset *f, off_t offset) { if(offset>=f->source_offset) { offset -= f->source_offset; } else { offset = 0; } return offset; } static off_t b_file_read_offset_seek(bfile_io_read_t fd, off_t offset, int whence) { struct bfile_read_offset *f=(void *)fd; off_t rc; BDBG_OBJECT_ASSERT(f, bfile_read_offset); BDBG_MSG(("b_file_read_offset_seek: %#lx %lu:%d", (unsigned long)fd, (unsigned long)offset, whence)); if(whence==SEEK_SET) { offset += f->source_offset; } rc = f->source->seek(f->source, offset, whence); if(rc>=0 && rcsource_offset) { /* if seeked behind source_offset, seek back */ rc = f->source->seek(f->source, f->source_offset, SEEK_SET); } if(rc>=0) { /* correct returned offset */ rc = b_file_correct_offset(f, rc); } return rc; } static int b_file_read_offset_bounds(bfile_io_read_t fd, off_t *first, off_t *last) { off_t source_first=0, source_last=0; struct bfile_read_offset *f=(void *)fd; int rc; BDBG_OBJECT_ASSERT(f, bfile_read_offset); rc = f->source->bounds(f->source, &source_first, &source_last); source_first = b_file_correct_offset(f, source_first); source_last = b_file_correct_offset(f, source_last); if(first) { *first = source_first; } if(last) { *last = source_last; } return rc; } static const struct bfile_io_read b_file_read_offset_read_ops = { b_file_read_offset_read, b_file_read_offset_seek, b_file_read_offset_bounds, BIO_DEFAULT_PRIORITY }; bfile_io_read_t bfile_read_offset_attach(bfile_io_read_t source, off_t offset) { struct bfile_read_offset *f; f=BKNI_Malloc(sizeof(*f)); if (!f) { return NULL; } BDBG_OBJECT_INIT(f, bfile_read_offset); f->ops = b_file_read_offset_read_ops; f->source = source; f->source_offset = offset; return &f->ops; } void bfile_read_offset_detach(bfile_io_read_t file) { struct bfile_read_offset *f=(void *)file; BDBG_OBJECT_ASSERT(f, bfile_read_offset); BDBG_OBJECT_DESTROY(f, bfile_read_offset); BKNI_Free(f); return; }