4

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.

Kache
  • 15,647
  • 12
  • 51
  • 79

3 Answers3

1

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

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
0

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 Singhal
  • 93,253
  • 21
  • 125
  • 158
0

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

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234