Why does the change time(ctime) of a directory change when creating a new file in it? - linux

According to the documentation:
Change time (ctime) This marks when a file's metadata was changed,
such as permissions or ownership. This is also known as the "update"
time in some documentation.
Yet when I create a new file in a directory and run the istat command on the directory afterwards I notice that the ctime aka "update" time of the directory has changed. I thought that the ctime should only change if you change the metadata of the directory?

According to stat() system call specification:
The stat() function shall update any time-related fields (as described in XBD File Times Update), before writing into the stat structure.
In the corresponding File Times Update document:
Each function or utility in POSIX.1-2017 that reads or writes data (even if the data does not change) or performs an operation to change file status (even if the file status does not change) indicates which of the appropriate timestamps shall be marked for update.
The list of POSIX system calls contains the following calls related to creation of objects inside a directory:
link()
Upon successful completion, link() shall mark for update the last file status change timestamp of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.
mkdir()
Upon successful completion, mkdir() shall mark for update the last data access, last data modification, and last file status change timestamps of the directory. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.
mkfifo()
Upon successful completion, mkfifo() shall mark for update the last data access, last data modification, and last file status change timestamps of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.
mknod()
Upon successful completion, mknod() shall mark for update the last data access, last data modification, and last file status change timestamps of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.
open()
If O_CREAT is set and the file did not previously exist, upon successful completion, open() shall mark for update the last data access, last data modification, and last file status change timestamps of the file and the last data modification and last file status change timestamps of the parent directory.
symlink()
Upon successful completion, symlink() shall mark for update the last data access, last data modification, and last file status change timestamps of the symbolic link. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

The subdirectory listing is contained in a file, so when you update a file in the directory, it updates the metadata in the directory listing for that file (mtime, etc). Hence, the subdirectory itself is a file that has been modified.

Related

Rotate logfiles on an hourly basis by appending date and hour

I wanted to implement a log rotation option in linux. I have a *.trc file where all the logs are getting written. I wanted a new log file to be created every hour. I have done some analysis and found the below
I have done some analysis and got to know about the logrotate option. Where we need to update the rotation details for a specific file in the logrotate.conf file
I wanted to know if there is an option without using the logrotate option. I wanted to rotate the logfiles on an hourly basis, so something like appending date and hour information to the log file and create new files based on the current hour information.
Im looking for some suggestions on how to implement the log rotation using the second option specified above.
Any details on the above would be really helpful
If you have control over the process that creates the logs, you could just timestamp the file at the moment of creation. This will remove the need to rename the log.
Before you write every line you check the time. If one hour passed after that file was created, you close the current file and open a new one with a new timestamp.
If you do not have control over the process, you can pipe the output of your process (stdout,stderr) to multilog, which is a binary that's part of the package daemon-tools in most Linux distros.
https://cr.yp.to/daemontools/multilog.html

linux api rename behavior when new refer to an existing file

When I am reading the document for rename in the page https://linux.die.net/man/3/rename, i found the following
If the link named by the new argument exists, it shall be removed and old renamed to new. In this case, a link named new shall remain visible to other processes throughout the renaming operation and refer either to the file referred to by new or old before the operation began. Write access permission is required for both the directory containing old and the directory containing new.
How should I understand the following
refer either to the file referred to by new or old before the operation began
in this case a file with the same name with what new points exists, then after the rename operation, the new should points to either the old or the new. But the document says it is before the operation began which makes me confused.
How should I understand this? Could you give me an example?
What this phrase means is that, during rename, the old new is replaced with the new new atomically.
What this means is that there is no point during the rename operation where trying to access new will result in a file not found error. Every access will result in either the old or the new new being returned.
After the rename is done (assuming it finished successfully), of course the new new will be referenced under that name.
This highlights rename's usefulness in atomically replacing files. If you have a path containing some important file, and you need to update that file such that, no matter what happens, anyone any time that opens /var/lib/important will get either the old or the new version, this is the sequence of operations you need to do:
Create an updated version of the file with the path /var/lib/important.new.
Flush and close the /var/lib/important.new.
rename("/var/lib/important.new", "/var/lib/important");
Depending on your use case, flush /var/lib.
This guarantees that no matter what happens (process crash, power failures, kernel faults), either the old or the new file are available, complete and correct.
That last step (flushing the directory) is only necessary if you need to rely on it being the new version of the file that is available. If you do not do it, a power failure might cause the old file to re-appear after a restart. Typical uses don't bother with this step.

