mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
7.0 KiB
307 lines
7.0 KiB
/***************************************************************************\
|
|
*
|
|
* FSREAD.C
|
|
*
|
|
* Copyright (C) Microsoft Corporation 1990.
|
|
* All Rights reserved.
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* Program Description: File System Manager functions for read and seek
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* Revision History: Created 03/12/90 by JohnSc
|
|
*
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* Known Bugs: None
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <orkin.h>
|
|
#include "_mvfs.h"
|
|
#include "imvfs.h"
|
|
|
|
|
|
#include "fspriv.h"
|
|
|
|
/***************************************************************************\
|
|
* *
|
|
* Private Functions *
|
|
* *
|
|
\***************************************************************************/
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: FPlungeQfshr( qfshr )
|
|
*
|
|
* Purpose: Get back a qfshr->fid that was flushed
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: qfshr - fid need not be valid
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: fTruth of success
|
|
*
|
|
* args OUT: qfshr->fid is valid (or we return FALSE)
|
|
*
|
|
* globals OUT: rcFSError
|
|
*
|
|
\***************************************************************************/
|
|
BOOL PASCAL
|
|
FPlungeQfshr( qfshr )
|
|
#ifdef SCROLL_TUNE
|
|
#pragma alloc_text(SCROLLER_TEXT, FPlungeQfshr)
|
|
#endif
|
|
QFSHR qfshr;
|
|
{
|
|
if ( qfshr->fid == fidNil )
|
|
{
|
|
qfshr->fid = FidOpenFm( (qfshr->fm),
|
|
qfshr->fsh.bFlags & fFSOpenReadOnly
|
|
? wReadOnly | wShareRead
|
|
: wReadWrite | wShareRead );
|
|
|
|
if ( qfshr->fid == fidNil )
|
|
{
|
|
SetFSErrorRc( RcGetIOError() );
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
Check size of file, then reset file pointer.
|
|
Certain 0-length files (eg con) give us no end of grief if
|
|
we try to read from them, and since a 0-length file could
|
|
not possibly be a valid FS, we reject the notion.
|
|
*/
|
|
if ( LSeekFid( qfshr->fid, 0L, wSeekEnd ) < sizeof(FSH) )
|
|
{
|
|
SetFSErrorRc( rcInvalid );
|
|
return FALSE;
|
|
}
|
|
LSeekFid( qfshr->fid, 0L, wSeekSet );
|
|
}
|
|
|
|
SetFSErrorRc( rcSuccess );
|
|
return TRUE;
|
|
}
|
|
/***************************************************************************\
|
|
* *
|
|
* Public Functions *
|
|
* *
|
|
\***************************************************************************/
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LcbReadHf()
|
|
*
|
|
* Purpose: read bytes from a file in a file system
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - file
|
|
* lcb - number of bytes to read
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: number of bytes actually read; -1 on error
|
|
*
|
|
* args OUT: qb - data read from file goes here (must be big enough)
|
|
*
|
|
* Notes: These are signed longs we're dealing with. This means
|
|
* behaviour is different from read() when < 0.
|
|
*
|
|
\***************************************************************************/
|
|
LONG PASCAL
|
|
LcbReadHf( hf, qb, lcb )
|
|
#ifdef SCROLL_TUNE
|
|
#pragma alloc_text(SCROLLER_TEXT,LcbReadHf)
|
|
#endif
|
|
HF hf;
|
|
QV qb;
|
|
LONG lcb;
|
|
{
|
|
QRWFO qrwfo;
|
|
LONG lcbTotalRead;
|
|
FID fid;
|
|
LONG lifOffset;
|
|
|
|
DPF3("LcbRead hf %u, bytes %lu ", hf, lcb);
|
|
|
|
assert( hf != NULL );
|
|
qrwfo = QLockGh( hf );
|
|
assert( qrwfo != NULL );
|
|
|
|
DPF3(" current %ld ", qrwfo->lifCurrent);
|
|
|
|
SetFSErrorRc( rcSuccess );
|
|
|
|
if ( lcb < (LONG)0 )
|
|
{
|
|
SetFSErrorRc( rcBadArg );
|
|
UnlockGh( hf );
|
|
DPF3(" error, lcb<0\n");
|
|
return (LONG)-1;
|
|
}
|
|
|
|
if ( qrwfo->lifCurrent + lcb > qrwfo->lcbFile )
|
|
{
|
|
lcb = qrwfo->lcbFile - qrwfo->lifCurrent;
|
|
if ( lcb <= (LONG)0 )
|
|
{
|
|
UnlockGh( hf );
|
|
DPF3(" error, returning 0\n");
|
|
return (LONG)0;
|
|
}
|
|
}
|
|
|
|
|
|
/* position file pointer for read */
|
|
|
|
if ( qrwfo->bFlags & fFSDirty )
|
|
{
|
|
fid = qrwfo->fidT;
|
|
lifOffset = (LONG)0;
|
|
}
|
|
else
|
|
{
|
|
QFSHR qfshr = QLockGh( qrwfo->hfs );
|
|
|
|
if ( !FPlungeQfshr( qfshr ) )
|
|
{
|
|
UnlockGh( qrwfo->hfs );
|
|
UnlockGh( hf );
|
|
DPF3(" error, returning -1\n");
|
|
return (LONG)-1;
|
|
}
|
|
|
|
fid = qfshr->fid;
|
|
lifOffset = qrwfo->lifBase;
|
|
|
|
UnlockGh( qrwfo->hfs );
|
|
}
|
|
|
|
if ( LSeekFid( fid, lifOffset + sizeof( FH ) + qrwfo->lifCurrent, wSeekSet )
|
|
!=
|
|
lifOffset + sizeof( FH ) + qrwfo->lifCurrent )
|
|
{
|
|
if ( RcGetIOError() == rcSuccess )
|
|
SetFSErrorRc( rcInvalid );
|
|
else
|
|
SetFSErrorRc( RcGetIOError() );
|
|
UnlockGh( hf );
|
|
DPF3(" error 2, returning -1\n");
|
|
return (LONG)-1;
|
|
}
|
|
|
|
|
|
/* read the data */
|
|
|
|
lcbTotalRead = LcbReadFid( fid, qb, lcb );
|
|
SetFSErrorRc( RcGetIOError() );
|
|
|
|
/* update file pointer */
|
|
|
|
if ( lcbTotalRead >= 0 )
|
|
{
|
|
qrwfo->lifCurrent += lcbTotalRead;
|
|
assert(qrwfo->lifCurrent>=0);
|
|
}
|
|
|
|
|
|
UnlockGh( hf );
|
|
|
|
DPF3(" now %ld ", qrwfo->lifCurrent);
|
|
DPF3(" read %ld\n", lcbTotalRead);
|
|
|
|
return lcbTotalRead;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LSeekHf( hf, lOffset, wOrigin )
|
|
*
|
|
* Purpose: set current file pointer
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - file
|
|
* lOffset - offset from origin
|
|
* wOrigin - origin (wSeekSet, wSeekCur, or wSeekEnd)
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: new position offset in bytes from beginning of file
|
|
* if successful, or -1L if not
|
|
*
|
|
* state OUT: File pointer is set to new position unless error occurs,
|
|
* in which case it stays where it was.
|
|
*
|
|
\***************************************************************************/
|
|
LONG PASCAL
|
|
LSeekHf(
|
|
HF hf,
|
|
LONG lOffset, /* should this be named li? */
|
|
WORD wOrigin)
|
|
{
|
|
QRWFO qrwfo;
|
|
LONG lif;
|
|
|
|
DPF3("LSeekHf %u, offs %ld, origin %u ", hf, lOffset, wOrigin);
|
|
|
|
assert( hf != NULL );
|
|
qrwfo = QLockGh( hf );
|
|
assert( qrwfo != NULL );
|
|
|
|
DPF3(" current %ld ", qrwfo->lifCurrent);
|
|
|
|
switch ( wOrigin )
|
|
{
|
|
case wFSSeekSet:
|
|
{
|
|
lif = lOffset;
|
|
break;
|
|
}
|
|
case wFSSeekCur:
|
|
{
|
|
lif = qrwfo->lifCurrent + lOffset;
|
|
break;
|
|
}
|
|
case wFSSeekEnd:
|
|
{
|
|
lif = qrwfo->lcbFile + lOffset;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
lif = (LONG)-1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( lif >= (LONG)0 )
|
|
{
|
|
qrwfo->lifCurrent = lif;
|
|
assert(qrwfo->lifCurrent>=0);
|
|
SetFSErrorRc( rcSuccess );
|
|
}
|
|
else
|
|
{
|
|
lif = (LONG)-1;
|
|
SetFSErrorRc( rcInvalid );
|
|
}
|
|
|
|
DPF3(" now %ld ", qrwfo->lifCurrent);
|
|
|
|
UnlockGh( hf );
|
|
|
|
DPF3(" returning %ld\n", lif);
|
|
|
|
return lif;
|
|
}
|