MAGIC(3)
π
MAGIC(3) β the magic file interface, bestie edition
okay so this is from the Library Functions Manual and honestly? it's giving "ancient Unix lore but make it fetch". sit down, grab a strawberry drink π, we're learning the magic file interface β no cap, it's iconic.
β¨ NAME β¨
magic β the magic file interface. that's it, that's the vibe. π
π¦ SYNOPSIS π¦
#include <magic.h>
Magic_t
{
unsigned long flags;
};
Magic_t* magicopen(unsigned long flags);
void magicclose(Magic_t* magic);
int magicload(Magic_t* magic, const char* path, unsigned long flags);
int magiclist(Magic_t* magic, Sfio_t* sp);
char* magictype(Magic_t* magic, const char* path, struct stat* st);
literally copy this exactly, i'm begging π«Ά
πΈ DESCRIPTION πΈ
these routines are your main character entrance into the file(1) command's magic file. so slay. magicopen hands you back a magic session handle, and likeβ¦ you pass that handle to every other routine in here. it's the group chat invite link, basically. π
flags can be any of these:
MAGIC_MIMEβ return the MIME type string instead of the magic file description. you want the vibe label, not the essay.MAGIC_PHYSICALβ don't follow symbolic links. we're staying in our lane, no chasing.MAGIC_STATβ the stat structurestyou pass tomagictypewill contain validstat(2) information. seemagictypebelow, i got you.MAGIC_VERBOSEβ turns on verbose error messages. so when it goes wrong you get the full story π
magicclose closes the magic session. bye bestie, thanks for coming π
magicload loads the magic file named by path into the magic session. flags are the same as with magicopen. and here's the tea β more than one magic file can be loaded into a session, and the files are searched in load order. so order matters, periodt. if path is 0 then the default magic file gets loaded.
magiclist lists the magic file contents on the sfio(3) stream sp. it's the debugging magic entries tool, aka the "what is actually in here" button π
magictype returns the type string for path with optional stat(2) information st. here's the whole flowchart, stay with me:
- if
st == 0thenmagictypecallsstaton a private stat buffer. - else if
magicopenwas called with theMAGIC_STATflag thenstis assumed to contain valid stat information. - otherwise
magictypecallsstatonst.
magictype always returns a non-null string. always. if errors are encountered on path then the return value will contain information on those errors, e.g. cannot stat. so even the failure is informative, we love a communicative king π
π§ FORMAT π§
the magic file format is a backwards compatible extension of an ancient System V file implementation. yes, ancient. we respect the elders. π
but with the extended format you can write a single magic file that works on all platforms, which is highkey a serve. most of the net magic files floating around work with magic, but they usually double up on le and be entries that are automatically handled by magic. so like, redundant. do less. π
a magic file entry describes a procedure for determining a single file type based on the file pathname, stat(2) information, and the file data.
an entry is a sequence of lines, each line being a record of space separated fields. the general record format is:
[op]offset type [mask]expression description [mimetype]
# in the first column introduces a comment. the first record in an entry contains no op; the remaining records for an entry contain an op.
integer constants are as in C: 0x* or 0X* for hexadecimal, 0* for octal and decimal otherwise. cute and classic.
the op field
the op field may be one of:
+β the previous records must match but the current record is optional.>is an old-style synonym for+. (legacy icon behavior, we stan both)&β the previous and current records must match.{β starts a nesting block that is terminated by}. a nesting block pushes a new context for the+and&ops. the{and}records have no other fields.id{β a function declaration and call for the single character identifierid. the function return is a nesting block end record}. function may be redefined. functions have no arguments or return value.id()β a call to the functionid.
the offset field
the offset field is either the offset into the data upon which the current entry operates, or a file metadata identifier.
offsets are either integer constants or offset expressions. an offset expression is contained in (...) and is a combination of integral arithmetic operators and the @ indirection operator. indirections take the form @integer where integer is the data offset for the indirection value.
the size of the indirection value is taken either from one of the suffixes B(byte,1char), H(short,2chars), L(long,4chars), pr Q(quead,8chars), or from the type field. (yes, that's literally how it's written, i don't make the rules π« )
valid file metadata identifiers are:
atimeβ the string representation ofstat.st_atime.blocksβstat.st_blocks.ctimeβ the string representation ofstat.st_ctime.fstypeβ the string representation ofstat.st_fstype.gidβ the string representation ofstat.st_gid.Theβ thestat.st_modefile mode bits inmodecanon(3)canonical representation (i.e., the good old octal values).mtimeβ the string representation ofstat.st_mtime.nlinkβstat.st_nlink.sizeβstat.st_size.nameβ the file path name sans directory.uidβ the string representation ofstat.st_uid.
the type field
the type field specifies the type of the data at offset.
integral types may be prefixed by le or be for specifying exact little-endian or big-endian representation, but the internal algorithm automatically loops through the standard representations to find integral matches, so representation prefixes are rarely used. however β this looping may cause some magic entry conflicts; use the le or be prefix in these cases. only one representation is used for all the records in an entry. noted, bestie. π
valid types are:
byteβ a 1 byte integer.shortβ a 2 byte integer.longβ a 4 byte integer.quadβ an 8 byte integer. tests on this type may fail is the local compiler does not support an 8 byte integral type and the corresponding value overflows 4 bytes.dateβ the data at offset is interpreted as a 4 byte seconds-since-the-epoch date and converted to a string.editβ the expression field is aned(1)style substitution expressiondel old del new del[flags]where the substituted value is made available to the description field%sformat. in addition to the flags supported byed(3)arelthat converts the substituted value to lower case anduthat converts the substituted value to upper case. if old does not match the string data at offset then the entry record fails. πmatchβ expression field is astrmatch(3)pattern that is matched against the string data at offset.stringβ the expression field is a string that is compared with the string data at offset.
the optional mask field
the optional mask field takes the form &number where number is anded with the integral value at offset before the expression is applied.
the expression field
the contents of the expression field depends on the type. string type expressions are described in the type field entries above. * means any value and applies to all types.
integral type expressions take the form [operator] operand where operand is compared with the data value at offset using operator. operator may be one of <, <=, ==, >= or >. operator defaults to == if omitted.
operand may be an integral constant or one of the following builtin function calls:
magic()β a recursive call to the magic algorithm starting with the data at offset. it's giving recursion, it's giving main character energy π₯loop(function,offset,increment)β call function starting at offset and increment offset by increment after each iteration. iteration continues until the description text does not change.
the description field
the description field is the most important because it is this field that is presented to the outside world. π when constructing description fields one must be very careful to follow the style layed out in the magic file, lest yet another layer of inconsistency creep into the system. (the drama of it all π)
the description for each matching record in an entry are concatenated to form the complete magic type. if the previous matching description in the current entry does not end with space and the current description is not empty and does not start with comma, dot or backspace then a space is placed between the descriptions (most optional descriptions start with comma).
the data value at offset can be referenced in the description using %s for the string types and %ld or %lu for the integral types. format specifiers, we love to see them β¨
the mimetype field
the mimetype field specifies the MIME type, usually in the form a/b.
π FILES π
../lib/file/magic located on $PATH
π EXAMPLES π
okay these are literally the best part, look at these little guys:
0 long 0x020c0108 hp s200 executable, pure
o{
+36 long >0 , not stripped
+4 short >0 , version %ld
}
0 long 0x020c0107 hp s200 executable
o()
0 long 0x020c010b hp s200 executable, demand-load
o()
the function o(), shared by 3 entries, determines if the executable is stripped and also extracts the version number. shared function, no notes, obsessed π«Ά
0 long 0407 bsd 386 executable
&mode long &0111!=0
+16 long >0 , not stripped
this entry requires that the file also has execute permission. permission check = vibe check β
π¦ SEE ALSO π¦
file(1), mime(4), tw(1), modecanon(3)
and that's the whole page, bestie!! π it's the MAGIC(3) page from the Library Functions Manual β yeah, that's the source right there, no date on this one so don't come for me β go forth and read your magic files with confidence. periodt. π
β¨π
π¦ where this page comes from
- opensuse-leap 16.0: ksh-devel 93vu-bp160.1.33 Β· CPL-1.0
- opensuse-leap 16.0: ksh-devel 93vu-bp160.1.33 Β· CPL-1.0
- opensuse-leap 16.0: ksh-devel 93vu-bp160.1.33 Β· CPL-1.0
- opensuse-leap 16.0: ksh-devel 93vu-bp160.1.33 Β· CPL-1.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms