[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-kernel
Subject: Fw: Availability Dates for FENRIS (NetWare) File System for Linux Open Sources
From: "Jeff Merkey" <jmerkey () timpanogas ! com>
Date: 1999-05-31 22:38:28
[Download RAW message or body]
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
["nwfile.c" (application/octet-stream)]
/***************************************************************************
*
* 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"
ULONG NWReadFile(VOLUME *volume, DOS *dos, ULONG offset, BYTE *buf, long count)
{
register long cluster, index;
register ULONG bytesRead = 0, bytesLeft = 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 = dos->FileSize - offset;
if (count <= 0)
return 0;
// if a subdirectory then return 0
if (dos->Flags & SUBDIRECTORY_FILE)
return 0;
bytesLeft = count;
StartIndex = offset / volume->ClusterSize;
StartOffset = offset % volume->ClusterSize;
// we always start with an index of zero
index = 0;
cluster = dos->FirstBlock;
vindex = StartIndex;
if ((bytesLeft > 0) && (cluster < 0))
{
// check for EOF
if (cluster == (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 += 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 += bytesLeft;
}
return bytesRead;
}
// vindex is always equal to StartIndex here
voffset = StartOffset;
// if this value exceeds the suballoc record size,
// ReadSuballoc record will reduce this size to the
// current record allocation.
vsize = bytesLeft;
cbytes = ReadSuballocRecord(volume, voffset, cluster, buf, vsize);
bytesRead += cbytes;
bytesLeft -= cbytes;
buf += 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 += bytesLeft;
}
return bytesRead;
}
vindex = StartIndex;
FAT = GetFatEntry(volume, cluster);
if (FAT)
index = 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 = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
NWFSSetUserSpace(buf, 0, vsize);
bytesRead += vsize;
bytesLeft -= vsize;
buf += vsize;
vindex++;
}
// found our index block, perform the copy operation
if ((bytesLeft > 0) && (vindex == index))
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
cbytes = ReadClusterWithOffset(volume, cluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesRead += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
// bump to the next cluster
cluster = FAT->FATCluster;
// check if the next cluster is a suballoc element or EOF marker
if ((bytesLeft > 0) && (cluster < 0))
{
// end of file
if (cluster == (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 += bytesLeft;
}
return bytesRead;
}
// check for valid index
if ((index + 1) == vindex)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
// if this value exceeds the suballoc record size,
// ReadSuballoc record will reduce this size to the
// current record allocation.
vsize = bytesLeft;
cbytes = ReadSuballocRecord(volume, voffset, cluster, buf, vsize);
bytesRead += cbytes;
bytesLeft -= cbytes;
buf += 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 += bytesLeft;
}
return bytesRead;
}
// get next fat table entry and index
FAT = GetFatEntry(volume, cluster);
if (FAT)
index = 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 += bytesLeft;
}
return bytesRead;
}
ULONG NWWriteFile(VOLUME *volume, DOS *dos, ULONG offset, BYTE *buf, long count)
{
register long cluster, index;
register ULONG bytesWritten = 0, bytesLeft = 0, lcount = 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 = 0;
// if a subdirectory then return 0
if (dos->Flags & SUBDIRECTORY_FILE)
return 0;
bytesLeft = count;
StartIndex = offset / volume->ClusterSize;
StartOffset = offset % volume->ClusterSize;
// we always start with an index of zero
index = 0;
pcluster = cluster = dos->FirstBlock;
vindex = StartIndex;
if ((bytesLeft > 0) && (cluster < 0))
{
// check for EOF
if (cluster == (ULONG) -1)
{
// vindex is always equal to StartIndex here
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, (ULONG) -1);
if (ncluster == -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 = ncluster;
pcluster = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
while (bytesLeft > 0)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster == -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 = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
// we have detected a suballoc element in the fat chain if we
// get to this point
SuballocSize = GetSuballocSize(volume, cluster);
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
// this case assumes we will free the current suballoc element
if ((bytesLeft + voffset) > SuballocSize)
{
WorkSpace = 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 = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, (ULONG) -1);
if (ncluster == -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 = ReadSuballocData(volume, 0, cluster, WorkSpace, SuballocSize);
if (cbytes != SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// now write the previous data from the suballoc element
// into the newly allocated cluster.
cbytes = WriteClusterWithOffset(volume, ncluster, 0, WorkSpace, SuballocSize,
KERNEL_ADDRESS_SPACE);
if (cbytes != SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// free the suballoc element in bit block list
FreeSuballocRecord(volume, cluster);
// this case
dos->FirstBlock = ncluster;
pcluster = ncluster;
// now write the user data into the suballoc element
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
NWFSFree(WorkSpace);
while (bytesLeft > 0)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster == -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 = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
else
{
// 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 = StartOffset;
// at this point, bytesLeft is either equal to or
// less than the size of the current suballocation
// record.
vsize = bytesLeft;
cbytes = WriteSuballocRecord(volume, voffset, cluster, buf, vsize);
bytesWritten += cbytes;
bytesLeft -= cbytes;
return (bytesWritten ? bytesWritten : -1);
}
}
FAT = GetFatEntryAndLRU(volume, cluster, &lru);
if (FAT)
index = 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))
{
// 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 = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to next cluster
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, cluster);
if (ncluster == -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 != cluster)
? SetClusterValue(volume, pcluster, ncluster)
: (dos->FirstBlock = ncluster);
// update previous cluster to new cluster
pcluster = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
// found our index block, perform the copy operation
if ((bytesLeft > 0) && (vindex == index))
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
cbytes = WriteClusterWithOffset(volume, cluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
// save the previous cluster
pcluster = cluster;
// bump to the next cluster
cluster = FAT->FATCluster;
// check if the next cluster is a suballoc element or EOF
if ((bytesLeft > 0) && (cluster < 0))
{
// end of file
if (cluster == (ULONG) -1)
{
while (bytesLeft > 0)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster == -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 = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
// we have detected a suballoc element in the fat chain if we
// get to this point
SuballocSize = GetSuballocSize(volume, cluster);
voffset = 0;
if (vindex == StartIndex)
voffset = 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 = 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 = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster == -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 = ReadSuballocData(volume, 0, cluster, WorkSpace, SuballocSize);
if (cbytes != SuballocSize)
{
NWFSFree(WorkSpace);
return (bytesWritten ? bytesWritten : -1);
}
// now write the previous data from the suballoc element
// into the newly allocated cluster.
cbytes = WriteClusterWithOffset(volume, ncluster, 0, WorkSpace, SuballocSize,
KERNEL_ADDRESS_SPACE);
if (cbytes != 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 = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
NWFSFree(WorkSpace);
while (bytesLeft > 0)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
vsize = (bytesLeft > (volume->ClusterSize - voffset))
? (volume->ClusterSize - voffset) : bytesLeft;
// allocate cluster and point forward link to EOF
ncluster = AllocateClusterSetIndexSetChain(volume, vindex, -1);
if (ncluster == -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 = ncluster;
cbytes = WriteClusterWithOffset(volume, ncluster, voffset, buf, vsize,
USER_ADDRESS_SPACE);
bytesWritten += cbytes;
bytesLeft -= cbytes;
buf += cbytes;
vindex++;
}
return (bytesWritten ? bytesWritten : -1);
}
else
{
// 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) == vindex)
{
voffset = 0;
if (vindex == StartIndex)
voffset = StartOffset;
// at this point, bytesLeft is either equal to or
// less than the size of the current suballocation
// record.
vsize = bytesLeft;
cbytes = WriteSuballocRecord(volume, voffset, cluster,
buf, vsize);
bytesWritten += cbytes;
bytesLeft -= cbytes;
}
}
return (bytesWritten ? bytesWritten : -1);
}
// get next fat table entry and index
FAT = GetFatEntryAndLRU(volume, cluster, &lru);
// if the fat chain terminates, then exit
if (!FAT)
return (bytesWritten ? bytesWritten : -1);
index = FAT->FATIndex;
lcount++;
}
return (bytesWritten ? bytesWritten : -1);
}
-
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/
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic