Open function C "file not found" on Xcode but terminal works - c

I work on Xcode and I have a simple function that opens a file using open in C.
void mfs_workwith() {
char *token, *temp_token;
char *search = ".";
temp_token = (char*)malloc(sizeof(char)*strlen(cc[1]));
strcpy(temp_token, cc[1]);
if ((token = strtok(temp_token, search)) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if ((token = strtok(NULL, " \n\0")) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if (strcmp(token, "mfs") == 0) {
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
if ((file_mfs = open(filename, O_RDWR)) == -1) {
perror("open error");
} else {
printf("open successful \n");
}
}
}
The name of the file is stored in a global array and then copied into local buffers in order to tokenize and check if it has the right format (.mfs).
Then if everything is ok I make a fresh copy of the name of the file and call open with it.
My problem is that when I run my program in terminal it runs fine, prints open successful and then continues. But when I try to run it in Xcode it fails with this error:
No such file or directory
I am giving the input file.mfs which is the name of a file in the same directory.
Am I missing something obvious?

I found the problem thanks to iharob's comment. It seems xcode has a hard time opening relative paths since it uses a different file while running the program. There is a relative discussion here:
Open method opens files with full path only C++
thanks again everyone.

This:
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
is broken, it fails to allocate room for the string's terminator, so it causes buffer overflow and undefined behavior.
Also, you never need to scale by sizeof (char), that's always 1. It should be:
filename = malloc(strlen(cc[1]) + 1);
strpcy(filename, cc[1]);
or, if you have it, just:
filename = strdup(cc[1]);

Related

Reading all files in two directories at the same time

I have a problem with task. I have two path to directories. I can read all files from first path in argv[1] but can't open files from second folder from argv[2]. Quantity of files is equal. The way at the begining to write name of fales in array is failed because their is about a few hundred.I have an example how I try reading files. Need help. Thanks!
#include "stdafx.h"
#include "windows.h"
int main(int argc, char* argv[])
{
FILE *fp = 0;
uchar tmpl1[BUFFER_SIZE] = { 0 };
uchar tmpl2[BUFFER_SIZE] = { 0 };
size_t size;
size_t n;
FILE *Fl = 0;
if (argc != 3 || argv[1] == NULL || argv[2] == NULL)
{
printf("Error", argv[0]);
return -1;
}
char Fn[255];
HANDLE hFind;
WIN32_FIND_DATA ff;
char Fn1[255];
HANDLE hFind1;
WIN32_FIND_DATA ff1;
sprintf_s(Fn, 255, "%s\\*", argv[1]);
sprintf_s(Fn1, 255, "%s\\*", argv[2]);
if ((hFind = FindFirstFile(Fn, &ff)) != INVALID_HANDLE_VALUE)
{
if ((hFind1 = FindFirstFile(Fn1, &ff1)) != INVALID_HANDLE_VALUE)
{
do
{
if (ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
ff1.dwFileAttributes;
sprintf_s(Fn, "%s\\%s", argv[1], ff.cFileName);
sprintf_s(Fn1, "%s\\%s", argv[2], ff1.cFileName);
// here I can't read file's name from second folder
printf(Fn, "%s\\%s", argv[1], ff.cFileName);
printf(Fn1, "%s\\%s", argv[2], ff1.cFileName);
if (fopen_s(&fp, Fn, "rb") != 0)
{
printf("Error reading\nUsage: %s <tmpl1>\n", argv[1]);
return -1;
}
size = _filelength(_fileno(fp));
n = fread(tmpl1, size, 1, fp);
fclose(fp);
fp = 0;
} while (FindNextFile(hFind, &ff));
// also I have a problem how read next file in second directory
FindClose(hFind);
}
}
return 0;
}
I didn't read why you want to scan two directories concurrently.
When I saw "at the same time" in the title I thought "concurrently". Afterwards, I saw the presented code and realized it shall be done rather "interleaved" instead of "concurrently" but that's not essential.
I assume you want to associate the file names in the first directory somehow to the file names in the second directory. This might be comparing the file names, read data from a file of first directory and read other data from an associated file of second directory, or may be something completely different.
However, based on this assumption, you have to consider that:
You should not assume to get file names in any useful order when scanning with FindFirstFile()/FindNextFile(). These functions return the files in its "physical order" i.e. how they are listed internally. (At best, you get . and .. always as first entries but I even wouldn't count on this.)
Considering this, I would recommend the following procedure:
read file names from first directory and store them in an array names1
read file names from second directory and store them in an array names2
sort arrays names1 and names2 with an appropriate criterion (e.g. lexicographically)
process the arrays names1 and names2.
As you see, the "read file names from directory and store them in an array" could be implemented as function and re-used as well as the sorting.
This said, finally, the answer for how to interleave two directory scans:
HANDLE hFind1 = FindFirstFile(Fn1, &ff1);
HANDLE hFind2 = FindFirstFile(Fn2, &ff2);
while (hFind1 != INVALID_HANDLE_VALUE || hFind2 != INVALID_HANDLE_VALUE) {
if (hFind1 != INVALID_HANDLE_VALUE) {
/** #todo process ff1 somehow */
}
if (hFind2 != INVALID_HANDLE_VALUE) {
/** #todo process ff2 somehow */
}
/* iterate: */
if (!FindNextFile(hFind1, &ff1)) {
FindClose(hFind1); hFind1 = INVALID_HANDLE_VALUE;
}
if (!FindNextFile(hFind2, &ff2)) {
FindClose(hFind2); hFind2 = INVALID_HANDLE_VALUE;
}
}
Please, note that I "abuse" the handles hFind1 and hFind2 itself for loop repetition. Thus, I do not need the extra ifs. (I like things like that.)
Btw. this loop iterates until both directories are scanned completely (even if they don't contain the same number of entries).
If you want to iterate instead until at least one directory is scanned completely you may achieve this by simply changing the while condition to:
while (hFind1 != INVALID_HANDLE_VALUE && hFind2 != INVALID_HANDLE_VALUE) {
if the loop shall be terminated as soon as at least one directory scan fails.
At last, a little story out of my own past (where I learnt a useful lesson regarding this):
I just had finished my study (of computer science) and was working at home on a rather fresh installed Windows NT when I started to copy a large directory from a CD drive to harddisk. The estimated time was round-about 1 hour and I thought: 'Hey. It does multi-tasking!' Thus, I started a second File Manager to copy another directory from this CD drive concurrently. When I hit the OK button, the prompt noises of the CD drive alerted me as well as the estimated time which "exploded" to multiple hours. After that, I behaved like to expect: tapped on my forehead and mumbled something like "unshareable resources"... (and, of course, stopped the second copying and went for a coffee instead.)

open() file does not exists when file actually exists

I'm writing a simple HTTP server and I'm getting a file does not exists return value when the file does exist
printf("%s\n", html_path);
if ((fd = open(html_path, "r")) >= 0){ //file found
stat(file_name, &st);
file_size = st.st_size;
printf("%d\n", file_size);
while (read(fd, response, RCVBUFSIZE) > 0){
}
}
else { //file not found
strcpy(response, "404 File not found\n");
send(clntSocket, response, 32, 0);
}
the print statement is to verify the path and it looks like this:
/mounts/u-zon-d2/ugrad/kmwe236/HTML/index.html
note that this path is on a server that we use at our university. it's the path that shows when I command pwd
I have confirmed that the file exists. is there something wrong with my path?
There was an error opening the file, but you don't know that it was because the file was not found because you're didn't check the value of errno.
In the else section, add the following:
else { //file not found
// copy the value of errno since other function calls may change its value
int err = errno;
if (err == ENOENT) {
strcpy(response, "404 File not found\n");
send(clntSocket, response, 32, 0);
} else {
printf("file open failed: error code %d: %s\n", err, strerror(err));
}
}
If the file does not in fact exist you'll handle the error properly. If not, you'll print an error message that tells you what did happen.
You're also calling open incorrectly. The second parameter is an int containing flags. To open a file for reading, use O_RDONLY.
open does not have the 2nd parameter as a string. You using open with the parameters of fopen.
For a webserver fopen, fprintf, fclose is a better choise then more lowlevel open, read, ...
Cheers,
Chris
You need to check where you program is executing as it will try to open the path relative from that location. To check use:
char cwd[1024];
getcwd(cwd, sizeof(cwd));
puts(cwd);
Then you can concatenate your path using:
strncat(cwd, html_path, 100);
You may find that you have to go up one directory or something to then find the file you're looking for.
Also note that if you're debugging your program via gdb it may execute from a different location from your regular build location which may make it harder to spot bugs.

C, trouble with stat()

I have never used stat() before and am not sure what is going wrong.
I have a server program that takes a GET request and parses out the file path. I also have a client program in the same directory that sends the GET request. The server program is taking the GET request and parsing out the file path correctly. The path to the directory where both programs are is: ~/asimes2/hw2/
If I have the client program send: GET /Makefile HTTP/1.0\r\n\r\n
Then the server program receives the same thing. I have two printf()s to confirm I am parsing the file path correctly and to see the full path. It outputs:
File path = '/Makefile'
Full path = '~/asimes2/hw2/Makefile'
NOT FOUND!
Makefile does exist in ~/asimes/hw2. Here is the code:
// Alex: Parse the PATH from the GET request using httpGet
char* filePath, * pathStart = strchr(httpGet, '/');
if (pathStart != NULL) {
// Alex: Increment to the first '/'
httpGet += (int)(pathStart-httpGet);
// Alex: Assuming " HTTP" is not a part of the PATH, this finds the end of the PATH
char* pathEnd = strstr(httpGet, " HTTP");
if (pathEnd != NULL) {
int endLoc = (int)(pathEnd-httpGet);
filePath = (char*)malloc((endLoc+1)*sizeof(char));
strncpy(filePath, httpGet, endLoc);
filePath[endLoc] = '\0';
}
else errorMessageExit("The GET request was not formatted as expected");
}
else errorMessageExit("The GET request was not formatted as expected");
printf("File path = '%s'\n", filePath);
char* fullPath = (char*)malloc((14+strlen(filePath))*sizeof(char));
strcpy(fullPath, "~/asimes2/hw2");
strcat(fullPath, filePath);
printf("Full path = '%s'\n", fullPath);
struct stat fileStat;
if (stat(fullPath, &fileStat) == -1) printf("NOT FOUND!\n");
else printf("HOORAY\n");
My answer only addresses your issue with the file name.
The shell interprets this: ~/asimes2/hw2/Makefile
It's not a valid filename to pass to stat() with the ~
You should be able replace the leading ~ with something link /home/ or wherever the actual home directory is.
Try this:
char* fullPath = malloc((80+strlen(filePath))*sizeof(char));
strcpy(fullPath, "/home/ubuntu/asimes2/hw2");
strcat(fullPath, filePath);
printf("Full path = '%s'\n", fullPath);
You need to glob pathnames, see glob(7). You could perhaps use wordexp(3) to expand the ~, $ etc...
HTTP servers usually have some configurable document root, perhaps /var/www. Then the URL pathname /Makefile is transformed to /var/www/Makefile
You should perhaps use some HTTP server library like libonion
And you should use errno at least for debugging purposes on syscall failure, so code
if (stat(fullPath, &fileStat) == -1)
printf("%s NOT FOUND! %s\n", fullPath, strerror(errno));
Perhaps chroot(2) might interest you. And read Advanced Linux Programming!

Reading in .txt file with different extension in C

At the moment my program has no problem reading in a .txt file, but my program needs to read in a text file with a different file extension (.emu is the requirement). When simply changing the same file's extension to .emu, the variable 'file' is NULL and therefore the file isn't opened, can anyone help?
Had a little look around and haven't been able to find a solution so any help is much appreciated
here's the source code:
void handleArgs (const char *filename, int trace, int before, int after) {
FILE *file = fopen(filename, "r");
char *address = malloc(MAX_ADD_LENGTH * sizeof(char));
char *instruction = malloc(MAX_INS_LENGTH * sizeof(char));
long int addressDecoded;
if (file == NULL || file == 0) {
fprintf(stderr, "Error: Could not open file");
}
else {
if (ferror(file) == 0) {
while (fscanf(file, "%s %s", address, instruction) != EOF) {
if (strlen(address) == 8 && strlen(instruction) == 8) {
addressDecoded = strtol(address, NULL, 16);
printf("%ld\n", addressDecoded);
//instruction = decodeInstruction(instruction);
}
else {
fprintf(stderr, "Error: particular line is of wrong length");
}
}
}
}
fclose(file);
}
argument 'filename' when executing is simply '/foopath/test.emu'
There's nothing special to C about the file extension. Reread your code for simple errors like changing the filename in one place, but not the other. If you're passing in the filename, pass the whole name, not just the part to the left of the period.
Files are data, and have names. What comes before the dot in a name, is just as much a part of it as what comes after -- the extensions were created just as hints as to what the file contains, but they are NOT required to be strictly related to the file's contents.
The file may not exist, or your priviledges may not be enough to open it. Or maybe there's some other kind of error. How can you diagnose this?
When you use a system call and it doesn't behave the way you want to, there's a variable called errno in errno.h (#include <errno.h>) that will contain a number representing the status of the last call. There's a huge list of symbolic constants to put names to these values, you can google it up.
For example, if you try to open a file and the returned pointer is useless, you might want to check errno to see if the file existed, or if you're exceding system restrictions for opened files, etc.

Issue on file existence in C

Here is my code which checks if the file exists :
#include<stdio.h>
#include<zlib.h>
#include<unistd.h>
#include<string.h>
int main(int argc, char *argv[])
{
char *path=NULL;
FILE *file = NULL;
char *fileSeparator = "/";
size_t size=100;
int index ;
printf("\nArgument count is = %d", argc);
if (argc <= 1)
{
printf("\nUsage: ./output filename1 filename2 ...");
printf("\n The program will display human readable information about the PNG file provided");
}
else if (argc > 1)
{
for (index = 1; index < argc;index++)
{
path = getcwd(path, size);
strcat(path, fileSeparator);
printf("\n File name entered is = %s", argv[index]);
strcat(path,argv[index]);
printf("\n The complete path of the file name is = %s", path);
if (access(path, F_OK) != -1)
{
printf("File does exist");
}
else
{
printf("File does not exist");
}
path=NULL;
}
}
return 0;
}
On running the command ./output test.txt test2.txt
The output is:
$ ./output test.txt test2.txt
Argument count is = 3
File name entered is = test.txt
The complete path of the file name is = /home/welcomeuser/test.txt
File does not exist
File name entered is = test2.txt
The complete path of the file name is = /home/welcomeuser/test2.txt
File does not exist
Now test.txt does exist on the system:
$ ls
assignment.c output.exe output.exe.stackdump test.txt
and yet test.txt is shown as a file not existing.
Please help me understand the issue here. Also, please feel free to post any suggestions to improve the code/avoid a bug.
Regards,
darkie
Just because the call to access() fails does not mean that the file does not exist. The call could fail for other reasons.
Use printf("error:%s\n", strerror(errno)); to print out the text of the error message.
Also you are still incorrectly appending to "path" received from getcwd as you were in your previous question. Even though it is not crashing, it is still not correct and could cause you problems... possibly even the problem you have now.
getcwd() allocates a buffer for your path, but that buffer is only sized to fit the path. you are appending to that buffer, going past the end. That's bad, you can't do that. It will cause problems, and occasionally crashes. you need to pause and understand how this getcwd function works and how to properly use it.
I strongly suggest allocating enough room to store the path via malloc() and fpathconf() (hint, PATH_MAX).
A non-standard way of allocating and assembling it would be asprintf().
Just be sure to free the resulting path when its no longer needed, and check every call that could possibly fail due to user typos for failure.
If using malloc(), always check for failure (the result being NULL).
Good luck with your assignment :)

Resources