Fw: Availability Dates for FENRIS (NetWare) File System for Linux Open Sources (non-HTML version)

Jeff Merkey (jmerkey@timpanogas.com)
Mon, 31 May 1999 15:20:41 -0600


This is a multi-part message in MIME format.

------=_NextPart_000_0047_01BEAB79.25032C30
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Some folks requested a "non- Microsoft LookOut Version". Here you go.

Jeff

----- Original Message -----
From: Jeff Merkey
To: linux-kernel@vger.rutgers.edu
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.

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.

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_000_0047_01BEAB79.25032C30
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 <linux/module.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/modversions.h>

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_0047_01BEAB79.25032C30--

-
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/