I have written a Java application that has to monitor a live log file. However I have not thought of the possibly of the file being locked, and that is exactly the case now.
Is there a way to disable the ability to add filelocks in a directory under Windows? If I would succeed, what would happen to the program writing to the logs (I think it's written in C#).
I am suspecting the logger locks the file to prevent it from being deleted, I cannot see any reason why it would need to prevent reads on it.
Does anyone perhaps know another solution to "cancel" the read-part of a file lock from within Java, if that even makes sense?
The entire idea of a lock is that when you acquire it, you have some sort of guarantee that you have exclusive access (of the desired type(s)) to the file. Perhaps the programmer of the other application made a mistake or did not give much thought to how he/she locked the file.
I don't think there are clean ways to bypass this problem (except hooking the OS calls?). You could open the file before running the other application, but chances are the application wouldn't even start up in that case.
Related
Here's the scenario:
Some application reads contents of a file. It does so by opening it for shared reading, and then at some point closing it (as I've seen it in Procmon.exe, see image). Right after the file is closed, I want to run my own code editing that file.
The only answer I've found so far is looping File.Open() in a try block and firing an event when it throws an exception, and that won't work for shared read access, let alone how ugly it is.
Is there a package or a custom class I can use?
Edit: The application doesn't lock the file. To make sure, I tried running File.OpenRead(); Thread.Sleep(); before the application launch, and it loaded the file as intenteded. It crashed with File.OpenWrite() though, so I'm convinced there are no locks placed by the application.
Edit: Tried writing some test programs with Restart Manager API implementations, none of them seem to be capturing non-locking reading.
I am busy writing an additional module to an existing C# application. In my module I have to generate some data and add it to ZIP archives created by the main program. (Ionic.Zip library is used). In most cases I can successfully update existing archives and store them again. But sometimes (and quite often) this does not work, since, as far as I understand, something in the main program opens a stream to the concerned archive file and fails to close it before I try to access it.
It is absolutely clear that the process that locks the files is the main program itself (tested with a tool based on How do I find out which process is locking a file using .NET?).
I am not aware of any technical possibility to trace down the point in the code where a file is opened without being (somewhere) closed, but it is my hope that such a technique may exist however and that someone could share some information on it.
TIA
I wrote a custom control for output file name selection with the typical: text box for the filename, a "browse" button, and some other functionality specific to my application.
The text box changes color depending on the filename. If the file location cannot be written to, it turns red. If the file already exist, it turns yellow. Otherwise, it remains the system-assigned color.
To see if a file exists, I use IO.File.Exists; simple enough.
I implemented the "if the file can be written to" as a simple try-catch block where a file is actually opened, something written in it, closed, then deleted. If at any point an exception is thrown, I know the user can't use that filename and I turn the text box red.
This is a catch-all; since I'm doing the actual operation I intend to do, it is fool-proof. However, it seems irresponsible to have software creating and deleting files like crazy just to see if it can.
So my question is, how do I replicate this functionality without creating files? I can see I have to:
Check the path for legality (e.g., 'z:' is not a valid filename). This entails parsing the path and making sure all directories exist.
If the location exists, I have to check for write permissions. (Several answered questions exist to this end.)
Is there anything else?
EDIT
Within minutes I see people are already voting up an answer that criticizes that I'm checking at all that the file is accessible before actual writing to it occurs. While I appreciate experts "standing back" from my question to see whether or not there is a completely different way to achieve it, telling me I shouldn't be doing it is not an answer to my question.
So let me elaborate on my application (I am not expecting hundreds of users at the same time).
I use this file chooser control in data acquisition applications. In many situations the test that you are about to run is "expensive" in one way or another. Therefore it is critical to set things up very carefully. Overwriting data can be very expensive (and for the fearful user I have a checkbox that will append the date and time down to the millisecond to the filename).
So the purpose of my indicator colors is not to provide a surefire way for the software to know the file can be written to (that check is still done at the instant it actually has to), it's to serve as an indicator to the user that at least he has set up the file name correctly so if he goes forward he is guaranteed not to overwrite old data and he's almost sure a last-minute IO error (filename typo) won't let the experiment run unrecorded.
I suggest this - don't check anything before user commits the action. With your current approach, even if you verified the file is okay, it may be locked 5 seconds later when the user actually commits to write to a file. Doing preliminary checks may only give user a false impression of estimated success. Especially consider this point on a terminal server with 100+ simultaneous users.
There is nothing wrong with showing a prompt with Retry/Cancel/etc. if no access, and let user decide.
EDIT:
No offense, but there are standards on how such collisions are handled. Windows standard is to show a prompt to the user. Also consider this - if you suddenly have a deny in write access to the folder, which you are not expected to have, you probably need to hire another system/network administrator.
If the operation is costly, make sure this guy is paid well. C'mon, what if your network goes down during writing? Hard drive? Router? There are many reasons why writing to a file can be interrupted, and you should be prepared for that. If you cannot afford it, make sure you have invested in good infrastructure and good people to support it.
Down on earth, you can increase chances of acquiring a successful lock on the file:
Pick a unique file name, using datetime-based hash as a suffix/prefix.
Write to user's home directory, also known as %UserProfile%, it is likely that you will succeed.
I can understand your problem with not wanting to risk losing "expensive" data because the file couldn't be written and a responsible program will do it's best to avoid the situation.
I would do this by cacheing the results. Before the test is run write a mock result to a file somewhere in the user data space, then leave the file open and write the real result to the file. After this is done write it to the user-specified file. Provide a recovery option that will read the cache file and write it out to the user's file.
Your approach could fail because just because the file was writable at the start doesn't mean it's still writable. The network could have gone down. Someone could have removed the flash drive. Someone else could be doing a large data transfer through a buggy router. (Real world case--it took me a long time to prove it was a network problem and not my program. finally accepted it was their fault when I showed that dir :*.* /s on multiple machines at once would almost certainly cause one or more to fail.)
Is there any way to make a file totally uneditable and undeleteable ? I am creating simple Anti-Virus program and I want to protect my malware signatures which are saved in files.
The short answer is 'you can't.' The long answer follows. =)
You may implement it via file permissions, but those can be changed if a process have enough privileges.
TMK, the only way to implement this kind of restriction is to keep a process running, with the file open in exclusive mode. That won't prevent an application like Unlocker from killing your main process or deleting the block handles, though.
No, you can't. If a software runs with enough privileges, it will be able to erase them along with your antivirus. This also happens with commercial antivirus software.
What you can do, in order to at least prevent modifications, is store the definitions as compressed, signed and, encrypted. In this way, unless the malware can obtain the criptographic key, it won't be able to meaningfully modify the virus database, but only to delete it. In both cases, your software can detect the intervention and try to react (but if a malware is privileged enough to delete system files, maybe it' already too late)
you cant really do so, but you can try outsmarting malware...
Save a checksum of the file so you know if it was tampered.
Use Async Encryption on the file (somwhat similar to 1.)
make the signatures downloadable through Internet access, and make your software download those...
check the last accessed times of the files.
there are many more tricks like the four above, but they are all NOT boolet proof...
One Crazy idea that i dont really know how to implement... but came to mind is that:
you can create a SATA/IDE Driver and make the a specific file unaccesible...
but again thats my kind of creativity crazy talk :)
The best you can do with C# is to just set the permissions of the file so that only your service has full access, and anyone else doesn't. That don't protects against someone/something that managed to get administrator access, as they always can change permissions.
What many antiviruses do for self-protecting their files and services is to install kernel-mode drivers that block both the critical files and processes, so not even administrators can stop them. Of course C# is unable to create them.
I am implementing an event handler that must open and process the content of a file created by a third part application over which I have no control. I am warned by a note in "C# 4.0 in a nutshell" (page 495) about the risk to open a file before it is fully populated; so I am wondering how to manage this occurrence. To keep at minimum the load on the event handler, I am considering to have the handler simply insert in a queue the file names and then to have a different thread to manage the processing, but, anyways, how may I make sure that the write is completed and the file read is safe? The file size could be arbitrary.
Some idea? Thanks
A reliable way to achieve what you want might be to use FileSystemWatcher + NTFS USN journal.
Maybe more complicated than you expected, but FileSystemWatcher alone won't tell you for sure that the newly created file has been closed
-first, the FileSystemWatcher, to know when a file is created. From there you have the complete file path, and are 1 or 2 pinvokes away from getting the file unique ID (which can help you to track it during its whole lifetime).
-then, read the USN journal, which tracks everything that occurs on your drive. Filter on entries corresponding to your new file's ID, and read the journal until reaching the entry with the 'Close' event.
From there, unless your file is manipulated in special ways (opened and closed multiple times by the application that generates it), you can assume it is safe to read it and do whatever you wanted to do with it.
A really great C# implementation of an USN journal parser is StCroixSkipper's work, available here:
http://mftscanner.codeplex.com/
If you are interested I can give you more help about USN journal, as I use it in my project.
Our workaround is to watch for a specific extension. When a file is uploaded, the extension is ".tmp". When its done uploading, it's renamed to have the proper extension.
Another alternative is to have the server try to move the file in a try/catch block. If the fie isn't done being uploaded, the attempt to move the file will throw an exception, so we wait and try again.
Realistically, you can't know. If the other applications "write" operation is to open the file denying write access to everyone else then when it's done, close the file. When you get a notification then you could simply open the file requesting write access and if that fails, you know the operation isn't complete. But, if the "write" operation is to open the file, write, close the file, open the file again, and write again, etc., then you're pretty much out of luck.
The best solution I've seen is to set a timer after the last notification. When the timer elapses, try to open the file for write--if you can, assume the "operation" is done and do what you need to do. If the open fails, assume the operation is still in progress and wait some more.
Of course, nothing is foolproof. Despite the above, another operation could start while you're doing what you want with the file and cause interaction problems.