Program hangs after opening file with open and fdopen [duplicate] - c

This question already has answers here:
Why does open make my file descriptor 0?
(4 answers)
Closed 5 years ago.
I'm using open() with O_RDWR and then using the descriptor in fdopen() with "r+". I check that the file exists first with access(), and check for open() returning -1 then check that the FILE *fp set from fdopen() isn't NULL.
Now whenever I use any function such as fgets() or fgetc() with fp the program hangs in my terminal. I get no compiler warnings. Any ideas?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv) {
char buffer[512];
int file_descriptor;
FILE *file;
if (argc != 2) {
puts("ERROR: Missing argument");
exit(0);
}
else if (access(argv[1], F_OK) == -1) { // Check if file exists
puts("ERROR: File does not exist");
exit(0);
} else if (file_descriptor = open(argv[1], O_RDWR) == -1) { // Check for open() failure
puts("ERROR: Unable to open file using open()");
exit(0);
}
file = fdopen(file_descriptor, "r+"); // Use descriptor
if (file == NULL) {
puts("ERROR: Unable to open file using fdopen()");
fclose(file);
exit(0);
}
// fscanf(file, "%c", stdout); // Hangs
// fgets(buffer, sizeof(buffer), file); // Hangs
printf("%c", fgetc(file)); // Hangs
fclose(file);
return 0;
}

The expression
file_descriptor = open(argv[1], O_RDWR) == -1
does not work as you expect it to, because the equality operator == have higher precedence than the assignment operator. That means the expression is more like
file_descriptor = (open(argv[1], O_RDWR) == -1)
which means your file_descriptor will be either 0 or 1 depending on how the comparison went.
You need to use parentheses for the assignment:
(file_descriptor = open(argv[1], O_RDWR)) == -1

To add to the other answer. It's "hanging" because the bug causes it actually to read standard input (file descriptor 0). Try typing something and it will read it.

Related

create new file with system calls

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.

C - Declare a file in function parameters

so here is my problem :
int isopen()
{
int fd;
fd = open("myfile", O_RDONLY);
if (fd == 0)
printf("file opening error");
if (fd > 0)
printf("file opening success");
return(0);
}
int main(void)
{
isopen();
return(0);
}
Is use this code to check if this the open command worked, as i'm just starting to lurn how to use it.
Basically this code is working just fine, but I would like to declare the file I would like to open directly in the parameters of my function isopen.
I saw some other posts using main's argc and argv, but I really need to declare my file in the parameters of my function isopen, not using argc & argv.
Is it even possible ?
Thank you for your help, I'm quite lost here.
Your question is unclear, but maybe you want this:
int isopen(const char *filename)
{
int fd;
fd = open(filename, O_RDONLY);
if (fd < 0) //BTW <<<<<<<<<<<< fd < 0 here !!
printf("file opening error");
else // else here
printf("file opening success");
return(0);
}
int main(void)
{
isopen("myfile");
return(0);
}
BTW, the isopen function as it stands here is still pretty useless as it just opens the file and throwing away fd.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int isOpen(char *filename)
{
return open(filename, O_RDONLY);
}
int main()
{
printf("%d\n", isOpen("/home/viswesn/file1.txt"));
printf("%d\n", isOpen("file2.txt"));
return 0;
}
Output
viswesn#viswesn:~$ cat /home/viswesn/file1.txt
hello
viswesn#viswesn:~$
viswesn#viswesn:~$ cat /home/viswesn/file2.txt
cat: /home/viswesn/file2.txt: No such file or directory
viswesn#viswesn:~$
viswesn#viswesn:~$ ./a.out
3 <---------- File exist and it give file descriptor number '3'
STDIN-0, STDOUT-1, STDERR-2 are reserved and
next file opened will start with 3 and it keeps going
-1 <--------- File not found; so open gives -1 as error

System calls in C (File Descriptor)

