How to force deletion of file in C? - c

How can I remove opened file in linux?
In shell I can do this:
rm -rf /path/to/file_or_directory
But how can I do it in C?
I don't want to using system() function.
I have seen unlink and remove method but it's haven't any flags to set force deletion.

The unlink and remove functions force deletion. The rm command is doing extra checks before it calls one of those functions. But once you answer y, it just uses that function to do the real work.

Well, I hope this answers your question.. This program searches the current directory for the filename, you have to add the feature of opening a different directory, which shouldn't be too hard... I don't understand the last line of your question, can you elaborate? But flags aren't necessary for remove and unlink (They force delete)...
#include<stdio.h>
int main()
{
int status;
char file_name[25];
printf("Enter the name of file you wish to delete\n");
fgets(file_name,25,stdin);
status = remove(file_name);
if( status == 0 )
printf("%s file deleted successfully.\n",file_name);
else
{
printf("Unable to delete the file\n");
perror("Error");
}
return 0;
}

To perform a recursive removal, you have to write a moderately complicated program which performs a file system walk. ISO C has no library features for this; it requires platform-specific functions for scanning the directory structure recursively.
On POSIX systems you can use opendir, readdir and closedir to walk individual directories, and use programming language recursion to handle subdirectories. The functions ftw and its newer variant nwft perform an encapsulated file system walk; you just supply a callback function to process the visited paths. nftw is better because it has a flags argument using which you can specify the FTW_DEPTH flag to do the search depth first: visit the contents of a directory before reporting the directory. That, of course, is what you want for recursive deletion.
On MS Windows, there is FindFirstFile and FindNextFile to cob together a recursive traversal.
About -f, that only suppresses certain checks done by the rm program above and beyond what the operating system requires. Without -f, you get prompted if you want to delete a read-only file, but actually, in a Unix-like system, only the directory write permission is relevant, not that of the file, for deletion. The remove library function doesn't have such a check.
By the way, remove is in ISO C, so it is platform-independent. On POSIX systems, it calls rmdir for directories and unlink for other objects. So remove is not only portable, but lets you not worry about what type of thing you're deleting. If a directory is being removed, it has to be empty though. (Not a requirement of the remove function itself, but of mainstream operating systems that support it).

remove or unlink is basically equivalent to rm -f already--that is, it removes the specified item without prompting for further input.
If you want something equivalent to rm -r, you'll need to code up walking through the directory structure and deleting items individually. Boost Filesystem (for one example) has code to let you do that fairly simply while keeping the code reasonably portable.

Related

How to programatically move a Linux symlink to a different file system (copy) in C?

