home *** CD-ROM | disk | FTP | other *** search
- /*-
- * $Id: hanfile.c,v 1.6 90/02/10 21:38:26 Rhialto Exp $
- * $Log: hanfile.c,v $
- * Revision 1.6 90/02/10 21:38:26 Rhialto
- * Optimized 12-bit fat unpacking.
- *
- * Revision 1.5 90/01/27 20:26:51 Rhialto
- * Fixed ATTR_ARCHIVED bit in MSWrite()
- *
- * Revision 1.4 90/01/23 02:32:23 Rhialto
- * Add 16-bit FAT support.
- *
- * Revision 1.3 90/01/23 00:39:04 Rhialto
- * Always return -1 on MSWrite error.
- *
- * Revision 1.2 89/12/17 23:04:39 Rhialto
- * Add ATTR_READONLY support
- *
- * Revision 1.1 89/12/17 20:03:11 Rhialto
- * Initial revision
- *
- * HANFILE.C
- *
- * The code for the messydos file system handler.
- *
- * This parts handles files and the File Allocation Table.
- *
- * This code is (C) Copyright 1989,1990 by Olaf Seibert. All rights reserved.
- * May not be used or copied without a licence.
- -*/
-
- #include "han.h"
- #include "dos.h"
-
- #ifdef DEBUG
- # define debug(x) dbprintf x
- #else
- # define debug(x)
- #endif
-
- extern char DotDot[1 + 8 + 3];
-
- /*
- * Read the FAT from the disk, and count the free clusters.
- */
-
- int
- GetFat()
- {
- int i;
- byte *secptr;
-
- if (!Fat && !(Fat = AllocMem((long) Disk.bps * Disk.spf, BufMemType))) {
- debug(("No memory for FAT\n"));
- return 0;
- }
- FatDirty = FALSE;
- for (i = 0; i < Disk.spf; i++) {
- if (secptr = GetSec(Disk.res + i)) {
- CopyMem(secptr, Fat + i * Disk.bps, (long) Disk.bps);
- FreeSec(secptr);
- } else {
- /* q&d way to set the entire FAT to FAT_EOF */
- setmem(Fat + i * Disk.bps, (int) Disk.bps, FAT_EOF); /* 0xFF */
- }
- }
-
- debug(("counting free clusters\n"));
-
- Disk.nsectsfree = 0;
- for (i = MS_FIRSTCLUST; i <= Disk.maxclst; i++) {
- if (GetFatEntry((word) i) == FAT_UNUSED)
- Disk.nsectsfree += Disk.spc;
- }
-
- return 1;
- }
-
- void
- FreeFat()
- {
- if (Fat) {
- FreeMem(Fat, (long) Disk.bps * Disk.spf);
- Fat = NULL;
- FatDirty = FALSE;
- }
- }
-
- /*-
- * The FAT consists of 12-bits entries for each cluster,
- * indicating the next cluster in the chain, or FFF for EOF.
- *
- * Every two entries are packed in three bytes, like this:
- *
- * Two entries abc 123 (for one cluster and the next)
- * are packed as bc 3a 12
- -*/
-
- word
- GetFatEntry(cluster)
- word cluster;
- {
- if (!Fat && !GetFat())
- return FAT_EOF;
-
- if (Disk.fat16bits) {
- return OtherEndianWord(((word *)Fat)[cluster]);
- } else {
- register int offset = 3 * (cluster / 2);
- register word twoentries;
-
- if (cluster & 1) {
- twoentries = Fat[offset + 1] >> 4;
- twoentries |= Fat[offset + 2] << 4;
- } else {
- twoentries = Fat[offset];
- twoentries |= (Fat[offset + 1] & 0x0F) << 8;
- }
-
- /*
- * Convert the special values 0xFF0 .. 0xFFF to 16 bits so they
- * can be checked consistently.
- */
- if (twoentries >= 0xFF0)
- twoentries |= 0xF000;
-
- return twoentries;
- }
- }
-
- #ifndef READONLY
-
- void
- SetFatEntry(cluster, value)
- word cluster;
- word value;
- {
- if (!Fat && !GetFat())
- return;
-
- if (Disk.fat16bits) {
- ((word *)Fat)[cluster] = OtherEndianWord(value);
- } else {
- register int offset = 3 * (cluster / 2);
-
- if (cluster & 1) { /* 123 kind of entry */
- Fat[offset + 2] = value >> 4;
- Fat[offset + 1] &= 0x0F;
- Fat[offset + 1] |= (value & 0x0F) << 4;
- } else { /* abc kind of entry */
- Fat[offset + 0] = value;
- Fat[offset + 1] &= 0xF0;
- Fat[offset + 1] |= (value >> 8) & 0x0F;
- }
- }
-
- FatDirty = TRUE;
- }
-
- /*
- * Find a free cluster to install as the one following this one. Start
- * looking for it right after the given one, so we allocate the cluster
- * chain as contiguous as possible. If we run off the end of the disk, we
- * start again at the beginning. The termination test should not be
- * necessary (and won't work if we are given MSFIRSTCLUST - 1) but won't
- * harm either.
- */
-
- word
- FindFreeCluster(prev)
- word prev;
- {
- register word i;
-
- if (prev == 0 || prev == FAT_EOF)
- prev = MS_FIRSTCLUST - 1;
-
- if (Disk.nsectsfree >= Disk.spc) {
- for (i = prev + 1; i != prev; i++) {
- if (i > Disk.maxclst) /* Wrap around */
- i = MS_FIRSTCLUST;
- if (GetFatEntry(i) == FAT_UNUSED) {
- SetFatEntry(i, FAT_EOF);
- if (prev >= MS_FIRSTCLUST)
- SetFatEntry(prev, i);
- Disk.nsectsfree -= Disk.spc;
- return i;
- }
- }
- }
- return FAT_EOF;
- }
-
- /*
- * Add a cluster to a cluster chain. For input, we get some cluster we
- * know that is on the chain, even if it is the first one.
- */
-
- word
- ExtendClusterChain(cluster)
- register word cluster;
- {
- register word nextcluster;
-
- /*
- * Find the end of the cluster chain to tack the new cluster on to.
- * Then FindFreeCluster will (or won't) extend the chain for us.
- */
- if (cluster != 0)
- while ((nextcluster = NextCluster(cluster)) != FAT_EOF) {
- cluster = nextcluster;
- }
-
- return FindFreeCluster(cluster);
- }
-
- /*
- * Free a chain of clusters by setting their FAT entries to FAT_UNUSED.
- */
-
- void
- FreeClusterChain(cluster)
- register word cluster;
- {
- register word nextcluster;
-
- while (cluster != FAT_EOF) {
- nextcluster = NextCluster(cluster);
- SetFatEntry(cluster, FAT_UNUSED);
- Disk.nsectsfree += Disk.spc;
- cluster = nextcluster;
- }
- }
-
- #endif /* READONLY */
-
- /*
- * This routine opens a file.
- */
-
- struct MSFileHandle *
- MSOpen(parentdir, name, mode)
- struct MSFileLock *parentdir;
- char *name;
- long mode;
- {
- struct MSFileLock *fl;
- struct MSFileHandle *fh = NULL;
- long lockmode;
-
- switch (mode) {
- case MODE_NEWFILE:
- case MODE_READWRITE:
- lockmode = EXCLUSIVE_LOCK ^ MODE_CREATEFILE;
- break;
- default:
- mode = MODE_OLDFILE;
- case MODE_OLDFILE:
- lockmode = SHARED_LOCK;
- }
-
- if (fl = MSLock(parentdir, name, lockmode)) {
- makefh:
- if (fl->msfl_Msd.msd_Attributes & ATTR_DIR) {
- error = ERROR_OBJECT_WRONG_TYPE;
- MSUnLock(fl);
- } else if (fh = AllocMem((long) sizeof (*fh), MEMF_PUBLIC)) {
- #ifndef READONLY
- /* Do we need to truncate the file? */
- if (mode == MODE_NEWFILE && fl->msfl_Msd.msd_Cluster) {
- FreeClusterChain(fl->msfl_Msd.msd_Cluster);
- fl->msfl_Msd.msd_Cluster = 0;
- fl->msfl_Msd.msd_Filesize = 0;
- UpdateFileLock(fl);
- }
- #endif
- fh->msfh_Cluster = fl->msfl_Msd.msd_Cluster;
- fh->msfh_SeekPos = 0;
- fh->msfh_FileLock = fl;
- } else {
- error = ERROR_NO_FREE_STORE;
- MSUnLock(fl);
- }
- return fh;
- }
- #ifndef READONLY
- /*
- * If the file was not found, see if we can make a new one. Therefore
- * we need to have an empty spot in the desired directory, and create
- * an MSFileLock for it.
- */
-
- if (!(lockmode & MODE_CREATEFILE) && (fl = EmptyFileLock)) {
- debug(("Creating new file\n"));
- EmptyFileLock = NULL;
- fl->msfl_Msd.msd_Attributes = ATTR_ARCHIVED;
- UpdateFileLock(fl);
-
- goto makefh;
- }
- if (EmptyFileLock) {
- MSUnLock(EmptyFileLock);
- EmptyFileLock = NULL;
- }
- #endif
-
- return NULL;
- }
-
- void
- MSClose(fh)
- register struct MSFileHandle *fh;
- {
- if (fh) {
- MSUnLock(fh->msfh_FileLock);
- FreeMem(fh, (long) sizeof (*fh));
- }
- }
-
- long
- MSSeek(fh, position, mode)
- struct MSFileHandle *fh;
- long position;
- long mode;
- {
- long oldpos = fh->msfh_SeekPos;
- long newpos = oldpos;
- long filesize = fh->msfh_FileLock->msfl_Msd.msd_Filesize;
- word cluster = fh->msfh_Cluster;
- word oldcluster;
- word newcluster;
-
- switch (mode) {
- case OFFSET_BEGINNING:
- newpos = position;
- break;
- case OFFSET_CURRENT:
- newpos += position;
- break;
- case OFFSET_END:
- newpos = filesize - position;
- break;
- }
-
- if (newpos < 0 || newpos > filesize) {
- error = ERROR_SEEK_ERROR;
- return -1;
- }
- newcluster = newpos / Disk.bpc;
- oldcluster = oldpos / Disk.bpc;
-
- if (oldcluster > newcluster) { /* Seek backwards */
- cluster = fh->msfh_FileLock->msfl_Msd.msd_Cluster;
- oldcluster = 0;
- }
- if (oldcluster < newcluster) {
- if (CheckLock(fh->msfh_FileLock))
- return -1L;
- while (oldcluster < newcluster) {
- cluster = NextCluster(cluster);
- oldcluster++;
- }
- }
- fh->msfh_Cluster = cluster;
- fh->msfh_SeekPos = newpos;
-
- return oldpos;
- }
-
- long
- MSRead(fh, userbuffer, size)
- register struct MSFileHandle *fh;
- register byte *userbuffer;
- register long size;
- {
- long oldsize;
-
- if (CheckLock(fh->msfh_FileLock))
- return -1L;
-
- if (fh->msfh_SeekPos + size > fh->msfh_FileLock->msfl_Msd.msd_Filesize)
- size = fh->msfh_FileLock->msfl_Msd.msd_Filesize - fh->msfh_SeekPos;
-
- oldsize = size;
-
- while (size > 0) {
- word offset;
- word sector;
- byte *diskbuffer;
- long insector;
- long tocopy;
-
- offset = fh->msfh_SeekPos % Disk.bpc;
- sector = ClusterOffsetToSector(fh->msfh_Cluster, (word) offset);
- if (diskbuffer = GetSec(sector)) {
- offset %= Disk.bps;
- insector = Disk.bps - offset;
- tocopy = lmin(size, insector);
-
- CopyMem(diskbuffer + offset, userbuffer, tocopy);
- userbuffer += tocopy;
- size -= tocopy;
- FreeSec(diskbuffer);
- /* MSSeek(fh, tocopy, (long) OFFSET_CURRENT); */
- if ((fh->msfh_SeekPos += tocopy) % Disk.bpc == 0)
- fh->msfh_Cluster = NextCluster(fh->msfh_Cluster);
- } else { /* Read error. Return amount successfully
- * read, if any. Else return -1 for error. */
- if (size == oldsize) {
- return -1L;
- }
- return oldsize - size;
- }
- }
-
- return oldsize;
- }
-
- long
- MSWrite(fh, userbuffer, size)
- register struct MSFileHandle *fh;
- register byte *userbuffer;
- register long size;
- {
- #ifdef READONLY
- return -1;
- #else
- long oldsize;
- struct MSFileLock *fl = fh->msfh_FileLock;
- word prevclust = fl->msfl_Msd.msd_Cluster;
- word update = 0;
-
- if (CheckLock(fl))
- return -1;
-
- if (fl->msfl_Msd.msd_Attributes & ATTR_READONLY) {
- error = ERROR_WRITE_PROTECTED;
- return -1;
- }
-
- oldsize = size;
-
- while (size > 0) {
- /*
- * Do we need to extend the file?
- */
-
- if (fh->msfh_Cluster == 0 || fh->msfh_Cluster == FAT_EOF) {
- word newclust;
-
- newclust = ExtendClusterChain(prevclust);
- debug(("Extend with %d\n", newclust));
- if (newclust != FAT_EOF) {
- if (prevclust == 0) { /* Record first cluster in dir */
- fl->msfl_Msd.msd_Cluster = newclust;
- }
- fh->msfh_Cluster = newclust;
- prevclust = newclust;
- } else {
- error = ERROR_DISK_FULL;
- goto error;
- }
- }
- {
- word offset;
- word sector;
- byte *diskbuffer;
- long insector;
- long tocopy;
-
- offset = fh->msfh_SeekPos % Disk.bpc;
- sector = ClusterOffsetToSector(fh->msfh_Cluster, (word) offset);
- offset %= Disk.bps;
- insector = Disk.bps - offset;
- tocopy = lmin(size, insector);
-
- if (tocopy == Disk.bps)
- diskbuffer = EmptySec(sector);
- else
- diskbuffer = GetSec(sector);
-
- if (diskbuffer != NULL) {
- CopyMem(userbuffer, diskbuffer + offset, tocopy);
- userbuffer += tocopy;
- size -= tocopy;
- MarkSecDirty(diskbuffer);
- FreeSec(diskbuffer);
- /* MSSeek(fh, tocopy, (long) OFFSET_CURRENT); */
- if ((fh->msfh_SeekPos += tocopy) % Disk.bpc == 0)
- fh->msfh_Cluster = NextCluster(fh->msfh_Cluster);
- if (fh->msfh_SeekPos > fl->msfl_Msd.msd_Filesize)
- fl->msfl_Msd.msd_Filesize = fh->msfh_SeekPos;
- fl->msfl_Msd.msd_Attributes |= ATTR_ARCHIVED;
- update = 1;
- } else { /* Write error. */
- error:
- if (update)
- UpdateFileLock(fl);
- #if 1
- return -1; /* We loose the information about how much
- * data we wrote, but the standard file system
- * seems to do it this way. */
- #else
- if (size == oldsize) {
- return -1;
- }
- return oldsize - size; /* Amount successfully written */
- #endif
- }
- }
- }
-
- if (update)
- UpdateFileLock(fl);
-
- return oldsize;
- #endif
- }
-
- long
- MSDeleteFile(parentdir, name)
- struct MSFileLock *parentdir;
- byte *name;
- {
- #ifdef READONLY
- return DOSFALSE;
- #else
- register struct MSFileLock *fl;
-
- fl = MSLock(parentdir, name, EXCLUSIVE_LOCK);
- if (fl) {
- if (fl->msfl_Msd.msd_Attributes & ATTR_READONLY) {
- error = ERROR_DELETE_PROTECTED;
- goto error;
- }
- if (fl->msfl_Msd.msd_Attributes & ATTR_DIRECTORY) {
- struct FileInfoBlock fib;
-
- /*
- * We normally can't get REAL exclusive locks on directories,
- * so we check here just to be sure. We don't want to delete
- * anyone's current directory, do we?
- */
-
- if (fl->msfl_Refcount != 1 || fl == RootLock) {
- error = ERROR_OBJECT_IN_USE;
- goto error;
- }
- if (MSExamine(fl, &fib) && /* directory itself */
- MSExNext(fl, &fib)) { /* should fail */
- if (error == 0) {
- not_empty:
- error = ERROR_DIRECTORY_NOT_EMPTY;
- error:
- MSUnLock(fl);
- return DOSFALSE;
- }
- }
- if (error != ERROR_NO_MORE_ENTRIES)
- goto error;
-
- error = 0;
- }
- if (fl->msfl_Msd.msd_Cluster)
- FreeClusterChain(fl->msfl_Msd.msd_Cluster);
- fl->msfl_Msd.msd_Name[0] = DIR_DELETED;
- WriteFileLock(fl);
- MSUnLock(fl);
-
- return DOSTRUE;
- }
- return DOSFALSE;
- #endif
- }
-
- long
- MSSetDate(parentdir, name, datestamp)
- struct MSFileLock *parentdir;
- byte *name;
- struct DateStamp *datestamp;
- {
- #ifdef READONLY
- return DOSFALSE;
- #else
- register struct MSFileLock *fl;
-
- fl = MSLock(parentdir, name, EXCLUSIVE_LOCK);
- if (fl) {
- ToMSDate(&fl->msfl_Msd.msd_Date, &fl->msfl_Msd.msd_Time, datestamp);
- WriteFileLock(fl);
- MSUnLock(fl);
-
- return DOSTRUE;
- }
- return DOSFALSE;
- #endif
- }
-
- /*
- * Create a new directory, with its own initial "." and ".." entries.
- */
-
- struct MSFileLock *
- MSCreateDir(parentdir, name)
- struct MSFileLock *parentdir;
- byte *name;
- {
- #ifdef READONLY
- return DOSFALSE;
- #else
- register struct MSFileLock *fl;
-
- /*
- * Go create a new file. If we fail later, we have an empty file that
- * we delete again.
- */
-
- fl = MSLock(parentdir, name, EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
- if (fl || error == ERROR_OBJECT_IN_USE) {
- error = ERROR_OBJECT_EXISTS;
- goto error;
- }
- if (error != 0) {
- goto error;
- }
- if (fl = EmptyFileLock) {
- debug(("Creating new dir\n"));
- EmptyFileLock = NULL;
- if ((fl->msfl_Msd.msd_Cluster = FindFreeCluster(FAT_EOF)) != FAT_EOF) {
- struct MsDirEntry direntry;
- byte *sec;
- word sector;
-
- sector = ClusterToSector(fl->msfl_Msd.msd_Cluster);
- sec = EmptySec(sector);
- if (sec == NULL)
- goto error_no_free_store;
- setmem(sec, (int) Disk.bps, 0);
-
- /*
- * Turn the file into a directory.
- */
- fl->msfl_Msd.msd_Attributes = ATTR_DIRECTORY;
- UpdateFileLock(fl);
-
- /*
- * Create the "." entry.
- */
- direntry = fl->msfl_Msd;
- strncpy(direntry.msd_Name, DotDot + 1, 8 + 3);
- OtherEndianMsd(&direntry);
- ((struct MsDirEntry *) sec)[0] = direntry;
-
- /*
- * Get the real parent directory because we will duplicate the
- * directory entry in the subdirectory.
- */
-
- parentdir = MSParentDir(fl);
- if (parentdir == NULL) /* Cannot happen */
- parentdir = MSDupLock(RootLock);
-
- /*
- * Create the ".." entry.
- */
- direntry = parentdir->msfl_Msd;
- strncpy(direntry.msd_Name, DotDot, 8 + 3);
- direntry.msd_Attributes = ATTR_DIRECTORY;
- OtherEndianMsd(&direntry);
- ((struct MsDirEntry *) sec)[1] = direntry;
-
- MSUnLock(parentdir);
-
- MarkSecDirty(sec);
- FreeSec(sec);
-
- /*
- * Clear out the rest of the newly created directory.
- */
-
- while ((sector = NextClusteredSector(sector)) != SEC_EOF) {
- sec = EmptySec(sector);
- if (sec == NULL)
- goto error_no_free_store;
- setmem(sec, (int) Disk.bps, 0);
- MarkSecDirty(sec);
- FreeSec(sec);
- }
- } else {
- MSUnLock(fl);
- fl = NULL;
- MSDeleteFile(parentdir, name);
- error = ERROR_DISK_FULL;
- }
- }
- if (EmptyFileLock) {
- MSUnLock(EmptyFileLock);
- EmptyFileLock = NULL;
- }
- return fl;
-
- error_no_free_store:
- error = ERROR_NO_FREE_STORE;
- error:
- if (fl)
- MSUnLock(fl);
- return DOSFALSE;
- #endif
- }
-
- /*
- * Rename a file or directory, possibly moving it to a different
- * directory.
- *
- * "Tuned" to also work in full directories by first deleting the source
- * name, then look for a slot to put the destination name. If that fails,
- * we undo the deletion. By playing with the cache, we even avoid a write
- * of the sector with the undeleted entry.
- */
-
- long
- MSRename(slock, sname, dlock, dname)
- struct MSFileLock *slock;
- byte *sname;
- struct MSFileLock *dlock;
- byte *dname;
- {
- #ifdef READONLY
- return DOSFALSE;
- #else
- struct MSFileLock *sfl;
- struct MSFileLock *dfl;
- long success;
- struct CacheSec *scache;
- ulong oldstatus;
-
- success = DOSFALSE;
- scache = NULL;
- dfl = NULL;
-
- sfl = MSLock(slock, sname, SHARED_LOCK);
- if (sfl == NULL || sfl == RootLock)
- goto error;
-
- /*
- * Now we are going to pull a dirty trick with the cache. We are going
- * to temporarily delete the source file, in the chache only, and
- * undelete it again if we cannot create the new name. And above all
- * we want to avoid unnecessary writes if we decide not to do the
- * deletion after all.
- */
- {
- byte *sec;
- byte old;
-
- if ((sec = GetSec(sfl->msfl_DirSector)) == NULL)
- goto error;
- scache = FindSecByBuffer(sec);
- oldstatus = scache->sec_Refcount;
-
- old = sfl->msfl_Msd.msd_Name[0];
- sfl->msfl_Msd.msd_Name[0] = DIR_DELETED;
- WriteFileLock(sfl);
- sfl->msfl_Msd.msd_Name[0] = old;
-
- /*
- * Don't FreeSec it yet; we don't want it written out to disk.
- */
- }
-
- /*
- * Now we have freed the directory entry of the source name, we might
- * be able to use it for the destination name. But only if we also
- * temporarily hide the MSFileLock on that spot. Gross hack ahead!
- */
-
- sfl->msfl_DirOffset = ~sfl->msfl_DirOffset;
- dfl = MSLock(dlock, dname, EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
- sfl->msfl_DirOffset = ~sfl->msfl_DirOffset;
-
- if (dfl != NULL || error == ERROR_OBJECT_IN_USE) {
- error = ERROR_OBJECT_EXISTS;
- goto undelete;
- }
- dfl = EmptyFileLock;
- EmptyFileLock = NULL;
- if (dfl == NULL) {
- /*
- * Sigh, we could not create the new name. But because of that, we
- * are sure that we need to write nothing to the disk at all. So
- * we can safely reset the sector-dirty flag to what it was
- * before, if we also restore the cached sector.
- */
- undelete:
- WriteFileLock(sfl);
- scache->sec_Refcount = oldstatus;
- goto error;
- }
- /*
- * Now, if the moved entry was a directory, and it was moved to a
- * different directory, we need to adapt its "..", which is the second
- * entry.
- */
-
- if (sfl->msfl_Msd.msd_Attributes & ATTR_DIRECTORY &&
- sfl->msfl_Parent != dfl->msfl_Parent) {
- struct MSFileLock *parentdir;
- struct MsDirEntry *dir;
-
- if (dir = (struct MsDirEntry *)
- GetSec(DirClusterToSector(sfl->msfl_Msd.msd_Cluster))) {
- parentdir = MSParentDir(dfl);
- /*
- * Copy everything except the name which must remain "..". But
- * first a quick consistency check...
- */
- debug(("Creating new \"..\" "));
- if (dir[1].msd_Name[1] == '.') {
- CopyMem(&parentdir->msfl_Msd.msd_Attributes,
- &dir[1].msd_Attributes,
- (long) sizeof (struct MsDirEntry) -
- OFFSETOF(MsDirEntry, msd_Attributes));
- dir[1].msd_Attributes = ATTR_DIRECTORY;
- OtherEndianMsd(&dir[1]);
- MarkSecDirty(dir);
- }
- #ifdef DEBUG
- else
- debug(("!!! No \"..\" found ??\n"));
- #endif
- MSUnLock(parentdir);
- FreeSec(dir);
- }
- }
- /*
- * Move the name from the new entry to the old filelock. We do this
- * for the case that somebody else has a lock on the (possibly moved)
- * file/directory. Also move the other administration.
- */
-
- strncpy(sfl->msfl_Msd.msd_Name, dfl->msfl_Msd.msd_Name, 8 + 3);
- sfl->msfl_DirSector = dfl->msfl_DirSector;
- sfl->msfl_DirOffset = dfl->msfl_DirOffset;
- /*
- * Free the old, and get the new parent directory. They might be the
- * same, of course...
- */
- MSUnLock(sfl->msfl_Parent);
- sfl->msfl_Parent = dfl->msfl_Parent;
- dfl->msfl_Parent = NULL;
- sfl->msfl_Msd.msd_Attributes &= ~ATTR_ARCHIVED;
- WriteFileLock(sfl); /* Write the new name; the old name
- * already has been deleted. */
- success = DOSTRUE;
-
- error:
- if (sfl)
- MSUnLock(sfl);
- if (dfl)
- MSUnLock(dfl);
- if (scache)
- FreeSec(scache->sec_Data);
-
- return success;
- #endif
- }
-