follwing code has written to open a file and write data to terminal using sysyem calls in linux.
To read the value of the file descriptor (fd) it should assign a value. As we know in if else statement, from if part else part or else if part one part will implement at a time. So according to following code fd will have a value only at else if line. But when I pass a file name and run this program it opens the file. File opening is happen in while loop from read(() system call. But while loop is in else part and since file descriptor can't have any value theoretically. So how does the read function get recognize the file exactly? This is confusing me.
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#define SIZE 10
int main(int argc, char *argv[])
{
int fd,n;
char buff[SIZE];
if(argc != 2)
{
printf("USAGE : %s\n",argv[0] );
exit(1);
}
else if ((fd = open(argv[1],0)) == -1)
{
perror("STATUS");
exit(1);
}
else
{
while((n = read(fd,buff,SIZE)) > 0)
{
write(1,buff,SIZE);
}
close(fd);
}
}
Following happens here:
Let's suppose the program is started with xyz.txt on the command line and let's suppose the xyz.txt file does exist:
if(argc != 2)
{
// we don't get here because argc == 2
printf("USAGE : %s\n",argv[0] );
exit(1);
}
else if ((fd = open(argv[1],0)) == -1) // the statement in the if clause will therefore
// be executed, fd will be something different
// from -1 because open succeeded
{
perror("STATUS"); // therefore we dont ge here either
exit(1);
}
else
{ // instead we get here and
while((n = read(fd,buff,SIZE)) > 0) // everything works as expected
{
write(1,buff,SIZE);
}
close(fd);
}

C program to use Unix System call for I/O [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
My professor asked me to write a simple C program, then asked me to convert using Unix system calls. I have try changing the values around but nothing is working.
Requirement:
Write a new C program newcat, which performs exactly as oldcat, but uses the following UNIX system calls for I/O.
int read(int fd, char *buf, int n);
int write(int fd, char *buf, int n);
int open(char *name, int accessmode, int permission);
int close(int fd);
To open a file for read, you can use the symbolic constant O_RDONLY defined in fcntl.h header file to specify the accessmode. Simply pass 0 for permission. That is, the code will appear as follows:
fd = open (filename, O_RDONLY, 0);
You will need the following header files: sys/types.h, unistd.h and fcntl.h
#include <stdio.h>
/* oldcat: Concatenate files */
int main(int argc, char *argv[])
{
void filecopy(FILE *, FILE *); /* prototype for function */
int fd = open(*fp, O_RDONLy,0)
char *prog = argv[0]; /* program name for errors */
if (argc == 1) /* no args; copy standard input */
filecopy(0, 1);
else
while (--argc > 0)
if (fd == -1) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
return(-1);
} else {
filecopy(fp, 1);
fclose(fp);
}
return(0);
}
/* filecopy: copy file ifp to ofp */
void filecopy(FILE *ifp, FILE *ofp)
{
int c;
while ((c = getc(ifp)) != EOF)
putc(c, ofp);
}
Is this the write idea? It still won't compile:
#include <stdio.h>
/* oldcat: Concatenate files */
int main(int argc, char *argv[])
{
void filecopy(int ifp, int ifo);
int fd = open(*File,O_RDONLY,0); //is this correct?
char *prog = argv[0];
if (argc == 1) /* no args; copy standard input */
filecopy(0, 1); //is this correct?
else
while (--argc > 0)
if ((fd == -1) //is this correct?{
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
return(-1);
} else {
filecopy(*FILE, 1);//is this correct?
close(*FILE);//is this correct?
}
return(0);
}
/* filecopy: copy file ifp to ofp */
void filecopy(FILE *ifp, FILE *ofp)//NO CLUE HOW THIS SHOULD BE
{
int c;
while (c = read(fd ,&something,1)//What is &ch/&something?
putc(c, ofp);
}
Assuming your oldcat uses the C standard library calls (like fopen), it's a simple matter of mapping those to the UNIX calls.
At a high level:
fopen -> open
fread -> read
fwrite -> write
fclose -> close
For example, when opening your input file with:
FILE *fIn = fopen ("jargon.txt", "r");
you could instead use:
int inFd = open ("jargon.txt", O_RDONLY, 0);
The other calls are very similar, with similar functionality at the C standard library and UNIX system call levels. Details on those calls can usually be obtained from the manpages by entering something like man 2 open into your shell, or by plugging man open into your favourite search engine.
The only "tricky" mapping is if you've used getchar/putchar-style calls to do the actual reading and writing but that too becomes easy when you realise that (for example) reading a character is functionally identical to reading a block of size one:
int c = getc (fIn);
or:
char c;
int numread = read (inFd, &c, 1);
For your added question:
So to open a file: if (fd = open (fp, O_RDONLY, 0); ) == NULL)
Not quite. The fopen function returns NULL on error because it returns a pointer to a FILE structure.
The lower level calls use file descriptors rather than file handles, the former being a small integer value. So, instead of:
FILE *fp = fopen ("nosuchfile", "r");
if (fp == NULL) doSomethingIntelligent();
you would do something like:
int fd = open ("nosuchfile", O_RDONLY, 0);
if (fd == -1) doSomethingIntelligentUsing (errno);
In terms of what you need to change, the following comes off the top of my head (so may not be totally exhaustive but should be a very good start):
Add the required headers.
Stop using FILE* totally, using int instead.
Translate the fopen/fclose calls to open/close. This includes the function name, different parameters and different return types.
Modify filecopy to use file descriptors rather than file handles.
use 1 instead of stdout when calling filecopy (the latter is a FILE *).
As an example of how to do this, the following program testprog.c will read itself and echo each character to standard output:
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
int main (void) {
int num, ch, inFd;
// Open as read only.
inFd = open ("testprog.c", O_RDONLY, 0);
if (inFd == -1)
printf ("\n**Error %d opening file\n", errno);
// Get and output esach char until EOF/error.
while ((num = read (inFd, &ch, 1) != 0) == 1)
putchar (ch);
// Detect error.
if (num != 0)
printf ("\n**Error %d reading file\n", errno);
// Close file and exit.
close (inFd);
return 0;
}
Please note that documentation of linux sys calls is present in manual called man pages which you can access by using man command in bash shell in a linux system. As UNIX and Linux are quite similar (maybe equivalent) for the syscalls you are interested in you can check the man page for those syscalls in Linux.
All the four read, write, open and close linux syscalls are explained in man pages. You can access the manual page for these syscalls by typing below commands in shell:
man 2 read
man 2 write
man 2 open
man 2 close
These should probably guide you to right direction.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
/* newcat: Concatenate files */
int main(int argc, char *argv[])
{
void filecopy(int ifp, int ofp); /* prototype for function */
int fd;
char *prog = argv[0]; /* program name for errors */
if (argc == 1) /* no args; copy standard input */
filecopy(0,1);
else
while (--argc > 0)
fd = open(*++argv , O_RDONLY,0);
if ( fd == -1) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
return(-1);
} else {
filecopy(fd, 1);
close(fd);
}
return(0);
}
/* filecopy: copy file ifp to ofp */
void filecopy(int ifp, int ofp)
{
int c;
while (read(ifp,&c,ofp ) != 0)
write(ofp,&c,ofp);
}

