What happens to Open File Handle if file is Moved or Deleted?


Overview

We’ll look at how the operating systems behave when we delete, move or replace files that have open handles.

We’ll first briefly talk about files and inodes. After that, we’ll look at the different scenarios and see which one occurs in each case.

Understanding Files and Inodes

Files stored on a Linux file system use inode numbers to keep track of their contents.

We usually list the contents of a directory by listing its file names (links) and then their corresponding inode numbers (hard links).

We can use stat on a file and see which inode it refers to −

$ touch inode_example
$ stat inode_example
   File: inode_example
   Size: 0              Blocks: 0          IO Block: 4096           regular empty file
Device: fd03h/64771d    Inode: 20448632    Links: 1

This file is linked to inode 204488632, and stat also shows that there is one link. Let's add a new hard-linked file and run stat on it again.

$ ln inode_example hardlink_inode_example
$ stat inode_example
   File: inode_example
   Size: 0                 Blocks: 0             IO Block: 4096     regular empty file
Device: fd03h/64771d       Inode: 20448632       Links: 2

We can see that each link has an incremental value added to its URL. We can now use stat on hardlink_inode_example, too −

$ stat hardlink_inode_example
   File: hardlink_inode_example
   Size: 0               Blocks: 0              IO Block: 4096       regular empty file
Device: fd03h/64771d     Inode: 20448632        Links: 2

Unlike hard links, which share an inodes number, symbolic links have their inodes numbered separately from the parent directory.

Deleting the File

A new process is spawned every time we create a new connection. Each process has an associated memory space where data is stored. In order to access the data, the operating system must translate the address into a physical location within the memory space.

Let’s create a shell file named remove_opened_file to test our idea.

#!/bin/bash

FILE="/tmp/remove_example"
( 
   sleep 1
   echo "Before rm." >&4
   rm "$FILE"
   if [ ! -e "$FILE" ]; then
      echo "The file $FILE was removed."
   fi
   echo "After rm." >&4
) 4>"$FILE" &
( 
   sleep 2
   echo "This is the content in file handle 4:"
   cat <&4
) 4<"$FILE"

We start by launching two sub_shells, and then we use redirection to create and access /tmp/remove_examples as file handle 4 in each sub-shell. When the sub-shell terminaes, the system closes the file handles.

Let's run it and check if it works.

$ ./remove_opened_file.sh
The file /tmp/remove_example was removed.
This is the content in file handle 4:
Before rm.
After rm.

When we delete a directory, we're not really deleting the files inside; instead, we're just removing the link between the filename and the inodes. So, although the files themselves disappear, they remain accessible through their inodes.

When the system removes an inodes, it deletes its contents.

  • There are no more hard links pointing to it

  • There are no open file handles

Removing a file doesn't necessarily mean that the amount of free disk storage decreases

Moving the File

There are two ways for the system to transfer files from one place to another −

  • Renaming the file

  • Copying its content to the destination, then removing the source

Depending on the circumstances, the program uses one approach or another. For example, if we're copying the files from one location to another, then the program might use the Copy command.

The File Is Renamed

If the original filename is changed, this doesn't affect the open files. We can still write into and read from them. As the inodes are the same, the contents we write after the move will be written into the new location.

Let's write move_open_file.sh to test moving an open file.

#!/bin/bash

FILE=/tmp/move_example
FILE_NEW=/tmp/move_example.new

( 
   echo "Before mv." >&4
   mv "$FILE" "$FILE_NEW";
   if [ ! -e "$FILE" -a -e "$FILE_NEW" ]; then
      echo "The file $FILE was moved to $FILE_NEW."
   fi
   echo "After mv." >&4
   echo "This is the content in $FILE_NEW:"
   cat "$FILE_NEW"
) 4>"$FILE"

Here, we use a sub shell and redirection as we did in the last example. We first create an open file handle for writing to the output file. Then, we run the mV command.

We can tell that the files were copied from the same location because they share the same name. Now let’s see if we can change their names.

The file /tmp/move_example was moved to /tmp/move_example.new.

The File Is Copied

When the system copies a source document to a target location, the original contents of the source document are not preserved. Instead, the copy contains only the information contained within the source document. Once the source document is closed, any changes made to the source document are lost.

Now we need to modify our move_opened_files.sh script so that the destination is in a separate filesystem. Usually /tmp and /home reside in different filesystems. Here's the result −

The file /tmp/move_example was moved to /home/baeldung/move_by_copy_example.new.

This is the content in /home/baeldung/move_by_copy_example.new −

Before mv.

Replacing the File

When the new version of the program replaces the old one, the system removes the old version of the program. This means we can continue using the old version of the software until we close the application’s window.

We can write a shell script called replace_opened_file which tests whether an opened file has been replaced by another one.

#!/bin/bash

FILE=/tmp/replace_example
FILE_OLD=/tmp/replace_example.old

echo "This is the old file." > $FILE_OLD

( 
   sleep 1
   echo "Before mv." >&4
   mv "$FILE_OLD" "$FILE"
   echo "After mv." >&4
) 4>"$FILE" &

( 
   sleep 2
   echo "This is the content in file handle 4:"
   cat <&4
   echo "This is the content in $FILE:"
   cat $FILE
) 4<"$FILE"

In this script, let us first create an old version of the same document. Then we open a new shell and write a new version of the same document into it. Finally, we print the contents of the newly written document.

Let's run replace_opened_file.

$ ./replace_opened_file.sh

This is the content in file handle 4 −

Before mv.
After mv.

Conclusion

We looked at what happens when we delete files, copy them, or change their location.

We saw that we can delete or replace a single document, and we can still access it using its open document handle, even though we've deleted or replaced it.

On one hand, we saw that if we moved the files into the same directory, then the open handles would be pointing to the new files. But if we moved them to another directory, then the open files would be pointing to the old files.

Updated on: 26-Dec-2022

238 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements