Check if files exists (given by command line arguments) - c

I have to a do C program that uses the unix environment. I have already purchased the "Advancing Programming in the Unix Environment" book and it has helped out a lot so far. However, some of my questions have gone unanswered and I'm looking for some help.
I'm trying to write a program that can verify if the first and second arguments entered if a copy program exist. If the first argument does not exist, then an error message and exit must occur. If the second argument does exist, then an overwrite prompt must be displayed. I'm not exactly sure how to verify if a file already exists or not basically.
I have seen a few people saying that you can do (!-e) or something like that to verify the file existing/not existing.
If anyone could help me, I'd really appreciate it.

The access() function is designed to tell you if a file exists (or is readable, writeable or executable).
#include <unistd.h>
int result;
const char *filename = "/tmp/myfile";
result = access (filename, F_OK); // F_OK tests existence also (R_OK,W_OK,X_OK).
// for readable, writeable, executable
if ( result == 0 )
{
printf("%s exists!!\n",filename);
}
else
{
printf("ERROR: %s doesn't exist!\n",filename);
}

in your int main(int argc, char** argv) { block.
if (argc == 3) {
// then there were 3 arguments, the program name, and two parameters
} else if (argc == 2) {
// then prompt for the "second" argument, as the program name and one
// parameter exists
} else {
// just print out the usage, as we have a non-handled number of arguments
}
now if you want to verify that the file exists, that's different than verifying that the program argument exists. Basically attempt to open the file and read from it, but pay close attention to catching the integer error codes and checking them for errors. This will prevent your program from progressing into bits where those critical operations are assumed to have worked.
There is a common, yet misguided conception among new programmers when dealing with files in C. Basically, one really wants to make sure that a specific block of code works (the copying block in your case), so they check, check, and double-check conditions before the block is executed. Check if the file exists, check if it has correct permissions, check that it isn't a directory, etc. My recommendation is that you not do this.
Your copying block should be able to fail properly, just as properly as it should be able to succeed. If it fails, then typically you have all the information necessary to print out a meaningful error message. Should you check first and then act there will always be a small time gap between the check and action, and that time gap will eventually see the file removed or altered after the checks have passed, yet before it is read. Under such a scenario all of the pre-checking code failed to provide any benefit.
Code without benefit is just a nesting ground for future bugs and architectural problems. Don't waste your time writing code that has dubious (or no) benefit. When you suspect that some code you have written has little benefit, you need to restructure your code to put it in the right place. When you suspect that code someone else has written has little benefit, you need to first doubt your suspicions. It is trivially easy to not see the motivations behind a piece of code, and even more so when just starting out in a new language.
Good Luck!
--- code for the weary ---
#include <errorno.h>
#include <stdio.h>
#include <stdlib.h>
extern int errno;
int main(int argc, char** argv) {
// to hold our file descriptor
FILE *fp;
// reset any possible previously captured errors
errno = 0;
// open the file for reading
fp = fopen(argv[1], "r");
// check for an error condition
if ( fp == 0 && errno != 0 ) {
// print the error condition using the system error messages, with the
// additional message "Error occurred while opening file"
perror("Error occurred while opening file.\n");
// terminate the program with a non-successful status
exit(1);
}
}

Related

How to identify whether a particular file is called first time in C

While executing a C program,A debug print should be inserted to a log file (say log.txt),
but this C program is executed from various places.
So, multiple logs were found in log.txt
I want that debug to be present only once in the log.txt.
How to insert a check in C program to achieve the above requirement
I have tried with static variable, but it works only if for the function called first time
not the file.
whether access function would help this scenario??
You need some way for the programs to store that they've done a thing, know as a semaphore.
Simplest thing to do is use a shared location like /var/run/ to place a semaphore file. Then each program attempts to create that file. If it already exists, they can assume someone else already performed the action.
To do that we use the open system call (not fopen) for fine control. Using both the O_CREAT and O_EXCL flags says to create the file, and error if it already exists. This is atomic, we're checking if the file exists and creating it in one action. There's no way two programs could accidentally check & create at the same time.
#include <stdio.h>
#include <fcntl.h>
#include <stdbool.h>
bool check_semaphore(const char *file) {
if( open(file, O_CREAT|O_EXCL) >= 0 ) {
return true;
}
else {
return false;
}
}
int main() {
if( check_semaphore("did_debug_log") ) {
FILE *log = fopen("log.txt", "a");
if( !log ) {
perror("Couldn't open log.txt");
}
fprintf(log, "Some debug stuff\n");
}
}
You can use more sophisticated shared storage as a semaphore, like shared memory or a shared database such as SQLite, but the basic technique is the same. Check if the operation has been complete while also declaring you're going to do it in an atomic operation.

How to make flex use a text-containing file (.txt/.c/etc.) as its input

I am completely new to flex, and my experience in programming is rather little. I need to create a scanner using flex that will output a stream of tokens eventually. For the moment, I just need to get the absolute basics up and running. I want the compiled output file "a.exe" to be able to be run from the text within a SINGLE file and not user input. The output should also be to a file. The assignment asks that the program is able to run like so in a cmd/PS window:
.\a.exe inputfile.txt outputfile.txt
Where input and output files are whatever file names are added in that order.
As it stands currently, my program creates the output file I designate, but nothing is written to it. When trying to read the Flex Manual, I am very confused as I am still very new to computer sciences in general.
As per the moment, I just want to get an executable file that will adhere to the rules section and output properly. This said I am generically just counting the characters in the input file and trying to display them to an output file. I also am trying to help the others in my class have a place to begin (as none of us were formally taught in this affair) so I am taking the time to try and create this file generically (with installation and usage instructions) so that I can give them a place to start the actual assignment of making the scanner.
I installed Flex 2.5.4a from http://gnuwin32.sourceforge.net/packages.html. I edited my Path to include the bin file after installation.
I build the file using the command "flex tokenout.l" and then "gcc lex.yy.c" and it generates an a.exe file. The file does not seem to work much at all past creating the output file.
code:
int num_lines = 0;
int num_chars = 0;
FILE *yyin;
FILE *yyout;
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
int yywrap(void) {
return 0;
}
int main(int argc, char *argv[])
{
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
fprintf(yyout,"# of lines = %d, # of chars = %d\n", num_lines, num_chars);
fclose(yyin);
fclose(yyout);
return 0;
}
The result should be that the line "# of lines = the actual # of lines, # of chars = the actual # of characters" to the file designated as the second argument.
Currently the file designated by the second argument is created but remains blank.
Lex (flex) calls (or more precisely, generates code that calls) yywrap upon reaching the end of its input stream (in yyin). The job of this function is to:
Take care of closing the input file if needed / appropriate.
Switch to the next input file, if there is a next file.
Return nonzero (1, preferably) if flex should finish up, 0 if yyin is now re-opened to the next file.
Or, as the manual puts it:
When the scanner receives an end-of-file indication from YY_INPUT, it then checks the ‘yywrap()’ function. If ‘yywrap()’ returns false (zero), then it is assumed that the function has gone ahead and set up yyin to point to another input file, and scanning continues. If it returns true (non-zero), then the scanner terminates, returning 0 to its caller. Note that in either case, the start condition remains unchanged; it does not revert to INITIAL.
If you do not supply your own version of ‘yywrap()’, then you must either use ‘%option noyywrap’ (in which case the scanner behaves as though ‘yywrap()’ returned 1), or you must link with ‘-lfl’ to obtain the default version of the routine, which always returns 1.
(Modern flex has <<EOF>> rules which are generally a better way to deal with stacked input files, since transitions between files should almost always force a token boundary.)
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
As it stands currently, my program creates the output file I designate, but nothing is written to it.
You're confused because you don't know what your program is doing, and you don't know what it's doing because it's not telling you. What you need is feedback. In particular, you need to check for errors.
For example, what if the first fopen(3) fails? What if yyparse fails, or doesn't return? (It won't.) Check for errors, and have the program tell you what's happening.
#include <err.h>
if( argc < 3 ) {
errx(EXIT_FAILURE, "syntax: foo in out");
}
if( (yyin = fopen(argv[1],"r")) == NULL ) {
err(EXIT_FAILURE, "could not read '%s'", argv[1]);
}
if (yyout = fopen(argv[2],"w")) == NULL ) {
err(EXIT_FAILURE, "could not write '%s'", argv[2]);
}
printf("starting yyparse\n");
if( 0 != yyparse() ) {
errx(EXIT_FAILURE, "parse error");
}
printf("starting yylex\n");
if( 0 != yylex() ) {
errx(EXIT_FAILURE, "lex error");
}
The above ensures the program is started with sufficient arguments, ensures both files are open successfully, and checks for errors parsing and lexing. That's just an example, though. As John Bollinger advised, you don't need yyparse because you're not using bison, and yyout controls only the file used by the flex ECHO statement. You can use your own global FILE * handle, and fprintf(3) to it in your flex actions.
What i think you will find is that you never see "starting yylex" on the screen, because yyparse never returns, because -- if it is being generated somewhere -- it's not returning, because it's calling yylex, which never returns anything to it.
I would delete those lines, and set flex debugging on with
yy_flex_debug = 1;
before calling yylex. I think you'll find it makes more sense then.
You appear to be starting by adapting an example program from the Flex manual. That's fine, but maybe your very first step should be getting the exact example program working. After that, take it one step at a time. For example, the next step might be to get it to use the first argument as the name of the input file (and no other changes).
With respect to the partial program you have presented, I see two semantic issues:
When you use flex with bison (or yacc), it is the generated parser (accessed via yyparse()) that calls yylex(), and generally it will do so repeatedly until the input is exhausted. It is not useful in that case for the main program to call the lexer directly.
yyout is the file to which flex will direct the output of ECHO statements, nothing more, nothing less. It is not particularly useful to you, and I would ignore it for now.

