Skip to content

Instantly share code, notes, and snippets.

@danieloneill
Created April 9, 2019 03:42
Show Gist options
  • Save danieloneill/492420111421047a6b926c81feb7ced7 to your computer and use it in GitHub Desktop.
Save danieloneill/492420111421047a6b926c81feb7ced7 to your computer and use it in GitHub Desktop.
Parse /etc/mime.types in C, produce a linked-list of all mimetypes and filetype associations.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MIMETYPE_MAX 32768*4
#define MIMETYPE_EXT_MAX_LENGTH 16
#define MIMETYPE_EXT_MAX_COUNT 16
// Linked list of our mimetypes:
struct s_mimetype {
char mimetype[64];
int extensioncount;
char *extensions[MIMETYPE_EXT_MAX_COUNT];
struct s_mimetype *next;
};
struct s_mimetype *mimes = NULL;
void read_mimetypes()
{
FILE *fh = fopen("/etc/mime.types", "r");
if( !fh )
{
fprintf(stderr, "Failed to read /etc/mime.types!\n");
return;
}
// Slurp it into a big ol' buffer. If yours is larger than this, well, make this bigger.
char *mimeraw = (char*)malloc( MIMETYPE_MAX+1 );
size_t rin = fread( mimeraw, 1, MIMETYPE_MAX, fh );
fclose( fh );
mimeraw[ rin ] = '\0';
bool onext = false;
bool comment = false;
struct s_mimetype *mime = (struct s_mimetype *)malloc(sizeof(struct s_mimetype));
memset( mime, 0, sizeof(struct s_mimetype) );
for( int x=0; mime && x < rin; x++ )
{
char ch = mimeraw[x];
if( ch == '#' )
comment = true;
else if( ch == '\r' || ch == '\n' )
{
if( mime->mimetype[0] == '\0' )
{
// it's empty.
onext = false;
comment = false;
continue;
}
// done this entry, move along now.
mime->next = mimes;
mimes = mime;
mime = NULL;
mime = (struct s_mimetype *)malloc(sizeof(struct s_mimetype));
memset( mime, 0, sizeof(struct s_mimetype) );
onext = false;
comment = false;
continue;
}
else if( comment )
continue;
else if( onext )
{
int extnum = mime->extensioncount - 1;
int extlen = strlen( mime->extensions[extnum] );
if( ch == ' ' || ch == '\t' )
{
// next one, or we're in padding still..
if( extlen == 0 )
continue;
if( mime->extensioncount+1 >= MIMETYPE_EXT_MAX_COUNT )
{
// At our limit.
comment = true;
continue;
}
mime->extensioncount++;
extnum++;
mime->extensions[extnum] = (char *)malloc(MIMETYPE_EXT_MAX_LENGTH+1);
mime->extensions[extnum][0] = '\0';
continue;
}
else if( extlen < MIMETYPE_EXT_MAX_LENGTH )
{
mime->extensions[extnum][extlen] = ch;
extlen++;
mime->extensions[extnum][extlen] = '\0';
}
}
else
{
int mlen = strlen( mime->mimetype );
if( mlen >= sizeof(mime->mimetype) )
{
// At capacity!
comment = true;
continue;
}
else if( ch == ' ' || ch == '\t' )
{
onext = true;
int extnum = mime->extensioncount;
mime->extensions[extnum] = (char *)malloc(MIMETYPE_EXT_MAX_LENGTH+1);
mime->extensions[extnum][0] = '\0';
mime->extensioncount++;
continue;
}
mime->mimetype[mlen] = ch;
mlen++;
mime->mimetype[mlen] = '\0';
}
}
if( mime->mimetype[0] != '\0' )
{
mimes->next = mime;
mimes = mime;
}
else
free( mime );
free( mimeraw );
}
void free_mimetypes()
{
struct s_mimetype *mnext;
for( struct s_mimetype *m=mimes; m; )
{
mnext = m->next;
for( int x=0; x < m->extensioncount; x++ )
free( m->extensions[x] );
free( m );
m = mnext;
}
}
void spill_beans()
{
for( struct s_mimetype *m=mimes; m; m=m->next )
{
printf("[%s] =>", m->mimetype);
for( int x=0; x < m->extensioncount; x++ )
printf(" (%s)", m->extensions[x]);
printf("\n");
}
}
int main(int argc, char **argv)
{
read_mimetypes();
spill_beans();
free_mimetypes();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment