ability to delete a file from inspecting the ls-l output - linux

Down below there are four outputs of the ls -l command for the file and it's parent directory.
In which of the four scenarios student1 can delete file1? (the answer is in red)
I don't understand why the answer is the red one, moreover what does it mean in the ls -l output that there are only - and not anything else in the permissions part? Is it just saying that no one has permission for this file, and if so why is it still the answer?

Deleting a file is not an operation on the file, but on the directory. This is because the "file" entry in the directory is not a file; it is just a reference to the file (semantics are odd because of the overloaded meaning of the word "file" and the imprecision in common usage.) In order to delete a file (eg, remove a reference to it), you just need execute and read permission on the directory the file is in. Hence scenario 1 in your case.
Note that removing a reference (a "link") to a file in one directory only results in the deletion of that file if that is the last reference in the file system. That reference count is given in column 2 of the output of ls -l, so in your case the file linked to by the name "file1" in the directory "directory1" will get garbage collected by the filesystem. (eg, the data will be deleted.)
Of course, the data can also be deleted if the file is overwritten or truncated, so my entire answer is based on the assumption that you use "deleted" to mean "unlinked" or "removed". Imprecise language is rampant!

Related

Is it possible to read a short-lived file reliably in /tmp due to periodic cleanup?

I'm considering making my application create a file in /tmp. All I'm doing is making a temporary file that I'll copy to a new location. On a good day this looks like:
Write the temp file
Move the temp file to a new location
However on my system (RHEL 7) there is a file at /usr/lib/tmpfiles.d/tmp.conf which indicates that /tmp gets cleaned up every 10 days. From what I can tell this is the default installation. So, what I'm concerned about is that I have the following situation:
Write the temp file
/tmp gets cleaned up
Move the temp file to a new location (explodes)
Is my concern founded? If so, how is this problem solved in sophisticated programs? If there are no sophisticated tricks, then it's a bit puzzling to me as I don't have a concrete picture of what the utility of /tmp is if it can be blown away completely at any moment.
this should not be a problem if you keep a file descriptor open during your operation. As long as a file descriptor is open, the FS keeps the file on disk but it just don't appear when using ls. So If you create another name for this file, it will "resurect" in some way. Keeping an open fd on a file that is deleted is a common way to create temporary files on linux
see the man 3 unlink:
The unlink() function shall remove a link to a file. [..] unlink() shall remove the link named by the pathname pointed to by
path and shall decrement the link count of the file
referenced by the link.
When the file's link count becomes 0 and no process has the file open, the space occupied by the file shall be freed and the file
shall no longer be accessible. If one or more
processes have the file open when the last link is removed, the link shall be removed before unlink() returns, but the removal of
the file contents shall be postponed until all
references to the file are closed.

The links to a file

