#include #include #include #include #include #include #include #include #include #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; }