mkfifo() not able to create file in C - c

I'm trying to create a named pipe in C, but have not had any success.
Here is my code:
#define FIFO_NAME "/tmp/myfifo"
int main(){
int fd;
fd = mkfifo(FIFO_NAME, 0666);//, 0);
if(fd<0){
fprintf(stderr,"Error creating fifo\n");
exit(0);
}
On running the above code every time output comes out:
Error creating fifo
Please help.

You want to replace fprintf(stderr,"Error creating fifo\n"); by perror("mkfifo() failed");. This gives you the long text error message which corresponds to the value of errno set by mkfifo() on failure.
– alk
Thanks that worked, it had a existing file by same name.
– vidit jain

Related

fprintf() to stdout not working after creating and opening a FIFO

When my program starts, it just creates a fifo and opens it, after that I just want to output some information to the screen, however, nothing gets printed out. Here's a snippet of my code:
void listen(const server_config_t* server_conf)
{
// Create FIFO
if (mkfifo(SERVER_FIFO_PATH, 0660) == -1) {
fprintf(stdout, "server FIFO not created as it already exists. continuing...\n");
}
// Open FIFO (for reading)
int fd;
if ((fd = open(SERVER_FIFO_PATH, O_RDONLY)) == -1) {
// fprintf(stderr, "error: could not open server FIFO\n");
perror("FIFO");
exit(1);
}
// Open dummy FIFO (for writing, prevent busy waiting)
// TODO: find way to wait without another file descriptor?
int fd_dummy;
if ((fd_dummy = open(SERVER_FIFO_PATH, O_WRONLY)) == -1) {
perror("DUMMY FIFO");
exit(1);
}
// TODO: this should print immediately after starting,
// but doesn't for some reason
fprintf(stdout, "server listening... %d %s\n", server_conf->num_threads,
server_conf->password);
fflush(stdout);
.
.
.
}
Here's my output:
I've tried commenting out the fifo creation and opening, and when I do that the message gets printed correctly to the screen.
Opening a FIFO normally blocks until the other end is opened as well, see http://man7.org/linux/man-pages/man7/fifo.7.html. So your program probably waits in open(SERVER_FIFO_PATH, O_RDONLY) and does not reach any other fprintf or perror.
Your attempt to open the FIFO for reading first and then for writing does not work because the first open does not return.
You should be able to see this when you step through your program using a debugger.
BTW: When mkfifo returns -1 you should check if errno is EEXIST. There could be other errors that would also result in return value -1, see https://linux.die.net/man/3/mkfifo
As you can see from your output, there is blocking. That is, your current process cannot go on until the other end of the FIFO is opened for write. You should glance at the man page.
As to your error, there are two cases maybe the directory into which you want to place the FIFO doesn't permit to do that. Second case may be due to a system error. To overcome the issue, you need to change your fprintf as following.
#include <string.h>
#include <stdlib.h>
..
..
fprintf(stderr, "server FIFO not created as it already exists. Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);

C: not able to open message queue

I'm working on OpenSuse 42.3 Leap. This is my first touch with Unix message queues and I have some basic trouble with simple opening a new queue. My original issue was I wasn't able to open two queues but after few tries I got the problem reduced to this strange behaviour:
If I compile and run this
#include<stdio.h>
#include <mqueue.h>
int main() {
// printf("Hello world!\n");
/* create queue */
char *q_name = "/myQueue";
mqd_t desc = mq_open(q_name, O_RDWR | O_CREAT);
if(desc == (mqd_t) -1)
perror("Error in mq_open");
printf("We have opened %d\n", desc);
/* close descriptor and unlink name */
if (mq_close(desc)) perror("Error in close:");
if (mq_unlink(q_name)) perror("Error in unlink:");
return 0;
}
it works great with standard output:
We have opened 3
The queue is closed correctly and I can rerun it with no error.
But if I uncomment the line
printf("Hello world!\n");
it obviously still correctly compiles but when run it outputs
Hello world!
Error in mq_open: Invalid argument
We have opened -1
Error in close:: Bad file descriptor
Error in unlink:: No such file or directory
If instead of simple 'Hello world! I try to print:
printf("Hello world! My pid = %d\n", getpid());
then instead of Invalid argument the error
Error in mq_open: Bad address
is produced.
Any idea why this simple printf crashes the queue opening?
From the mq_open manual page:
If O_CREAT is specified in oflag, then two additional arguments must
be supplied. [...]
You don't supply them, so you have undefined behaviour. What seems to happen is that the missing arguments are taken from somewhere in memory where they would have been, and what happens to be there is different depending on what your program did just before.

Check if input file is a valid file in C

I am trying to open a file in c using open() and I need to check that the file is a regular file (it can't be a directory or a block file). Every time I run open() my returned file discriptor is 3 - even when I don't enter a valid filename!
Here's what I have
/*
* Checks to see if the given filename is
* a valid file
*/
int isValidFile(char *filename) {
// We assume argv[1] is a filename to open
int fd;
fd = open(filename,O_RDWR|O_CREAT,0644);
printf("fd = %d\n", fd);
/* fopen returns 0, the NULL pointer, on failure */
}
Can anyone tell me how to validate input files?
Thanks!
Try this:
int file_isreg(const char *path) {
struct stat st;
if (stat(path, &st) < 0)
return -1;
return S_ISREG(st.st_mode);
}
This code will return 1 if regular, 0 if not, -1 on error (with errno set).
If you want to check the file via its file descriptor returned by open(2), then try:
int fd_isreg(int fd) {
struct stat st;
if (fstat(fd, &st) < 0)
return -1;
return S_ISREG(st.st_mode);
}
You can find more examples here, (specifically in the path.c file).
You should also include the following headers in your code (as stated on stat(2) manual page):
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
For future reference, here is an excerpt of the stat(2) manpage regarding the POSIX macros available for st_mode field validations:
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
int isValidFile(char *filename) {
// We assume argv[1] is a filename to open
int fd;
fd = open(filename,O_RDWR|***O_CREAT***,0644);
printf("fd = %d\n", fd);
/* fopen returns 0, the NULL pointer, on failure */
}
you are using 0_CREAT which prompts the function to create if the file doesn't exist.this in the table its number is 3 (0,1,2 being std input std output and std error)
Wrong: check if the file is OK, then if it is, go open it and use it.
Right: go open it. If you can't, report the problem and bail out. Otherwise, use it (checking and reporting errors after each opetation).
Why: you have just checked that a file is OK. That's fine, but you cannot assume it will be OK in 0.000000017 seconds from now. Perhaps the disk wil overheat and break down. Perhaps some other process will mass-delete your entire file collection. Perhaps your cat will trip over the network cable. So let's just check if it's OK again, and then go open it. Wow, what a great idea! No wait...

Writing string to a .mc file

I'm trying to write data to a file and it's not appearing but I know the program is finishing. I establish a writable file getting the name from a command argument
FILE *outFilePtr;
Then I create the file through:
outFilePtr=fopen(outFileString,"w"); //outFileString is the name of the file from command
Now I attempt to print to this file which has a .mc extension:
fprintf(outFilePtr,"%s\n","1001") //example string
The file gets created and nothing is written to it. This is probably a dumb question but can you not write strings to machine code files? I'm trying to find a solution to this problem if that's the case.
You should check the results of fopen and fprintf. This works for me:
#include <stdio.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
FILE *outFilePtr;
outFilePtr = fopen("asdf.mc", "w");
if(!outFilePtr) {
perror("Couldn't open it");
fprintf(stderr, "errno: %d\n", errno);
exit(-1);
}
if(fprintf(outFilePtr, "%s\n", "1001") < 0)
{
fclose(outFilePtr);
perror("Couldn't write to it");
fprintf(stderr, "errno: %d\n", errno);
exit(-1);
}
fclose(outFilePtr);
}
If there is a problem opening the file (permissions, etc), perror will show it. For example, using an empty string for the filename gave me this in a window$ machine:
Couldn't open it: Invalid argument
errno: 22
If I close outFilePtr before the fprintf, this error gets displayed:
Couldn't write to it: Bad file descriptor
errno: 9
please check that you close the file(using fclose(fptr)) after fprintf()..

Anonymous stream in c

Can I make an anonymous stream in c? I don't want to create a new file on the file system, just have a stream that one function can fwrite to while the other can fread from it. Not c++, c.
Maybe You're looking for pipes.
Forward Your STDOUT to the pipe.
Then the other application would read from the pipe.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#define RDR 0
#define WTR 1
char ** parseargs(char *string);
int main(void){
char mode = 'r';
char prog[50] = "/bin/ps --version";
char **argv;
int p[2];
pid_t pid;
FILE *readpipe;
int pipein, pipeout;
char buf;
/* create the pipe */
if(pipe(p) != 0){
fprintf(stderr, "error: could not open pipe\n");
}
pipein = p[RDR];
pipeout = p[WTR];
if((pid = fork()) == (pid_t) 0){
close(pipein);
dup2(pipeout, 1);
close(pipeout);
if(execv(argv[0], argv) == -1){
fprintf(stderr, "error: failed to execute %s\n", argv[0]);
}
_exit(1);
}
close(pipeout);
readpipe = fdopen(pipein, &mode);
while(!feof(readpipe)){
if(1 == fread(&buf, sizeof(char), 1, readpipe)){
fprintf(stdout, "%c", buf);
}
}
return 0;
}
Yes, tmpfile() is one way to do it. However, I believe tmpfile() is frowned upon these days due to security concerns.
So, you should use mkstemp in POSIX or tmpfile_s in Windows instead of tmpfile().
These will all still create files in the filesystem, though. They're temporary in that they "go away" when the program exits.
Another option, which doesn't create a physical file is mmap().
Oops, just found it... maybe. tmpfile() returns a tmeporary FILE *
Is that the right way to do it?
If you're on Unix (or a similar OS), you want to read Beej's Guide to Unix Interprocess Communication (it's a good read no matter what your OS is).
Check it out at Beej's Guides.
In a rapid glance there I noticed a few things you could probably use with more or less work (and with the optional creation of a file/resource):
Pipes
FIFOs
Message Queues
Shared Memory Segments
Memory Mapped Files
Unix Sockets

Resources