forked from hummypkg/hmt
136 lines
2.3 KiB
C
136 lines
2.3 KiB
C
|
#include <stdio.h>
|
||
|
#include <errno.h>
|
||
|
#include <ctype.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <time.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#include "lint.h"
|
||
|
|
||
|
struct hmt *
|
||
|
open_file(char *filename, int readonly)
|
||
|
{
|
||
|
struct hmt *hmt;
|
||
|
struct stat st;
|
||
|
char *ext;
|
||
|
uint16_t magic;
|
||
|
|
||
|
if (!(hmt = malloc(sizeof(struct hmt))))
|
||
|
{
|
||
|
perror("malloc");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (debug)
|
||
|
printf("Opening file '%s' (readonly=%d)\n", filename, readonly);
|
||
|
|
||
|
strcpy(hmt->fname, filename);
|
||
|
|
||
|
if ((ext = strrchr(hmt->fname, '.')))
|
||
|
{
|
||
|
ext++;
|
||
|
if (debug)
|
||
|
printf(" Extension: '%s'", ext);
|
||
|
|
||
|
if (strcmp(ext, "hmt"))
|
||
|
{
|
||
|
*ext = '\0';
|
||
|
strcat(hmt->fname, "hmt");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
strcat(hmt->fname, ".hmt");
|
||
|
|
||
|
if (debug)
|
||
|
printf(" Actual: '%s'\n", hmt->fname);
|
||
|
|
||
|
if (stat(hmt->fname, &st) == -1)
|
||
|
{
|
||
|
perror(hmt->fname);
|
||
|
free(hmt);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
hmt->binsize = st.st_size;
|
||
|
|
||
|
if (debug)
|
||
|
printf("Opening %s, %lu bytes.\n", hmt->fname,
|
||
|
(unsigned long)hmt->binsize);
|
||
|
|
||
|
hmt->readonly = readonly;
|
||
|
|
||
|
if ((hmt->fd = open(hmt->fname, readonly ? O_RDONLY : O_RDWR, 0)) == -1)
|
||
|
{
|
||
|
perror(hmt->fname);
|
||
|
free(hmt);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
hmt->bin = (uint8_t *)mmap(NULL, hmt->binsize,
|
||
|
readonly ? PROT_READ : PROT_READ|PROT_WRITE,
|
||
|
MAP_SHARED, hmt->fd, 0);
|
||
|
if (hmt->bin == MAP_FAILED)
|
||
|
{
|
||
|
if (debug)
|
||
|
printf("mmap() failed, falling back to read.\n");
|
||
|
/* This occurs if the underlying filesystem does not support
|
||
|
* mmap, e.g. NTFS. Fallback to holding the file in memory.
|
||
|
*/
|
||
|
if (!(hmt->bin = (uint8_t *)malloc(hmt->binsize)))
|
||
|
{
|
||
|
perror("malloc");
|
||
|
free(hmt);
|
||
|
close(hmt->fd);
|
||
|
return NULL;
|
||
|
}
|
||
|
read(hmt->fd, hmt->bin, hmt->binsize);
|
||
|
hmt->mmapped = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (debug)
|
||
|
printf("File mapped into memory.\n");
|
||
|
hmt->mmapped = 1;
|
||
|
}
|
||
|
|
||
|
magic = read_uint16(hmt->bin, 0);
|
||
|
|
||
|
if (magic != 0x1701)
|
||
|
{
|
||
|
printf("Invalid HMT file, %s\n", hmt->fname);
|
||
|
close_file(hmt);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
hmt->modified = 0;
|
||
|
parse_hmt(hmt);
|
||
|
|
||
|
return hmt;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
close_file(struct hmt *hmt)
|
||
|
{
|
||
|
if (debug)
|
||
|
printf("Closing file.\n");
|
||
|
|
||
|
if (hmt->mmapped)
|
||
|
munmap((void *)hmt->bin, hmt->binsize);
|
||
|
else
|
||
|
{
|
||
|
if (hmt->modified && !hmt->readonly)
|
||
|
{
|
||
|
lseek(hmt->fd, SEEK_SET, 0);
|
||
|
write(hmt->fd, hmt->bin, hmt->binsize);
|
||
|
}
|
||
|
free(hmt->bin);
|
||
|
}
|
||
|
if (hmt->fd > 0)
|
||
|
close(hmt->fd);
|
||
|
hmt->fd = -1;
|
||
|
}
|
||
|
|