-7

I want to remove a file present in /tmp, say san.txt

I have two approach, Which one is better and why ?

approach one:

int main(){
        int status;
        pid_t pid = fork();
        if(-1 == pid){
                printf("fork() failed");
                exit(EXIT_FAILURE);
        }else if(pid == 0){
                execl("/bin/sh", "sh", "-c", "rm /tmp/san.txt", (char *) NULL);
        }else{
                printf("[%d]fork with id %d\n",pid);
                waitpid(pid,&status,0);
        }
return 0;
}

Approach 2:

int main(){
        int ret = unlink("/tmp/san.txt");
        if ( 0 == ret){
                printf("file removed \n");
        }
        return 0;
}
Sandeep_black
  • 1,352
  • 17
  • 18
  • 8
    Is this a serious question? If you want to use an external command instead of unlinking, and you want to use the shell to do it instead of calling it directly, and you want to fork/exec/wait the shell instead of calling `system`, surely you missed the step where you run php and have it `system` python so you can `subprocess` that `sh` with `shell=True` to make extra triple sure? – abarnert May 13 '18 at 07:24
  • Why would you want to run a shell (`rm` is not a built-in shell command anyhow)? Your second approach is poor anyway since it does not report errors. – cdarke May 13 '18 at 07:30
  • 1
    @abarnert I'm pretty sure a proper Rube Goldberg solution would also involve using a web API to start a calliope to scare a mouse into running across the keyboard to press the return key and execute the command. – Gordon Davisson May 13 '18 at 07:34
  • 1
    @GordonDavisson Needs more XML, but you're getting close. Also, is the mouse trained by a computer that was trained by machine learning? – abarnert May 13 '18 at 07:35
  • @abarnert I found system command vulnerable https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152177. So better to use fork/exec/wait. – Sandeep_black May 13 '18 at 07:45
  • 1
    @Sandeep_Black Passing a command to /bin/sh the way you do has the exact same vulnerabilities. – Gordon Davisson May 13 '18 at 07:49
  • 1
    @Sandeep_Black The problem you quoted is about passing user data to the shell as part of a command, and the solution is to _not use the shell_ and exec `/usr/bin/any_cmd` directly. – abarnert May 13 '18 at 07:50
  • 1
    @Sandeep_Black Generally, the more steps there are involved in a process, the more things there are to go wrong. If you call `unlink`, it unlinks a file. If you`execl("/bin/rm" "rm" "filename")`, there's a possibility that `rm` might misparse the filename (for example, if it starts with "-", `rm` will try to parse it as options rather than a filename). If you call `system` or pass it as an argument to `/bin/sh`, then the shell will misparse any shell metacharacters in the filename, get confused by any of a number of environment vars, etc. It's best to avoid unnecessary complexity. – Gordon Davisson May 13 '18 at 08:05

2 Answers2

2

With a single file, rm and unlink do the same task, remove the file. As POSIX defined, rm and unlink both call to unlink() system call.

In GNU rm, it calls to unlinkat()system call, which is equivalent to the unlink() or rmdir() function except in the case where path specifies a relative path.

Note

On some systems, unlink can also remove directory. At least in GNU system, unlink can never delete the name of a directory.

bhavesh27
  • 94
  • 7
1

Better than either of those would be

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#define  FILENAME  "/tmp/san.txt"

int main(void)
{
    if (remove(FILENAME) == -1) {
        fprintf(stderr, "%s: %s.\n", FILENAME, strerror(errno));
        return EXIT_FAILURE;
    }

    printf("%s successfully deleted.\n", FILENAME);
    return EXIT_SUCCESS;
}

The above code uses only standard C features, so should be portable across systems (although on different systems, you might wish to change FILENAME, as it is not a valid path on all systems).

The standard C function remove() can delete both files and empty directories.

Rather than only tell when an operation is successful, you will want to tell the user when and why the operation failed. (When it fails, it is usually very important for the user to know/understand why it failed. If you don't tell the user that, they are likely to switch to a better program, and hate yours for being obtuse.)

When the file to be removed is specified using an absolute path, there is no reason to fork a child process and do the removal in the child process. (The cases where one might fork a child process, are related to filesystem traversal (as the number of concurrent open file descriptors is limited per process), and multithreaded processes on systems without *at() functions.)

Nominal Animal
  • 38,216
  • 5
  • 59
  • 86