/*
* Copyright (c) 1996 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick 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; either version 2 of the License, or
* (at your option) any later version.
*
* Flick 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 Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
/*******************************************************************************
********************************************************************************
*
* ops.c Server operation functions
*
********************************************************************************
*******************************************************************************/
#include <stdio.h>
#include "file.h"
#include "cache.h"
/*******************************************************************************
* int IsDir ()
*
* This function checks to see if the open file is a dir.
*******************************************************************************/
int IsDir ()
{
if (!(*Dir))
return 0;
YfsError = EISDIR;
return -1;
}
/*******************************************************************************
* int IsNotDir ()
*
* This function checks to see if the open file is a dir.
*******************************************************************************/
int IsNotDir ()
{
if (*Dir)
return 0;
YfsError = ENOTDIR;
return -1;
}
/*******************************************************************************
* Handle Lookup (char * Name, Handle Dir)
*
* This function performs a lookup on a file or directory. The filehandle
* associated with the Name is returned; if the file doesn't exist, an error
* occurs.
*******************************************************************************/
Handle Lookup (char * Name, Handle Dir)
{
char PartialName [129];
int NamePos, Count;
Handle Current;
if (Name[0])
if (Name[0] == '/') /* name starts with '/', Dir is irrelevant */
{
Current = 1; /* 1 is the root file handle */
NamePos = 1;
}
else
{
Current = Dir; /* Set to search for Name in current Dir */
NamePos = 0;
}
else /* If name is NULL, return error */
{
YfsError = EINVAL;
return (Handle) -1;
}
while (Current != ((Handle) -1) && Name[NamePos])
{
Count = 0;
while (Name[NamePos] != 0 && Name[NamePos] != '/' && Count < 128)
/* parse the Name if it started with '/'. Extract the string between */
/* the first two '/'s. */
{
PartialName[Count++] = Name[NamePos]; /* Check these chars for validity */
NamePos++;
}
if (Count == 0 || Count == 128) /* if Name == NULL or Name > 128 */
{ /* error */
YfsError = EINVAL;
return (Handle) -1;
}
PartialName[Count] = 0; /* get ready to extract next string */
if (Name[NamePos] == '/') /* move past the '/' */
NamePos++;
if ( Access (Current) == -1 ||
IsNotDir ()) /* if unable to access the */
{ /* the directory, error */
YfsError = ENOENT;
return (Handle) -1;
}
Current = FindFilename (PartialName); /* search for PartialName in dir */
/* that's currently accessed */
/* couldn't find -> path not valid */
}
return Current; /* after entire Name is parsed, return */
}
/*******************************************************************************
* int CreateFile (char * filename, Handle dir)
*
* This function creates a new file with the name filename and in the
* parent directory dir.
*******************************************************************************/
int CreateFile (char * filename, Handle dir)
{
int loop = 0;
Handle newfile;
while ( filename[loop] != 0 && loop < 128 ) /* check for invalid chars */
if ( filename[loop++] == '/' ) /* if '/', then error */
{
YfsError = EINVAL;
return -1;
}
if (loop == 0 || loop == 128) /* check for NULL or long filename */
{
YfsError = EINVAL;
return -1;
}
newfile = MakeFile (); /* create a new, blank Handle */
if ( newfile == -1 ) /* if not created, error */
return -1;
/* Fill in handle and write it to disk */
*LinkCount = 1;
TimeStamp (); /* time stamp it */
Update (); /* write all the new info to disk */
/* If either of the following checks succeeds, then CreateFile failed. */
/* Delete the Handle, write info to disk, and error. */
if ( Access (dir) == -1 || /* cannot access dir? */
IsNotDir () ||
FindFilename (filename) != -1 || /* filename used in dir already? */
AddFilename (newfile, filename) == -1) /* cannot add filename? */
{
Access (newfile);
DeleteFile ();
Update ();
return -1;
}
TimeStamp (); /* time stamp the parent dir */
Update (); /* write info to disk (stamp!) */
return 0;
}
/*******************************************************************************
* int CreateLink (char * linkname, Handle dir, Handle file)
*
* This function creates a hard link linkname in the directory dir to the
* file specified by file.
*******************************************************************************/
int CreateLink (char * linkname, Handle dir, Handle file)
{
int loop = 0;
while ( linkname[loop] != 0 && loop < 128 ) /* check for invalid chars */
if ( linkname[loop++] == '/' ) /* if '/', error */
{
YfsError = EINVAL;
return -1;
}
/* if file name is the wrong length, error */
if (loop == 0 || loop == 128)
{
YfsError = EINVAL;
return -1;
}
/* check if the file exists == is accessible */
if ( Access (file) == -1 )
return -1;
/* Make sure that the file is not a dir */
if (IsDir ())
return -1;
/* Increment link count in Handle and write back to disk */
(*LinkCount)++;
Update ();
/* Check for valid directory, existing file, and attempt */
/* to add the file. If any fail, delete newly created link. */
if ( Access (dir) == -1 ||
IsNotDir () ||
FindFilename (linkname) != -1 ||
AddFilename (file, linkname) == -1)
{
Access (file);
DeleteFile (); /* delete the newly created entry */
Update (); /* write info back to disk */
return -1;
}
TimeStamp (); /* time stamp the parent dir */
Update (); /* write back to disk */
return 0;
}
/*******************************************************************************
* int CreateDir (char * dirname, Handle dir)
*
* This function creates a directory entry with the name dirname in the
* parent directory specified by dir.
*******************************************************************************/
int CreateDir (char * dirname, Handle dir)
{
int loop = 0;
Handle newdir;
/* might have to allow one slash at the end ASK ASK ASK ABOUT THIS!!! */
/* check if dirname is valid. Allow one slash at the end, but no */
/* slashes in between. */
while ( dirname[loop] != 0 && loop < 128 )
if ( dirname[loop++] == '/' && dirname[loop+1] != 0 )
{
YfsError = EINVAL;
return -1;
}
/* if file name is the wrong length, error */
if (loop == 0 || loop == 128)
{
YfsError = EINVAL;
return -1;
}
newdir = MakeFile (); /* create empty new dir */
if ( newdir == -1 ) /* if not created, error */
return -1;
/* Fill in handle and '.' and '..'. Write back to disk. */
*Dir = 1;
if (AddFilename ( newdir, ".") == -1 ||
AddFilename ( dir, "..") == -1)
{
DeleteFile ();
return -1;
}
TimeStamp (); /* time stamp the new dir */
Update (); /* write back to disk */
/* check for valid directory, existing file, and attempt to add */
/* the directory. If either fails, delete the new directory */
/* and write back to disk. */
if ( Access (dir) == -1 ||
IsNotDir () ||
FindFilename (dirname) != -1 ||
AddFilename (newdir, dirname) == -1)
{
Access (newdir);
DeleteFile ();
Update ();
return -1;
}
TimeStamp (); /* time stamp the parent dir */
Update (); /* write back to disk */
return 0;
}
/*******************************************************************************
* int Delete ( Handle file, Handle dir)
*
* This function removes the file or the directory specified by file.
* dir is the directory where the file to be deleted resides.
*******************************************************************************/
int Delete ( char * name, Handle dir)
{
Handle file;
/* Try to access the file to be deleted */
file = Lookup (name, dir);
if ( file == -1 || Access (file) == -1 )
return -1;
/* Check that if a dir, it is an empty dir */
if (IsDir() && *DirEntryCount > 2)
{
YfsError = ENOTEMPTY;
return -1;
}
/* Check if the parent directory exists. Attempt to remove the file from */
/* dir. RemoveFilename will error when file does not exist in dir. */
if ( Access (dir) == -1 ||
IsNotDir () ||
RemoveFilename (name) == -1 )
return -1;
(*DirEntryCount)--;
TimeStamp (); /* time stamp the parent directory */
Update (); /* write back */
Access (file);
DeleteFile (); /* just update the Handle table, and free blocks */
Update (); /* writes back the Handle if one exists */
return 0;
}
/*******************************************************************************
* int Read (Handle file, int count, int offset, char * buffer)
*
* This function reads count bytes from the file or dir specified by file
* into the buffer. offset specifies the starting location. The function
* returns the number of bytes read.
*******************************************************************************/
int Read (Handle file, int count, int offset, char * buffer)
{
int ReadSize;
/* check if file exists */
if ( Access (file) == -1 )
return -1;
/* If count is zero, exit (don't touch file) */
if (count == 0)
return 0;
/* Check for valid offset */
if (offset < 0)
{
YfsError = EINVAL;
return -1;
}
/* check the offset to make sure it's not past the end of file */
ReadSize = (*FileSize) - offset < count ? (*FileSize) - offset : count;
if (ReadSize <= 0)
{
YfsError = ESPIPE;
return -1;
}
/* Attempt to read in the data */
return FileRead (ReadSize, offset, buffer);
}
/*******************************************************************************
* int Write (Handle file, int count, int offset, char * buffer)
*
* This function writes count bytes from the buffer into the file, where
* offset specifies the starting location. The function returns the number
* of bytes written; we either write the entire count bytes, or not write the
* file at all.
*******************************************************************************/
int Write (Handle file, int count, int offset, char * buffer)
{
/* Attempt to access file and make sure it's not a dir */
if ( Access (file) == -1 || IsDir ())
{
YfsError = EISDIR;
return -1;
}
/* If count is zero, exit (don't touch file) */
if (count == 0)
return 0;
/* Check for valid offset */
if (offset < 0)
{
YfsError = EINVAL;
return -1;
}
/* check the offset to make sure it's not past the end of file */
if (*FileSize < offset)
{
YfsError = ESPIPE;
return -1;
}
/* Attempt to write out the data */
if ( FileWrite (count, offset, buffer) == -1 )
{
return -1;
}
TimeStamp (); /* time stamp the file */
Update (); /* write back */
return count;
}
/*******************************************************************************
* int Sync (Handle file)
*
* This function ensures that the info in the cache corresponding to the
* file is consistent with the contents of file on disk.
*******************************************************************************/
extern int UniqueNumber;
extern int FreeBlockCount;
extern int FreeBlocks[4096];
int Sync (Handle fh)
{
char Data[512];
if (fh > 0)
return CacheSync (fh);
else
{
if (CacheReadDisk ((int) -fh, Data, 1, 0) == -1)
return -1;
PrintBlock( Data);
return 0;
}
}
int PrintBlock (char buf[512])
{
int i, j;
/*// Test code */
for (i = 0; i < 32; i++)
{
for (j = 0; j < 16; j++)
printf ("%x%x%s", ((unsigned )buf[i*16 + j] / 16) % 16, (unsigned )buf[i*16 + j] % 16, j == 3 || j == 7 || j == 11 ? " " : " ");
printf (" ");
for (j = 0; j < 16; j++)
printf ("%c", buf[i*16 + j] % 128 > 32 ? buf[i*16 + j] % 128: '`');
printf ("\n");
}
printf ("Unique number: %i\n", UniqueNumber);
printf ("Next free blocks: %i %i %i\n", FreeBlocks[FreeBlockCount - 1],FreeBlocks[FreeBlockCount - 2],FreeBlocks[FreeBlockCount - 3]);
return 0;
}
/*******************************************************************************
* int SyncDisk ()
*
* This function ensures that the info on disk is consistent with the info
* maintained in the file system in main memory.
*******************************************************************************/
int SyncDisk ()
{
int count;
for (count = 4096; count--;)
CacheSync (count);
return 0;
}
/*******************************************************************************
* int Shutdown (void)
*
* This function requests that the file system perform an orderly shutdown.
*******************************************************************************/
int Shutdown (void)
{
return SyncDisk ();
}
/*******************************************************************************
* int Stamp (Handle file)
*
* This function returns the time of last modification of the file (which
* may be a file or dir).
*******************************************************************************/
int Stamp (Handle file)
{
if ( Access (file) == -1 )
return -1;
/* Return the time stamp */
return *Time;
}
/*******************************************************************************
* int Stat (Handle file)
*
* This function returns the number of bytes contained in file.
*******************************************************************************/
int Stat (Handle file)
{
if ( Access (file) == -1 ) /* attempt to access file */
return -1;
/* Return the size info */
YfsError = *Dir;
return *FileSize;
}
syntax highlighted by Code2HTML, v. 0.9.1