Fw: Availability Dates for FENRIS (NetWare) File System for Linux Open Sources
Jeff Merkey (jmerkey@timpanogas.com)
Mon, 31 May 1999 13:52:08 -0600
This is a multi-part message in MIME format.
------=_NextPart_000_0045_01BEAB6C.C69C9200
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0046_01BEAB6C.C69C9200"
------=_NextPart_001_0046_01BEAB6C.C69C9200
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
----- Original Message -----=20
From: Jeff Merkey=20
To: linux-kernel@vger.rutgers.edu=20
Sent: Monday, May 31, 1999 11:14 AM
Subject: Availability Dates for FENRIS (NetWare) File System for Linux =
Open Sources
Linux Community,
We had planned on June 1, 1999 as for release of the tar containing the =
source code for FENRIS on our website, however, we had forgotten that =
Moday May 31, 1999 is a US holiday (Memorial Day). As such, FENRIS will =
be available the following day in the evening.
We apologize for the inconveniance. The FENRIS For Linux tar containing =
the source code for version 1.4 of NWFS for Linux will be available June =
3, 1999 in the morning for download from www.timpanogas.com. We will =
make one final code review pass for bugs and completeness on June 2, =
1999, then the code will be available from our website either the =
evening of June 2, 1999 or the following morning (depending on where on =
planet earth you are when we publish it to our site). We also are =
putting in a fix for Document Solutions in Alabama that allows Linux to =
mount NetWare volumes > 560 GB in size, we are finalizing these changes. =
=20
The license statement for this open source is in an attached source file =
for everyone's review. Anyone wanting to make changes or comments to =
the license needs to get this info to us NLT June 2, 1999 before we =
publish the code. Also, anyone who feels they contributed that may left =
out should let us know so we can get your names into the first release =
as contributors.
We will also be posting a subsequent release of the Open Source 1.5 in =
two weeks, and two weeks thereafter we will post 1.6 (around July 1, =
1999). Releases will then follow as required for bug fixes and =
enhancements. It is anticipated at some point, we will release =
quarterly to all. The two interim releases for June are to integrate =
bug fixes and to put some final touches on 4 and 8 way volume mirroring, =
and write hotfixing.=20
The nwfs-utils tar containing the open source code utilities to fsck, =
create, and maintain NetWare volume and partitions will be available =
later in the week, and will also be part of the nwfs quarterly releases.
Very Truly Yours,
Jeff Merkey
CEO, TRG
------=_NextPart_001_0046_01BEAB6C.C69C9200
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
----- Original Message -----=20
Sent: Monday, May 31, 1999 11:14 AM
Subject: Availability Dates for FENRIS (NetWare) File System =
for=20
Linux Open Sources
Linux Community,
We had planned on June 1, 1999 as for =
release of=20
the tar containing the source code for FENRIS on our website, however, =
we had=20
forgotten that Moday May 31, 1999 is a US holiday (Memorial Day). =
As such,=20
FENRIS will be available the following day in the evening.
We apologize for the =
inconveniance. The=20
FENRIS For Linux tar containing the source code for version 1.4 of NWFS =
for=20
Linux will be available June 3, 1999 in the morning for download from www.timpanogas.com. We will =
make one=20
final code review pass for bugs and completeness on June 2, 1999, then =
the code=20
will be available from our website either the evening of June 2, 1999 or =
the=20
following morning (depending on where on planet earth you are when we =
publish it=20
to our site). We also are putting in a fix for Document Solutions =
in=20
Alabama that allows Linux to mount NetWare volumes > 560 GB in size, =
we are=20
finalizing these changes.
The license statement for this open =
source is in an=20
attached source file for everyone's review. Anyone =
wanting to=20
make changes or comments to the license needs to get this info to us NLT =
June 2,=20
1999 before we publish the code. Also, anyone who feels they =
contributed=20
that may left out should let us know so we can get your names into the =
first=20
release as contributors.
We will also be posting a subsequent =
release of the=20
Open Source 1.5 in two weeks, and two weeks thereafter we will post 1.6 =
(around=20
July 1, 1999). Releases will then follow as required for bug fixes =
and=20
enhancements. It is anticipated at some point, we will release =
quarterly=20
to all. The two interim releases for June are to integrate bug =
fixes and=20
to put some final touches on 4 and 8 way volume mirroring, and write=20
hotfixing.
The nwfs-utils tar containing the open =
source code=20
utilities to fsck, create, and maintain NetWare volume and =
partitions will=20
be available later in the week, and will also be part of the nwfs =
quarterly=20
releases.
Very Truly =
Yours,
Jeff Merkey
CEO, TRG
------=_NextPart_001_0046_01BEAB6C.C69C9200--
------=_NextPart_000_0045_01BEAB6C.C69C9200
Content-Type: application/octet-stream;
name="nwfile.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="nwfile.c"
/************************************************************************=
***
*
* Copyright (c) 1998, 1999 Timpanogas Research Group, Inc.
* 895 West Center Street
* Orem, Utah 84057
* jmerkey@timpanogas.com
*
* This program is free software; you can redistribute it and/or modify =
it
* under the terms of the GNU General Public License as published by =
the
* Free Software Foundation, version 2, or any later version.
*
* This program 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 GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License =
along
* with this program; if not, write to the Free Software Foundation, =
Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* You are free to modify and re-distribute this program in accordance
* with the terms specified in the GNU Public License. The copyright
* contained in this code is required to be present in any derivative
* works and you are required to provide the source code for this
* program as part of any commercial or non-commercial distribution.
* You are required to respect the rights of the Copyright holders
* named within this code.
*
* jmerkey@timpanogas.com and TRG, Inc. are the official maintainers of
* this code. You are encouraged to report any bugs, problems, fixes,
* suggestions, and comments about this software to =
jmerkey@timpanogas.com
* or linux-kernel@vger.rutgers.edu. New releases, patches, bug fixes, =
and
* technical documentation can be found at www.timpanogas.com. TRG =
will
* periodically post new releases of this software to =
www.timpanogas.com
* that contain bug fixes and enhanced capabilities.
*
* Original Authorship : v1.4
* source code written by Jeff V. Merkey, TRG, Inc. 11/1/98 to =
6/1/99
*
* Original Contributors : v1.4
* engineer consulting Jeff V. Merkey, TRG, Inc. 11/1/98 to =
6/1/99
* technical consulting Darren Major, TRG, Inc. 11/1/98 to =
6/1/99
* technical consulting Drew Spencer, Caldera Systems 11/1/98 to =
6/1/99
* technical consulting Steve Spicer, Document Solutions 4/15/99 =
6/1/99
* (testing for very large NetWare volumes > 560 GB)
*
*************************************************************************=
***
*
*
* AUTHOR : Jeff V. Merkey (jmerkey@timpanogas.com)
* FILE : NWFILE.C
* DESCRIP : FENRIS NetWare File Management
* DATE : December 14, 1998
*
*
*************************************************************************=
**/
#include "version.h"
#include "globals.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "nwfs.h"
#include "nwstruct.h"
#include "nwdir.h"
#include "hash.h"
#include "externs.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
ULONG NWReadFile(VOLUME *volume, DOS *dos, ULONG offset, BYTE *buf, long =
count)
{
register long cluster, index;
register ULONG bytesRead =3D 0, bytesLeft =3D 0;
register ULONG StartIndex, StartOffset;
register FAT_ENTRY *FAT;
register ULONG voffset, vsize, vindex, cbytes;
// adjust size and range check for EOF
if ((offset + count) > dos->FileSize)
count =3D dos->FileSize - offset;
if (count <=3D 0)
return 0;
// if a subdirectory then return 0
if (dos->Flags & SUBDIRECTORY_FILE)
return 0;
bytesLeft =3D count;
StartIndex =3D offset / volume->ClusterSize;
StartOffset =3D offset % volume->ClusterSize;
// we always start with an index of zero
index =3D 0;
cluster =3D dos->FirstBlock;
vindex =3D StartIndex;
if ((bytesLeft > 0) && (cluster < 0))
{
// check for EOF
if (cluster =3D=3D (ULONG) -1)
{
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size. bytesLeft will have been set by count, which is
// range checked to the actual length of the file.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
// index should be null here
if (StartIndex)
{
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
// vindex is always equal to StartIndex here
voffset =3D StartOffset;
// if this value exceeds the suballoc record size,
// ReadSuballoc record will reduce this size to the
// current record allocation.
vsize =3D bytesLeft;
cbytes =3D ReadSuballocRecord(volume, voffset, cluster, buf, =
vsize);
bytesRead +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
vindex =3D StartIndex;
FAT =3D GetFatEntry(volume, cluster);
if (FAT)
index =3D FAT->FATIndex;
while (FAT && FAT->FATCluster && (bytesLeft > 0))
{
// if we found a hole, then return zeros until we
// either satisfy the requested read size or
// we span to the next valid index entry
while ((bytesLeft > 0) && (vindex < index))
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
NWFSSetUserSpace(buf, 0, vsize);
bytesRead +=3D vsize;
bytesLeft -=3D vsize;
buf +=3D vsize;
vindex++;
}
// found our index block, perform the copy operation
if ((bytesLeft > 0) && (vindex =3D=3D index))
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
cbytes =3D ReadClusterWithOffset(volume, cluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesRead +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
// bump to the next cluster
cluster =3D FAT->FATCluster;
// check if the next cluster is a suballoc element or EOF marker
if ((bytesLeft > 0) && (cluster < 0))
{
// end of file
if (cluster =3D=3D (ULONG) -1)
{
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
// check for valid index
if ((index + 1) =3D=3D vindex)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
// if this value exceeds the suballoc record size,
// ReadSuballoc record will reduce this size to the
// current record allocation.
vsize =3D bytesLeft;
cbytes =3D ReadSuballocRecord(volume, voffset, cluster, buf, =
vsize);
bytesRead +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
}
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
// get next fat table entry and index
FAT =3D GetFatEntry(volume, cluster);
if (FAT)
index =3D FAT->FATIndex;
}
// filesize may exceed allocation, which means the rest of
// the file is sparse. fill zeros into the requested
// size.
if (bytesLeft > 0)
{
NWFSSetUserSpace(buf, 0, bytesLeft);
bytesRead +=3D bytesLeft;
}
return bytesRead;
}
#define STAGE_WRITE 0
ULONG NWWriteFile(VOLUME *volume, DOS *dos, ULONG offset, BYTE *buf, =
long count)
{
register long cluster, index;
register ULONG bytesWritten =3D 0, bytesLeft =3D 0, lcount =3D 0;
register ULONG StartIndex, StartOffset, SuballocSize;
register FAT_ENTRY *FAT;
register ULONG voffset, vsize, vindex, cbytes;
register long pcluster, ncluster;
register BYTE *WorkSpace;
MIRROR_LRU *lru =3D 0;
// if a subdirectory then return 0
if (dos->Flags & SUBDIRECTORY_FILE)
return 0;
bytesLeft =3D count;
StartIndex =3D offset / volume->ClusterSize;
StartOffset =3D offset % volume->ClusterSize;
// we always start with an index of zero
index =3D 0;
pcluster =3D cluster =3D dos->FirstBlock;
vindex =3D StartIndex;
if ((bytesLeft > 0) && (cluster < 0))
{
// check for EOF
if (cluster =3D=3D (ULONG) -1)
{
#if (STAGE_WRITE)
NWFSPrint("[1] ");
#endif
// vindex is always equal to StartIndex here
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, (ULONG) =
-1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// this case
dos->FirstBlock =3D ncluster;
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
while (bytesLeft > 0)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// set previous cluster chain to point to this entry
SetClusterValue(volume, pcluster, ncluster);
// update previous cluster to new cluster
// this will force inserts after the end of this cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
// we have detected a suballoc element in the fat chain if we
// get to this point
#if (STAGE_WRITE)
NWFSPrint("[2] ");
#endif
SuballocSize =3D GetSuballocSize(volume, cluster);
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
// this case assumes we will free the current suballoc element
if ((bytesLeft + voffset) > SuballocSize)
{
WorkSpace =3D NWFSCacheAlloc(SuballocSize, SA_WORKSPACE_TAG);
if (!WorkSpace)
{
// if we could not get memory to copy the suballoc record,
// then return (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, (ULONG) =
-1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// here we read the previous data from the suballoc element
cbytes =3D ReadSuballocData(volume, 0, cluster, WorkSpace, =
SuballocSize);
if (cbytes !=3D SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// now write the previous data from the suballoc element
// into the newly allocated cluster.
cbytes =3D WriteClusterWithOffset(volume, ncluster, 0, WorkSpace, =
SuballocSize,
KERNEL_ADDRESS_SPACE);
if (cbytes !=3D SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// free the suballoc element in bit block list
FreeSuballocRecord(volume, cluster);
// this case
dos->FirstBlock =3D ncluster;
pcluster =3D ncluster;
// now write the user data into the suballoc element
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
NWFSFree(WorkSpace);
while (bytesLeft > 0)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// set previous cluster chain to point to this entry
SetClusterValue(volume, pcluster, ncluster);
// update previous cluster to new cluster
// this will force inserts after the end of this cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
else
{
#if (STAGE_WRITE)
NWFSPrint("[3] ");
#endif
// for this case, since our target write size fits within
// the previously allocated suballoc element, then just
// write the data.
// vindex will always be equal to StartIndex here
voffset =3D StartOffset;
// at this point, bytesLeft is either equal to or
// less than the size of the current suballocation
// record.
vsize =3D bytesLeft;
cbytes =3D WriteSuballocRecord(volume, voffset, cluster, buf, vsize);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
return (bytesWritten ? bytesWritten : -1);
}
}
FAT =3D GetFatEntryAndLRU(volume, cluster, &lru);
if (FAT)
index =3D FAT->FATIndex;
while (FAT && FAT->FATCluster && (bytesLeft > 0))
{
// if we found a hole, then allocate and add a new cluster
// to the file and continue to add clusters and write until
// bytesLeft is < 0 or we find the next valid cluster in the
// fat chain
while ((bytesLeft > 0) && (vindex < index))
{
#if (STAGE_WRITE)
NWFSPrint("[4] ");
#endif
// we can only get here if we detected the next
// fat element is greater than the target index
// (the file has holes, and we hit an index
// larger than we expected).
// we simply extend the file by allocating clusters
// until we complete the write or the target index
// equals the current cluster. obvioulsy, we must
// insert nodes into the fat chain for each element we
// allocate.
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to next cluster
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, =
cluster);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// set previous cluster chain to point to this entry
// if pcluster and cluster are equal, then we are
// inserting at the front of the cluster chain
// so adjust the directory block
(pcluster !=3D cluster)
? SetClusterValue(volume, pcluster, ncluster)
: (dos->FirstBlock =3D ncluster);
// update previous cluster to new cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
// found our index block, perform the copy operation
if ((bytesLeft > 0) && (vindex =3D=3D index))
{
#if (STAGE_WRITE)
NWFSPrint("[5] ");
#endif
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
cbytes =3D WriteClusterWithOffset(volume, cluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
// save the previous cluster
pcluster =3D cluster;
// bump to the next cluster
cluster =3D FAT->FATCluster;
// check if the next cluster is a suballoc element or EOF
if ((bytesLeft > 0) && (cluster < 0))
{
// end of file
if (cluster =3D=3D (ULONG) -1)
{
#if (STAGE_WRITE)
NWFSPrint("[6] ");
#endif
while (bytesLeft > 0)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// set previous cluster chain to point to this entry
SetClusterValue(volume, pcluster, ncluster);
// update previous cluster to new cluster
// this will force inserts after the end of this cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
// we have detected a suballoc element in the fat chain if we
// get to this point
#if (STAGE_WRITE)
NWFSPrint("[7] ");
#endif
SuballocSize =3D GetSuballocSize(volume, cluster);
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
// this case assumes we will free the current suballoc element
// and copy it to a cluster or another suballoc element
if ((bytesLeft + voffset) > SuballocSize)
{
WorkSpace =3D NWFSCacheAlloc(SuballocSize, SA_WORKSPACE_TAG);
if (!WorkSpace)
{
// if we could not get memory to copy the suballoc record,
// then return (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// here we read the previous data from the suballoc element
cbytes =3D ReadSuballocData(volume, 0, cluster, WorkSpace, =
SuballocSize);
if (cbytes !=3D SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// now write the previous data from the suballoc element
// into the newly allocated cluster.
cbytes =3D WriteClusterWithOffset(volume, ncluster, 0, WorkSpace, =
SuballocSize,
KERNEL_ADDRESS_SPACE);
if (cbytes !=3D SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// free the suballoc element in bit block list
FreeSuballocRecord(volume, cluster);
// set previous cluster chain to point to this entry
SetClusterValue(volume, pcluster, ncluster);
// update previous cluster to new cluster
// this will force inserts after the end of this cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
NWFSFree(WorkSpace);
while (bytesLeft > 0)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
vsize =3D (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster =3D AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster =3D=3D -1)
{
// if we could not get a free cluster, then return
// (out of drive space)
return (bytesWritten ? bytesWritten : -1);
}
// zero fill the new cluster
ZeroPhysicalVolumeCluster(volume, ncluster);
// set previous cluster chain to point to this entry
SetClusterValue(volume, pcluster, ncluster);
// update previous cluster to new cluster
// this will force inserts after the end of this cluster
pcluster =3D ncluster;
cbytes =3D WriteClusterWithOffset(volume, ncluster, voffset, buf, =
vsize,
USER_ADDRESS_SPACE);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
buf +=3D cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
else
{
#if (STAGE_WRITE)
NWFSPrint("[8] ");
#endif
// for this case, since our target write size fits within
// the previously allocated suballoc element, then just
// write the data.
// check for valid index
if ((index + 1) =3D=3D vindex)
{
voffset =3D 0;
if (vindex =3D=3D StartIndex)
voffset =3D StartOffset;
// at this point, bytesLeft is either equal to or
// less than the size of the current suballocation
// record.
vsize =3D bytesLeft;
cbytes =3D WriteSuballocRecord(volume, voffset, cluster,
buf, vsize);
bytesWritten +=3D cbytes;
bytesLeft -=3D cbytes;
}
}
return (bytesWritten ? bytesWritten : -1);
}
// get next fat table entry and index
FAT =3D GetFatEntryAndLRU(volume, cluster, &lru);
// if the fat chain terminates, then exit
if (!FAT)
return (bytesWritten ? bytesWritten : -1);
index =3D FAT->FATIndex;
lcount++;
}
return (bytesWritten ? bytesWritten : -1);
}
ULONG NWExclusiveWriteFile(VOLUME *volume, DOS *dos, HASH *hash,
ULONG offset, BYTE *buf, long count)
{
register ULONG retCode;
NWLockDirectory(hash);
retCode =3D NWWriteFile(volume, dos, offset, buf, count);
NWUnlockDirectory(hash);
return retCode;
}
ULONG TrgDebugTrans =3D 0;
NW_STATUS TrgGetPartitionInfoFromVolumeInfo(IN ULONG VolumeNumber,
IN ULONG SectorOffsetInVolume,
OUT void **PartitionPointer,
OUT ULONG *SectorOffsetInPartition,
OUT ULONG *SectorsLeftInSegment)
{
register VOLUME *volume =3D VolumeTable[VolumeNumber];
register ULONG i, ClusterOffset, SectorOffset, ClusterTotal =3D 0;
register ULONG VirtualSectorOffset, VirtualSegmentOffset;
register NWPART *NWPart;
ClusterOffset =3D (SectorOffsetInVolume / =
volume->SectorsPerCluster);
SectorOffset =3D (SectorOffsetInVolume % volume->SectorsPerCluster);
for (i=3D0; i < volume->NumberOfSegments; i++)
{
#if VERBOSE
if (TrgDebugTrans)
{
NWPart =3D volume->Partitions[i];
NWFSPrint("[0x%08X] start-%X sba-%X\n",
NWPart->PartitionPointer,
volume->Segments[i]->SegmentClusterStart,
volume->SegmentBlockAddress[i]);
}
#endif
if (volume->Segments[i])
{
if ((ClusterOffset >=3D ClusterTotal) &&
(ClusterOffset < (volume->SegmentClusters[i] + ClusterTotal)))
{
NWPart =3D volume->Partitions[i];
*PartitionPointer =3D NWPart->PartitionPointer;
VirtualSegmentOffset =3D ((ClusterOffset -
volume->Segments[i]->SegmentClusterStart) *
volume->SectorsPerCluster) +
SectorOffset;
VirtualSectorOffset =3D VirtualSegmentOffset +
(volume->SegmentBlockAddress[i] *
volume->SectorsPerBlock);
#if VERBOSE
if (TrgDebugTrans)
{
NWFSPrint("clstr-%X total-%X rclstr-%X start-%X [0x%08X]\n",
(unsigned int)ClusterOffset,
(unsigned int)volume->VolumeClusters,
(unsigned int)(ClusterOffset - =
volume->Segments[i]->SegmentClusterStart),
(unsigned int)volume->Segments[i]->SegmentClusterStart,
(unsigned int)NWPart->PartitionPointer);
NWFSPrint("vso-%X + [(sba-%X * spb-8) =3D -%X] vso-%X\n",
(unsigned int)VirtualSegmentOffset,
(unsigned int)volume->SegmentBlockAddress[i],
(unsigned int)(volume->SegmentBlockAddress[i] * =
volume->SectorsPerBlock),
(unsigned int)VirtualSegmentOffset);
}
#endif
*SectorOffsetInPartition =3D VirtualSectorOffset;
*SectorsLeftInSegment =3D (volume->SegmentClusters[i] *
volume->SectorsPerCluster) -
VirtualSegmentOffset;
return NwSuccess;
}
ClusterTotal +=3D volume->SegmentClusters[i];
}
}
return NwInvalidParameter;
}
NW_STATUS TrgLookupFileAllocation(IN ULONG VolumeNumber,
IN HASH *hash,
IN ULONG *StartingSector,
IN ULONG *Context,
OUT ULONG *SectorOffsetInVolume,
OUT ULONG *SectorCount)
{
register ULONG StreamSize, StreamOffset, SpanningClusters;
register VOLUME *volume =3D VolumeTable[VolumeNumber];
register long cluster, index;
register ULONG StartIndex, StartOffset, rc;
register FAT_ENTRY *FAT, *LFAT;
SUBALLOC_MAP map;
// if a subdirectory then return error
if (!hash || hash->Flags & SUBDIRECTORY_FILE)
return NwInvalidParameter;
// get the proper namespace stream cluster and size
switch (hash->NameSpace)
{
case DOS_NAME_SPACE:
case MAC_NAME_SPACE:
cluster =3D hash->FirstBlock;
StreamSize =3D hash->FileSize;
break;
default:
return NwInvalidParameter;
}
// calculate a size offset and range check for EOF
StreamOffset =3D ((*StartingSector) * 512);
// make certain to round the file size up to the next sector boundry
if (StreamOffset > ((StreamSize + 511) & ~511))
return NwEndOfFile;
StartIndex =3D StreamOffset / volume->ClusterSize;
StartOffset =3D StreamOffset % volume->ClusterSize;
// we always start with an index of zero
index =3D 0;
if (cluster < 0)
{
// check for EOF
if (cluster =3D=3D (ULONG) -1)
{
*Context =3D 0;
return NwEndOfFile;
}
// index must be null here
if (StartIndex)
{
*Context =3D 0;
return NwEndOfFile;
}
rc =3D MapSuballocNode(volume, &map, cluster);
if (rc)
{
*Context =3D 0;
return NwFileCorrupt;
}
if (StartOffset >=3D map.Size)
{
*Context =3D 0;
return NwEndOfFile;
}
if (StartOffset >=3D map.clusterSize[0])
{
if (map.Count =3D=3D 1)
{
*Context =3D 0;
return NwEndOfFile;
}
*StartingSector =3D (StartIndex * volume->SectorsPerCluster) +
(map.clusterSize[0] / 512);
*SectorCount =3D (map.clusterSize[1] / 512);
*SectorOffsetInVolume =3D (map.clusterNumber[1] * =
volume->SectorsPerCluster) +
(map.clusterOffset[1] / 512);
*Context =3D 0;
return NwSuccess;
}
else
{
*StartingSector =3D (StartIndex * volume->SectorsPerCluster);
*SectorCount =3D (map.clusterSize[0] / 512);
*SectorOffsetInVolume =3D (map.clusterNumber[0] * =
volume->SectorsPerCluster) +
(map.clusterOffset[0] / 512);
*Context =3D 0;
return NwSuccess;
}
}
FAT =3D GetFatEntry(volume, cluster);
if (FAT)
index =3D FAT->FATIndex;
while (FAT && FAT->FATCluster)
{
// we detected a hole in the file
if (StartIndex < index)
{
*StartingSector =3D (StartIndex * volume->SectorsPerCluster);
*SectorOffsetInVolume =3D 0;
// return the full size of the hole as a single run
*SectorCount =3D volume->SectorsPerCluster +
((index - StartIndex) * volume->SectorsPerCluster);
*Context =3D cluster; // point to this cluster
return NwSuccess;
}
// we found our cluster in the chain
if (StartIndex =3D=3D index)
{
*StartingSector =3D (StartIndex * volume->SectorsPerCluster);
*SectorOffsetInVolume =3D (cluster * volume->SectorsPerCluster);
// see how far this span runs continguous by checking both
// the index and the cluster number of this fat entry.
NWFSPrint("clstr-%X index-%d nclstr-%X nindex-%d\n",
(unsigned int) cluster,
(int) index,
(unsigned int) FAT->FATCluster,
(int) FAT->FATIndex);
for (SpanningClusters =3D 0;
FAT && FAT->FATCluster &&
(FAT->FATCluster =3D=3D (cluster + 1)) &&
(FAT->FATCluster > 0) && cluster > 0; )
{
// check if next index number is also in sequence
LFAT =3D GetFatEntry(volume, FAT->FATCluster);
if (LFAT)
{
if (LFAT->FATIndex !=3D (index + 1))
break;
}
SpanningClusters++;
cluster =3D FAT->FATCluster;
if (cluster < 0)
break;
// get next fat table entry and index
FAT =3D GetFatEntry(volume, cluster);
if (FAT)
index =3D FAT->FATIndex;
}
// return size of run plus any contiguous clusters we detected
*SectorCount =3D volume->SectorsPerCluster +
(SpanningClusters * volume->SectorsPerCluster);
*Context =3D FAT->FATCluster; // point to next cluster
return NwSuccess;
}
// bump to the next cluster
cluster =3D FAT->FATCluster;
// check if the next cluster is a suballoc element or EOF marker
if (cluster < 0)
{
// end of file
if (cluster =3D=3D (ULONG) -1)
{
*Context =3D 0;
return NwEndOfFile;
}
// check for valid index
if ((index + 1) =3D=3D StartIndex)
{
rc =3D MapSuballocNode(volume, &map, cluster);
if (rc)
{
*Context =3D 0;
return NwFileCorrupt;
}
if (StartOffset >=3D map.Size)
{
*Context =3D 0;
return NwEndOfFile;
}
if (StartOffset >=3D map.clusterSize[0])
{
if (map.Count =3D=3D 1)
{
*Context =3D 0;
return NwEndOfFile;
}
*StartingSector =3D (StartIndex * volume->SectorsPerCluster) +
(map.clusterSize[0] / 512);
*SectorCount =3D (map.clusterSize[1] / 512);
*SectorOffsetInVolume =3D (map.clusterNumber[1] * =
volume->SectorsPerCluster) +
(map.clusterOffset[1] / 512);
*Context =3D 0;
return NwSuccess;
}
else
{
*StartingSector =3D (StartIndex * volume->SectorsPerCluster);
*SectorCount =3D (map.clusterSize[0] / 512);
*SectorOffsetInVolume =3D (map.clusterNumber[0] * =
volume->SectorsPerCluster) +
(map.clusterOffset[0] / 512);
*Context =3D 0;
return NwSuccess;
}
}
return NwEndOfFile;
}
// get next fat table entry and index
FAT =3D GetFatEntry(volume, cluster);
if (FAT)
index =3D FAT->FATIndex;
}
return NwEndOfFile;
}
------=_NextPart_000_0045_01BEAB6C.C69C9200--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/