Implementing rename in fuse file system - c

I'm trying to implement an in-memory file system using fuse. The rename function accepts 'from' and 'to' parameters.
When I tried doing this on bash,
mv file1 file2,
it internally calls rename function (I used the -d option to check it).
When i try to rename the function in the GUI, it again calls the rename function.
But if file2 is an already existing file, mv command overwrites it whereas the GUI prevents me from renaming the file. How do I enforce this constraint because internally both these actions call the rename function with no distinction.

The rename function replaces the target file atomically with removal of the old name. This is the whole point of it, and if it doesn't do that correctly, various things would break badly. For applications that want to prevent renaming over top of another file, they have to use the link function (which will fail if the target exists) first, then unlink the old name if link succeeded.

Related

How to rename a directory in C?

I searched online to find that how to change the directory name? But I found nothing. All I found was rename() that was changing filenames. I want to change a directory name. Linux uses mv command for renaming a directory but if the directory contains large files then moving will take time more right? I want to do this in C.
On every file system I can think of, renaming a directory doesn't actually involve moving the files to a new location but rather changing a record in the file system.
To move a directory on Windows:
if(!MoveFileW(L"C:\\Path\\OldDirName", L"C:\\Path\\NewDirName"))
{
// Operation failed
}
On *nix:
if(rename("/path/olddirname", "/path/newdirname") != 0)
{
// Operation failed
}
Wrapper macros:
#ifdef __linux__
#define MvDir(old, new) (rename((old), (new)) != 0)
#elif defined(WINVER)
#define MvDir(old, new) !(MoveFileW((L ## old), (L ## new))
#endif
This also automatically wraps the success-test of the expression into a 1/0 value for you.
...how to change the directory name? ...All I found was rename() that was changing filenames.
No, that's incorrect. rename is totally fine for renaming directories, also.
Linux uses mv command for renaming a directory but if the directory contains large files then moving will take time more right?
The mv command is typically implemented using rename, which is very fast. Renaming a directory does not necessarily require moving (or doing anything with) the files in it.
If you're doing a more complicated rename, like trying to rename a/b/c to d/e/f, and if this ends up trying to move things onto a different mounted filesystem, then a simple directory rename won't work, and yes, actually "moving" (actually copying) of files would be required. In that case, the rename() call will fail, so you'll know. (errno should contain EXDEV.)
In the cross-device case, the mv command will do the expensive work of copying files, but only if it has to.
If you use rename from a C program, you'll get a quick rename for renames on the same filesystem, and an error for renames that attempt to cross filesystems, and you'll never get any expensive copies unless you code them up yourself.

Rename code in c have a error

