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