fopen and fopen_s seem to be crashing on long file names - c

I am using visual studio 2013 to build a c application
The code looks like this -
int main( int argc, char *argv[] )
{
char *InFilename = NULL;
char *OutFilename = NULL;
int ff_count; // counts the number of successive 0xff's read from the file buffer
int fpga_end, nios_start, nios_end; // used to report the size of each region
int file_length, file_index, temp_length, new_file_length;
int root_length;
int result;
FILE *infile = NULL;
FILE *outfile = NULL;
printf("Start JIC 2 rbf\r\n");
if ((argc != 2))
{
printf("\r\n\r\nV1.2 - Usage: <jic2rbf> <name of jicfile> \r\n");
printf("\r\n This program strips out the header info at the top of the file\r\n");
printf("\r\n and most of the ff's at the bottom. \r\n");
exit(1);
}
//
// Extract the name of the input file up to the '.' and use it to create the output file name with a .rbf extension.
//
InFilename = argv[1];
root_length = strcspn(InFilename,".");
printf("Root len = %d\r\n",root_length);
OutFilename = (char *)malloc(root_length+EXT_LENGTH);
memcpy(OutFilename,InFilename,root_length);
OutFilename[root_length] = 0;
strcat(OutFilename,".rbf");
printf("In file to be used %s\r\n", InFilename);
printf("Out file to be used %s\r\n", OutFilename);
result = fopen_s(&outfile, OutFilename, "wb");
if (result)
{
printf("Cannot open this file %s\r\n - 0x%x", OutFilename, result);
return 0;
}
printf("Open In - %d\r\n",result);
If I call this executable from a dos command line with -
E:/projects/Q4300_Hdcp/q_series_hdcp_base/fpga/q_series_hdcp_tx_dual_singleHID/par/q_series_hdcp_tx_dual_singleHID/output_files/q_series_hdcp_tx_dual_singleHID_elf.jic
The entire application works
If I call the application with the following command line -
E:/projects/Q4300_Hdcp/q_series_hdcp_base/fpga/q_series_hdcp_tx_dual_fpga/par/q_series_hdcp_tx_dual_fpga/output_files/q_series_hdcp_tx_dual_fpga_elf.jic
I do not see the printf("Open In - %d\r\n",result); output. The application just seems to crash.
I thought it might be some sort of buffer overflow in the file name but the shorter file name works..... If I cd to the directory with the file and call with the command line q_series_hdcp_tx_dual_fpga_elf.jic that works.
If I dir the file - E:/projects/Q4300_Hdcp/q_series_hdcp_base/fpga/q_series_hdcp_tx_dual_fpga/par/q_series_hdcp_tx_dual_fpga/output_files/q_series_hdcp_tx_dual_fpga_elf.jic
I see the file.......
I do not know how to catch the exception or what else to pursue to resolve this, any ideas would be great.
Thanks,
Martin

Try changing this line:
OutFilename = (char *)malloc(root_length+EXT_LENGTH);
to this:
OutFilename = malloc(1 + root_length + EXT_LENGTH);
to allocate space for the null terminator. Also, no need to cast malloc's return value.

DOS has some severe limits on command line length
so when the command line is too long, problems such as you are experience will occur.
Did you really mean that your using Visual Studio and Windows?
Many of the limitations of DOS have been carried forward into Windows and Visual Studio

Related

C can't open file in Unix but works fine on macOSx

I've written a program to reverse a .txt file, line-by-line, and return the output to a new file. It is part of the requirements for the command line arguments to NOT include the .txt extension, so I add in at the top of the program before fopen is called on the file. This works perfectly fine in macOSx terminal, as you can see here: https://imgur.com/a/HqUFd
However, when I upload this to my school's server, I get the following output: https://imgur.com/a/rCdaI
Relevant code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define NUMARG 3
#define INFILEARG 1
#define OUTFILEARG 2
int countWords(const char *sentence);
int main(int argc, char *argv[]){
/* File pointers */
FILE *finp;
FILE *foutp;
/* Three levels of strings: word < line < text.
Both token variables to use with strtok splitting the text. */
char **holdWords = NULL, *holdLine = NULL, *holdText = NULL,
*lineToken = NULL, *wordToken = NULL;
int stringSize = 0, totalStrings, i;
size_t size = 0;
/* Add .txt extension */
int inFileNameSize = sizeof(argv[INFILEARG]);
int outFileNameSize = sizeof(argv[OUTFILEARG]);
char inFileName[inFileNameSize+4]; //add 4 to have room for ".txt"
char outFileName[outFileNameSize+4];
strcat(inFileName, argv[INFILEARG]);
strcat(inFileName, ".txt");
strcat(outFileName, argv[OUTFILEARG]);
strcat(outFileName, ".txt");
/* Check for errors in argument number and opening files. */
if(argc != NUMARG){
printf("You have to put the input and output files after the program name.\n"); fflush(stdout);
return(1);
}
if( (finp = fopen(inFileName, "r")) == NULL ){
printf("Couldn't open %s for reading.\n", inFileName); fflush(stdout);
return(1);
}
if( (foutp = fopen(outFileName, "w")) == NULL){
printf("Couldn't open %s for writing.\n", outFileName); fflush(stdout);
return(1);
}
Can anyone help me figure out what's going on here? Thank you.
EDIT TO EXPLAIN WHY DIFFERENT THAN LINKED QUESTION: While it's helpful to know why a pointer to an array can't be sizeof'd, my question is about getting the size of a string (one pointer, not a pointer to a pointer). I get an error when using strlen on my mac, yet it works on unix. I get an error when using sizeof of the unix, yet sizeof works on my mac.
It appears your have a buffer overflow, you can see this by the fact the file names printed appear corrupted.
If you look at the lines:
/* Add .txt extension */
int inFileNameSize = sizeof(argv[INFILEARG]);
int outFileNameSize = sizeof(argv[OUTFILEARG]);
Your error lies in the use of the sizeof operator. This returns the sizeof the type not the length of the string. Hence your in/outFileNameSize variable is too short for the actual string you are copying into it.

fopen() return "No such file or directory"

I have some problem with fopen() function in C.
I'am parsed directory and put all the paths to char array(char**). After that i should to open all these files. And...
fopen returns "No such file or directory" for some files. And I Am really don't understand, why.
All paths are right. I checked it.
I have all privileges to
open these files.
If I copy path to file from error log and try
to open only this file via my programm - it works.
Others
programms don't work with these files(i think).
What can I do wrong?
int main(int argc, char *argv[]){
char** set = malloc(10000*sizeof(char*));
char* path = argv[1];
listdir(path, set); /* Just parse directory. Paths from the root. No problem in this function. all paths in the variable "set" are right */
int i=0;
while(i<files){ /* files is number of paths */
FILE* file = fopen(set[i++],"rb");
fseek(file, 0L, SEEK_END);
int fileSize = ftell(file);
rewind(file);
/*reading bytes from file to some buffer and close current file */
i++;
}
}
You increments 'i' twice. May be mistakenly?
You can get file size w/o open it using stat().
ftell() returns "long", don't cast it in "int" as it can be shorten and you loose correct value.
Try this code:
#include <stdio.h>
#include <sys/stat.h>
/* example of listdir, replace it with your real one */
int listdir(const char *path, char *set[])
{
set[0] = "0.txt";
set[1] = "1.txt";
set[2] = "2.txt";
set[3] = "3.txt";
set[4] = "4.txt";
return 5;
}
int main(int argc, char *argv[]) {
int files;
char *path = argv[1];
char **set = malloc(1000 * sizeof(char *));
files = listdir(path, set);
for (int i = 0; i < files; i++) {
struct stat st;
stat(set[i], &st);
printf("FileSize of %s is %zu\n", set[i], st.st_size);
}
free(set);
}
(I am guessing you are on some Posix system, hopefully Linux)
Probably your listdir is wrong. FWIW, if you use readdir(3) in it, you need to concatenate the directory name and the file name (with a / in between, perhaps using snprintf(3) or asprintf(3) for that purpose).
But surely,
FILE* file = fopen(set[i++],"rb"); ////WRONG
is doubly wrong. First, you are incrementing i++ twice (and here it is too early). Then, you should read fopen(3) and handle the failure case, at least with:
char* curpath = set[i];
assert (curpath != NULL);
FILE* file = fopen(curpath, "rb");
if (!file) { perror(curpath); exit(EXIT_FAILURE); };
testing the result of fopen against failure is mandatory. Notice that I am passing the same curpath to perror(3) on failure.
You may also want to check that your current working directory is what you expect. Use getcwd(2) for that.
Use also strace(1) (on Linux) to understand what system calls are done by your program.

system call not parsing output to a file in c, file created but no data inside the file

I have written a small code which takes input from the user and passes it to the system ("command>/tmp/j"), here the file j is being created but there is no information inside it related to the input present in the command.
For eg: If I have given ps -f as input to the string command, the system() should execute it and store it inside file /tmp/j, but here the file j is being created but there is no output data inside it.
I have seen many questions, but all those are using popen() and the input is predefined in them.
#include<stdio.h>
#include<sys/syscall.h>
main()
{
enum msgtype {PROCESS_LIST_REQUEST=1, PROCESS_LIST_RESPONSE, DIRECTORY_LIST_REQUEST, DIRECTORY_LIST_RESPONSE, ERROR_REQUEST};
struct head
{
int version;
int msg_length;
int header_length;
enum msgtype msg_type;
char data;
char *reqtype;
};
struct head *buf;
buf = malloc((sizeof(struct head)));
buf->reqtype=malloc(40);
char req[10];
char *command;
command = malloc((sizeof(char) * 10));
fgets(req, sizeof(req),stdin);
buf->reqtype = req;
printf("%s" , buf->reqtype); //just to make sure correct thing is present
command = buf->reqtype;
printf("%s",command);//just to make sure correct thing is present
system ("command>/tmp/j");
{
FILE *fp;
char c;
fp = fopen("/tmp/j", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else {
do {
c = getc(fp);
putchar(c);
} while (c != EOF);
}
fclose(fp);
}
}
This line
system ("command>/tmp/j");
Tries to run an executable literally called command, and redirects its output to /tmp/j. The redirection happens, thus creating the file /tmp/j, but then command (whatever it may be) produces no output.
Also, this
command = malloc((sizeof(char) * 10));
followed by this
command = buf->reqtype;
causes the memory from the malloc() call to leak.
As somebody else says
system ("command>/tmp/j");
tries to run a program called 'command'. YOu need to do
char buff[256];
snprintf(buff, sizeof(buff), "%s>/tmp/j", command);
system(buff);

Reading a text file line by line and saving to an array (C Language)

Here's my issue:
I'm currently working on a project for university. We're suppose to do a program that receives .pbm and .pgm files as input, and then we're suppose to handle them in some ways. But for now the main thing is to successfully receive them.
Each .pbm and .pgm file's first line is a "magic number". A set of characters like P1, P2 (...) P6.
Our goal is to receive a .pbm file as input, save the first line, dynamically allocate a string so it is just as big as its content (P6\n, for example), so we can then detect the magic number. The same applies to every other line. We basically just want a way to save each line into an array, making them just as big as their content.
Me and my project partner are both beginners: file handling, pointers, dynamic memory and headers are still pretty hard to us. Thank you in advance.
---EDIT--- (Forgot the code, as an user pointed out)
int main(int argc, char const *argv[])
{
readFile(argv[1], "EI_2012-13_ascii.pbm");
return 0;
}
void readFile (const char* input_file, char* filename){
char *line_buffer, *line;
FILE *file_stream = NULL;
if(!check_extension(filename, ".pbm") &&
!check_extension(filename, ".pgm") && !check_extension(filename, ".ppm"))
ERROR(ERR_EXT, "Invalid file extension!\n");
file_stream = fopen(input_file, "r");
if (file_stream == NULL)
ERROR(ERR_EXT, "Couldn't open the file for reading");
line_buffer = malloc(sizeof(2));
fscanf(file_stream, "%s", line_buffer);
//line = strchr(line_buffer, '\n');
printf("%s\n", line_buffer);
printf("%d\n", sizeof(line_buffer));
fclose(file_stream);
}
With this code we were attempting to output a string and its size underneath it. Strangely we keep getting the same output: 4. We needed that the malloc received a proper argument, the size of the line until the '\n'.
You can detect the magic number reading the file line by line using Linux function getline() as shown below,
void readFile (const char* input_file, char* filename){
char *line;
FILE *file_stream = NULL;
ssize_t read; size_t len = 0;
file_stream = fopen(input_file, "r");
if (file_stream == NULL)
ERROR(ERR_EXT, "Couldn't open the file for reading");
while((read = getline(&line, &len, file_stream)) != 1){
printf("%s", line);
printf("length of line: %zu\n", read);
}
if (line)
free(line);
fclose(file_stream);
}

read text file in xcode

i tried to read text file in xcode but this
"EXC_BAD_ACCESS message showed up when i tried to build my program
here is my code
and i put inputA.txt file in the same folder with project file
my friend told me that i should put txt file in debug folder is this why i cannot read txt
file in this code? please help me...
macbook user.
int main (int argc, const char * argv[]) {
FILE* fp;
char mychar;
char arr[50][2] = {0, };
int i = 0;
int j, k;
graphType* G_;
G_ = (graphType*)malloc(sizeof(graphType));
Create(G_);
fp = fopen("inputA.txt", "r");
//fp = fopen("inputB.txt", "r");
//fp = fopen("inputC.txt", "r");
while(1){
for(j = 0 ; j < 2 ; j++){
mychar = fgetc(fp);
if(mychar == EOF)
break;
else if(mychar == ' ')
continue;
arr[i][j] = mychar;
}
i++;
}
Per default your binary will be generated in ProjectDir/build/Mode, with Mode being Debug or Release, and will have that as its working directory. If you want to refer to a file in the project directory, you'd have to use ../../input.txt in that case.
The build locations are configured in the "Build Locations" section in a targets or projects build tab. The working directory can be manually changed in the settings for the executable ("General", "Set the working directory to:") if needed.
If you are having doubts then you can always find out what the working directory is:
#include <unistd.h>
int main() {
char buf[2048];
getcwd(buf, sizeof(buf));
printf("%s", buf);
}
Most likely inputA.txt is not in the same file as the binary. You should make sure the text file is copied to the output directory in your project (whether manually or by hand).
Also, fopen will return NULL if the file couldn't be opened, so you might want to add a check for that.
if (fp == NULL)
{
printf("Could not open file!");
return 1;
}
fopen is probably returning null because your text file isn't in the right place. Don't forget to check for null!

Resources