i want to move a file from a directory to anther directory with C Coding.
I search and find rename(); function , but when working it doesnt work and have a error:
my code:
#include <stdio.h>
int main() {
if(rename("/root/tmpfile.php", "/home/check-tmp.php"))
perror( NULL );
}
the code well compiled but when running this code showing this error:
Invalid cross-device link
How to move a file from a directory to anther directory without using System for fopen?
Aslo , i finded many codes and ways to do it but doesnt working all codes.
Please say me a way and make sure it will work
Thanks.
Many aspects of the behavior of `rename' are inherently platform-dependent: The rename operation might not be able to move a file from one file system to another , it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists.
In other words, your system does not support rename files cross different partitions (your root partition and your home partition are different.)
So the solution is when it fails, copy the file to the destination and delete the original.
The rename call can only rename and move files within a single disk partition. The error "cross-device link" indicates that you attempted to move a file from one partition to another. (If you were on a Windows system, you can imagine if you tried to rename a file from C: to D:.)
When you use the Unix mv command to move files, it first tries a rename, but if it fails in this way, it falls back and makes a new copy of the file in the new location, then deletes the original. That's what you would have to have your code do in this situation, too.
(Copying a file is easy enough, but there are plenty of library functions out there that will do it for you, and also take care of things like preserving the last-modified time and other file attributes.)

Delete files with AppleScript to recycle bin or permanently

I'm writing an AppleScript in which I want to insert a subroutine to delete specified files. With a flag I wish to control whether the given file is moved to the recycle bin or deleted permanently.
Actually my script looks like this:
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete POSIX file theFile
else
do shell script "rm " & theFile
end if
end MyDeleteProc
Now I want to know if this case is correct so far or is there maybe another Finder command or a parameter for the delete command that I overlooked so I will be able to simplify the script above?
AppleScript is a temperamental beast, and the devil is often in the details.
While #adayzdone's answer provides the crucial pointer - use of the System Events application's delete command to achieve permanent deletion, working out the exact syntax takes trial and error:
Caveat: This handler works with both files and folders - targeting a folder with allowUndo set to false therefore permanently deletes that folder's entire subtree.
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete theFile as POSIX file
else
tell application "System Events" to delete alias theFile
end if
end MyDeleteProc
On OS X 10.9.4 I had to do the following to make this work:
Finder context: Had to change POSIX file theFile to theFile as POSIX file (postfix form) - don't ask me why.
System Events context: Using "cast" alias with the POSIX path provided is the only form of the command that worked for me.
That said, a little tweak to your original function would make it work, too (and unless you delete many files one by one, performance probably won't matter):
Note, however, that just using rm only works with files - if you wanted to extend it to folders, too, use rm -rf instead - the same caveat re permanently deleting entire subtrees applies.
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete theFile as POSIX file
else
do shell script "rm " & quoted form of theFile
end if
end MyDeleteProc
Note the use of quoted form of, which safely passes the file path to the shell, encoding characters such as spaces properly.
You can use System Events to permanently delete a file.

Creating a unique temporary directory from pure C in windows

I'd like to create a unique temporary directory in Windows from some C
code (not C++ or C#). I want to do this so that I can put some temp
files in the directory, and then delete them all easily when I'm done
(by removing the directory recursively).
I'm essentially looking for an equivalent of the linux
mkdtemp
function. There is a C# answer here, and responses on this
question
suggest using Boost. But since I'm using C, those solutions don't work
for me.
The best I've been able to come up with so far is to use
GetTempFileName
followed by CreateDirectory,
but the problem there is that if I ask
GetTempFileName
to create a unique file name, it will also create the file (which I
don't want, since I want to make a directory instead).
Relatedly, there's
GetTempPath,
which returns the location of the user's temp folder from environment
variables - but since I want to create my own directory that I can
safely delete later, I still need to create a directory inside any
path it would return.
It looks like if I want a unique directory to be created, I'll have to
create a temp file, get the name, delete it, and then create a
directory with the same name - which sounds very messy.
Any other ideas?
You can use what GetTempPath returns concatenated with a Guid to ensure uniqueness of the directory. You can create a Guid using UuidCreate or CoCreateGuid Function.
To delete recursively the directory, there is an example here in pure C: How to remove directory recursively? based on FindFirstFile, FindNextFile, DeleteFile and RemoveDirectory.
There is also SHFileOperation but it's more heavyweight and is based on the Windows Shell functions, and the Shell DLLs are not always wanted, especially if you're writing server code.
Use GetTempPath then CreateDirectory with a random name under it, optionally retrying if CreateDirectory fails due to it already existing. But if your name generation is good enough, the likelihood of a collision with an existing name is much smaller than the likelihood of a blackhat guessing your password or even your private key, so you might as well ignore it.
Use _tempnam tmpnam_s to create a filename that doesn't exist yet, and then use CreateDirectory to create the directory. There's technically a race condition if you do this, in that another process could potentially create a file or directory with that name in the time in between when you generate the filename and when you create the directory, but the odds of that are rather unlikely. To protect against that, you can loop until you succeed.
For recursively removing a directory tree, you can use SHFileOperation. Alternatively, you can do the directory traversal yourself with FindFirstFile/FindNextFile, DeleteFile, and RemoveDirectory.
If you want to remove the directory automatically upon exiting, register a function using atexit. This will only work for normal program termination (i.e. via the exit function or via returning from main/WinMain). This will not work for abnormal program termination (e.g. via abort, an access violation, someone else calling TerminateProcess, etc.).

How to delete files with exclamation marks! using emacs' delete-file

I'm trying to make emacs' delete-file function delete files with exclamation marks in their names.
The particular use case is that I have set emacs to save all backup files in a single directory and to delete old backup files. However, when all backup files are placed in one directory, the directory separator / is replaced with !.
When delete-file is called on a file with an exclamation mark in its name, it returns zero and the file is not deleted. It doesn't signal any error. Normally, delete-file returns nil. Anyway, emacs' backup system uses delete-file for deletion, and I'd rather not redefine the entire function just to change a single line.
I've tried backslashing the exclamation marks and shell-quoting the filename string, and neither has worked. I found out that something in my config is causing this, but I haven't figured out what yet. I have tracked the source of the problem to my custom system-move-file-to-trash function, which I now have to debug.
So, how can I make this work?
Emacs version:
GNU Emacs 23.1.50.1
emacs-snapshot:
Installed: 1:20090730-1~jaunty1
M-x delete-file
Then just enter the name of the file, don't escape anything, just the name,
!home!blah!filename
and it just works. And the same goes for the lisp invocation,
(delete-file "!home!blah!filename")
I found the answer. My custom system-move-file-to-trash function, which delete-file will automatically use, inappropriately called shell-quote-argument on the file name. Apparently arguments to a command run using call-process do not need to be shell-quoted.

Resources