2

I have a function that takes a url and returns the requested file type but I cant figure out how I can free and return the malloc'd char*.

const char* lookup(const char* path){
    char* rawEnding;
    char* ending = malloc(strlen(path));
    char* mime = malloc(strlen(path));

    rawEnding = strrchr(path, '.');
    if(strcasecmp(rawEnding, ".css") == 0 || strcasecmp(rawEnding, ".html") == 0 || strcasecmp(rawEnding, ".javascript") == 0 || strcasecmp(rawEnding, ".php") == 0)  {
        memmove(ending, rawEnding+1, strlen(rawEnding));
        sprintf(mime, "text/%s", ending);
        free(ending);
        return mime;
    } else if (strcasecmp(rawEnding, ".gif") == 0 || strcasecmp(rawEnding, ".ico") == 0 || strcasecmp(rawEnding, ".png") == 0) {
        memmove(ending, ending+1, strlen(ending));
        sprintf(mime, "image/%s", ending);
        return mime;
    } else if (strcasecmp(rawEnding, ".jpg") == 0 || strcasecmp(rawEnding, ".jpeg") == 0) {
        return "text/jpeg";
    } else {
        return NULL;
    }
}
4
  • 1
    If you want to return mime you have to free it outisde the function. Commented Feb 25, 2016 at 17:26
  • You can't free and return something, because freeing it destroys it. You have to free it from the outside, and because of that you must only return malloc'd memory or NULL. Commented Feb 25, 2016 at 17:31
  • Your code will fail if strrchr returns NULL. You're also not allocating enough memory for your returned string. For example, if path is "x.gif", mime will point to a 5-character buffer but your code will try to put 10 characters including the terminating NUL into those 5 characters. Commented Feb 25, 2016 at 17:45
  • well, I found a much easier way for the code to work but thanks for all of your help! Commented Feb 25, 2016 at 18:00

2 Answers 2

3

It is a bad idea if a function returns a string literal in one case and a pointer to a dynamically allcated memory in the other case. Your function should always return dynamically allocated memory or NULL. So you can freethe memory outside the function.

const char* lookup( const char* path )
{
    char* rawEnding = strrchr( path, '.' );
    if ( rawEnding == NULL )
        return NULL;

    char* ending = rawEnding + 1;
    if ( strcasecmp( ending, "css" ) == 0 ||
         strcasecmp( ending, "html" ) == 0 ||
         strcasecmp( ending, "javascript" ) == 0 ||
         strcasecmp( ending, "php" ) == 0)
    {   
        int len = strlen( "text/" ); 
        char* mime = malloc( len + strlen( ending ) + 1 );
        strcpy( mime, "text/" );
        strcpy( mime + len, ending );
        return mime;
    }
    else if ( strcasecmp( ending, "gif" ) == 0 ||
              strcasecmp( ending, "ico" ) == 0 ||
              strcasecmp( ending, "png" ) == 0)
    {
        int len = strlen( "image/" ); 
        char* mime = malloc( len + strlen( ending ) + 1 );
        strcpy( mime, "image/" );
        strcpy( mime + len, ending );
        return mime;
    }
    else if ( strcasecmp( ending, "jpg" ) == 0 ||
              strcasecmp( ending, "jpeg" ) == 0)
    {
        char* mime = malloc( strlen( "text/jpeg" ) + 1 );
        strcpy( mime, "text/jpeg" );
        return mime;
    }
    return NULL;
}
Sign up to request clarification or add additional context in comments.

Comments

0

I see that if the ending is "jpg" or "jpeg" you convert it to "text/jpeg". Is this what you meant?

You cannot free mime because you want to use it in the calling function. Once you finish using it, you can then free it after first checking that it is not "text.jpg" or NULL.

Alternatively, you can handle it with a single return. Then on the outside, you can free mime as long as it is not NULL.

if(strcasecmp(rawEnding, ".css") == 0 || strcasecmp(rawEnding, ".html") == 0 || strcasecmp(rawEnding, ".javascript") == 0 || strcasecmp(rawEnding, ".php") == 0)  {
    memmove(ending, rawEnding+1, strlen(rawEnding));
    sprintf(mime, "text/%s", ending);
    free(ending);
    // return mime;
} else if (strcasecmp(rawEnding, ".gif") == 0 || strcasecmp(rawEnding, ".ico") == 0 || strcasecmp(rawEnding, ".png") == 0) {
    memmove(ending, ending+1, strlen(ending));
    sprintf(mime, "image/%s", ending);
    // return mime;
} else if (strcasecmp(rawEnding, ".jpg") == 0 || strcasecmp(rawEnding, ".jpeg") == 0) {
    strcpy(mime, "text/jpeg");
} else {
    free(mime);
    mime = NULL;
}
return mime;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.