- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
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.