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()
Related
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin18.0.0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define _GNU_SOURCE
#define __USE_GNU 1
#include <fcntl.h>
int main()
{
int fd = open("./test.txt", O_WRONLY|O_DIRECT);
close(fd);
return 0;
}
I use clang -o out test.c and get the following result:
test.c:14:39: error: use of undeclared identifier 'O_DIRECT'
int fd = open("./test.txt", O_WRONLY|O_DIRECT);
How can I solve the problem?
Thank you.
With this snippet it is impossible to tell what you are trying to do, but in general do not use nonstandard stuff in applications intended to be portable.
The portable way to accomplish your task is probably fsync.
To sum up
For LINUX, the O_DIRECT flag has to be included. For Mac OSX, O_DIRECT is not available. Instead, fcntl(fd, F_NOCACHE, 1) looks to be the canonical solution where fd is the file descriptor of the file. For Windows, there is a flag called FILE_FLAG_NO_BUFFERING as the counterpart in Windows of O_DIRECT
Reference here
It's my first time working with posix; I included:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
And I've this snippet.
stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFREG) {
/* Handle regular file */
}
But using GCC 4.8.3 on Gentoo if I compiled with -std=c99 or -std=c11 or -std=gnu99 or -std=gnu11 I got this error:
error: ‘S_ISFMT’ undeclared (first use in this function)
If I omit -std=* I got no errors. But I want all the features of -std=c99 too (like the keyword restrict or for(int i;;) etc ...)
How could I compile my code?
Modern POSIX-compliant systems are required to provide the S_IFMT and S_IFREG values. The only version of POSIX that does not require this (and in fact, forbids it) is POSIX.1-1990, which appears to be the standard on your machine.
In any case, every POSIX-compliant system provides macros that allow you to check the type of the file. These macros are equivalent to the masking method.
So in your case, instead of (sb.st_mode & S_IFMT) == S_IFREG, just write S_ISREG(sb.st_mode).
Put either #define _BSD_SOURCE or #define _XOPEN_SOURCE before any #include in your source code. To see why this works, look right above #define S_IFMT __S_IFMT in sys/stat.h, then in feature_test_macros(7) man page.
K&R2 provides:
#define S_IFMT 0160000 /* type of file: */
#define S_IFDIR 0040000 /* directory */
in chapter 8.6 Example-Listing Directories.
I do NOT encourage to use this solution, furthermore, I hope that some experts may teach us whether it is right or not implemented, pros-cons, alternatives, and so. Thx in advance!
Example of MWE.
Code creator:
https://clc-wiki.net/wiki/K%26R2_solutions:Chapter_8:Exercise_5
Added the S_IFMT and S_IFDIR defines (at beginning).
Input argument: a.out
Output I get (through https://www.onlinegdb.com/online_c_compiler#):
9116 a.out Owner: root
MWE:
/* these defines at beginning to highlight them */
#define S_IFMT 0160000 /* type of file: */
#define S_IFDIR 0040000 /* directory */
/*
Modify the fsize program to print the other information contained in the inode entry.
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <dirent.h>
#include <pwd.h>
#define MAX_PATH 1024
#ifndef DIRSIZ
#define DIRSIZ 14
#endif
void dirwalk( char *dir,void (*fcn)(char *)){
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;
if((dfd = opendir(dir))==NULL){
puts("Error: Cannot open Directory");
return;
}
puts(dir);
// Get each dir entry
while((dp=readdir(dfd)) != NULL){
// Skip . and .. is redundant.
if(strcmp(dp->d_name,".") == 0
|| strcmp(dp->d_name,"..") ==0 )
continue;
if(strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
puts("Error: Name too long!");
else{
sprintf(name,"%s/%s",dir,dp->d_name);
// Call fsize
(*fcn)(name);
}
}
closedir(dfd);
}
void fsize(char *name){
struct stat stbuf;
if(stat(name,&stbuf) == -1){
puts("Error: Cannot get file stats!");
return;
}
if((stbuf.st_mode & S_IFMT) == S_IFDIR){
dirwalk(name,fsize);
}
struct passwd *pwd = getpwuid(stbuf.st_uid);
//print file name,size and owner
printf("%81d %s Owner: %s\n",(int)stbuf.st_size,name,pwd->pw_name);
}
int main(int argc,char *argv[]){
if(argc==1)
fsize(".");
else
while(--argc>0)
fsize(*++argv);
return 0;
}
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.
For my question let's suppose I have two functions, both of them with the prototypes on a .h file in a library folder, and the implementation in a .c auxiliary file (shown below), and I will use both of them in my program.
calsis.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include "include/calsis.h" /* Extern header */
char folder_name[30] = "Information";
void no_args() /* Function 1 */
{
printf("Hello, world!\n");
if ( mkdir(folder_name, S_IRWXU) == -1 )
perror("Can't create a new folder");
}
void with_args(char *foo) /* Function 2 */
{
printf("Hello, world!\n");
printf("Name: %s\n", foo);
if ( mkdir(folder_name, S_IRWXU) == -1 )
perror("Can't create a new folder");
}
For something I will do later, I need in both functions to create a folder with mkdir, but, in the generation of the object file calsis.o by the compilation of the .c file with the implemented functions, the compilation with GCC gives me a warning that the mkdir function is implicity declared.
Any idea I can remove this warning?
You haven't included the header for mkdir:
From man(2) mkdir:
SYNOPSIS
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
I was reading through this Advanced Linux Programming tutorial when I encountered a problem. I was trying to eject the CD-ROM drive using this code:
int fd = open(path_to_cdrom, O_RDONLY);
// Eject the CD-ROM drive
ioctl(fd, CDROMEJECT);
close(fd);
Then I try to compile this code and get the following output:
In file included from /usr/include/linux/cdrom.h:14,
from new.c:2:
/usr/include/asm/byteorder.h: In function ‘___arch__swab32’:
/usr/include/asm/byteorder.h:19: error: expected ‘)’ before ‘:’ token
/usr/include/asm/byteorder.h: In function ‘___arch__swab64’:
/usr/include/asm/byteorder.h:43: error: expected ‘)’ before ‘:’ token
So what am I doing wrong?
The error message you're seeing looks like something is wrong in your #include lines, not with the code you posted. I tried compiling http://www.advancedlinuxprogramming.com/listings/chapter-6/cdrom-eject.c and it compiles just fine.
According to this, you need to specify O_NONBLOCK when opening the device, otherwise it won't work.
From that page:
cdrom = open(CDDEVICE,O_RDONLY | O_NONBLOCK)
You are missing a #include, I think. Do you have:
#include <fcntl.h>
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
Those are the ones in the example...
In the previous examples the following includes are not needed.
#include <sys/stat.h>
#include <sys/types.h>
Also as stated before you may need to open with O_NONBLOCK
You can find more options for interacting with the CDROM device in the header file located at '/usr/include/linux/cdrom.h' or here https://github.com/torvalds/linux/blob/master/include/uapi/linux/cdrom.h
Also here is another example for opening and closing the CD tray with the mentioned changes.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main (int argc, char* argv[])
{
// Path to CD-ROM drive
char *dev = "/dev/dvd";
int fd = open(dev, O_RDONLY | O_NONBLOCK);
if(fd == -1){
printf("Failed to open '%s'\n", dev);
exit(1);
}
printf("fd :%d\n", fd);
// Eject the CD-ROM tray
ioctl (fd, CDROMEJECT);
sleep(2);
// Close the CD-ROM tray
ioctl (fd, CDROMCLOSETRAY);
close(fd);
return 0;
}
The open syscall has some unwanted behaviours which must be handled by setting it to Not blocking ie O_NONBLOCK
Also check that you have included the header file
#include <linux/cdrom.h>