Node.js file rotation

I have a process that periodically gets files from a server and copy them with SFTP to a local directory. It should not overwrite the file if it already exists. I know with something like Winston I can automatically rotate the log file when it fills up, but in this case I need a similar functionality to rotate files if they already exist.
An example:
The routine copies a remote file called testfile.txt to a local directory. The next time it's run the same remote file is found and copied. But now I want to rename the first testfile.txt to testfile.txt.0 so it's not overwritten. And so on - after a while I'd have a directory of files with the name testfile.txt.N and the most recent testfile.txt.
What you can do is you can append date and time on the file name that gives every filename a unique name and also helps you archive it.
For example you text.txt can be either 20170202_181921_test.txt or test_20170202_181921.txt
You can use a JavaScript Date Object to get date and time.
P.S show your code of downloading files so that I can add more to that.

inode - move a file which is already opened

On linux, on a ext4 partition there is a movie, if I open the movie & watch it, then I move or rename the movie.
After the previous cache use up, it need to read more cache from original file, then it still could do that.
The question is:
How file system & inode achieve this?
Using rename() on a file within the same file system just changes the name that points to the inode. You can even use rename() to move that name into another directory - as long as it's in the same file system:
The rename() function shall change the name of a file. The old
argument points to the pathname of the file to be renamed. The new
argument points to the new pathname of the file. ...
Note that the POSIX specification for rename() is a lot more specific than the C Standard rename() specification:
7.21.4.2 The rename function
Synopsis
#include <stdio.h>
int rename(const char *old, const char *new);
Description
The rename function causes the file whose name is the string pointed
to by old to be henceforth known by the name given by the string
pointed to by new . The file named old is no longer accessible by
that name. If a file named by the string pointed to by new exists
prior to the call to the rename function, the behavior is
implementation-defined.
Returns
The
rename
function returns zero if the operation succeeds, nonzero if it fails,
269)
in
which case if the file existed previously it is still known by its original name.
(That's the entire C Standard specification for rename(). Read the POSIX link for a lot more information.)
So how can you rename a file while your watching it in an application? The underlying inode that your movie-watching process's open file descriptor uses to access the file that you just rename()'d doesn't change.
That's the same reason why you can unlink() (delete) a file while it's in use - all you're doing is removing the entry that points to the inode - one of the links to the inode. The space used by the file isn't freed until the last link to the inode is removed - and an open file descriptor counts as a link. That's also why the function that deletes the directory entry for a file is called unlink() - that's all it does. And yes, a file (inode) can have more than one link pointing to it.

How does modifying a directory affect its Parent Directory timestamp in Linux?

For example, if I create a directory, check its timestamp, then create a directory inside the first directory a minute later, the timestamp for the mtime will change to when the new directory was created. However if I wait another minute and create a third directory inside the second, the second directory will update the mtime to the third directory's time while the first directory will still have the 2nd directory's original mtime. Despite the contents of the first directory changing when the third directory is created, the mtime doesn't change.
Is there documentation as to how linux looks to change mtime? Or is it only able to see direct children changes to update mtime?
This is the closest I could find. From the stat man page:
The field st_mtime is changed by file modifications, for example, by
mknod(2), truncate(2), utime(2) and write(2) (of more than zero
bytes). Moreover, st_mtime of a directory is changed by the creation
or deletion of files in that directory. The st_mtime field is not
changed for changes in owner, group, hard link count, or mode.
-Source
This wording implies to me that a modification in mtime of a nested directory is not considered a modification by the parent directory, since it does not qualify as a mknod, truncate, utime, or write operation.
Hope this helps!

Resources