diff --git a/include/map.h b/include/map.h index ecbcee3..a795fa9 100644 --- a/include/map.h +++ b/include/map.h @@ -13,6 +13,7 @@ typedef enum mm_err { MAP_ERR_UNMAP, MAP_ERR_OPEN, MAP_ERR_CLOSE, + MAP_ERR_STAT, } map_result_t; typedef union memory_map { @@ -41,4 +42,27 @@ map_result_t map_file(const char* file, bool write, usize size, off_t offset, ma map_result_t map_anon(void* ptr, usize len, map_t *pOUT map); map_result_t map_free(map_t map); +const char* map_error_str(map_result_t res); + +_mixin int _map_handle_err(const char* stmt, const char* file, int line, const char* func, map_result_t res) +{ + if(res == MAP_SUCCESS) return 1; + else { + const char* err = map_error_str(res); + ERROR("mapping failed at %s:%d->%s(): on stmt `%s`", file, line, func, stmt); + switch(res) { + // Non-errno errors + case MAP_ERR_UNKNOWN: + case MAP_SUCCESS: + fprintf(stderr, err); + if(0) + // errno errors + default: + perror(err); + return 0; + } + } +} +#define map_handle_err(stmt) _map_handle_err(#stmt, __FILE__, __LINE__, __func__, stmt) + #endif /* _MAP_H */ diff --git a/src/main.c b/src/main.c index 1df6c2f..40d4d8f 100644 --- a/src/main.c +++ b/src/main.c @@ -12,6 +12,8 @@ #include +#include + void prog_info(FILE* out) { fprintf(out, PROG_NAME " v%s - " PROG_DESCRIPTION @@ -43,9 +45,15 @@ noreturn void usage_then_exit(int err, int argc, char** argv) int main(int argc, char** argv) { - TRACE("main start"); - - usage_then_exit(0, argc, argv); + TRACE("main start with %d (pn: %s, a1: %s)", argc, argv[0], argv[1] ?: ""); + + if(!argv[1] || !argv[2]) usage_then_exit(1, argc, argv); + + map_t needle; + INFO("Mapping needle file `%s'", argv[1]); + if(!map_handle_err(map_file(argv[1], false, 0, 0, &needle))) return 2; + + if(!map_handle_err(map_free(needle))) return 3; TRACE("main end"); diff --git a/src/map.c b/src/map.c index 3750c4c..74c9122 100644 --- a/src/map.c +++ b/src/map.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -12,17 +13,21 @@ static inline void _map_init(map_t *pOUT map) { memset(map, 0xff, sizeof(map_t)); + TRACE("blanked %p->%lu to 0xff", map, sizeof(map_t)); } static inline bool _map_is_file(const map_t* map) { + TRACE("fd element of union is %x (%d)", map->file.fd, map->file.fd); return map->file.fd > 0; } map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT map) { + TRACE("mapping %lu bytes of fd %d (%s) from offset %lu to %p", size, fd, write ? "rw" : "ro", offset, map); void* ptr = mmap(NULL, size, PROT_READ | (write ? PROT_WRITE : 0), MAP_SHARED, fd, offset); if(ptr == MAP_FAILED) return MAP_ERR_MMAP; + TRACE("mapped %p->%lu", ptr, size); map->file = (struct mm_file){ .origin = ptr, .len = size, @@ -34,16 +39,31 @@ map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT ma map_result_t map_file(const char* file, bool write, usize size, off_t offset, map_t *pOUT map) { + TRACE("mapping %lu bytes of file `%s' (%s) from %lu to %p", size, file, write ? "rw" : "ro", offset, map); + int fd = open(file, write ? O_RDWR : O_RDONLY); if(fd < 0) return MAP_ERR_OPEN; + TRACE("opened file %d", fd); + + if(!size) { + TRACE("user asked for max-size map (size: 0), stating %d to find size...", fd); + struct stat st; + // Find size of file + if(fstat(fd, &st) != 0) return (close(fd), MAP_ERR_STAT); + TRACE("fstat() reports size is %lu", st.st_size); + size = st.st_size; + } + TRACE("passing fd %d, size %lu to `map_fd()`", fd, size); return map_fd(fd, write, size, offset, map); } map_result_t map_anon(void* ptr, usize len, map_t *pOUT map) { + TRACE("mapping anon at %p (%s) of size %lu (map %p)", ptr, ptr ? "fixed" : "dynamic", len, map); ptr = mmap(ptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | (ptr ? MAP_FIXED : 0), -1, 0); if(ptr==MAP_FAILED) return MAP_ERR_MMAP; + TRACE("mapped ptr %p->%lu", ptr, len); // Make sure .file.fd is -1, so we can tell this is anon in `map_free()`. _map_init(map); map->anon = (struct mm_anon) { @@ -55,9 +75,30 @@ map_result_t map_anon(void* ptr, usize len, map_t *pOUT map) map_result_t map_free(map_t map) { + TRACE("unmapping %p->%lu", map.origin, map.len); if( munmap(map.anon.origin, map.anon.len) != 0) return MAP_ERR_UNMAP; if( _map_is_file(&map) ) { + TRACE("map is file, closing fd %d", map.file.fd); if( close(map.file.fd) != 0 ) return MAP_ERR_CLOSE; } return MAP_SUCCESS; } + +const char* map_error_str(map_result_t res) +{ + switch(res) + { +#define CASE(err, str) case err: return str + CASE(MAP_ERR_MMAP, "mmap() failed (creating a map)"); + CASE(MAP_ERR_UNMAP, "munmap() failed (freeing a map)"); + CASE(MAP_ERR_OPEN, "open() failed (mapping a filepath)"); + CASE(MAP_ERR_CLOSE, "close() failed (freeing a file-map)"); + CASE(MAP_ERR_STAT, "fstat() failed: (mapping a full filepath)"); + + CASE(MAP_SUCCESS, "success"); +#undef CASE + default: + ERROR("unkown or invalid error code %d", (int)res); + return "unknown error"; + } +}