Search code examples
c++cincludefile-type

Trying to use/include/compile 3rd party library, libmagic. C/C++ filetype detection


After looking for a way to detect the filetype of a file stream, I found that the Unix file command uses libmagic and I'm trying to make use of the library myself, but I can't get it to work. I've rarely integrated 3rd party code in my own, so that's probably a big part of my problem as well.

Why:

I'm doing this because I have a portable gui image viewing app that will need to detect archive file types (rar, zip, more?) from given filename and then the image file types inside. I'm hoping that I can use libmagic for Windows and Linux (and Mac), so if this isn't the case, stop me now b/c I'll need to find something else.

Attempt:

I found somebody doing something similar, but I can't follow what they're doing, and I've no idea how compile/run anything at all to start messing around.

My first instinct was to do something like:

// fileTypeTest.cpp, placed in file-5.03/src/ (source from link above)
#include <stdio.h>
#include "magic.h"
int main() {
  magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
  magic_load(myt,NULL);
  printf("magic output: '%s'\n",magic_file(myt,__FILE__));
  magic_close(myt);

  return 0;
}

then compile with something like:

$ gcc magic.c -o magic.o
$ g++ fileTypeTest.cpp -o fileTypeTest magic.o

which (obviously?) doesn't work. I don't even know where to start looking, what questions to ask, or if this is the right direction to go to solve my original problem in the first place.


Edit: Now I have

#include    <stdio.h>
#include    <magic.h>

int main(int argc, char* argv[]) {
  if (argc != 2) {
    printf("bad arguments");
    return 0;
  }
  magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
  magic_load(myt,NULL);
  printf("magic output: '%s'\n", magic_file(myt, argv[1]));
  magic_close(myt);

  return 0;
}

compiling with:

$ g++ -L/usr/lib -libmagic fileTypeTest.cpp -o fileTypeTest

works. I had to go to synaptic and install libmagic-dev though. I'll have to test to see if I can just copy /usr/lib/libmagic.a into my source directory when compiling my app on Windows's MingW, but that'll be for another question later, I suppose.


Solution

  • __FILE__ is a reserved pre-processing symbol macro used for debugging/logging purposes. Consider this as an example:

    // This file is called test.c
    char *p = NULL;
    if (!(p = malloc((1 * sizeof(char) + 1)))){
       printf("Error in file: %s @ line %d\n\tMalloc failed\n", __FILE__, __LINE__);
       exit(-1);
    }
    

    If the call to malloc failed you will see the output in the above example like this:

    Error in file: test.c @ line 23
           Malloc failed
    

    Notice how the code picks up the original source code. The above example illustrates the usage of this.

    I think your code should be something like this:

    // fileTypeTest.cpp, placed in file-5.03/src/ (source from link above)
    #include <stdio.h>
    #include "magic.h"
    int main(int argc, char **argv) {
      if (argc > 1){
         magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
         magic_load(myt,NULL);
         printf("magic output: '%s'\n",magic_file(myt,argv[1]));
         magic_close(myt);
      }
      return 0;
    }
    

    The code above checks if there is a parameter that is passed into this program and the parameter would be a filename, i.e. argv[0] points to the executable name (the compiled binary), argv[1] points to the array of chars (a string) indicating the filename in question.

    To compile it:

    g++ -I/usr/include -L/usr/lib/libmagic.so  fileTestType.cpp -o fileTestType
    g++ -L/usr/lib -lmagic fileTestType.cpp -o fileTestType
    

    Edit: Thanks Alok for pointing out the error here...

    If you are not sure where the libmagic reside, look for it in the /usr/local/lib, and /usr/local/include - this depends on your installation.

    See this to find the predefined macros here.

    Hope this helps, Best regards, Tom.