<commit_before>/* jgfs2
 * (c) 2013 <NAME>
 * The source code of this project is distributed under the terms of the
 * simplified BSD license. See the LICENSE file for details.
 */


#include "dev.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "debug.h"


struct dev dev;
static struct dev dev_null = {
	.read_only = true,
	.debug_map = false,
	
	.page_size = 0,
	
	.path = NULL,
	.fd   = -1,
	
	.size_byte = 0,
	.size_sect = 0,
	
	.map_cnt = 0,
};


void *dev_map_sect(uint32_t sect_num, uint32_t sect_cnt) {
	if (sect_num + sect_cnt > dev.size_sect) {
		errx("%s: bounds violation: [%" PRIu32 ", %" PRIu32 ") > %" PRIu32,
			__func__, sect_num, sect_num + sect_cnt, dev.size_sect);
	}
	
	uint64_t byte_off = SECT_TO_BYTE(sect_num);
	uint64_t byte_len = SECT_TO_BYTE(sect_cnt);
	
	/* if not page-aligned, make it so */
	uint32_t adjust = (byte_off % dev.page_size);
	if (adjust != 0) {
		byte_len += adjust;
		byte_off /= dev.page_size;
	}
	
	int prot = PROT_READ | (dev.read_only ? 0 : PROT_WRITE);
	void *addr = mmap(NULL, byte_len, prot, MAP_SHARED, dev.fd, byte_off);
	
	if (addr == MAP_FAILED) {
		err("%s: mmap failed: sect [%" PRIu32 ", %" PRIu32 ")",
			__func__, sect_num, sect_num + sect_cnt);
	}
	
	++dev.map_cnt;
	
	if (dev.debug_map) {
		debug_map_push(addr, sect_num, sect_cnt);
	}
	
	return (addr + adjust);
}

void dev_unmap_sect(void *addr, uint32_t sect_num, uint32_t sect_cnt) {
	if (sect_num + sect_cnt > dev.size_sect) {
		errx("%s: bounds violation: [%" PRIu32 ", %" PRIu32 ") > %" PRIu32,
			__func__, sect_num, sect_num + sect_cnt, dev.size_sect);
	}
	
	uint64_t byte_off = SECT_TO_BYTE(sect_num);
	uint64_t byte_len = SECT_TO_BYTE(sect_cnt);
	
	/* if not page-aligned, make it so */
	uint32_t adjust = (byte_off % dev.page_size);
	if (adjust != 0) {
		byte_len += adjust;
		byte_off /= dev.page_size;
		
		addr -= adjust;
	}
	
	if (munmap(addr, byte_len) < 0) {
		err("%s: munmap failed: addr %p, sect [%" PRIu32 ", %" PRIu32 ")",
			__func__, addr, sect_num, sect_num + sect_cnt);
	}
	
	--dev.map_cnt;
	
	if (dev.debug_map) {
		debug_map_pop(addr, sect_num, sect_cnt);
	}
}

void dev_fsync(void) {
	if (fsync(dev.fd) < 0) {
		warn("fsync failed");
	}
}

void dev_msync(void *addr, size_t length) {
	if (msync(addr, length, MS_SYNC) < 0) {
		warn("msync failed");
	}
}

void dev_open(const char *dev_path, bool read_only, bool debug_map) {
	dev = dev_null;
	
	if ((dev.page_size = sysconf(_SC_PAGESIZE)) < 0) {
		err("could not get system page size");
	}
	
	dev.read_only = read_only;
	dev.debug_map = debug_map;
	
	dev.path = strdup(dev_path);
	int flags = (dev.read_only ? O_RDONLY : O_RDWR);
	if ((dev.fd = open(dev.path, flags)) < 0) {
		err("failed to open '%s'", dev.path);
	}
	
	dev.size_byte = lseek(dev.fd, 0, SEEK_END);
	lseek(dev.fd, 0, SEEK_SET);
	
	dev.size_sect = dev.size_byte / JGFS2_SECT_SIZE;
}

void dev_close(void) {
	if (dev.fd != -1) {
		dev_fsync();
		
		if (dev.map_cnt != 0) {
			warnx("%" PRIu32 " device regions are still mapped", dev.map_cnt);
			
			if (dev.debug_map) {
				debug_map_dump();
			}
		}
		
		if (close(dev.fd) < 0) {
			warn("close failed");
		}
		
		dev.fd = -1;
	}
	
	dev.path = NULL;
}<commit_msg>lib: lock device when in use by libjgfs2<commit_after>/* jgfs2
 * (c) 2013 <NAME>
 * The source code of this project is distributed under the terms of the
 * simplified BSD license. See the LICENSE file for details.
 */


#include "dev.h"
#include <fcntl.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <unistd.h>
#include "debug.h"


