1

Here is my poor attempt:

//open:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//raad, write, exit:
#include <unistd.h>
#include <stdlib.h>
//renameat2:
#include<stdio.h>

int main(){
        int fd1, fd2;
        //do I need those ifs?
        if((fd1 = open("foo", O_RDWR)) == -1){
            write(2, "File failed to open in read/write mode\n", 33);
            exit(-1);
        }

        if((fd2 = open("bar", O_RDWR)) == -1 ){
            write(2, "File failed to open in read/write mode\n", 34);
            exit(-1);
        }

        renameat2(AT_FDCWD,fd1,AT_FDCWD,fd2, RENAME_EXCHANGE);

        close(fd1);
        close(fd2);
        exit(0);
}

I'm trying to use the system call function "renameat2", but it gives me errors:

main.c:24:3: warning: implicit declaration of function 'renameat2'; did you mean 'rename'?

main.c:24:13: error: 'AT_FDCWD' undeclared (first use in this function)

main.c:24:40: error: 'RENAME_EXCHANGE' undeclared (first use in this function)

fastAlgo
  • 83
  • 6
  • Does adding `#define _GNU_SOURCE` at the very top, above all the `#include`s, fix it? – Joseph Sible-Reinstate Monica Apr 29 '20 at 17:53
  • Yes, it helped. But it recursively opens two more more questions: Why it helped, and now how to deal with: main.c:22:28: warning: passing argument 2 of 'renameat2' from incompatible pointer type [-Wincompatible-pointer-types] – fastAlgo Apr 29 '20 at 18:35
  • OK I got it. I found the mistake and edited it. Now, why does this helped? #define _GNU_SOURCE – fastAlgo Apr 29 '20 at 18:43

1 Answers1

2

Two problems:

First, since renameat2 isn't part of any standard, you need to #define _GNU_SOURCE before you include any header files to use it. See man 7 feature_test_macros for a longer explanation of this.

Second, renameat2 doesn't support AT_EMPTY_PATH like other syscalls do (and even if it did, that's not how you'd use it), so you need to pass it the names of the files you want to rename, not FDs. It follows from this that you don't need to open the files.

Here's your code with both of those things fixed:

#define _GNU_SOURCE

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
        renameat2(AT_FDCWD,"foo",AT_FDCWD,"bar", RENAME_EXCHANGE);

        exit(0);
}

And here's a more flexible version with better error handling:

#define _GNU_SOURCE

#include <fcntl.h>
#include <stdio.h>

int main(int argc, char *argv[]){
    if(argc != 3) {
        fputs("Wrong number of arguments\n", stderr);
        return 1;
    }
    if(renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE)) {
        perror("renameat2");
        return 1;
    }
    return 0;
}
  • maybe it would be better: exit(renameat2(AT_FDCWD,"foo",AT_FDCWD,"bar", RENAME_EXCHANGE)); ? – fastAlgo Apr 29 '20 at 19:34
  • Yes, but put a negative sign in front of `renameat2`, because if it fails, it returns `-1`, but your process should return `1`. It also might be worth actually using an `if` statement so you can use `perror` to say why it failed. – Joseph Sible-Reinstate Monica Apr 29 '20 at 19:36
  • Can you show me how to do it, please? And thank you for the answers. – fastAlgo Apr 29 '20 at 19:37