Opening multiple directories in C - c

I am trying to make a program that creates a directory in which multiple directories are created, then in each directory I am creating a file. I cannot seem to open those "multiple directories" so that I can put my file there. I tried using name3 as a parameter, and I also tried creating a const char* with name3's value and nothing worked.
error: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. Aborted (core dumped)
here is my code
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
int make_directory(char * name) {
int checker=mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO);
return checker;
}
char** getNames() {
char** names=malloc(10*sizeof(char*));
for(int i=0;i<10;i++) {
if(i==9) {
names[i]=malloc(3*sizeof(char));
names[i][0]='1';
names[i][1]='0';
names[i][2]='\0';
} else {
names[i]=malloc(2*sizeof(char));
names[i][0]=49+i;
names[i][1]='\0';
}
}
return names;
}
int makeTenDirs() {
char **names=getNames();
char *name2;
for(int i=0;i<10;i++) {
name2=NULL;
name2=getcwd(NULL,0);
strncat(name2,"/input/dir",11);
strncat(name2,names[i],1);
int s=make_directory(name2);
}
name2=NULL;
name2=getcwd(NULL,0);
strncat(name2,"/input/dir",11);
strncat(name2,names[0],1);
strncat(name2,"0",2);
int s=make_directory(name2);
}
int main() {
char **names=getNames();
FILE *file;
DIR *dir;
DIR *dir2;
struct dirent *dent;
char * name1="./input";
char *name3;
int proceed=make_directory("./input");
if(proceed==-1) {
printf("Error making the directory\n");
}
makeTenDirs();
dir=opendir("./input");
if(dir!=NULL) {
name3=getcwd(NULL,0);
while((dent=readdir(dir))!=NULL){
if(strcmp(dent->d_name,"..")!=0 && strcmp(dent->d_name,".")!=0) {
name3=getcwd(NULL,0);
strncat(name3,"/input/",8);
strncat(name3,dent->d_name,10);
printf("%s\n",name3);
dir2=opendir(name3);
if(dir2!=NULL) {
printf("alo");
}
}
}
}
closedir(dir);
free(names);
return 0;
}
Any tips on how to open the directories (and maybe put the files in them)?

