commit
cd5db67f23
@ -0,0 +1 @@
|
|||||||
|
obj/
|
@ -0,0 +1,44 @@
|
|||||||
|
SRC = $(wildcard src/*.c)
|
||||||
|
INCLUDE=include
|
||||||
|
|
||||||
|
PROJECT=fcmp
|
||||||
|
|
||||||
|
OPT_FLAGS+= -fgraphite -fno-strict-aliasing
|
||||||
|
|
||||||
|
RELEASE_CFLAGS?= -O3 -march=native -flto $(OPT_FLAGS)
|
||||||
|
RELEASE_LDFLAGS?= -O3 -flto
|
||||||
|
|
||||||
|
DEBUG_CFLAGS?= -O0 -g
|
||||||
|
DEBUG_LDFLAGS?= -O0
|
||||||
|
|
||||||
|
CFLAGS+= -Wall -pedantic --std=gnu11 $(addprefix -I,$(INCLUDE))
|
||||||
|
LDFLAGS+=
|
||||||
|
|
||||||
|
OBJ = $(addprefix obj/,$(SRC:.c=.o))
|
||||||
|
|
||||||
|
.PHONY: release
|
||||||
|
release: | dirs $(PROJECT)-release
|
||||||
|
|
||||||
|
.PHONY: debug
|
||||||
|
debug: | dirs $(PROJECT)-debug
|
||||||
|
|
||||||
|
dirs:
|
||||||
|
@mkdir -p obj/src
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -c $< $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
$(PROJECT)-release: CFLAGS := $(RELEASE_CFLAGS) $(CFLAGS)
|
||||||
|
$(PROJECT)-release: LDFLAGS := $(RELEASE_LDFLAGS) $(LDFLAGS)
|
||||||
|
$(PROJECT)-release: $(OBJ)
|
||||||
|
$(CC) $^ $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
strip $@
|
||||||
|
|
||||||
|
$(PROJECT)-debug: CFLAGS := $(DEBUG_CFLAGS) $(CFLAGS)
|
||||||
|
$(PROJECT)-debug: LDFLAGS := $(DEBUG_LDFLAGS) $(LDFLAGS)
|
||||||
|
$(PROJECT)-debug: $(OBJ)
|
||||||
|
$(CC) $^ $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf obj
|
||||||
|
rm -f $(PROJECT)-{release,debug}
|
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _MAP_H
|
||||||
|
#define _MAP_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#define restrict __restrict__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct mmap {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
void* ptr;
|
||||||
|
size_t len;
|
||||||
|
} mmap_t;
|
||||||
|
|
||||||
|
int open_and_map(const char* file, mmap_t* restrict ptr);
|
||||||
|
int unmap_and_close(mmap_t map);
|
||||||
|
|
||||||
|
#ifdef _cplusplus
|
||||||
|
}
|
||||||
|
#undef restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _MAP_H */
|
@ -0,0 +1,55 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <map.h>
|
||||||
|
|
||||||
|
static const char* _prog_name = "fcmp";
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s <file1> <file2>\n", _prog_name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline const void* die_if_null(const void* ptr)
|
||||||
|
{
|
||||||
|
if (!ptr) usage();
|
||||||
|
else return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
_prog_name = argv[0];
|
||||||
|
|
||||||
|
const char* f1 = die_if_null(argv[1]);
|
||||||
|
const char* f2 = die_if_null(argv[2]);
|
||||||
|
|
||||||
|
mmap_t map1, map2;
|
||||||
|
if (!open_and_map(f1, &map1)) {
|
||||||
|
fprintf(stderr, "Failed to open or map %s\n", f1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!open_and_map(f2, &map2)) {
|
||||||
|
fprintf(stderr, "Failed to open or map %s\n", f2);
|
||||||
|
unmap_and_close(map1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map1.len != map2.len) return 2;
|
||||||
|
|
||||||
|
if (memcmp(map1.ptr, map2.ptr, map1.len) != 0) return 1;
|
||||||
|
|
||||||
|
register int rval=0;
|
||||||
|
if(!unmap_and_close(map1)) {
|
||||||
|
fprintf(stderr, "Failed to unmap and close %s", f1);
|
||||||
|
rval=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!unmap_and_close(map2)) {
|
||||||
|
fprintf(stderr, "Failed to unmap and close %s", f2);
|
||||||
|
rval=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include<stdio.h>
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
#include<unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include<sys/mman.h>
|
||||||
|
#include<fcntl.h>
|
||||||
|
|
||||||
|
#define FILEMODE S_IRWXU | S_IRGRP | S_IROTH
|
||||||
|
|
||||||
|
#include <map.h>
|
||||||
|
|
||||||
|
int open_and_map(const char* file, mmap_t* restrict ptr)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
if ((fd = open(file, O_RDONLY, FILEMODE)) < 0) {
|
||||||
|
perror("Failed to open file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstat(fd, &st) < 0) {
|
||||||
|
perror("Failed to stat file");
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
register struct mmap map = { .fd = fd, .ptr = NULL, .len = st.st_size };
|
||||||
|
|
||||||
|
if ((map.ptr = mmap(NULL, map.len, PROT_READ, MAP_SHARED,fd, 0)) == MAP_FAILED) {
|
||||||
|
perror("mmam() failed");
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = map;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unmap_and_close(mmap_t map)
|
||||||
|
{
|
||||||
|
if (munmap(map.ptr, map.len) < 0) {
|
||||||
|
perror("munmap() failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (close(map.fd) <0) {
|
||||||
|
perror("Failed to close fd");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
Loading…
Reference in new issue