David Marec 5 kuukautta sitten
vanhempi
commit
7954bbfb18
3 muutettua tiedostoa jossa 180 lisäystä ja 0 poistoa
  1. 23 0
      swap/Makefile
  2. 32 0
      swap/README.md
  3. 125 0
      swap/swap16.c

+ 23 - 0
swap/Makefile

@@ -0,0 +1,23 @@
+CFLAGS+=-O3 -Wall
+CFLAGS+=-msse4.2
+
+LDFLAGS+=-lutil -msse4.2 -Wl,-O3
+
+PROG=swap16
+PROG_OBJS=swap16.o
+
+.SYSPATH:	 $(.CURDIR)/../Mk
+.PHONY: clean
+.MAIN: $(PROG)
+
+$(PROG): $(PROG_OBJS)
+	$(CC) -o ${.TARGET} ${.ALLSRC} $(LDFLAGS)
+
+%o: 
+	$(CC) -o ${.TARGET} -c ${.IMPSRC}
+
+clean:
+	rm -f *.o $(PROG)
+
+.include <hardening.mk>
+

+ 32 - 0
swap/README.md

@@ -0,0 +1,32 @@
+# inplace Swap bytes
+
+Echange d'octects 2 par 2 sur un fichier, en utilisant les _intrinsics_.
+
+
+Sur un fichier texte:
+
+```sh
+ echo '0123456789ABCDEF' > alpha
+ ./swap16 --input alpha
+Parsing:       17B.
+Swab   :  0.000 ms.
+ cat alpha
+1023546798ABDCEF%
+```
+
+Sur un fichier plus épais:
+```sh
+ dd if=/dev/urandom of=/tmp/r.dummy bs=4M count=100
+ cp /tmp/r.dummy /tmp/r.true
+ ./swap16 --input /tmp/r.dummy
+Parsing:       400M.
+Swab   :  46.875 ms.
+ cmp /tmp/r.dummy /tmp/r.true
+/tmp/r.dummy /tmp/r.true differ: char 1, line 1
+ ./swap16 --input /tmp/r.dummy
+Parsing:       400M.
+Swab   :  46.875 ms.
+ cmp /tmp/r.dummy /tmp/r.true
+```
+
+

+ 125 - 0
swap/swap16.c

@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <getopt.h>
+#include <time.h>
+#include <libutil.h>
+
+#define swab16(x) (u_int16_t)__builtin_bswap16((u_int16_t)(x))
+
+/*
+ * smart helpers
+ */
+void fd_close(int *fd)
+{
+	close(*fd);
+	*fd = -1;
+}
+#define _smartfd __attribute((cleanup(fd_close)))
+
+void file_close(FILE **fd)
+{
+	fclose(*fd);
+	*fd = NULL;
+}
+#define _smartfile __attribute((cleanup(file_close)))
+
+__attribute__((noreturn)) static int usage(void)
+{
+	fputs("swap16 [--input] file\n", stderr);
+	exit (EXIT_SUCCESS);
+}
+
+/*
+ * Print human readable numbers
+ *
+ * @width: spaces
+ * @bytes: value in bytes
+ */
+static void printsize(size_t width, off_t bytes)
+{
+	/*
+	 * Reserve one space before the size and allocate room for
+	 * the trailing '\0'.
+	 */
+	char buf[5];
+
+	humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
+			HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+	(void)printf("%*s", (u_int)width, buf);
+}
+
+int main(int argc, char *argv[])
+{
+	static struct option longopts[] = {
+		{ "input",   required_argument, NULL, 'i' },
+		{ NULL,	0, NULL, 0 }
+	};
+
+	int ch;
+	_smartfd int fd = -1;
+	char *inputfile = NULL;
+
+	while ((ch = getopt_long(argc, argv, "hi:", longopts, NULL)) != -1) {
+		switch (ch) {
+			case 'i':
+				inputfile = optarg;
+				break;
+			case 0:
+				/* long option */
+				break;
+			default:
+				usage();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	/* if not already set, get the last arguments as the input filename */
+	if (!inputfile && argv) {
+		inputfile = *argv;
+		argv++;
+	}
+
+	/* sanity checks */
+	if (*argv || (inputfile == NULL))
+		usage();
+
+	fd = open(inputfile, O_RDWR);
+	if (fd < 0) {
+		err(EXIT_FAILURE, "failed to open %s:", inputfile);
+	}
+
+	/* File analysis */
+	struct stat statbuf = { 0 };
+	fstat(fd, & statbuf);
+
+	printf("Parsing:");
+	printsize(10, statbuf.st_size);
+	puts(".");
+
+	char *addr = (char *)mmap(NULL, (size_t)statbuf.st_size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
+	u_int16_t *sbmax=(u_int16_t *)(addr + statbuf.st_size);
+	u_int16_t *sb=(u_int16_t *)addr;
+
+	if (addr == NULL)
+		err(EXIT_FAILURE, "Failed to map file %s:\n", inputfile);
+
+	clock_t t1, t0;
+
+	t0 = clock();
+	for (;sb < sbmax; sb+=sizeof(u_int16_t))
+		*(sb)=swab16(*sb);
+	t1 = clock();
+	printf("Swab   : %6.3f ms.\n", 1000.0 * (double)(t1 - t0) / CLOCKS_PER_SEC);
+
+	munmap(addr, (size_t)statbuf.st_size);
+
+	return EXIT_SUCCESS;
+}
+