Stage 25

Write system call ensures that new blocks are brought it if the lseek is equal to multiple of 512 and is equal to the file size.

Set the MODE_FLAG in the process table entry to 5, 
indicating that the process is in the write system call.

//Switch to Kernel Stack - See Kernel Stack Management during System Calls. 
Save the value of SP to the USER SP field in the Process Table entry of the process.
Set the value of SP to the beginning of User Area Page.

If the word is to be written to STDOUT (terminal device)    /* indicated by a file descriptor value of -2 */
         Call the terminal_write()function in the Device manager  Module .
         Switch back to the user stack by restoring USER SP from the process table.
             Set the MODE_FLAG in the process table entry of the parent process to 0.
             Return 0.   /* success */

/* If not terminal, write to file. */

If file descriptor is invalid, return -1.    /* File descriptor value should be within the range 0 to 7 (both included). */

Locate the Per-Process Resource Table of the current process.

If the Resource identifier field of the Per Process Resource Table entry is invalid or does not indicate a FILE, return -1.   
/* No file is open with this file descriptor. */

Get the index of the Open File Table entry from the Per Process Resource Table entry.

Get the index of the Inode Table entry from the Open File Table entry. 

If the current user is not root and the current user does not own the file and      /* Check the process table entry */
the exclusive permission is set, return -3. 

Acquire the Lock on the File by calling the acquire_inode() function in the File Manager module.  
If acquiring the inode fails, return -1.

Get the Lseek position from the Open File Table entry.

If lseek position is same as the MAX_FILE_SIZE, release_inode() and return -2.  /* Maximum file size of 2048 reached*/

If the Lseek position is a multiple of 512 and the same as File size in the inode table /* New block to be allocated */  
              Get a free disk block by calling the get_free_block() function in the Memory Manager module.

              If no free disk block is found release_inode() and return -2. 

              Set the new disk block found in the corresponding (lseek / 512) disk block field  in the Inode table entry.


Find the disk block number and the position in the block from which input is to be written.
Write the word to the File Buffer by calling the buffered_write() function in the Buffer Manager module.

If Lseek equals file size, increment file size in the inode table entry and also in the memory copy of the root file.

Increment the Lseek position in the Open File Table entry.

Release the Lock on the File by calling the release_inode() function in the Resource Manager module.

Switch back to the user stack by restoring USER SP from the process table.
Set the MODE_FLAG in the process table entry of the parent process to 0.

Return 0.   /* success */
Set the MODE_FLAG in the process table entry to 21, 
indicating that the process is in the shutdown system call.

//Switch to the Kernel Stack. see kernel stack management during system calls
Save the value of SP to the USER SP field in the Process Table entry of the process.
Set the value of SP to the beginning of User Area Page.

If the current process is not the shell, return -1. /* Shell process has the PID 2 */
If the current user is not the root, return -1.

Kill all user processes except the idle, login and the current process(shell) by calling the 
kill_all() function in the Process Manager module.

Loop through the Buffer Table
    If the buffer is dirty
        Commit changes to the disk by calling the disk_store() function in the Device Manager module.

Commit the inode table, root file, user table and disk free list to the disk by calling the 
disk_store() function in the Device Manager Module.

Halt the system.