hsfsops.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1994-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include "hsfs_sig.h"
#include <sys/bootconf.h>
#include <sys/bootdebug.h>
#define THE_EPOCH 1970
#define END_OF_TIME 2099
/* May not need this... */
static uint_t sua_offset = 0;
/* The root inode on an HSFS filesystem can be anywhere! */
/* Only got one of these...ergo, only 1 fs open at once */
struct dirinfo {
int loc;
};
struct hs_direct {
struct direct hs_ufs_dir;
struct hs_direntry hs_dir;
};
/*
* Function prototypes
*/
static int boot_hsfs_mountroot(char *str);
static int boot_hsfs_unmountroot(void);
static int boot_hsfs_close(int fd);
static void boot_hsfs_closeall(int flag);
struct boot_fs_ops boot_hsfs_ops = {
"hsfs",
};
static time_t hs_date_to_gmtime(int, int, int, int);
/*
* There is only 1 open (mounted) device at any given time.
* So we can keep a single, global devp file descriptor to
* use to index into the di[] array. This is not true for the
* fi[] array. We can have more than one file open at once,
* so there is no global fd for the fi[].
* The user program must save the fd passed back from open()
* and use it to do subsequent read()'s.
*/
static int
{
int retval;
/* Set up the saio request */
/* Maybe the block is in the disk block cache */
/* Not in the block cache so read it from disk */
return (retval);
}
}
return (0);
return (0);
}
return (1);
}
static ino_t
{
register char *q;
char c;
printf("null path\n");
return (0);
}
/* Read the ROOT directory */
printf("find(): root_ino opendir() failed!\n");
return ((ino_t)-1);
}
while (*path) {
while (*path == '/')
path++;
if (*(q = path) == '\0')
break;
while (*q != '/' && *q != '\0')
q++;
c = *q;
*q = '\0';
if (c == '\0')
break;
*q = c;
return ((ino_t)-1);
}
*q = c;
path = q;
continue;
} else {
*q = c;
return (0);
}
}
return (inode);
}
static fileid_t *
{
if (fd >= 0) {
}
return (0);
}
static ino_t
{
register int len;
return (0);
return (0);
}
return (0);
}
/* first look through the directory entry cache */
return (in);
}
}
continue;
continue;
/* put this entry into the cache */
}
}
return (0);
}
/*
* get next entry in a directory.
*/
static struct hs_direct *
{
register int off;
for (;;) {
return (NULL);
}
if (off == 0) {
/* check the block cache */
if (set_bcache(filep))
return ((struct hs_direct *)-1);
}
continue;
}
return (&hsdep);
}
}
/*
* Get the next block of data from the file. If possible, dma right into
* user's buffer
*/
static int
{
register caddr_t p;
static int pos;
static int blks_read;
/* find the amt left to be read in the file */
if (diff <= 0) {
printf("Short read\n");
return (-1);
}
/* which block (or frag) in the file do we read? */
/* which physical block on the device do we read? */
if (size > ISO_SECTOR_SIZE)
/*
* optimization if we are reading large blocks of data then
* we can go directly to user's buffer
*/
*rcount = 0;
return (-1);
}
read_opt++;
if ((blks_read++ & 0x3) == 0)
return (0);
} else
return (-1);
/*
* round and round she goes (though not on every block..
* - OBP's take a fair bit of time to actually print stuff)
*/
if ((blks_read++ & 0x3) == 0)
}
return (0);
}
/*
* This is the high-level read function. It works like this.
* We assume that our IO device buffers up some amount of
* data ant that we can get a ptr to it. Thus we need
* and this greatly increases our IO speed. When we already
* have data in the buffer, we just return that data (with bcopy() ).
*/
static ssize_t
{
size_t i, j;
caddr_t n;
int rcount;
return (-1);
}
/* that was easy */
if ((i = count) == 0)
return (0);
n = buf;
while (i > 0) {
/* If we need to reload the buffer, do so */
i -= rcount;
} else {
/* else just bcopy from our buffer */
j = MIN(i, j);
buf += j;
i -= j;
}
}
return (buf - n);
}
/*
* This routine will open a device as it is known by the
* V2 OBP.
* Interface Defn:
* err = mountroot(string);
* err: 0 on success
* -1 on failure
* string: char string describing the properties of the device.
* We must not dork with any fi[]'s here. Save that for later.
*/
static int
boot_hsfs_mountroot(char *str)
{
ihandle_t h;
char *bufp;
printf("mountroot()\n");
/*
* If already mounted, just return success.
*/
if (root_ino != 0) {
return (0);
}
if (h == 0) {
return (-1);
}
devp->di_dcookie = h;
head->fi_filedes = 0;
/* Setup read of the "superblock" */
printf("mountroot(): read super block failed!\n");
return (-1);
}
/* Since RRIP is based on ISO9660, that's where we start */
return (-1);
}
/* Now we fill in the volume descriptor */
/* Make sure we have a valid logical block size */
return (-1);
}
/* Since an HSFS root could be located anywhere on the media! */
int i;
printf("ID=");
for (i = 0; i < ISO_ID_STRLEN; i++)
}
return (0);
}
/*
* Unmount the currently mounted root fs. In practice, this means
* closing all open files and releasing resources. All of this
* is done by boot_hsfs_closeall().
*/
int
boot_hsfs_unmountroot(void)
{
if (root_ino == 0)
return (-1);
return (0);
}
/*
* We allocate an fd here for use when talking
* to the file itself.
*/
/*ARGSUSED*/
static int
{
static int filedes = 1;
/* build and link a new file descriptor */
return (-1);
}
return (filep->fi_filedes);
}
/*
* hsfs_fstat() only supports size, mode and times at present time.
*/
static int
{
return (-1);
return (0);
case IFDIR:
break;
case IFREG:
break;
default:
break;
}
/* file times */
return (0);
}
/*
* We don't do any IO here.
* We just play games with the device pointers.
*/
/*ARGSUSED*/
static off_t
{
return (-1);
return (0);
}
static int
boot_hsfs_close(int fd)
{
/* Clear the ranks */
/* unlink and deallocate node */
return (0);
} else {
/* Big problem */
return (-1);
}
}
/*ARGSUSED*/
static void
boot_hsfs_closeall(int flag)
{
extern int verbosemode;
prom_panic("Filesystem may be inconsistent.\n");
if (verbosemode)
root_ino = 0;
}
static uint_t
{
uint_t i;
uchar_t c;
int ret_code = 0;
return (0);
if (IDE_REGULAR_FILE(c)) {
} else if (IDE_REGULAR_DIR(c)) {
} else {
printf("parse_dir(): file type=0x%x unknown.\n", c);
return ((uint_t)-1);
}
/* Some initial conditions */
/* Special Case: Current Directory */
/* Special Case: Parent Directory */
/* Other file name */
} else {
for (i = 0; i < nmlen; i++) {
if (c == ';')
break;
else if (c == ' ')
continue;
else
}
}
/* System Use Fields */
ce_lbn = 0;
if ((int)(ce_len) > 0) {
while (ce_lbn) {
#ifdef noisy
#endif /* noisy */
#ifdef noisy
#endif /* noisy */
#ifdef noisy
#endif /* noisy */
if (ret_code) {
printf("parse_dir(): set_bcache() failed (%d)\n",
ret_code);
break;
}
#ifdef noisy
#endif /* noisy */
}
}
}
static uint_t
{
uint_t i;
break;
if (susp_len == 0)
break;
for (i = 0; i < hsfs_num_sig; i++) {
#ifdef noisy
#endif /* noisy */
switch (i) {
case SUSP_SP_IX:
if (CHECK_BYTES_OK(susp)) {
#ifdef lint
/* Like the man said, this may not be needed */
i = (int)sua_offset;
#endif /* lint */
}
break;
case SUSP_CE_IX:
#ifdef noisy
(boothowto & RB_VERBOSE))
printf("parse_susp(): "
"CE: ce_lbn = %d ce_len=%d\n",
#endif /* noisy */
break;
case SUSP_ST_IX:
return (ce_lbn);
case RRIP_SL_IX:
#ifdef noisy
(boothowto & RB_VERBOSE))
printf("parse_susp(): ******* SL *******\n");
#endif /* noisy */
break;
case RRIP_RR_IX:
break;
case RRIP_NM_IX:
if (!RRIP_NAME_FLAGS(susp)) {
}
break;
}
break;
}
}
if (i > hsfs_num_sig) {
printf("parse_susp(): Bad SUSP\n");
break;
}
}
return (ce_lbn);
}
static void
{
/* Try the inode cache first */
return;
}
#ifdef noisy
static void
{
printf("%s o=%d b=%d c=%d m=%x\n",
str,
}
#endif /* noisy */
static int
{
/*
* Read directory entries from the file open on "fd" into the
* "size"-byte buffer at "dep" until the buffer is exhausted
* or we reach EOF on the directory. Returns the number of
* entries read.
*/
int n;
int cnt = 0;
/*
* Bogus file descriptor, bail out now!
*/
return (-1);
}
/*
* Compute name length and break loop if there's not
* enough space in the output buffer for the next
* entry.
*
* NOTE: "SLOP" is the number of bytes inserted into the dirent
* struct's "d_name" field by the compiler to preserve
* alignment.
*/
sizeof (off_t));
if (n > size) {
break;
}
size -= n;
cnt += 1;
}
return (cnt);
}
static void
{
if (type == HS_VOL_TYPE_HS) {
} else if (type == HS_VOL_TYPE_ISO) {
} else
prom_panic("hs_dodates: bad volume type");
}
/*
* hs_parse_dirdate
*
* Parse the short 'directory-format' date into a Unix timeval.
* This is the date format used in Directory Entries.
*
* If the date is not representable, make something up.
*/
void
{
} else {
}
}
return;
}
/*
* hs_parse_longdate
*
* Parse the long 'user-oriented' date into a Unix timeval.
* This is the date format used in the Volume Descriptor.
*
* If the date is not representable, make something up.
*/
void
{
} else {
}
}
}
/* cumulative number of seconds per month, non-leap and leap-year versions */
0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280,
0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500
};
static time_t cum_sec_leap[] = {
0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400,
0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680
};
#define SEC_PER_DAY 0x15180
#define SEC_PER_YEAR 0x1e13380
/*
* hs_date_to_gmtime
*
* Convert year(1970-2099)/month(1-12)/day(1-31) to seconds-since-1970/1/1.
*
* Returns -1 if the date is out of range.
*/
static time_t
{
int y;
return (-1);
/*
* Figure seconds until this year and correct for leap years.
* Note: 2000 is a leap year but not 2100.
*/
sum = y * SEC_PER_YEAR;
/*
* Point to the correct table for this year and
* add in seconds until this month.
*/
/*
* Add in seconds until 0:00 of this day.
* (days-per-month validation is not done here)
*/
return (sum);
}