views:

333

answers:

3

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.

A: 

I don't know why you think the above "obviously" doesn't work. See How to mix C and C++ in the C++ FAQ for details.

Looks like magic.h has proper extern "C" { } enclosures. So, compiling your code with g++ should work nicely. You can #include <magic.h> in your .cpp file, and use all the libmagic functions.

  • Is there a particular error you're getting?
  • I have not checked your use of the libmagic functions.
  • You need to link with libmagic. Your g++ command needs -lmagic.
  • Since magic.h is most likely in a standard place, you should use #include <magic.h>.

Tell us what your error is for more specific help.

Alok
+1  A: 

__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.

tommieb75
He might be testing things out, so he decided to find the mime-type of the source file itself.
Alok
You mean `-L/usr/lib -lmagic` obviously.
Alok
@Alok: Damn...another fine mistake.... Thanks for pointing this out.. :(
tommieb75
A: 

Where is magic.h in the filesystem? Is the preprocessor finding it? If not, use -I<path>.

dmckee