I was wondering why every file has 1 link to itself.
I'll try to be more clear.
By inserting from bash the command " ls -l " you'll end up with a list of files each preceded by different data divided in columns. The number of links to a file is in the third column. Can someone explain me why a file has that information setted to 1 instead of 0?
I get why the directories have two, if you explore one you'll find the " . " and the " . . " subdirectories, the former points at the directory itself, while the latter to the previous directory, but the file can't contain the " . " subdirectory since it's a file, so shouldn't it be 0?
Because there is nothing special about the first hard link (soft links are different, they're really just special files containing the textual target) to a file, it's just a directory entry that refers to the inode behind it.
This is a consequence of the decision to separate data (inode) from references to the data (directory entry).
So don't think of the file being one directory entry, with other files linked to it. Think instead of the data in the file being the thing, with as many directory entries as you need referring to it. When you hard-link directory entry a to an existing b, you're really linking it to the inode behind b, and they are equals in every sense of the word. The data is only ever destroyed when the final hard link to it is disconnected.
The filename you see is a hard link to the underlying object that represents the file, and ones with 0 links get automatically removed by the filesystem.
You have misinterpreted the number of links pointing to the file's inode, with the fact of having a link pointint to itself (see below).
Just consider the possibility of having a link... a link is an entry in a directory, that associates a name with an inode. The inode represents all the administrative data that is stored in a file (or a directory) and stores things like the permission bits, the dates of last read, last write or last inode change, pointers to the file's data blocks, etc.
There's one integer field in each inode that reflects the number of links that point to it (and this is what ls shows). This is needed for efficiency reasons, as it is redundant information. Just navigating the whole filesystem we can determine the number of directory entries that point to the same inode... but that is impractical to do, so the link count is maintained each time a node is linked or unlinked. So the next question is: Why is the number of directory entries pointing to the file's inode necessary? There's a bookkeeping reason. In order to detect when it reaches zero, as because of that, the kernel keeps the number of links pointing to an inode so it can free all the blocks belonging to the inode and the inode itself in order to recover the data after a file is removed (unlinked) the last time (when the counter gets down to zero)
Normally, a file has at least one such link, but it can have more. If you execute a command like:
ln foo bar
you are creating an alias for file foo, that now is called also bar. If you make your directory listing now, you'll see both file entries having 2 in the number of links field. More on, if you execute
ls -li foo bar
you'll see a first column, showing the inode number (this is a unique id for a file in a filesystem) of both files as the same inode... If you change the permissions to one of the links, you'll see the other file name his permissions changed also... this is because both filenames are aliases for the same file.
With respect with my first paragraph, a number of links is not the same thing as pointing to itself. Every directory has an entry that points to the directory's inode of the directory itself. This is the entry . that every directory has (this entry allows you to execute the ls command without parameters, for example, as when you don't specify parameters, the ls command uses . as the directory to list) and that makes that a directory has always 2 as a minimum (the 1 you observed for a file, plus the link of the . directory every directory has, for that number (check this and you'll see that this is an invariant of unix systems) Directories have 2 + number_of_subdirectories in its inode (one for the entry in the parent directory pointing to the directory itself, one for the directory entry . in the directory itself, and one for each subdirectories' entry .. parent directory, in the subdirectories of this directory) Check the numbers, it doesn't fail. And for files is the number of links (or aliases) a file can have. You cannot see files with 0 links as you are listing a directory, those files, case of existing, are being handled by the kernel, in the task of erasing them (freeing the blocks they used) Directories cannot have different aliases or names as files in order to conserve the hierarchical directory structure, only the two exceptions for . and .. are permitted and these are maintained (and enforced) by the kernel.

What is double dot(..) and single dot(.) in Linux?

The ls -ai command shows that . and .. have their inodes the same as the current directory and parent directory, respectively.
What exactly are . and ..?
Are they real files or even hard links? But as I have known, it's not allowed to create a hard link to a directory.
. represents the directory you are in and .. represents the parent directory.
From the dot definition:
This is a short string (i.e., sequence of characters) that is added to
the end of the base name (i.e., the main part of the name) of a file
or directory in order to indicate the type of file or directory.
On Unix-like operating systems every directory contains, as a minimum,
an object represented by a single dot and another represented by two
successive dots. The former refers to the directory itself and the
latter refers to its parent directory (i.e., the directory that
contains it). These items are automatically created in every
directory, as can be seen by using the ls command with its -a option
(which instructs it to show all of its contents, including hidden
items).
They are special name-inode maps which do count as hard-links (they do increase the link-count) though they aren't really hard-links, since, as you said, directories can't have hard-links. Read more here: Hard links and Unix file system nodes (inodes)
. represents the current directory that you are using and
.. represents the parent directory.
Example:
Suppose you are in the directory /etc/mysql and you wanted to move to the parent directory, i.e. /etc/. Then use cd..:
/etc/mysql> cd ..
And if you wanted to set the path of one file in the current directory bash file, use . with file name like this: ./filename
They are not hard links. You can more think of it like a shorthand for this directory (.) and parent of this directory (..).
Try to remove or rename . or ... Then you understand why it is not a hard link.

inotify --fromfile directive

I have a system fedora 15 with xfce window manager.
I installed an inotify util to play with.
I want to control, what happens with my files during my work process.
There is a command which i use today for running inotify
inotifywait --fromfile ~/list.inotify
That command easy read a list of folders and files to read and to ignore.
There is my list (list.inotify)
/home/alex
#/home/alex/Torrnets/
#/home/alex/.pulse-cookie
So it should read my home folder and ignore Torrents folder and .pulse-cookie file.
It ignores Torrents as well. But it won't ignore a .pulse-cookie file.
Any solution for this ? (please don't post a solution to use pattern based ignore, i want to work with a file list with absolute path's)
$man inotify
#<file>
When watching a directory tree recursively, exclude the specified file from being watched. The file must be specified with a relative or absolute path according to whether a relative or absolute path is given for watched directories. If a specific
path is explicitly both included and excluded, it will always be watched.
Note: If you need to watch a directory or file whose name starts with #, give the absolute path.
--fromfile <file>
Read filenames to watch or exclude from a file, one filename per line. If filenames begin with # they are excluded as described above. If <file> is `-', filenames are read from standard input. Use this option if you need to watch too many files to
pass in as command line arguments.
If you don't specify a -e argument, inotifywait will call inotify_add_watch with IN_ALL_EVENTS, which causes events to occur for files inside watched directories - note that inotify(7) says:
When monitoring a directory, the events marked with an asterisk (*) above can occur for files in the directory, in which case
the name field in the returned inotify_event structure identifies the name of the file within the directory.
If you have a look at the inotifywait code in question, you'll see that it only watches (and checks the exclude list against) directories. It would perhaps be a bit more user friendly if you were warned when specifying an exclusion that is not a directory or one that is never used, but that's the way it currently it is.

Linux - Restoring a file

I've written a vary basic shell script that moves a specified file into the dustbin directory. The script is as follows:
#!/bin/bash
#move items to dustbin directory
mv "$#" ~/dustbin/
echo "File moved to dustbin"
This works fine for me, any file I specify gets moved to the dustbin directory. However, what I would like to do is create a new script that will move the file in the dustbin directory back to its original directory. I know I could easily write a script that would move it back to a location specified by the user, but I would prefer to have one that would move it to its original directory.
Is this possible?
I'm using Mac OS X 10.6.4 and Terminal
You will have to store where the original file is coming from then. Maybe in a seperate file, a database, or in the files attributes (meta-data).
Create a logfile with 2 columns:
The complete filename in the dustbin
The complete original path and filename
You will need this logfile anyway - what will you do when a user deleted 2 files in different directories, but with the same name? /home/user/.wgetrc and /home/user/old/.wgetrc ?
What will you do when a user deletes a file, makes a new one with the same name, and then deletes that too? You'll need versions or timestamps or something.
You need to store the original location somewhere, either in a database or in an extended attribute of the file. A database is definitely the easiest way to do it, though an extended attribute would be more robust. Looking in ~/.Trash/ I see some, but not all files have extended attributes, so I'm not sure how Apple does it.
You need to somehow encode the source directory in the file. I think the easiest would be to change the filename in the dustbin directory. So that /home/user/music/song.mp3 becomes ~/dustbin/song.mp3|home_user_music
And when you copy it back your script needs to process the file name and construct the path beginning at |.
Another approach would be to let the filesystem be your database.
A file moved from /some/directory/somewhere/filename would be moved to ~/dustbin/some/directory/somewhere/filename and you'd do find ~/dustbin -name "$file" to find it based on its basename (from user input). Then you'd just trim "~/bustbin" from the output of find and you'd have the destination ready to use. If more than one file is returned by find, you can list the proposed files for user selection. You could use ~/dustbin/$deletiondate if you wanted to make it possible to roll back to earlier versions.
You could do a cron job that would periodically remove old files and the directories (if empty).

Resources