I want to know how "inotifywait" trace file's operation - file-io

I used "inotifywait" to trace the file's operation. I want to know its structure. How does it know that a file is created, read and deleted? How does it know that a directory is created and removed? What are kernel's files that inotifywait tracks. Which kernel's files doing these file's operation? Please help me find out. Thank you.

inotify is a feature built into the kernel (first included in version 2.6.13). Since a file create request or a file close (on write complete) request needs to go through the kernel, it is implicitly aware of all these operations. Same goes for directories, since the kernel is aware if the file created is a directory or not.
Which kernel's files doing these file's operation?
Are you asking for the inotify source code? You could possible start by looking at the header files here: http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/ (inotify.h)

Related

Prevent renaming of file from another binary on Mac OS

I am working with multiple processes that write to the same directory.
I have a directory dir1/
My process creates a file a.txt under dir1/. However the other process creates a-temp1.txt and renames it to a.txt. I don't have control over the other process since that code comes from a library. Can I prevent a-temp.txt from being renamed?
There's nothing you can do that the other process can't undo. Your best hope (other than changing your program to work sanely) is that the other process doesn't try too hard to do the rename. That is, it tries the simple approach and gives up if that fails.
In particular, you can set the UF_IMMUTABLE flag on either file and that will prevent one from being renamed to replace the other. You can set the flag using chflags(). Using Cocoa, you could also use [someURL setResourceValue:#YES forKey:NSURLIsUserImmutableKey error:NULL].
Keep in mind that you won't be able to change the file in any other way, either, until that flag is removed. If the other process is determined to rename the file, it has permission to remove the flag just like your process does.
Also keep in mind that a system such as this is inherently race-prone.
You really ought to use separate names for the files, or separate directories, or ditch that library that doesn't give you the control you need.
Set the user immutable flag chflags(...,uchg). This will keep the other process from changing your file unless it takes action to clear the bit. Of course I don't know how the other process will react to you putting things in it's way, but that wasn't the question.
You can use chflags() on an HFS+ (Mac OS X) file system to set the UF_APPEND attribute. (Do a man 2 chflags.) That will permit appending to the file, but not deleting or renaming, even by the same user.
You can, but it unlikely will solve your problem. I strongly suspect this is an X-Y problem, and almost certainly the correct solution is to redesign some part of this system entirely, probably by changing your file names, using unique temporary files, moving to another directory, or reworking the usage of the library (libraries only do what callers tell them to do; and libraries are just code anyway). You shouldn't try to defeat another process; you're all working for the same user.
All that said, sure, you can prevent your own userid from renaming over file. Just deny yourself permission. You can modify the file:
chmod 400 a.txt
That says that you can read the file but may not write it. However, if you already have an open file handle, you may continue to use it (so you can keep writing to the file, even though another process running as the same user may not).
Similarly, you may change permissions on the directory:
chmod 500 .
This would prevent the rename because file names are kept in the directory.

What kernel level operations are performed when editing a file?

Can anybody please explain to me what kernel level operations are performed, when a file is edited? The thing i'm confused with is that is it the case that a new inode is created every time a file is edited. Please explain the steps, if possible. I have searched the internet, but no satisfactory answers there.
Thanks in advance.
There's no single general answer, because this depends on what the application does when it's editing the file, what system it's running on, and what the file is stored on. It might be creating new temporary files, or clobbering and rewriting the original file, or using memory mapping, or using versioned filesystem features, or doing network file system operations, etc etc.
Instead of trying to answer this in the abstract, pick an open source editor you're interested in, and read through its source code and debug it to understand what it in particular is doing. Then if you have questions, you can read the API docs to figure out what kernel operations the functions it's calling map to or rely on.

Creating an objective-c file creation event stream

I'm trying to create a stream to monitor a few directories for new files but I've had no luck.
Bonus points if your solution recursively searches the directories.
Have you read the "Tracking File-System Changes" section of the File-System Performance Guidelines - this and the NSWorkspace class reference should tell you everything you need to know.

Ensure a file is not changed while trying to remove it

In a POSIX environment, I want to remove a file from disk, but calculate its checksum before removing it, to make sure it was not changed. Is locking enough? Should I open it, unlink, calculate checksum, and then close it (so the OS can remove its inode)? Is there any way to ensure no other process has an open file descriptor on the file?
To give a bit of context, the code performs synchronization of files across hosts, and there's an opportunity for data loss if a remote host removes a file but the file is being changed locally.
Your proposal of open,unlink,checksum,close won't work as is, because you'll be stuck if the checksum doesn't match (there is no POSIX-portable way of creating a link to a file given by a file descriptor). A better variant is rename,checksum,unlink,close, which lets you undo the rename or redo the copy if the checksum doesn't match. You'll still need to think of what you want to do if a third program has recreated the file in the meantime.
POSIX offers only cooperative locks. If you have control over the programs that may modify the file, make sure they use locks; if that's not an option, you're stuck without locks.
There is no portable way to see what (or even whether) processes have opened a file. On most Unix systems, lsof will show you, but this is not universal, not robust (a program could open the files just after lsof has finished looking), and incomplete (if the files are exported over NFS, there may be no way to know about active clients).
You may benefit from looking at what other synchronization programs are doing, such as rsync and unison.

Writing to files in bundle?

If you scroll down to the section 'Writing to Files and URLs' at this link, would the path varaible have to be a file on disk? Is it possible to write to a file in the bundle or must it always be deployed first?
You can write files to the application bundle as much as you'd like. Just get the path of the file through NSBundle's pathForResource:ofType: method and you can write to that file. If you want just the directory of the bundle, use resourcePath.
You don't want to do this, though. There are various reasons, but you'll break code signing, which is a big one. You should use the established conventions instead (such as writing to Library:Application Support:Your App).
EDIT: For a (possibly) more convincing reason of not to do this... When I was first learning Cocoa programming, I saved to the bundle because I didn't want to bother with the Library. It got really annoying, though, because every time you make a change to your program, you lose all of your saved data/settings for that program (assuming you're not using NSUserDefaults for preferences). I kept having to move it over from the old version to the new one. By using the Library, you don't have to worry about this.
The bundle is on disk; it's just the ".app" directory. You should not write to files in this directory, however. While currently possible on Mac, it will break code signing. On iPhone, you already can't write into your own bundle, and we should expect to see this limitation in the future on Mac. You should write your application files into various directories under ~/Library or ~/Documents as appropriate. See the File System Programming Guide for guidance.