rename() C function does not work across file systems. So I can move files via a copy by opening them, reading them and writing them to a new copy and then unlinking. But I have a hard time getting this to work with symlinks. (The idea is to move a folder with a bunch of other files/folders/symlinks etc inside of it). Basically implementing a mv command in C.
open(file, O_RDONLY)
while ((c = read(source_descriptor, buf, SIZE)) > 0){
write(d, buf, c);
}
unlink file;
Works good for normal files (and I have another function handling directories without issues). But whenever it hits a symlink I get perror spitting out No such file or directory.
I can detect if its a symlink via d_type but am not sure how to read/copy it once I have one since the normal file copy doesnt seem to work with symlinks because open() refuses to open them.
Once you have determined that you're dealing with a symlink (which can be done e.g. by using lstat()), you can read its contents with readlink() and recreate it at the target location by calling symlink().
See also man 7 symlink.
When you open a symlink without the O_NOFOLLOW flag, it will dereference the symlink (or symlink chain, if it's a symlink to a symlink). If the destination does not exist, open will fail. The O_NOFOLLOW flag makes sure, that if you attempt to open a symlink you will realiably get an error.
To "copy" a symlink, you'll have to read it with readlink and create a new symlink at the destination. However you may have to adjust the path it points to.
However if a program of yours has the need to copy directory trees on a *nix system, the correct way to implement this is not to reinvent the wheel, but to follow the Unix way and just execute the cp program with the right arguments.

C Programming: How to create a parent directory and insert files manually?

My goal is to, inside my C program, make a new directory. Within this directory, I want to create 15 simple text files. The part that I am stuck on is how to generate the 15 text files inside the newly created directory. I have created the new directory like this:
mkdir("new_dir", 0755);
But I am unsure of how to create a text file within it (in the same program). Any tips for this?
I am guessing you are on some POSIX system. The C11 standard (read n1570) does not know about directories (an abstraction provided by your operating system). If you are on Windows, it has a different WinAPI (you should then use CreateDirectory)
First, your call to mkdir(2) could fail (for a variety of reasons, including the fact that the directory did already exist). And very probably, you actually want to create the directory in the home directory, or document that you are creating it in the current working directory (e.g. leave the burden of some appropriate and prior cd shell builtin to your user). Practically speaking, the directory path should be computed at runtime as a string (perhaps using snprintf(3) or asprintf(3)).
So if you wanted to create a directory in the home directory of the user (remember that ~/foo/ is expanded by the shell during globbing, see glob(7)...; you need to fetch the home directory from environ(7)), you would code something like:
char pathbuf[256];
snprintf(pathbuf, sizeof(pathbuf), "%s/new_dir", getenv("HOME"));
to compute that string. Of course, you need to handle failure (of getenv(3), or of snprintf). I am leaving these checks as an exercise. You might want to keep the result of getenv("HOME") in some automatic variable.
Then you need to make the directory, and check against failure. At the very least (using perror(3) and see errno(3)):
if (mkdir (pathbuf, 0750)) { perror(pathbuf); exit(EXIT_FAILURE); }
BTW, the mode passed to mkdir might not allow every other user to write or access it (if it did, you could have some security vulnerability). So I prefer 0750 to yours 0755.
At last you need to create files inside it, perhaps using fopen(3) before writing into them. So some code like
int i = somenumber();
snprintf(pathbuf, sizeof(pathbuf),
"%s/new_dir/file%d.txt", getenv("HOME"), i);
FILE* f = fopen(pathbuf, "w");
if (!f) { perror(pathbuf); exit(EXIT_FAILURE); };
As Jonathan Leffler wisely commented, there are other ways.
My recommendation is to document some convention. Do you want your program to create a directory in the current working directory, or to create it in some "absolute" path, perhaps related to the home directory of your user? If your program is started by some user (and is not setuid or doesn't have root permissions, see credentials(7)) it is not permitted to create directories or files at arbitrary places (see hier(7)).
If on Linux, you'll better read some system programming book like ALP or newer. If you use a different OS, you should read the documentation of its system API.

removing files from C code

I have to remove few hundreds of files inside my C code. I use "remove" in a loop. Is there any faster way to do it than using "remove"? I ask this because I can't give wildchars using "remove".
No, there isn't a quicker way than using remove() - or unlink() on POSIX systems - in a loop.
The system rm command does that too - at least in the simple, non-recursive case where the names are given on the command line. The shell expands the metacharacters, and rm (in)famously goes along deleting what it was told to delete, unaware of the disastrous *.* notation that was used on the command line. (In the recursive case, it uses a function such as nftw() to traverse the directory structure in depth-first order and repeated calls to unlink() to remove the files and rmdir() to remove the (now-empty) directories.)
POSIX does provide functions (glob() and wordexp()) to generate lists of file names from metacharacters as used in the (POSIX) shell, plus fnmatch() to see whether a name matches a pattern.
You could use system to spawn a shell which would do the * expansion for you. This would probably not run any faster than just calling unlink() in a loop, though, because it would have to spawn a shell (start a new process). But it would be easier to code.

cleaning the files in directory in linux

I want to clean all files in a directory on Linux (not deleteing them, only clear their content)
I need to do it in C.
Actually, you really don't need to do it in C. UNIX includes tools that can just about do any task that you want.
find . -type f -exec cp /dev/null {} ';'
That particular snippet above will find all files under the current directory and attempt to copy the null device to it, effectively truncating the file to 0 bytes.
You can change the starting (top level) directory, restrict names (with -name '*.jpg' for example) and even restrict it to the current directory (no subdirectories) with -maxdepth 0.
There are many other options with find that you can discover by entering man find into your command line shell. Just don't enter it into Google, you may get more than you bargained for :-)
If the need to use C is an absolutely non-negotiable one, I would still do it this way but with:
system ("find . -type f -exec cp /dev/null {} ';'");
I'm not keen on re-writing software that someone's already put a bucketload of effort into providing for free :-)
If, after my advice, you still want to do it the hard way, you need to look into opendir, readdir and closedir for processing directories, then just use fopen in write mode followed by fclose on each candidate file.
If you want to navigate whole directory structures rather than just the current directory, you'll have to detect directories from readdir and probably recurse through them.
scandir to list them, then for every file:
fopen(, w+)
fstat to get the size
fwrite the whole file with zeroes? (this is what you mean by clear?)
fclose
A nice shell variant would be: shred -z directory/*
In Bash:
for i in directory/*; do > $i; done
This will preserve ownership and permissions of the file.
Don't do shell work in C! Save a huge amount of time by using the best tool for the job. If this is homework, mark it as such.
You can open the file in write mode and then close it.

How to generate random file name for socket under Linux?

I want to make a small program which use local namespace socket and I will need to use temporary file name as address of the socket.
So how to generate random file name under Linux?
+ I'm using the C programming language under Debian Linux.
+ Acoording to the GNU C Library Reference,tmpname is not safe.But the safe ones tmpfile and mkstemp create and open the generated file.Is there any safe and non-create-open to this.In other words, the function should forbidden any other request to create the generated file name under specific directory.
thanks.
If you're doing this in C, use mkdtemp to create a directory, and put your socket inside this directory.
Other functions such as tmpnam or mktemp are insecure; since they don't create and open the temp file for you, it's easy to be vulnerable to following a pre-existing symlink (placed by an attacker who guessed your temp filename) to some important file (like /etc/passwd), overwriting it.
Note that there's no way to 'lock' a path - all you can do is create something there. If you need to put a socket there eventually, using a directory as a placeholder is your best bet.
There is mktemp program which is available as part of GNU coreutils. See it's manpage for details.
Typical usage is as simple as this:
TEMPDIR=$(mktemp -d)
echo $TEMPDIR
touch $TEMPDIR/yourfile.txt
(As noted in other answer it is only safe to create a directory.)
You didn't specify the language you are using, but assuming it is a C/C++ dialect (or some other language with access to the C runtime library), you could use the tmpnam function.
There are some issues with tmpnam, the most serious of which is probably that the temporary file name you get back isn't actually "locked" until you use it to create a file, so theoretically some other process could create the file out from under you. You also have to make absolutely sure the buffer you pass tmpnam has enough space to hold the longest path your OS can support.
These days it is recommended that you call tmpfile instead. This will create the file for you in one (hopefully atomic) operation, and give you back a file handle. Another nice benefit is that the file is deleted for you automatically when you close it. No muss, no fuss.
Play with /dev/random.
A quick search on google gave me this hit:
< /dev/urandom tr -dc A-Za-z0-9 | head -c8
If you would like to do the same in C,
just open /dev/random and convert it into a string (ignore non valid chars).

Resources