Detecting file that isn't there

So this is one of the first programs I've ever used some self created error checks however for some reason when I compile this and run it using:
./file test1.txt test2.txt 10
I get absolutely an error suggesting that the output file exists and I've checked the file and it doesn't even when I change the name of the output file (second argument) I get nothing. Anyone who can help? I've been racking my brain for ages now. This is a UNIX homework assignment I'm compiling and running in Gentoo. I have it running in a VB and have a linked folder between my windows and linux OS's.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFFT 25
int main (int argc, char *argv[])
{
int count;
int readin;
int writeout;
printf ("This program was called \"%s\".\n",argv[0]);
if (argc > 1)
{
for (count = 1; count < argc; count++)
{
printf("argv[%d] = %s\n", count, argv[count]);
}
}
else
{
perror("The command had no arguments.\n");
exit(-1);
}
// check correct number of arguments parsed //
if (argc == 4)
{
printf("There are the correct number of arguments(4)\n");
}
else
{
perror("Not enough arguments! please try again \n");
exit(-1);
}
//Check original file is there//
int openFD = open(argv[1], O_RDWR);
if (openFD <0)
{
perror("Error unable to read file \n");
exit(-1);
}
//Check existence of output file, if it doesn't exist create it//
int CheckFile = open(argv[2], O_RDONLY);
if (CheckFile < 0)
{
perror("Error output file already exists \n");
exit(-1);
}
else
{
int CheckFile = open(argv[2], O_CREAT);
printf("The file has successfully been created \n");
}
//Create buffer
int bufsize = atoi(argv[3]);
char *calbuf;
calbuf = calloc(bufsize, sizeof(char));
//Read text from original file and print to output//
readin = read(openFD, calbuf, BUFFT);
if (readin < 0){
perror("File read error");
exit(-1);
}
writeout = write(openFD,bufsize,readin);
if (writeout <0){
perror("File write error");
exit(-1);
}
return 0;
}
The open call for HANDLE CheckFile is printing Error File Exists. This is your problem. You are printing out the wrong statement when Output File Is Not Found and moreover you are exiting which prevents the code to create any.
int CheckFile = open(argv[2], O_RDONLY);
if (CheckFile < 0)
{
//Means the file doesn't exist
int CheckFile = open(argv[2], O_CREAT);
// Check for errors here
}
And why are you trying to do this::
writeout = write(openFD,bufsize,readin);
when your HANDLE TO OUTPUT FILE IS CheckFile
int CheckFile = open(argv[2], O_RDONLY);
if (CheckFile < 0)
{
perror("Error output file already exists \n");
A negative return from open means that the file could not be opened, most likely because it does not exist ... it does not mean that the file already exists. Failing to open the input file certainly does not mean that the output file already exists. Please check your code more carefully for obvious errors, e.g.,
int CheckFile = open(argv[2], O_CREAT);
printf("The file has successfully been created \n");
Here you don't check the return code.
Take a look at this fragment of your code:
int CheckFile = open(argv[2], O_RDONLY);
if (CheckFile < 0)
{
perror("Error output file already exists \n");
exit(-1);
}
You are saying trying to open a file in READ ONLY MODE. From what I read in your question, it's not an error if the file doesn't exist, but in the code you are validating the opposite, if the file doesn't exists, throw an error (in fact your message error is incorrect here).
Double check your logic and you will find your solution.

Resources