I'm getting permission errors when trying to mkfifo() in the current directory. I definitely have permission to create files here. Any idea what the problem could be?
char dir[FILENAME_MAX];
getcwd(dir, sizeof(dir));
for(i = 0; i<num_nodes; i++)
{
char path[FILENAME_MAX];
sprintf(path, "%s/%d",dir, i);
printf("%s\n", path);
fifoArray[i] = mkfifo(path, O_WRONLY);
if(fifoArray[i] < 0)
{
printf("Couldn't create fifo\n");
perror(NULL);
}
}
You're creating it with an oflag not a mode_t.
mkfifo takes a second parameter of type mode_t
In other words something like: 0666. You're trying to feed it an oflag as defined in fcntl.h, this is normally like:
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
Hence, Invalid argument. Here's a way to open the fifo:
char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
if((fd = open(myfifo, O_RDONLY | O_NONBLOCK)) < 0){
printf("Couldn't open the FIFO for reading!\n");
return 0;
}
else {
//do stuff with the fifo
If you are relying on the output of perror to tell you that you are getting permission errors, you are likely mistaken. The call to printf is very likely changing errno, so that information is bogus. Do not call printf. Just write:
perror( path );
and see if the error messages change.
Related
I've written a simplified "cat" function in C. It is working fine, except when one of my argument is the name of a directory.
As it is an assignement, I'm only allowed to use "open", "read" and "close" functions in my code.
When "-1" is returned by function open(file, O_RDONLY), I call function ft_display_error to display error messages such as "No such file or directory".
Yet it doesn't work when "file" is a directory: in this case open will not return "-1". It will go on some kind of infinite loop.
void ft_display_file(char *file)
{
int fd;
char buf[BUF_SIZE + 1];
int ret;
fd = open(file, O_RDONLY);
if (fd == -1)
ft_display_error(file);
else
{
ret = read(fd, buf, BUF_SIZE);
while(ret)
{
buf[ret] = 0;
write(1, buf, ret);
ret = read(fd, buf, BUF_SIZE);
}
}
close(fd);
}
int main(int ac, char **av)
{
int i;
i = 1;
while (i < ac)
{
ft_display_file(av[i]);
i++;
}
}
Instead, I would like my program to identify that my argument is a directory, and then display the following message "cat: file: Is a directory.
Opening a directory for reading with open is the low level way of accessing its contents. Not very useful for you, but it doesn't allow to test for a directory.
If you cannot use stat (which is the best option) there seems to be another trick:
According to the documentation of open
The open() function shall fail if:
...
EISDIR
The named file is a directory and oflag includes O_WRONLY or O_RDWR.
So first try to open your file with O_RDWR (read-write) and if it fails, check if errno is equal to EISDIR
Code (untested)
fd = open(file, O_RDWR);
if ((fd == -1) && (errno == EISDIR))
{
// this is a directory
}
I was trying to copy what is written in a file to a different file (with system calls) but my code seems not to work. I have first tried just printing with printf() the buffer but it also does not work. My guess is that I'm reading the file incorrectly.
#define BUF_SIZE 200
int main(int argc, char *argv[]){
int entrada,salida,leidos;
char buffer[BUF_SIZE];
entrada = open(argv[1],O_RDONLY);
salida = creat(argv[2], 0644);
while( (leidos = read(entrada,buffer,BUF_SIZE)) > 0 ){
write(salida,buffer,leidos);
}
close(salida);
close(entrada);
return 0;
}
What's wrong with my implementation?
I think you're missing the appropriate open flags on the output . Try:
salida = creat(argv[2], O_WRONLY | O_CREAT, 0644);
However, as comments suggest, you're probably getting errors indicated by the return values and/or the errno variable, which you are ignoring.
Also, I would avoid Castellano-specific variable names. Writing C/C++ requires knowing English anyway, so better stick to that for naming; otherwise - people who don't speak Castellano will have trouble understanding your code.
Finally - why are you doing it this way? There are much nicer C++-friendly, or even C-friendly, ways to copy a file - which would also be portable (your code isn't). See:
Copy a file in a sane, safe and efficient way
As #einpoklum stated, the main problem must be probably searched in the way you are opening your output file (flags and permissions). Overall, your code is far from implementing the minimum debugging verbosity and I think that a few code flow controls would help you a lot in detecting the real problem in your code:
#include <stdio.h>
#include <stdlib.h>
#ifndef BUF_SIZE
#define BUF_SIZE 200
#endif
int main(int argc, char *argv[])
{
int entrada = open(argv[1], O_RDONLY);
if (entrada == -1)
{
fprintf(stderr, "Error opening: %s\n", argv[1]);
exit(-1);
}
int openFlags = O_CREAT | O_WRONLY | O_TRUNC;
mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
int salida = open(argv[2], openFlags, filePerms);
if (salida == -1)
{
fprintf(stderr, "Error opening: %s\n", argv[2]);
exit(-1);
}
ssize_t numRead;
char buf[BUF_SIZE];
while ((numRead = read(entrada, buf, BUF_SIZE)) > 0)
{
if (write(salida, buf, numRead) != numRead)
{
fprintf(stderr, "Writing error!\n");
exit(-1);
}
}
if (numRead == -1)
{
fprintf(stderr, "Reading error!\n");
exit(-1);
}
if (close(entrada) == -1)
{
fprintf(stderr, "Input closing error!\n");
exit(-1);
}
if (close(salida) == -1)
{
fprintf(stderr, "Output closing error!\n");
exit(-1);
}
exit(0);
}
Many of the functions you use return values that can provide you an insight on that's going on. Use them.
Im trying to create a new file / overwrite an existing file using systemcalls , but for some reason I have two problems:
1. When I'm first running the program it exits with value 0, so it seems like it created the file successfully, but I can't see anything in my project directory.
then when I secondly running the program the file is created, but an error message is printed on the screen.
2. Also after the first iteration of the program, I can't see the prinf message at the end of the main function.
Thanks for helping.
int readFileDesc = 0, writeFiledesc = 0;
int sourceFile = 1, destFile = 2, bufferSize = 3, isOverwrite;
if (argc != 4 && argc != 5) {
printf("Invalid number of arguments\n");
printf("Usage:\n");
printf(" ex1 [-f] SOURCE DEST BUFFER_SIZE");
exit(EXIT_FAILURE);
}
//Checking if -f [OP] is activated.
isOverwrite = (strcmp(argv[1], "-f") == 0);
if (isOverwrite) {
sourceFile++;
destFile++;
bufferSize++;
}
//Opening the source file
readFileDesc = open(argv[sourceFile], O_RDONLY);
if (readFileDesc < 0) {
perror("Unable to open source file for reading: ");
exit(EXIT_FAILURE);
}
//opening the destination file
if (!isOverwrite) {
//Case we dont have the -f [op] so we create the file.
writeFiledesc = open(argv[destFile],
O_CREAT | O_EXCL | O_WRONLY ,
S_IRUSR | S_IWUSR);
if (writeFiledesc < 0) {
perror("Unable to open destination file for reading: ");
exit(EXIT_FAILURE);
}
} else {
//Case we have the -f [op] so we override existing file.
writeFiledesc = open(argv[destFile], O_RDONLY | O_WRONLY | O_TRUNC);
if (writeFiledesc < 0) {
perror("Unable to open destination file for writing: ");
exit(EXIT_FAILURE);
}
}
//Assume the buffersize is legal.
bufferSize = atoi(argv[bufferSize]);
char data[bufferSize];
int nread, nwrite;
while ((nread = read(readFileDesc, data, bufferSize)) > 0) {
if ((nwrite = write(writeFiledesc, data, nread)) != nread) {
printf("write problem: ");
}
}
// cant see this!
printf("File %s was copied to %s" , argv[sourceFile] , argv[destFile]);
//handling errors
close(sourceFile);
close(destFile);
return EXIT_SUCCESS;
}
This is wrong:
writeFiledesc = open(argv[destFile], O_RDONLY | O_WRONLY | O_TRUNC);
Using both O_RDONLY and O_WRONLY is wrong. You need to use O_RDWR.
Per the POSIX standard for open():
SYNOPSIS
#include <sys/stat.h> #include <fcntl.h>
int open(const char *path, int oflag, ...);
...
Values for oflag are constructed by a bitwise-inclusive OR of flags
from the following list, defined in . Applications shall
specify exactly one of the first five values (file access modes)
below in the value of oflag:
O_EXEC
Open for execute only (non-directory files). The result is unspecified if this flag is applied to a directory.
O_RDONLY
Open for reading only.
O_RDWR
Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
O_SEARCH
Open directory for search only. The result is unspecified if this flag is applied to a non-directory file.
O_WRONLY
Open for writing only.
Any combination of the following may be used:
...
Also, read() and write() return ssize_t, not int.
I have written the following code to simulate the write() system call in C.
The program executes without errors, but the new content is not written to myfile.
What is the problem?
#include<stdio.h>
int main(int ac, char* av[])
{
int fd;
int i = 1;
char *sep = "";
if(ac < 1)
{
printf("Insuff arguments\n");
exit(1);
}
if((fd = open("myfile", 0660)) == -1)
{
printf("Cannot open file");
exit(1);
}
while(i<ac)
{
write(fd, av[i], strlen(av[i]));
write(fd, sep, strlen(sep));
i++;
}
close (fd);
}
you should check the return value of write and see what's going on with perror (for exemple),
anyway you are not calling open in the correct way
try
if ((fd=open("myfile", O_WRONLY | O_CREAT, 0660))==-1)
{
printf("Cannot open file");
exit(1);
}
while(i<ac)
{
write(fd,av[i],strlen(av[i])); //check the return value of write
write(fd,sep,strlen(sep));
perror("write");
i++;
}
close (fd);
and include unistd.h fcntl.h
You need to specify mode(read or write) of the open when you are opening a file. In your open call you didn't specify any mode and you are giving file permission flags. For more information refer manual page of open system call.
You can try this in open call
fd=open("myfile", O_WRONLY | O_CREAT, 0660);
check return value of your write call, it is failing because you didn't specify any mode and you are trying to write data in to that file.
I have a small program that tires to change the files access mode after it has been opened.
int main(int argc, char* argv[])
{
int fd;
char *filename = argv[1];
char data[1];
int curval; //current flag value
int newval; //new flag value
fd = open(filename, O_RDONLY);
while(read(fd, data, 1)>0)
{
write(STDOUT_FILENO, data, 1);
}
lseek(fd, 0, SEEK_SET);
if((curval = fcntl(fd, F_GETFL, 0))<0)
{
perror("file flag get failed");
}
printf("%d\n", curval);
newval = curval | O_WRONLY | O_APPEND;
printf("%d\n", newval);
if(fcntl(fd, F_SETFL, newval)<0)
{
perror("file flag set failed");
}
if(write(fd, argv[2], strlen(argv[2]))<0) //appending more data to the file
{
perror("write failed");
}
lseek(fd, 0, SEEK_SET);
while(read(fd, data, 1)>0)
{
write(STDOUT_FILENO, data, 1);
}
close (fd);
return 0;
}
Here is the output when i run this program with a text file as input.
$ cat input
this is the inital data
$ ./a.out input newdata
this is the inital data
0
1025
write failed: Bad file descriptor
this is the inital data
Why is the write in the program failing? Also I'm not able to find where the file status flag constants are defined. I checked in usr/include/
The behavior you are trying to perform is not allowed. From the fcntl(2) man page:
F_SETFL (long)
Set the file status flags to the value specified by arg. File
access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags
(i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored.
On Linux this command can only change the O_APPEND, O_ASYNC,
O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
If you read Linux manpage, you will see that fcntl cannot change file access modes (e.g., from read-only to read-write).