Below is a working implementation. I cleaned up all the warnings (you had some unused variables, makeTenDirs was not returning a value). Always look at and fix the warnings, use -Wall -Wextra flags to enable them. As I thought before, you were invoking undefined behavior by overwriting the buffers of name2 and name3. The way you were using getcwd it was allocating exactly enough space for name2 and name3. As soon as you strcat to that, you overwrite the buffer, invoking UB. At that point, the program can behave in completely unpredictable ways, including appearing to work. You hope your program crashes when there's UB so you're alerted to the problem. Below, I've used a 2nd operating mode of getcwd that doesn't internally malloc memory and instead keeps everything in automatic memory (on the stack). This relieves you of having to manage memory manually. I've included comments that hopefully explain everything, let me know if you have questions.
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <linux/limits.h> // for PATH_MAX
int make_directory(char * name) {
int checker=mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO);
return checker;
}
char** getNames() {
char** names=malloc(10*sizeof(char*));
for(int i=0;i<10;i++) {
if(i==9) {
names[i]=malloc(3*sizeof(char));
names[i][0]='1';
names[i][1]='0';
names[i][2]='\0';
} else {
names[i]=malloc(2*sizeof(char));
names[i][0]='1'+i;
names[i][1]='\0';
}
}
return names;
}
int makeTenDirs(char** names) {
// This is where your problems began. As I suggested before and confirmed
// when I actually ran the code, `getcwd(NULL, 0)` returns a pointer to
// dynamically allocated memory that's just big enough to hold the path.
// As soon as you strcat to that, you overflow the buffer causing
// undefined behavior. It crashed for me 2nd time through the loop, not
// immediately when the UB occurred. Your results could be entirely different,
// that is the essence of UB. To fix it, I will declare an automatic array
// of PATH_MAX large (4096 I believe). That should make this fixed size array
// able to handle any path on your _linux_ box (this code will not be portable
// to windows). Alternatively, you could do what you did before, just be sure
// to realloc the name2 memory _before_ strcat'ing so there's enough room for
// "/input/dir"
char name2[PATH_MAX];
// only acceptable place for one character variable names are loop index
// variables, and you'll even get some argument on that. Give your variables
// descriptive names (although, I'd probably just make this function void, not
// much utility in the return value here, which you didn't even return!)
int directoryMade = 0;
for(int i=0;i<10;i++) {
// This returns NULL if the `sizeof name` (==PATH_MAX == 4096) is too
// small to hold the path. That shouldn't be the case since no paths
// on the system should exceed PATH_MAX, but it's always a good idea
// to check for errors, that's what a lot of your C code should be
// doing, so get in the habit. Also, realize your old way created
// a memory leak each time since each call to getcwd would malloc more
// memory, and you overwrite the pointer to the previous block with the
// pointer to the new block. Now nothing is pointing at the previous
// block so you can't free it --> memory leak.
if (getcwd(name2, sizeof name2) == NULL)
{
perror("Path exceeded buffer length");
exit(-1);
}
// should be plenty of space to strcat now
strncat(name2,"/input/dir",11);
strncat(name2,names[i],1);
// not much utility b/c it keeps getting overwritten. You could check it each time
// and return if there's an error
directoryMade=make_directory(name2);
}
if (getcwd(name2, sizeof name2) == NULL)
{
perror("Path exceeded buffer length");
exit(-1);
}
strncat(name2,"/input/dir",11);
strncat(name2,names[0],1);
strncat(name2,"0",2);
directoryMade=make_directory(name2);
return directoryMade;
}
int main() {
char **names=getNames();
DIR *dir;
DIR *dir2;
struct dirent *dent;
int proceed=make_directory("./input");
if(proceed==-1) {
// you print an error here, but continue on anyway
// as if there was no error
printf("Error making the directory\n");
}
makeTenDirs(names); // you already fetched names, use them!
dir=opendir("./input");
if(dir!=NULL) {
// same problem here. name3 holds _exactly_ how much space it
// needs when you allow getcwd to malloc memory for it. As before,
// you can make name3 an array in automatic storage, or realloc it
// before strcat'ing
char name3[PATH_MAX];
// check for NULL return here too. Not showing it because I'm getting lazy
getcwd(name3, sizeof name3);
while((dent=readdir(dir))!=NULL){
if(strcmp(dent->d_name,"..")!=0 && strcmp(dent->d_name,".")!=0) {
// check for NULL return
getcwd(name3, sizeof name3);
strncat(name3,"/input/",8);
strncat(name3,dent->d_name,10);
printf("%s\n",name3);
dir2=opendir(name3);
if(dir2!=NULL) {
// printf is line-buffered, so this won't print right away unless
// you put a newline on it (or fflush(stdout);)
printf("alo\n");
// close this dir too?
closedir(dir2);
}
}
}
}
closedir(dir);
// this is NOT a complete free. You have a double pointer. You need to loop and
// free each of names[0], names[1], .. names[9], _then_ free(names). I'll leave
// that as an exercise. In general, you should have a matching number of malloc's
// and free's.
free(names);
return 0;
}

Related

How am I supposed to successfully achieve buffer overflow?

