faccessat and AT_* defines are undefined - c

// SYSTEM INCLUDE FILES
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
// C STANDARD LIBRARY INCLUDE FILES
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
char *source = "file1.txt";
char *dest = "file2.txt";
printf("%d\n", faccessat(AT_FDCWD, source, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
printf("%d\n", faccessat(AT_FDCWD, dest, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
printf("Value of errno: %s\n", strerror(errno));
return 0;
}
When compiling this code with clang 14 and the command clang -lrt -pthread -I/usr/include -std=c11 -o copy copy.c I run into numerous issues:
copy.c:21:20: warning: implicit declaration of function 'faccessat' is invalid in C99 [-Wimplicit-function-declaration]
printf("%d\n", faccessat(AT_FDCWD, source, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
^
copy.c:21:30: error: use of undeclared identifier 'AT_FDCWD'
printf("%d\n", faccessat(AT_FDCWD, source, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
^
copy.c:21:68: error: use of undeclared identifier 'AT_SYMLINK_NOFOLLOW'
printf("%d\n", faccessat(AT_FDCWD, source, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
^
copy.c:22:30: error: use of undeclared identifier 'AT_FDCWD'
printf("%d\n", faccessat(AT_FDCWD, dest, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
^
copy.c:22:66: error: use of undeclared identifier 'AT_SYMLINK_NOFOLLOW'
printf("%d\n", faccessat(AT_FDCWD, dest, F_OK | R_OK | W_OK, AT_SYMLINK_NOFOLLOW));
^
1 warning and 4 errors generated.
The same code works on my Mac with MacOS 12, but does not work on Ubuntu in WSL. How would I fix this issue?
I tried to reinstall build-essentials, clang, gcc, glibc. I reviewed the header files and found that fcntl.h does not contain the AT_* definitions, yet the man page says they do. I was expecting the header file to contain the definitions.

From what the comments have told me, and online, faccessat is a gnu extension in C, so to use it I would have to compile my code with -std=gnu11 to use these.

Related

ld: undefined reference even though include and library directory was specified

I want to use the libnetlink library shipped with iproute2. I specified it's include dir with -I and it's lib dir with -L. However I still get some undefined reference errors.
test.c: In function ‘addqdisc’:
test.c:26:3: warning: ignoring return value of ‘rtnl_open’, declared with attribute warn_unused_result [-Wunused-result]
26 | rtnl_open(rth, 0);
| ^~~~~~~~~~~~~~~~~
test.c:27:3: warning: ignoring return value of ‘rtnl_talk’, declared with attribute warn_unused_result [-Wunused-result]
27 | rtnl_talk(rth, &req.n, NULL);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/ld: /tmp/ccCnXM9F.o: in function `addqdisc':
test.c:(.text+0x79): undefined reference to `rtnl_open'
/usr/bin/ld: test.c:(.text+0x97): undefined reference to `rtnl_talk'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <libnetlink.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int addqdisc() {
struct rtnl_handle *rth;
struct {
struct nlmsghdr n;
struct tcmsg t;
char buf[64*1024];
} req = {
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE,
.n.nlmsg_type = RTM_NEWQDISC,
.t.tcm_family = AF_UNSPEC,
};
rtnl_open(rth, 0);
rtnl_talk(rth, &req.n, NULL);
}
int main() {
addqdisc();
return 0;
}
gcc test.c -o test -I/pwd/Downloads/linux-5.17/iproute2/include -l /pwd/Downloads/linux-5.17/iproute2/lib/libnetlink.a -lnetlink -static
Anyone knows why?

Why Clang compiler complains although all includes are presented

I'm trying to work through XDP tutorial and having issue with samples compilation. Why clang complains regarding includes that are already done?
Example:
common_params.c:105:4: warning: incompatible implicit declaration of built-in function ‘strncpy’
common_params.c:105:4: note: include ‘<string.h>’ or provide a declaration of ‘strncpy’
common_params.c:110:6: error: ‘errno’ undeclared (first use in this function)
110 | errno, strerror(errno));
| ^~~~~
common_params.c:15:1: note: ‘errno’ is defined in header ‘<errno.h>’; did you forget to ‘#include <errno.h>’?
14 | #include "common_params.h"
+++ |+#include <errno.h>
Cheching common_params.c shoes it already have string.h and errno.h included:
# head ../common/common_params.c
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <getopt.h>
#include <errno.h>
#include <stdio.h>
Files are presented in the box:
# ls -l /usr/include/errno.h
-rw-r--r-- 1 root root 23 Jun 6 18:36 /usr/include/errno.h
# ls -l /usr/include/string.h
-rw-r--r-- 1 root root 238 Jun 6 18:36 /usr/include/string.h
# cat /usr/include/errno.h
#include <asm/errno.h>
# cat /usr/include/asm/errno.h
#include <asm-generic/errno.h>
# head /usr/include/asm-generic/errno.h
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_GENERIC_ERRNO_H
#define _ASM_GENERIC_ERRNO_H
#include <asm-generic/errno-base.h>
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */

programm can not find constant in libary fcntl.h in c

I am learning C and somehow my programm can not find a constant defined in a libary. In my understanding S_IRUSR|S_IWUSR shoud be defined in fcntl.h, but I get while trying to compile this error:
... error: 'S_IRUSR' undeclared (first use in this function)
... error: 'S_IWUSR' undeclared (first use in this function)
My programm looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
int filedeskriptor;
char SchreibeTxt [100] = "Hallo getMonth", LeseTxt [100];
filedeskriptor = open("getMonthTxt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (filedeskriptor == -1){
printf("Fehler beim Öffnen von mydat \n");
exit (EXIT_FAILURE);
}
if (write(filedeskriptor, SchreibeTxt, sizeof(SchreibeTxt)) == -1){
printf("Fehler beim Schreiben in mydat \n");
exit (EXIT_FAILURE);
}
printf("In getMonthTxt geschrieben: %s \n", SchreibeTxt);
close(filedeskriptor);
return EXIT_SUCCESS;
}
Any help?
Thanks
It depends on according to which POSIX-version your compiler and implementation is build up to, because S_IRUSR and S_IWUSR are only provided inside of fcntl.h in POSIX.1-2008 as Ian Abbott said in the comments.
If your compiler uses a preceding POSIX-version, the macros S_IRUSR and S_IWUSR are not defined in fcntl.h as you can see here. They are then defined in the header sys/stat.h.
Here is a link to the description about the content of the header sys/stat.h, where you can find those:
https://pubs.opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html
So if your compiler uses a version predating POSIX.1-2008, add #include <sys/stat.h> at the top of your code or otherwise if you don´t need anything from fcntl.h replace it with that.
Maybe you're missing the headers
<sys/types.h>
<sys/stat.h>
man 2 open states 3 headers for open()

How to use an AC_CHECK_HEADER header in an AC_COMPILE_IFELSE program

I'm performing a header check for a non-standard <x86intrin.h> header provided by Clang and GCC. Other compilers follow Intel and use <immintrin.h>:
AC_CHECK_HEADER([x86intrin.h])
Autotools finds it on the Linux test systems:
checking x86intrin.h usability... yes
checking x86intrin.h presence... yes
checking for x86intrin.h... yes
I then use it in a test:
CXXFLAGS="-mrdseed"
XXX_PROGRAM="#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([$XXX_PROGRAM])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
The test fails:
checking if g++ supports -mrdseed... no
The machine has the feature and the compiler supports it. Looking at condefs.h from config.log shows HAVE_X86INTRIN_H is not being set as expected.
The manual shows how to use a header resulting from a check at 5.6.3 Generic Header Checks. I think I am doing roughly the same thing:
AC_CHECK_HEADERS([foo.h])
AC_CHECK_HEADERS([bar.h], [], [],
[#ifdef HAVE_FOO_H
# include <foo.h>
# endif
])
How do I use an AC_CHECK_HEADER header in an AC_COMPILE_IFELSE program?
Here is my test driver:
$ cat test.cxx
#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}
$ g++ -mrdseed test.cxx -o test.exe
test.cxx: In function ‘int main(int, char**)’:
test.cxx:7:12: error: ‘_rdseed32_step’ was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
test.cxx:7:12: note: suggested alternative: ‘_rdrand32_step’
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
$ g++ -DHAVE_X86INTRIN_H -mrdseed test.cxx -o test.exe
$ ./test.exe
$
Here is the distro and compiler:
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: Fedora
Description: Fedora release 28 (Twenty Eight)
Release: 28
$ g++ --version
g++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5)
Here are the relevant parts from config.log:
configure:17624: checking if g++ supports -mrdseed
configure:17631: g++ -o conftest -mrdseed conftest.cpp >&5
conftest.cpp: In function 'int main(int, char**)':
conftest.cpp:38:17: error: '_rdseed32_step' was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
conftest.cpp:38:17: note: suggested alternative: '_rdrand32_step'
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
configure:17631: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "Crypto++"
| ...
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_DLFCN_H 1
| #define LT_OBJDIR ".libs/"
| ...
| /* end confdefs.h. */
| #include <immintrin.h>
| #ifdef HAVE_X86INTRIN_H
| # include <x86intrin.h>
| #endif
| int main(int argc, char** argv) {
| unsigned int x;
| return _rdseed32_step(&x);
| }
configure:17645: result: no
You have tripped over an Autoconf gotcha. The docs for AC_CHECK_HEADER say:
If the system header file header-file is compilable, execute shell
commands action-if-found, otherwise execute action-if-not-found.
If you just want to define a symbol if the header file is available,
consider using AC_CHECK_HEADERS instead.
(Emphasis added)
Contrast that with the docs for AC_CHECK_HEADERS:
For each given system header file header-file in the blank-separated
argument list that exists, define HAVE_*header-file* (in all capitals).
If action-if-found is given, [...]
Note that unlike those for AC_CHECK_HEADERS, the docs for AC_CHECK_HEADER do not claim that any symbol will be defined if the header is found. In that case, the only thing done other than to report the result of the check is to run the commands in action-if-found. You can certainly put an AC_DEFINE in there to define a symbol, but you don't get that for free the way you do from AC_CHECK_HEADERS. If you want that, you can use AC_CHECK_HEADERS even for a single header.
I'm sure original the reason for the difference revolves around the fact that AC_CHECK_HEADERS checks possibly many headers. Additionally, sometimes you don't care about defining a symbol, or perhaps you expressly want to avoid doing so; for those cases you can use AC_CHECK_HEADER.
Here's a complete Autoconf input file that demonstrates a working variation on your check:
AC_PREREQ([2.69])
AC_INIT([test], [0.0.0])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
# Ensure that tests are run with the C++ compiler
AC_LANG([C++])
# Checks for header files.
AC_CHECK_HEADERS([x86intrin.h])
# Check support for -mrdseed
AS_IF([test "$ac_cv_header_x86intrin_h" = "yes"], [
CXXFLAGS_save=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -mrdseed"
XXX_PROGRAM="
#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
#include <x86intrin.h>
#endif
int main(void) {
unsigned int x;
return _rdseed32_step(&x);
}
"
AC_MSG_CHECKING([whether $CXX supports -mrdseed])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([$XXX_PROGRAM])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
CXXFLAGS=$CXXFLAGS_save
])
AC_OUTPUT

Migrating a C program from Linux to Windows

I want to open a file in C with the open() function,and this is the code I use:
int lire(){
char buf[1024];
int bytesRead;
int fildes;
char path[128];
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int flags = O_RDONLY;
printf("\n%s-->Donner l'emplacement du fichier :%s ", CYAN_NORMAL, RESETCOLOR);
scanf("%s", path);
fildes = ouvrir(path, flags, mode);
if(fildes == -1){
return 0;
}
while ((bytesRead = read(fildes, buf, sizeof buf)) > 0)
{
write(STDOUT_FILENO, buf, bytesRead);
}
close(fildes);
return 1;
}
int ouvrir(char *path, int flags, mode_t mode)
{
return open(path, flags, mode);
}
I've wrote this code for the first time in Linux, and It was working, but when I run it in Windows I got this error message:
error: 'S_IRUSR' undeclared (first use in this function)|
error: 'S_IWUSR' undeclared (first use in this function)|
error: 'S_IRGRP' undeclared (first use in this function)|
error: 'S_IROTH' undeclared (first use in this function)|
These are the headers I included:
#include <sys/types.h> //Specified in man 2 open
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h> // open function
#include <unistd.h> // close function
#include "colors.h"
#include "const.h"
#include <ctype.h>
#include <errno.h>
#include <string.h>
How can I solve that problem?
With Windows you need to include sys\stat.h, and the mode flags available are _S_IREAD and _S_IWRITE, which can be combined if needed. Documentation can be found here.
Note in particular this comment:
If a value other than the above is specified for pmode (even if it would specify a valid pmode in another operating system) or any value other than the allowed oflag values is specified, the function generates an assertion in Debug mode and invokes the invalid parameter handler as described in Parameter Validation. If execution is allowed to continue, the function returns -1 and sets errno to EINVAL.

Resources