/* * Copyright (c) 1996-1998 University of Utah and the Flux Group. * All rights reserved. * * This file is part of the Flux OSKit. The OSKit is free software, also known * as "open source;" you can redistribute it and/or modify it under the terms * of the GNU General Public License (GPL), version 2, as published by the Free * Software Foundation (FSF). To explore alternate licensing terms, contact * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271. * * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have * received a copy of the GPL along with the OSKit; see the file COPYING. If * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA. */ /* * Implementation of simple oskit_blkio subsetting objects, * e.g., for representing individual partitions on a disk. */ #include #include #include struct sub { oskit_blkio_t ioi; /* Interface to this object */ oskit_u32_t refs; /* Our reference count */ oskit_blkio_t *io; /* Reference to underlying I/O object */ oskit_off_t offset; /* Offset in underlying object */ oskit_off_t size; /* Size of our I/O segment */ }; /* * Query a subset I/O object for its interfaces. * This is extremely easy because we only export one interface * (plus its base type, IUnknown). */ static OSKIT_COMDECL query(oskit_blkio_t *io, const oskit_iid_t *iid, void **out_ihandle) { struct sub *s = (struct sub*)io; if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 || memcmp(iid, &oskit_blkio_iid, sizeof(*iid)) == 0) { *out_ihandle = &s->ioi; ++s->refs; return 0; } *out_ihandle = NULL; return OSKIT_E_NOINTERFACE; } /* * Clone a reference to our block I/O interface. */ static OSKIT_COMDECL_U addref(oskit_blkio_t *io) { struct sub *s = (struct sub*)io; return ++s->refs; } /* * Release a reference to our I/O interface. */ static OSKIT_COMDECL_U release(oskit_blkio_t *io) { struct sub *s = (struct sub*)io; if (--s->refs > 0) return s->refs; oskit_blkio_release(s->io); free(s); return 0; } /* * Return the block size of this block I/O object. */ static OSKIT_COMDECL_U getblocksize(oskit_blkio_t *io) { struct sub *s = (struct sub*)io; return oskit_blkio_getblocksize(s->io); } /* * Read from the block I/O subset object, * clipping accesses to the range of this subset. */ static OSKIT_COMDECL read(oskit_blkio_t *io, void *buf, oskit_off_t off, oskit_size_t count, oskit_size_t *amount) { struct sub *s = (struct sub*)io; if (off >= s->size) { *amount = 0; return 0; } if (off + count > s->size) { count = s->size - off; } return oskit_blkio_read(s->io, buf, s->offset + off, count, amount); } /* * Write data to the block I/O subset object, * clipping accesses to the range of this subset. */ static OSKIT_COMDECL write(oskit_blkio_t *io, const void *buf, oskit_off_t off, oskit_size_t count, oskit_size_t *amount) { struct sub *s = (struct sub*)io; if (off >= s->size) { *amount = 0; return 0; } if (off + count > s->size) { count = s->size - off; } return oskit_blkio_write(s->io, buf, s->offset + off, count, amount); } /* * Return the size of this subset I/O object. */ static OSKIT_COMDECL getsize(oskit_blkio_t *io, oskit_off_t *out_size) { struct sub *s = (struct sub*)io; *out_size = s->size; return 0; } /* * Attempt to set the size of this object, * which never succeeds in our case. */ static OSKIT_COMDECL setsize(oskit_blkio_t *io, oskit_off_t new_size) { return OSKIT_E_NOTIMPL; } /* * Operations vector for the subset block I/O interface. */ static struct oskit_blkio_ops ops = { query, addref, release, getblocksize, read, write, getsize, setsize }; oskit_error_t oskit_blkio_subset(oskit_blkio_t *io, oskit_off_t offset, oskit_off_t size, oskit_blkio_t **out_io) { struct sub *s; unsigned blksize; /* Sanity-check the offset and size */ blksize = oskit_blkio_getblocksize(io); if ((offset & (blksize-1)) || (size & (blksize-1))) return OSKIT_E_INVALIDARG; /* Create the new object */ s = malloc(sizeof(*s)); if (s == NULL) return OSKIT_E_OUTOFMEMORY; s->ioi.ops = &ops; s->refs = 1; s->io = io; oskit_blkio_addref(io); s->offset = offset; s->size = size; *out_io = &s->ioi; return 0; }