I am currently tackling on an assignment, where I need to upload exploit.c and target.c onto a ubuntu server, and successfully achieve a buffer overflow attack with exploit onto target. I was provided a shellcode. Now, target.c is not to be altered, just exploit.c. I had to use GDB on exploit.c to force an external breakpoint on foo() from target.c, to figure out the return addresses using info frame.
I was provided with the working shellcode, and minimal instructions.
I am pretty sure I was able to successfully pull the return addresses, but my issue is that I cannot figure out what code to put into exploit.c to have it successfully perform a buffer overflow attack. I was also instructed that one of the return addresses must be input into the exploit code for it to function properly.
I understand that the exploit is trying to call back to the return address, to then push itself into the buffer, so I can obtain access to the shell.
Here is exploit.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "shellcode.h"
// replace this define environment to have the correct path of your own target code
#define TARGET "/*******************"
int main(void)
{
char *args[3];
char *env[2];
char *tmp = NULL;
// Creating an input buffer that can cause buffer overflow in strcpy function in the target.c executable code
int buffSize = 1000;
char buff[buffSize];
// Intialize buffer elements to 0x01
int i;
for (i=0; i < buffSize; i++) buff[i] = 0x01;
// write your code below to fill the 22 bytes shellcode into the buff variable, and
// at the correct location overwrite the return address correctly in order to achieve stack overflow
// Your own code starts here:
strcpy (buff[buffSize-22], shellcode);
// Your code ends here.
// prepare command line input to execute target code
args[0] = TARGET; // you must have already compiled and generated the target executable code first
args[1] = buff; // the first input parameter to the target code (artfully crafted buffer overflow string)
args[2] = NULL;
env[0] = "FOO=bar";
env[1] = NULL;
if (0 > execve(TARGET, args, env))
fprintf(stderr, "execve failed.\n");
return 0;
}
Here is the target.c code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int foo(char* arg)
{
char localBuf[240];
short len = 240;
float var1=2.4;
int *ptr = NULL;
strcpy(localBuf, arg);
printf("foo() finishes normally.\n");
return 0;
}
int kbhit(void)
{
struct timeval tv;
fd_set read_fd;
tv.tv_sec=0; tv.tv_usec=0;
FD_ZERO(&read_fd); FD_SET(0,&read_fd);
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
return 0;
if(FD_ISSET(0,&read_fd))
return 1;
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "target: argc != 2\n");
exit(EXIT_FAILURE);
}
printf("Press any key to call foo function...\n");
while(!kbhit())
;
foo(argv[1]);
return 0;
}
I compiled both target and exploit. Then I ran GDB on exploit, and formed a breakpoint using "break target.c:10". Using Info Frame I was able to obtain the return addresses.
I used strcpy, because it is essentially the only line of code we were taught for this section involving overflow attacks, even though it clearly states in the document "Fill the shell executable code (in the string array shellcode[]) byte-by-
byte into the buff for your modified return address to execute, do not
use strcpy() because shellcode[] is not an ASCII string (and not
copying NULL byte, too)."
Exploit compiles fine, and it runs fine, but it does not give me access to a shell. I was instructed that I would know if it worked, if I was presented with two dollar signs ($$) instead of one ($).
I am a network engineer, and I am not entirely savvy with C, or attacking vulnerabilities in programs, any help would be appreciated. The entire lesson revolves around "stack overflow", but this assignment is called "buffer overflow attack".

Consistently Getting Null Value in C String using getcwd

I am trying to make a simple program that just writes your working directory to a file, and I cannot, for the life of me, figure out what I am doing wrong. No matter what I do, my buffer is storing null after my call to getcwd(). I suspect it may have to do with permissions, but allegedly, linux now did some wizardry to ensure that getcwd almost never has access problems (keyword, "almost"). Can anyone test it on their machines? Or is there an obvious bug I am missing?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("Error is with fopen if stops here\n");
FILE* out_file = fopen("dir_loc.sh","w+");
char* loc = malloc(sizeof(char)*10000);
size_t size = sizeof(loc);
printf("Error is with cwd if stops here\n");
loc = getcwd(loc,size);
printf("%s",loc);
fprintf(out_file,"cd %s",loc);
printf("Error is with fclose if stops here\n");
free(loc);
fclose(out_file);
return 0;
}
compiled with gcc main.c (the file is named "main.c")
EDIT: As was mentioned by different posters, sizeof(loc) was taking the size of a char pointer, and not the size of the amount of space allocated to that pointer. Changed it to malloc(sizeof(char)*1000) and it all works gravy.
Your problem is here:
size_t size = sizeof(loc);
You're getting the size of a char pointer, not the allocated memory for your char.
Change it to:
size_t size = sizeof(char) * 10000;
or even to
size_t size = 10000;
since sizeof(char) is guaranteed to be 1.
And since you're using size in your subsequent call to getcwd, you're obviously gonna have too little space to store most paths, so your result is unsurprising
If you don't want to go about changing multiple different numbers in the code every time you make a change, you can use #DEFINE text replacement to solve that.
Like this:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define LOC_ARRAY_SIZE 10000 // Here you define the array size
int main(int argc, char *argv[])
{
printf("Error is with fopen if stops here\n");
FILE* out_file = fopen("dir_loc.sh","w+");
char* loc = malloc(sizeof(char)*LOC_ARRAY_SIZE); // sizeof(char) could be omitted
size_t size = sizeof(char)*LOC_ARRAY_SIZE;
printf("Error is with cwd if stops here\n");
loc = getcwd(loc,size);
printf("%s",loc);
fprintf(out_file,"cd %s",loc);
printf("Error is with fclose if stops here\n");
free(loc);
fclose(out_file);
return 0;
}