Get return code from linux command in C program

I am basically trying to check if a particular file exists or not. For that I am using the test command of Unix.
sprintf(execbuf, "%s if test -r %s ; then true; else exit; fi;",
execbuf, st->file, NO_FILE);
It works fine, but I do not want to exit if the file is not here, rather it should return FAIL.
I am not able to figure out how to make the program return FAIL. I was thinking of using the exit code from the above command, but still I am not able to figure out how to use that exit code outside the Linux command in the program.
I'd recommend you rather just use the access() call, and not execute external shell commands to figure this out.
Just be aware that such cases are subject to race conditions - the file might exist when you call access() (or execute a shell command that determines whether the file exists), but it might be gone when you actually need it later on. If that's a problem for you, just open() the file, and use the file descriptor later on when you actually need it for I/O.
If you're not married to what your doing right now, then I'd suggest using stat:
#include <sys/stat.h>
#include <stdio.h>
int main (int argc, char** argv[])
{
struct stat sts;
if (stat(argv[1], &sts) == -1 && errno == ENOENT)
printf ("The file %s doesn't exist...\n", argv [1]);
else
printf("The file exists\n");
This will tell you if it exists or not. If you dont' want to pass it command line, parameter 1 is a const char*, so just pass it the file name.

Reading from files passed as command line arguements

I am trying to parse a given textfile, but so far, my program does not seem to be reading properly.
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fr; //file pointer
int buildingFloors = 1;
printf("sanity check\n");
fr = fopen (argv[0], "r");
fscanf(fr, "%d", &buildingFloors );
printf("%d\n", buildingFloors);
fclose(fr);
return 0;
}
I compile the program and run it on my redhat linux machine with the following command:
./sjf file.text
file.text is a text document with a "4" as the first character. So I would expect my output to be
sanity check
4
However, when I run my program I instead get
sanity check
1
Which implies that fscanf didn't properly read in the first character -- 4. Do I have some syntax error that's preventing the expected code functionality? Am I supposed to scanf for a character, and then convert that to an int somehow?
argv[0] is the name of the program (./sjf in your case), so you're trying to read in your own program's executable. Use argv[1] instead to get the first real program argument.
One thing which immediatly comes to mind is that the program args include the executable name as the first element
argv[0] is "sjf"
argv[1] is "file.text"
so you should be using
fr = fopen (argv[1], "r");
Remember when debugging to always try and narrow the problem down, if you know the location of the error the cause often becomes obvious or at least investigatable.
In this case you should check argc >= 2, print out argv[1] to ensure you are trying to open the right file, then also check that the file was opened successfully.
Finally check the fscanf error codes to see that fscanf was able to read the number.
Your code looks clear and straight-forward, but there is one important thing missing: error handling.
What happens if the file you want to open does not exist? fopen returns NULL in that case.
What happens if the file does not start with a number? fscanf returns the number of fields that have been successfully read, so you should check that the return value is at least 1.
You need to somehow handle these cases, probably by printing some error message and exiting the program. When you do that, be sure to include the relevant information in the error messages. Then you will find the bug that the other answers have already mentioned.