struct dev dev;
static struct dev dev_null = {
	.read_only = true,
	.debug_map = false,
	
	.page_size = 0,
	
	.path = NULL,
	.fd   = -1,
	
	.size_byte = 0,
	.size_sect = 0,
	
	.map_cnt = 0,
};


void *dev_map_sect(uint32_t sect_num, uint32_t sect_cnt) {
	if (sect_num + sect_cnt > dev.size_sect) {
		errx("%s: bounds violation: [%" PRIu32 ", %" PRIu32 ") > %" PRIu32,
			__func__, sect_num, sect_num + sect_cnt, dev.size_sect);
	}
	
	uint64_t byte_off = SECT_TO_BYTE(sect_num);
	uint64_t byte_len = SECT_TO_BYTE(sect_cnt);
	
	/* if not page-aligned, make it so */
	uint32_t adjust = (byte_off % dev.page_size);
	if (adjust != 0) {
		byte_len += adjust;
		byte_off /= dev.page_size;
	}
	
	int prot = PROT_READ | (dev.read_only ? 0 : PROT_WRITE);
	void *addr = mmap(NULL, byte_len, prot, MAP_SHARED, dev.fd, byte_off);
	
	if (addr == MAP_FAILED) {
		err("%s: mmap failed: sect [%" PRIu32 ", %" PRIu32 ")",
			__func__, sect_num, sect_num + sect_cnt);
	}
	
	++dev.map_cnt;
	
	if (dev.debug_map) {
		debug_map_push(addr, sect_num, sect_cnt);
	}
	
	return (addr + adjust);
}

void dev_unmap_sect(void *addr, uint32_t sect_num, uint32_t sect_cnt) {
	if (sect_num + sect_cnt > dev.size_sect) {
		errx("%s: bounds violation: [%" PRIu32 ", %" PRIu32 ") > %" PRIu32,
			__func__, sect_num, sect_num + sect_cnt, dev.size_sect);
	}
	
	uint64_t byte_off = SECT_TO_BYTE(sect_num);
	uint64_t byte_len = SECT_TO_BYTE(sect_cnt);
	
	/* if not page-aligned, make it so */
	uint32_t adjust = (byte_off % dev.page_size);
	if (adjust != 0) {
		byte_len += adjust;
		byte_off /= dev.page_size;
		
		addr -= adjust;
	}
	
	if (munmap(addr, byte_len) < 0) {
		err("%s: munmap failed: addr %p, sect [%" PRIu32 ", %" PRIu32 ")",
			__func__, addr, sect_num, sect_num + sect_cnt);
	}
	
	--dev.map_cnt;
	
	if (dev.debug_map) {
		debug_map_pop(addr, sect_num, sect_cnt);
	}
}

void dev_fsync(void) {
	if (fsync(dev.fd) < 0) {
		warn("fsync failed");
	}
}

void dev_msync(void *addr, size_t length) {
	if (msync(addr, length, MS_SYNC) < 0) {
		warn("msync failed");
	}
}

void dev_open(const char *dev_path, bool read_only, bool debug_map) {
	dev = dev_null;
	
	if ((dev.page_size = sysconf(_SC_PAGESIZE)) < 0) {
		err("could not get system page size");
	}
	
	dev.read_only = read_only;
	dev.debug_map = debug_map;
	
	dev.path = strdup(dev_path);
	int flags = (dev.read_only ? O_RDONLY : O_RDWR);
	if ((dev.fd = open(dev.path, flags)) < 0) {
		err("failed to open '%s'", dev.path);
	}
	
	if (flock(dev.fd, LOCK_NB | LOCK_EX) < 0) {
		err("could not lock '%s'", dev.path);
	}
	
	dev.size_byte = lseek(dev.fd, 0, SEEK_END);
	lseek(dev.fd, 0, SEEK_SET);
	
	dev.size_sect = dev.size_byte / JGFS2_SECT_SIZE;
}

void dev_close(void) {
	if (dev.fd != -1) {
		dev_fsync();
		
		if (dev.map_cnt != 0) {
			warnx("%" PRIu32 " device regions are still mapped", dev.map_cnt);
			
			if (dev.debug_map) {
				debug_map_dump();
			}
		}
		
		if (flock(dev.fd, LOCK_NB | LOCK_UN) < 0) {
			err("could not unlock '%s'", dev.path);
		}
		
		if (close(dev.fd) < 0) {
			warn("close failed");
		}
		
		dev.fd = -1;
	}
	
	dev.path = NULL;
}
{'fraction_non_alphanumeric': 0.1593481213218651, 'fraction_numerical': 0.02067300437603742, 'mean_word_length': 3.454301075268817, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3155395', 'n_tokens_mistral': 3131, 'n_tokens_neox': 2813, 'n_words': 645}