Why can't my program save a large amount (>2GB) to a file?

I am having trouble trying to figure out why my program cannot save more than 2GB of data to a file. I cannot tell if this is a programming or environment (OS) problem. Here is my source code:
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <math.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*-------------------------------------*/
//for file mapping in Linux
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/mman.h>
#include<sys/types.h>
/*-------------------------------------*/
#define PERMS 0600
#define NEW(type) (type *) malloc(sizeof(type))
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
void write_result(char *filename, char *data, long long length){
int fd, fq;
fd = open(filename, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
if (fd < 0) {
perror(filename);
return -1;
}
if (ftruncate(fd, length) < 0)
{
printf("[%d]-ftruncate64 error: %s/n", errno, strerror(errno));
close(fd);
return 0;
}
fq = write (fd, data,length);
close(fd);
return;
}
main()
{
long long offset = 3000000000; // 3GB
char * ttt;
ttt = (char *)malloc(sizeof(char) *offset);
printf("length->%lld\n",strlen(ttt)); // length=0
memset (ttt,1,offset);
printf("length->%lld\n",strlen(ttt)); // length=3GB
write_result("test.big",ttt,offset);
return 1;
}
According to my test, the program can generate a file large than 2GB and can allocate such large memory as well.
The weird thing happened when I tried to write data into the file. I checked the file and it is empty, which is supposed to be filled with 1.
Can any one be kind and help me with this?
You need to read a little more about C strings and what malloc and calloc do.
In your original main ttt pointed to whatever garbage was in memory when malloc was called. This means a nul terminator (the end marker of a C String, which is binary 0) could be anywhere in the garbage returned by malloc.
Also, since malloc does not touch every byte of the allocated memory (and you're asking for a lot) you could get sparse memory which means the memory is not actually physically available until it is read or written.
calloc allocates and fills the allocated memory with 0. It is a little more prone to fail because of this (it touches every byte allocated, so if the OS left the allocation sparse it will not be sparse after calloc fills it.)
Here's your code with fixes for the above issues.
You should also always check the return value from write and react accordingly. I'll leave that to you...
main()
{
long long offset = 3000000000; // 3GB
char * ttt;
//ttt = (char *)malloc(sizeof(char) *offset);
ttt = (char *)calloc( sizeof( char ), offset ); // instead of malloc( ... )
if( !ttt )
{
puts( "calloc failed, bye bye now!" );
exit( 87 );
}
printf("length->%lld\n",strlen(ttt)); // length=0 (This now works as expected if calloc does not fail)
memset( ttt, 1, offset );
ttt[offset - 1] = 0; // Now it's nul terminated and the printf below will work
printf("length->%lld\n",strlen(ttt)); // length=3GB
write_result("test.big",ttt,offset);
return 1;
}
Note to Linux gurus... I know sparse may not be the correct term. Please correct me if I'm wrong as it's been a while since I've been buried in Linux minutiae. :)
Looks like you're hitting the internal file system's limitation for the iDevice: ios - Enterprise app with more than resource files of size 2GB
2Gb+ files are simply not possible. If you need to store such amount of data you should consider using some other tools or write the file chunk manager.
I'm going to go out on a limb here and say that your problem may lay in memset().
The best thing to do here is, I think, after memset() ing it,
for (unsigned long i = 0; i < 3000000000; i++) {
if (ttt[i] != 1) { printf("error in data at location %d", i); break; }
}
Once you've validated that the data you're trying to write is correct, then you should look into writing a smaller file such as 1GB and see if you have the same problems. Eliminate each and every possible variable and you will find the answer.

Having issues with counting the number of bytes in use by files in a folder. Getting a segfault error

I am currently trying to count the number of bytes consumed by files in a certain directory. It recursively goes through all the folders on the current directory and counts the bytes of the files.
When I recursively call the function rec_bytes, I print off "Go in"... but when it returns the value... It segfaults.
I labeled the problematic line in the code below.
I think the problem has to do with open/closing directories.
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
int rec_Bytes(char path[])
{
int bytesSum = 0;
printf("PathX %s\n", path);
DIR *mydir = opendir(path); // Look in current directory
struct dirent *entry = NULL;
while((entry = readdir(mydir))) /* If we get EOF, the expression is 0 and
* the loop stops. */
{
if (!isDir(entry->d_name)) // Check to see if the entry is a directory of a file
{
char tempPath[] = "";
strcat(tempPath, path);
strcat(tempPath,"/");
strcat(tempPath,entry->d_name);
int tempSum = fileSize(tempPath); // Get file size
bytesSum += tempSum; // Add to sum
printf("%s\t%d\n", entry->d_name, tempSum);
}
else // The current entry is a directory
{
if ((strcmp((entry->d_name),"..") != 0) && (strcmp((entry->d_name),".")) != 0)
{
printf("Directory%s\n", entry->d_name);
char tempPath[] = "";
strcat(tempPath, path);
strcat(tempPath,"/");
strcat(tempPath,entry->d_name);
printf("Go in\n");
int tempSum = rec_Bytes(tempPath); <<<<<< Get segmentation fault here.
printf("Come Out%d\n", tempSum);
bytesSum += tempSum;
printf("%s\t%d\n", entry->d_name, tempSum);
}
}
}
closedir(mydir);
printf("XXXX\t%s\t%d\n", path, bytesSum);
return bytesSum;
}
// Thanks to : http://cboard.cprogramming.com/cplusplus-programming/117431-how-tell-if-file-directory.html
int isDir(const char* target)
{
struct stat statbuf;
stat(target, &statbuf);
return S_ISDIR(statbuf.st_mode);
}
Your problem is with lines like this...
char tempPath[] = "";
This will allocate a buffer with one byte, that byte being a null character. There is no room in that buffer for any longer string.
Basically, C does not have dynamically resizable strings. It has null terminated strings that live within fixed-size arrays of characters. This creates an issue when you won't know the length of the string until you've finished building it, of course.
Try something like...
char tempPath[5000] = "";
as a quick fix. Also, look up strncat - it's less likely to segfault. There's a printf variant as well, but I use too much C++ these days.
EDIT
Actually, the segfault is probably due to those strcats and printfs corrupting the stack. The segfault is probably when a function tries to return. The basic issue is the too-small string buffers thing, though.
Whoops!
The real quick fix is...
char tempPath[5000];
tempPath [0] = 0;
Otherwise, it won't always get initialised to an empty string when you expect it to.

fopen in C on solaris

I've been trying to get this code to work for hours! All I need to do is open a file to see if it is real and readable. I'm new to C so I'm sure there is something stupid I'm missing. Here is the code (shorthand, but copied):
#include <stdio.h>
main() {
char fpath[200];
char file = "/test/file.this";
sprintf(fpath,"~cs4352/projects/proj0%s",file);
FILE *fp = fopen(fpath,"r");
if(fp==NULL) {
printf("There is no file on the server");
exit(1);
}
fclose(fp);
//do more stuff
}
I have also verified that the path is correctly specifying a real file that I have read permissions to. Any other ideas?
Edit 1: I do know that the fpath ends up as "~cs4352/projects/proj0/test/file.this"
Edit 2: I have also tried the using the absolute file path. In both cases, I can verify that the paths are properly built via ls.
Edit 3: There errno is 2... I'm currently trying to track what that means in google.
Edit 4: Ok, errno of 2 is "There is no such file or directory". I am getting this when the reference path in fopen is "/home/courses1/cs4352/projects/proj0/index.html" which I verified does exist and I have read rights to it. As for the C code listed below, there may be a few semantic/newbie errors in it, but gcc does not give me any compile time warnings, and the code works exactly as it should except that it says that it keeps spitting errno of 2. In other words, I know that all the strings/char array are working properly, but the only thing that could be an issue is the fopen() call.
Solution: Ok, the access() procedure is what helped me the most (and what i am still using as it is less code, not to mention the more elegant way of doing it). The problem actually came from something that I didn't explain to you all (because I didn't see it until I used access()). To derrive the file, I was splitting strings using strtok() and was only splitting on " \n", but because this is a UNIX system, I needed to add "\r" to it as well. Once I fixed that, everything fell into place, and I'm sure that the fopen() function would work as well, but I have not tested it.
Thank you all for your helpful suggestions, and especially to Paul Beckingham for finding this wonderful solution.
Cheers!
The "~" is expanded by the shell, and is not expanded by fopen.
To test the existence and readability of a file, consider using the POSIX.1 "access" function:
#include <unistd.h>
if (access ("/path/to/file", F_OK | R_OK) == 0)
{
// file exists and is readable
}
First, file needs to be declared as char* or const char*, not simply char as you've written. But this might just be a typo, the compiler should at least give a warning there.
Secondly, use an absolute path (or a path relative to the current directory), not shell syntax with ~. The substitution of ~cs4352 by the respective home directory is usually done by the shell, but you are directly opening the file. So you are trying to open a file in a ~cs4352 subdirectory of your current working directory, which I guess is not what you want.
Other people have probably produced the equivalent (every modern shell, for example), but here's some code that will expand a filename with ~ or ~user notation.
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif
#include <assert.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *relfname(const char *name, char *buffer, size_t bufsiz)
{
assert(name != 0 && buffer != 0 && bufsiz != 0);
if (name[0] != '~')
strncpy(buffer, name, bufsiz);
else
{
const char *copy;
struct passwd *usr = 0;
if (name[1] == '/' || name[1] == '\0')
{
usr = getpwuid(getuid());
copy = &name[1];
}
else
{
char username[PATH_MAX];
copy = strchr(name, '/');
if (copy == 0)
copy = name + strlen(name);
strncpy(username, &name[1], copy - &name[1]);
username[copy - &name[1]] = '\0';
usr = getpwnam(username);
}
if (usr == 0)
return(0);
snprintf(buffer, bufsiz, "%s%s", usr->pw_dir, copy);
}
buffer[bufsiz-1] = '\0';
return buffer;
}
#ifdef TEST
static struct { const char *name; int result; } files[] =
{
{ "/etc/passwd", 1 },
{ "~/.profile", 1 },
{ "~root/.profile", 1 },
{ "~nonexistent/.profile", 0 },
};
#define DIM(x) (sizeof(x)/sizeof(*(x)))
int main(void)
{
int i;
int fail = 0;
for (i = 0; i < DIM(files); i++)
{
char buffer[PATH_MAX];
char *name = relfname(files[i].name, buffer, sizeof(buffer));
if (name == 0 && files[i].result != 0)
{
fail++;
printf("!! FAIL !! %s\n", files[i].name);
}
else if (name != 0 && files[i].result == 0)
{
fail++;
printf("!! FAIL !! %s --> %s (unexpectedly)\n", files[i].name, name);
}
else if (name == 0)
printf("** PASS ** %s (no match)\n", files[i].name);
else
printf("** PASS ** %s -> %s\n", files[i].name, name);
}
return((fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
}
#endif
You could try examining errno for more information on why you're not getting a valid FILE*.
BTW-- in unix the global value errno is set by some library and system calls when they need to return more information than just "it didn't work". It is only guaranteed to be good immediately after the relevant call.
char file = "/test/file.this";
You probably want
char *file = "/test/file.this";
Are you sure you do not mean
~/cs4352/projects/proj0%s"
for your home directory?
To sum up:
Use char *file=/test/file.this";
Don't expect fopen() to do shell substitution on ~ because it won't. Use the full path or use a relative path and make sure the current directory is approrpriate.
error 2 means the file wasn't found. It wasn't found because of item #2 on this list.
For extra credit, using sprintf() like this to write into a buffer that's allocated on the stack is a dangerous habit. Look up and use snprintf(), at the very least.
As someone else here mentioned, using access() would be a better way to do what you're attempting here.

Resources