Opening a file in C through a proccess

I am trying to create a a program that does the following actions:
Open a file and read one line.
Open another file and read another line.
Compare the two lines and print a message.
This is my code:
#include <stdio.h>
#include <string.h>
int findWord(char sizeLineInput2[512]);
int main()
{
FILE*cfPtr2,*cfPtr1;
int i;
char sizeLineInput1[512],sizeLineInput2[512];
cfPtr2=fopen("mike2.txt","r");
// I open the first file
while (fgets(sizeLineInput2, 512, cfPtr2)!=NULL)
// I read from the first 1 file one line
{
if (sizeLineInput2[strlen(sizeLineInput2)-1]=='\n')
sizeLineInput2[strlen(sizeLineInput2)-1]='\0';
printf("%s \n",sizeLineInput2);
i=findWord(sizeLineInput2);
//I call the procedure that compares the two lines
}
getchar();
return 0;
}
int findWord(char sizeLineInput2[512])
{
int x;
char sizeLineInput1[512];
File *cfPtr1;
cfPtr1=fopen("mike1.txt","r");
// here I open the second file
while (fgets(sizeLineInput1, 512,cfPtr1)!=NULL)
{
if (sizeLineInput1[strlen(sizeLineInput1)-1]=='\n')
sizeLineInput1[strlen(sizeLineInput1)-1]='\0';
if (strcmp(sizeLineInput1,sizeLineInput2)==0)
//Here, I compare the two lines
printf("the words %s and %s are equal!\n",sizeLineInput1,sizeLineInput2);
else
printf("the words %s and %s are not equal!\n",sizeLineInput1,sizeLineInput2);
}
fclose(cfPtr1);
return 0;
}
It seems to have some problem with file pointers handling. Could someone check it and tell me what corrections I have to do?
Deconstruction and Reconstruction
The current code structure is, to be polite about it, cock-eyed.
You should open the files in the same function - probably main(). There should be two parallel blocks of code. In fact, ideally, you'd do your opening and error handling in a function so that main() simply contains:
FILE *cfPtr1 = file_open("mike1.txt");
FILE *cfPtr2 = file_open("mike2.txt");
If control returns to main(), the files are open, ready for use.
You then need to read a line from each file - in main() again. If either file does not contain a line, then you can bail out with an appropriate error:
if (fgets(buffer1, sizeof(buffer1), cfPtr1) == 0)
...error: failed to read file1...
if (fgets(buffer2, sizeof(buffer2), cfPtr2) == 0)
...error: failed to read file2...
Then you call you comparison code with the two lines:
findWord(buffer1, buffer2);
You need to carefully segregate the I/O operations from the actual processing of data; if you interleave them as in your first attempt, it makes everything very messy. I/O tends to be messy, simply because you have error conditions to deal with - that's why I shunted the open operation into a separate function (doubly so since you need to do it twice).
You could decide to wrap the fgets() call and error handling up in a function, too:
const char *file1 = "mike1.txt";
const char *file2 = "mike2.txt";
read_line(cfPtr1, file1, buffer1, sizeof(buffer1));
read_line(cfPtr2, file2, buffer2, sizeof(buffer2));
That function can trim the newline off the end of the string and deal with anything else that you want it to do - and report an accurate error, including the file name, if anything goes wrong. Clearly, with the variables 'file1' and 'file2' on hand, you'd use those instead of literal strings in the file_open() calls. Note, too, that making them into variables means it is trivial to take the file names from the command line; you simply set 'file1' and 'file2' to point to the argument list instead of the hard-wired defaults. (I actually wrote: const char file1[] = "mike1.txt"; briefly - but then realized that if you handle the file names via the command line, then you need pointers, not arrays.)
Also, if you open a file, you should close the file too. Granted, if your program exits, the o/s cleans up behind you, but it is a good discipline to get into. One reason is that not every program exits (think of the daemons running services on your computer). Another is that you quite often use a resource (file, in the current discussion) briefly and do not need it again. You should not hold resources in your program for longer than you need them.
Philosophy
Polya, in his 1957 book "How To Solve It", has a dictum:
Try to treat symmetrically what is symmetrical, and do not destroy wantonly any natural symmetry.
That is as valid advice in programming as it is in mathematics. And in their classic 1978 book 'The Elements of Programming Style', Kernighan and Plauger make the telling statements:
[The] subroutine call permits us to summarize the irregularities in the argument list [...]
The subroutine itself summarizes the regularities of the code.
In more modern books such as 'The Pragmatic Programmer' by Hunt & Thomas (1999), the dictum is translated into a snappy TLA:
DRY - Don't Repeat Yourself.
If you find your code doing the 'same' lines of code repeated several times, write a subroutine to do it once and call the subroutine several times.
That is what my suggested rewrite is aiming at.
In both main() and findWord() you should not use strlen(sizeLineInputX) right after reading the file with fgets() - there may be no '\0' in sizeLineInput2 and you will have strlen() read beyond the 512 bytes you have.
Instead of using fgets use fgetc to read char by char and check for a newline character (and for EOF too).
UPD to your UPD: you compare each line of mike2.txt with each line of mike1.txt - i guess that's not what you want. Open both files one outside while loop in main(), use one loop for both files and check for newline and EOF on both of them in that loop.

Resources