Test if a file is deletable - c

Is there any way to determine if a file can be deleted before trying DeleteFile on it. I just want to test if a DeleteFile will succeed without really deleting the file. What I want to do is to create a hardlink to a file if it is not in use and to copy it if it is in use without FILE_SHARE_DELETE(there is in the system a handle opened on it woithout FILE_SHARE_DELETE flag).
Thank you!

Disclaimer: I don't really know anything about Windows programming. But I read documentation.
According to the MSDN documentation for CreateFile, you can specify DELETE in the dwDesiredAccess parameter, which will cause the CreateFile call to fail if the access right is not available. (You can also specify OPEN_EXISTING for dwCreationDisposition if you don't actually want to create a new file.) That should cover your use case.
However, it's worth pointing out that there is an race condition; you might do this test and then just afterwards, before you have a chance to act on the result, someone else might open the file without the FILE_SHARE_DELETE. So for the test to be meaningful, you'd need to know more about the lifecycle of files than is mentioned in your question (which you indeed might know; it isn't really necessary to mention it, so if you do, just ignore this paragraph.)

Thank you everyone for your answers. In the end after 3 days of searching(after 2 days I posted my question here) I found I needed. At the beginning (3 days ago) I thought DELETE flag is enough for the test, but it does not work - I still am able to open a handle even there is another handle open in the system without FILE_SHARE_DELETE flag. Anyway, starting from here I manage to find a solution in the end - making a CreateFile with FILE_FLAG_DELETE_ON_CLOSE - if I receive a valid handle than the file is deletable. Before closing the handle using NtSetInformationFile with FILE_DISPOSITION_INFORMATION I remove FILE_FLAG_DELETE_ON_CLOSE so this way I avoid deleting the file when closing the handle. And indeed I do have control over the lifecycle of that file - meaning that after I make the test no one should open it without SHARE_DELETE - at least not the processes I control which should be enough for what I have to do.

Related

How to check if a file is in read-only mode in C [duplicate]

This question already has answers here:
How can I determine if a file is read-only for my process on *nix? [duplicate]
(3 answers)
Closed 5 years ago.
How I can check if a file is in read-only mode in C? I would like to check if it is possible write in a file before opening it.
This is a case where it is easiest and most reliable to try opening the file for writing, and react appropriately if the open fails ('Easier to Ask for Forgiveness than for Permission') than to try and determine whether it will fail first ('Look Before You Leap') — see LBYL vs EAFP.
You can use stat(), but it is modestly tricky to determine the permissions correctly. Also, there could be ACLs that mean you can access the file for writing even if the permissions reported by stat() indicate that you can't (or vice versa). You could use access(filename, W_OK), and it will usually give you the correct answer — unless your program is running with effective UID different from real UID.
However, any LBYL strategy also suffers from TOCTOU — Time of Check, Time of Use — issues. The permissions on the file, or one of the directories leading to it, might change between the time when you check the file permissions and the time when you actually try to open the file. The permissions might have said "it is OK" but the file could have been removed, or changed to read-only since then.
You can use fopen, and check for the return value. Check here: http://www.tutorialspoint.com/c_standard_library/c_function_fopen.htm
You can use fstat() function.
See man 2 fstat for details:
http://linux.die.net/man/2/fstat
While retrieving the file permissions with the fstat/stat functions will give you good hints is the usual cases, I would recommend not to trust them too much as there are corner ones where the file will be writable despite being reported read only, for example if you are root, and also cases you won't be able to write the file despite being reported writeable, for example if it is located on a read-only file system.
ACLs might also play a similarly confusing role by reversing what the st_mode is reporting.

How would I go about checking the file system I'm working on in C

I'm making a program and one of the things it needs to do is transfer files. I would like to be able to check before I start moving files if the File system supports files of size X. What is the best way of going about this?
Go on with using a function like ftruncate to create a file of the desired size in advance, before the moving, and do the appropriate error-handling in case it fails.
There's no C standard generic API for this. You could simply try creating a file and writing junk to it until it is the size you want, then deleting it, but even that isn't guaranteed to give you the info you need - for instance another process might have come and written a large file in between your test and your transfer, taking up space you were hoping to use.

Is there a way to read HD data past EOF?

Is there a way to read a file's data but continue reading the data on the hard drive past the end of file? For normal file I/O I could just use fread(), but, obviously, that will only read to the end of the file. And it might be beneficial if I add that I need this on a Windows computer.
All my Googling for a way to do this is instead coming up with results about unrelated topics concerning EOF, such as people having problems with normal I/O.
My reasoning for this is that I accidentally deleted part of the text in a text file I was working on, and it was an entire day's worth of work. I Googled up a bunch of file recovery stuff, but it all seems to be about recovering deleted files, where my problem is that the file is still there but without some of its information, and I'm hoping some of that data still exists directly after the currently marked end of file and is neither fragmented elsewhere or already claimed or otherwise overwritten. Since I can't find a program that helps with this specifically, I'm hoping I can quickly make something up for it (I understand that, depending on what is involved, this might not be as feasible as just redoing the work, but I'm hoping that's not the case).
As far as I can foresee, though I might not be correct (not sure, which is why I'm asking for help), there are 3 possibilities.
Worst of the three: I have to look up Windows API functions that allow direct access to the entire hard drive (similar to its functions for memory, perhaps? those I have experience with) and scan the entire thing for the data that I still have access to from the file and then just continue looking at what's after it.
Second: I can get a pointer to the file, then I still have to get raw access to HD but at least have a pointer to the file in it?
Best of the three: Just open the file for write access, seek to the end, then write a ways past EOF to claim more space, but first hope that Windows won't clean the data before it hands it over to me so that I get garbage data which was the previous data in that spot which would actually be what I'm looking for? This would be awesome if it were that simple, but I'm afraid to test it out because I'd lose the data if it failed, so hopefully someone else already knows. The PC in question is running Vista Home Premium if that matters to anyone that knows the gory details of Windows.
Do either of those three seem plausible? Whether yea or nay, I'm also open (and eager) for other suggestions, especially those which are better than my silly ideas, and especially if they come with direction toward specific functions to use to get the job done.
Also, if anyone else actually has heard of a recovery program that doesn't just recover deleted files but which would actually work for a situation like this, and which is free and trustworthy, that works too.
Thanks in advance for any assistance.
You should get a utility for scanning the free space of a hard drive and recovering data from it, for example PhotoRec or foremost. Note however that if you've been using the machine much at all (even web browsing, which will create files in your cache), the data has likely already been overwritten. Do not save your recovery tools on the same hard drive, or even use the same PC to download them; get them from another computer and save them to a USB device, then run them from that device.
As for the conceptual content of your question, files are abstract objects. There is no such thing as data "past eof" except (depending on the implementation) perhaps up to the next multiple of the filesystem/disk "blocksize". Also it's possible (very likely) that your editor "saved" the file by truncating it and writing everything newly from the beginning, meaning there's not necessarily any correspondence between the old and new storage.
Your question doesn't make a lot of sense -- by definition there is nothing in the file after the EOF. By your further description, it appears that you want to read whatever happens to be on the disk after the last byte that is used by the file, which might be random garbage (unused space) or might be some other file. But in either case, this isn't 'data after the EOF' its just data on the disk that's not part of the file. Its even possible that it might be some other part of the same file, if the filesystem happens to lay out its data that way -- some filesystems scatter blocks in seemingly random ways across the disk and figuring out what bytes belong to which files requires understanding the filesystem metadata.

Createfile function

I am creating the file using Createfile function.
The C program is working fine but I am unable to see the created file in the respective folder.
Also "view hidden files" option is checked.
You can check if the function worked correctly by checking out the returned HANDLE value.
edit: A C program continues to function (incorrectly though) if a functions fails. It's therefore very important to check each and every returned HANDLE.
edit: The returned HANDLE should not be INVALID_HANDLE_VALUE. (But I can imagine that NULL isn't good either).
Two things to check for. Number one, did it actually succeed? From the docs:
Return Value
If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot.
If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
Number two, are you looking in the right place. Frequently, people who run their code from within an IDE don't realise that their current working directory is not always what they think it is. You can system("cd"); or something similar to see what it actually is.
Or, you can use absolute pathnames to ensure the file is being created at the right place (for testing, that is - you should never use absolute paths for production code).
If neither of those two suggestions help, you should post the code that shows the particular problem. Preferably enough so that we don't have to come back and ask for more.

Recommendations for encrypting/decrypting scripts elegantly?[Now on Sourceforge]

Update2:
Thanks for the input. I have implemented the algorithm and it is available for download at SourceForge. It is my first open source project so be merciful.
Update:
I am not sure I was clear enough or everyone responding to this understands how shells consume #! type of input. A great book to look at is Advanced Unix Programming. It is sufficient to call popen and feed its standard input as demonstrated here.
Original Question:
Our scripts run in highly distributed environment with many users. Using permissions to hide them is problematic for many reasons.
Since the first line can be used to designate the "interpreter" for a script the initial line can be used to define a a decrypter
#!/bin/decryptandrun
*(&(*S&DF(*SD(F*SDJKFHSKJDFHLKJHASDJHALSKJD
SDASDJKAHSDUAS(DA(S*D&(ASDAKLSDHASD*(&A*SD&AS
ASD(*A&SD(*&AS(D*&AS(*D&A(SD&*(A*S&D(A*&DS
Given that I can write the script to encrypt and place the appropriate header I want to decrypt the script (which itself may have an interpreter line such as #!/bin/perl at the top of it) without doing anything dumb like writing it out to a temporary file. I have found some silly commercial products to do this. I think this could be accomplished in a matter of hours. Is there a well known method to do this with pipes rather than coding the system calls? I was thinking of using execvp but is it better to replace the current process or to create a child process?
If your users can execute the decryptandrun program, then they can read it (and any files it needs to read such as decryption keys). So they can just extract the code to decrypt the scripts themselves.
You could work around this by making the decrtyptandrun suid. But then any bug in it could lead to the user getting root privileges (or at least privileges to the account that holds the decryption keys). So that's probably not a good idea. And of course, if you've gone to all the trouble of hiding the contents or keys of these decryption scripts by making them not readable to the user... then why can't you do the same with the contents of the scripts you're trying to hide?
Also, you can't have a #! interpreted executable as an interpreter for another #! interpreted executable.
And one of the fundamental rules of cryptography is, don't invent your own encryption algorithm (or tools) unless you're an experienced cryptanalyst.
Which leads me to wonder why you feel the need to encrypt scripts that your users will be running. Is there anything wrong with them seeing the contents of the scripts?
Brian Campbell's answer has the right idea, I'll spell it out:
You need to make your script unreadable but executable by the user (jbloggs), and to make decodeandrun setuid. You could make it setuid root, but it would be much safer to make it setgid for some group decodegroup instead, and then set the script file's group to decodegroup. You need to make sure that decodegroup has both read and execute permissions on the script file and that jbloggs is not a member of this group.
Note that decodegroup needs read permission for decodeandrun to be able to read the text of the script file.
With this setup, it is then possible (on Linux at least) for jbloggs to execute the script but not to look at it. But observe that this makes the decryption process itself unnecessary -- the script file might as well be plaintext, since jbloggs can't read it.
[UPDATE: Just realised that this strategy doesn't handle the case where the encrypted contents is itself a script that starts with #!. Oh well.]
You're solving the wrong problem. The problem is that you have data which you don't want your users to access, and that data's stored in a location to which the users have access. Start by attempting to fix the problem of users with more access than they require...
If you can't protect the whole script, you may want to look into just protecting the data. Move it to a separate location and encrypt it. Encrypt the data with a key only accessible by a specific ID (preferably not root), and write a small suid program to access the data. In your setuid program, do your validation of who should be running the program, and compare the name / checksum of the calling program (you can inspect the command line for the process in combination with the calling process's cwd to find the path, use lsof or the /proc filesystem) with the expected value before decrypting.
If it takes more than that, you really need to reevaluate the state of users on the system - they either have too much access or you have too little trust. :)
All of the exec()-family functions you link to accept a filename, not a memory address. I'm not sure at all how you would go about doing what you want, i.e. "hooking" in a decryption routine and then re-directing to the decrypted script's #! interpreter.
This would require you to decrypt the script into a temporary file, and pass that filename to the exec() call, but you (very reasonably) said you didn't want to expose the script by putting it in a temporary file.
If it were possible to tell the kernel to replace a new process with an existing one in memory, you would have a path to follow, but as far as I know, it isn't. So I don't think it will be very easy to do this "chained" #! following.

Resources