0

I am trying to build a path in C which will point to:

%appdata%/some/file.xx

I am trying to do it using these functions as it follows:

char *getenv( 
   const char *varname 
);
wchar_t *_wgetenv( 
   const wchar_t *varname 
);
char *appData = getenv("AppData"); //so far so good

char *myURL;
myURL = (char *)malloc(sizeof(char));

//when I comment the next two lines, everything is ok, but if I uncomment them I get tons of errors
strcpy(myURL, appData);
strcat(myURL, "/some/path.xx");

FILE *myFile = fopen(myURL, "r");

Any hints on how can I have this working ? I have been struggling with this for some days and I couldn't fix it yet.

I am also aware of another possibilities like: SHGetSpecialFolderPath, SHGetFolderPath() and SHGetKnownFolderIDList() but I wasn't able to use them as I am not so advanced.

Cajuu'
  • 1,154
  • 2
  • 19
  • 50

1 Answers1

4

sizeof(char) is always 1.

So

myURL = (char *)malloc(sizeof(char));

allocates only one byte. That is not enough. You should always test malloc against failure, and you should not cast the result of malloc when coding in C (and in C++, better use std::string or at least operator new).

Of course you need to #include all of <stdlib.h> (for malloc & getenv & exit ...) and <stdio.h> (for fopen & perror ...) & <string.h> (for strlen, strcat, strcpy ....)

And you are not sure that getenv("AppData") succeeds by returning a non NULL string.

So you should try:

 char *appdata = getenv("AppData");
 if (!appdata) 
    appdata="/some/default/path";
 size_t appdatalen = strlen(appdata);
 char* restpath= "/some/path.xx";
 size_t restpathlen = strlen(restpath);
 size_t fullpathlen = // 1 additional byte for terminating \0
     appdatalen+restpathlen+1;
 char *fullpath =  malloc(fullpathlen);
 if (!fullpath) { perror("malloc"); exit(EXIT_FAILURE); };
 strcpy (fullpath, appdata);
 strcat (fullpath, restpath);
 FILE *myFile = fopen(fullpath, "r");

I'm using fullpath, not myURL, since fopen cannot deal with URLs (like http://some.host.org/some/path). If you need to deal with genuine URLs you need some HTTP client library like libcurl.

You might instead of a heap allocated fullpath use a local buffer of PATH_MAX characters. See also this thread.

Don't forget to compile with all warnings & debug info (e.g. with gcc -Wall -Wextra -g if using GCC, and learn how to use the debugger (e.g. gdb). Additional compiler options like -fsanitize=address might be helpful. Addition debugging tools like valgrind also are helpful. Some of these tools might not be available on some operating systems (for beginners in C, I recommend using Linux).

Read about undefined behavior & buffer overflow.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Then, how should I correctly use the `malloc()` in this case ? Should I use `myURL = (char *)malloc(256*sizeof(char));` ? I've tried this way and I get exactly the same thing. – Cajuu' Jul 13 '15 at 05:35
  • @Alexander You should use `myURL = malloc(256);` to allocate a string with maximum length of 255 since `sizeof(char)` is 1 and you should not cast the return value from `malloc`. But Basile's answer is better since it actually calculates how many bytes you need to allocate. – Sami Kuhmonen Jul 13 '15 at 05:41
  • I got it. I will try your way @Basile. `URL` was just a typo. There should've been `path` instead. – Cajuu' Jul 13 '15 at 05:42
  • @BasileStarynkevitch do you have any idea why VS2012 is underlining the `malloc` word from `char *fullpath = malloc(fullpathlen);` and it says that: `a value of type void* cannot be used to initialize an entity of type char*` ? – Cajuu' Jul 13 '15 at 05:58
  • @alexander, he most likely just forgot the `char*` in front of the malloc. Do add it like you used it in your code originally – holroy Jul 13 '15 at 06:31