summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-block')
-rw-r--r--sys-block/f3/Manifest1
-rw-r--r--sys-block/f3/f3-6.0.ebuild78
-rw-r--r--sys-block/f3/files/f3-6.0-extra-target.patch108
-rw-r--r--sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3probe.patch50
-rw-r--r--sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3read.patch88
-rw-r--r--sys-block/f3/files/f3-6.0-respect-ldflags.patch40
-rw-r--r--sys-block/f3/files/f3-6.0-upstream-issue-44.patch25
-rw-r--r--sys-block/f3/files/f3-6.0-use-argp_parse.patch417
-rw-r--r--sys-block/f3/metadata.xml26
9 files changed, 833 insertions, 0 deletions
diff --git a/sys-block/f3/Manifest b/sys-block/f3/Manifest
new file mode 100644
index 000000000000..2f440a903bbc
--- /dev/null
+++ b/sys-block/f3/Manifest
@@ -0,0 +1 @@
+DIST f3-6.0.tar.gz 45355 SHA256 d72addb15809bc6229a08ac57e2b87b34eac80346384560ba1f16dae03fbebd5 SHA512 7960d01d7a2bd01a236006fcb4081cc7e2c0be674bc3e28137f00ea3f558a04eed47f10e7d3795c219943092ee43fb3189e19ff1925a7ed4ff5102130d65a470 WHIRLPOOL 5d96587b62528c3559061ee940342247934995cbcc919991ab53f75cc7e38d9400e3695535be1aaf80d17efc4530e89e61fead9af08c635ceba1c2937d3803d6
diff --git a/sys-block/f3/f3-6.0.ebuild b/sys-block/f3/f3-6.0.ebuild
new file mode 100644
index 000000000000..f65de3592906
--- /dev/null
+++ b/sys-block/f3/f3-6.0.ebuild
@@ -0,0 +1,78 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=6
+
+inherit flag-o-matic toolchain-funcs
+
+DESCRIPTION="Utilities to detect broken or counterfeit flash storage"
+HOMEPAGE="http://oss.digirati.com.br/f3/ https://github.com/AltraMayor/f3"
+
+PATCHES=(
+ "${FILESDIR}"/f3-6.0-fix-compiler-warnings_f3read.patch
+ "${FILESDIR}"/f3-6.0-fix-compiler-warnings_f3probe.patch
+ "${FILESDIR}"/f3-6.0-respect-ldflags.patch
+ "${FILESDIR}"/f3-6.0-use-argp_parse.patch
+ "${FILESDIR}"/f3-6.0-extra-target.patch
+ "${FILESDIR}"/f3-6.0-upstream-issue-44.patch
+)
+
+if [[ ${PV} == "9999" ]]; then
+ EGIT_REPO_URI="
+ git://github.com/AltraMayor/${PN}.git
+ https://github.com/AltraMayor/${PN}.git
+ "
+
+ PATCHES=()
+
+ inherit git-r3
+else
+ SRC_URI="https://github.com/AltraMayor/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
+ KEYWORDS="~amd64 ~x86"
+fi
+
+LICENSE="GPL-3+"
+SLOT="0"
+
+IUSE="extra"
+
+DEPEND="extra? (
+ sys-block/parted
+ virtual/udev
+ )"
+
+RDEPEND=""
+
+DOCS=( changelog README.md )
+
+src_prepare() {
+ default
+
+ sed -i \
+ -e 's:-ggdb::' \
+ -e 's:^PREFIX =:PREFIX ?=:' \
+ Makefile || die
+
+ tc-export CC
+
+ append-cflags -fgnu89-inline # https://github.com/AltraMayor/f3/issues/34
+}
+
+src_compile() {
+ default
+
+ if use extra; then
+ emake V=1 extra
+ fi
+}
+
+src_install() {
+ emake PREFIX="${ED%/}/usr" install
+
+ if use extra; then
+ emake PREFIX="${ED%/}/usr" install-extra
+ fi
+
+ dodoc "${DOCS[@]}"
+}
diff --git a/sys-block/f3/files/f3-6.0-extra-target.patch b/sys-block/f3/files/f3-6.0-extra-target.patch
new file mode 100644
index 000000000000..8523ca3f2b53
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-extra-target.patch
@@ -0,0 +1,108 @@
+From 64d169e2486121eaece555c56040d6aff71e0b51 Mon Sep 17 00:00:00 2001
+From: Michel Machado <michel@digirati.com.br>
+Date: Tue, 29 Mar 2016 12:56:43 -0400
+Subject: [PATCH] Mark experimental applications as stable
+
+The code of the applications f3probe, f3brew, and f3fix is now
+mature, and they have not received any significant bug report for
+about six months.
+
+From now on, one needs to compile these applications with
+```make extra```
+---
+ Makefile | 10 +++++-----
+ README.md | 29 ++++++++++++-----------------
+ 2 files changed, 17 insertions(+), 22 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 46853f5..ce54842 100644
+--- a/Makefile
++++ b/Makefile
+@@ -2,14 +2,14 @@ CC ?= gcc
+ CFLAGS += -std=c99 -Wall -Wextra -pedantic -MMD -ggdb
+
+ TARGETS = f3write f3read
+-EXPERIMENTAL_TARGETS = f3probe f3brew f3fix
++EXTRA_TARGETS = f3probe f3brew f3fix
+
+ PREFIX = /usr/local
+ INSTALL = install
+ LN = ln
+
+ all: $(TARGETS)
+-experimental: $(EXPERIMENTAL_TARGETS)
++extra: $(EXTRA_TARGETS)
+
+ install: all
+ $(INSTALL) -d $(PREFIX)/bin
+@@ -18,9 +18,9 @@ install: all
+ $(INSTALL) -oroot -groot -m644 f3read.1 $(PREFIX)/share/man/man1
+ $(LN) -sf f3read.1 $(PREFIX)/share/man/man1/f3write.1
+
+-install-experimental: experimental
++install-extra: extra
+ $(INSTALL) -d $(PREFIX)/bin
+- $(INSTALL) -oroot -groot -m755 $(EXPERIMENTAL_TARGETS) $(PREFIX)/bin
++ $(INSTALL) -oroot -groot -m755 $(EXTRA_TARGETS) $(PREFIX)/bin
+
+ f3write: utils.o f3write.o
+ $(CC) -o $@ $^ $(LDFLAGS) -lm
+@@ -45,4 +45,4 @@ cscope:
+ cscope -b *.c *.h
+
+ clean:
+- rm -f *.o *.d cscope.out $(TARGETS) $(EXPERIMENTAL_TARGETS)
++ rm -f *.o *.d cscope.out $(TARGETS) $(EXTRA_TARGETS)
+diff --git a/README.md b/README.md
+index f0399b4..e2f7f79 100644
+--- a/README.md
++++ b/README.md
+@@ -5,36 +5,31 @@ make
+ ```
+
+
+-## Compile experimental applications on Linux
++## Compile the extra applications on Linux
+
+ ### Install dependencies
+
+- - f3probe and f3brew require version 1 of the library libudev to compile.
+- On Ubuntu, you can install this library with the following command:
++f3probe and f3brew require version 1 of the library libudev, and
++f3fix requires version 0 of the library libparted to compile.
++On Ubuntu, you can install these libraries with the following command:
+ ```
+-sudo apt-get install libudev1 libudev-dev
+-```
+- - f3fix requires version 0 of the library libparted to compile.
+- On Ubuntu, you can install this library with the following command:
+-```
+-sudo apt-get install libparted0-dev
++sudo apt-get install libudev1 libudev-dev libparted0-dev
+ ```
+
+-### Compile experimental applications
++### Compile the extra applications
+
+ ```
+-make experimental
++make extra
+ ```
+
+ NOTES:
+- - Experimental software might compile on non-Linux platforms, but
+- there is no guarantee given that they are only tested on Linux.
+- - Please do not e-mail me saying that you want an experimental software
++ - The extra applications are only compiled and tested on Linux platform.
++ - Please do not e-mail me saying that you want the extra applications
+ to run on your platform; I already know that.
+- - If you want experimental software to run on your platform,
++ - If you want the extra applications to run on your platform,
+ help to port them, or find someone that can port them for you.
+- If you do port the software, please send me a patch to help others.
+- - Currently, f3probe, f3brew, and f3fix are experimental.
++ If you do port any of them, please send me a patch to help others.
++ - The extra applications are f3probe, f3brew, and f3fix.
+
+
+ ## Use example of f3write/f3read
diff --git a/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3probe.patch b/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3probe.patch
new file mode 100644
index 000000000000..739488b53f97
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3probe.patch
@@ -0,0 +1,50 @@
+From 77d2ceb374ff70b64e95a41f0e05486575147b53 Mon Sep 17 00:00:00 2001
+From: Michel Machado <michel@digirati.com.br>
+Date: Mon, 4 Jan 2016 13:49:05 -0500
+Subject: [PATCH] f3probe: avoid compiler warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When using -O2, GCC was issuing the following warning:
+
+cc -O2 -std=c99 -Wall -Wextra -pedantic -MMD -ggdb -c -o f3probe.o f3probe.c
+f3probe.c: In function ‘main’:
+f3probe.c:446:13: warning: ‘sdev’ may be used uninitialized in this function [-Wmaybe-uninitialized]
+ sdev_flush(sdev);
+ ^
+f3probe.c:369:30: note: ‘sdev’ was declared here
+ struct device *dev, *pdev, *sdev;
+ ^
+
+NOTE: The warning was wrong.
+ GCC could not follow that @args->save being true implied
+ @sdev to not be NULL.
+
+This patch addresses one of the issues discussed here:
+https://github.com/AltraMayor/f3/issues/34
+---
+ f3probe.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/f3probe.c b/f3probe.c
+index e647d7c..9f214ab 100644
+--- a/f3probe.c
++++ b/f3probe.c
+@@ -393,6 +393,7 @@ static int test_device(struct args *args)
+ pdev = NULL;
+ }
+
++ sdev = NULL;
+ if (args->save) {
+ sdev = create_safe_device(dev,
+ probe_device_max_blocks(dev), args->min_mem);
+@@ -434,7 +435,7 @@ static int test_device(struct args *args)
+ &read_count, &read_time_us,
+ &write_count, &write_time_us,
+ &reset_count, &reset_time_us);
+- if (args->save) {
++ if (sdev) {
+ uint64_t very_last_pos = real_size_byte >> block_order;
+ printf("Probe finished, recovering blocks...");
+ fflush(stdout);
diff --git a/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3read.patch b/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3read.patch
new file mode 100644
index 000000000000..0e4f61fca816
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-fix-compiler-warnings_f3read.patch
@@ -0,0 +1,88 @@
+From 52e252f5d6dc6d10fd85a45b0774bb0b29d5f989 Mon Sep 17 00:00:00 2001
+From: Michel Machado <michel@digirati.com.br>
+Date: Mon, 4 Jan 2016 13:22:18 -0500
+Subject: [PATCH] f3read: avoid compiler warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When using -O2, GCC was issuing the following warning:
+
+cc -O2 -std=c99 -Wall -Wextra -pedantic -MMD -ggdb -c -o f3read.o f3read.c
+f3read.c: In function ‘validate_file’:
+f3read.c:95:3: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
+ offset = *((uint64_t *) sector);
+ ^
+---
+ f3read.c | 28 ++++++++++++----------------
+ 1 file changed, 12 insertions(+), 16 deletions(-)
+
+diff --git a/f3read.c b/f3read.c
+index 1514365..2dc6942 100644
+--- a/f3read.c
++++ b/f3read.c
+@@ -42,12 +42,12 @@ static void validate_file(const char *path, int number,
+ {
+ char *full_fn;
+ const char *filename;
+- uint8_t sector[SECTOR_SIZE], *p, *ptr_end;
++ const int num_int64 = SECTOR_SIZE >> 3;
++ uint64_t sector[num_int64];
+ FILE *f;
+ int fd;
+- int offset_match, error_count;
+ size_t sectors_read;
+- uint64_t offset, expected_offset;
++ uint64_t expected_offset;
+ int final_errno;
+ struct timeval t1, t2;
+ /* Progress time. */
+@@ -84,32 +84,24 @@ static void validate_file(const char *path, int number,
+ /* Help the kernel to help us. */
+ assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL));
+
+- ptr_end = sector + SECTOR_SIZE;
+ sectors_read = fread(sector, SECTOR_SIZE, 1, f);
+ final_errno = errno;
+ expected_offset = (uint64_t)number * GIGABYTES;
+ while (sectors_read > 0) {
+ uint64_t rn;
++ int error_count, i;
+
+ assert(sectors_read == 1);
+- offset = *((uint64_t *) sector);
+- offset_match = offset == expected_offset;
+
+- rn = offset;
+- p = sector + sizeof(offset);
++ rn = sector[0];
+ error_count = 0;
+- for (; error_count <= TOLERANCE && p < ptr_end;
+- p += sizeof(rn)) {
++ for (i = 1; error_count <= TOLERANCE && i < num_int64; i++) {
+ rn = random_number(rn);
+- if (rn != *((__typeof__(rn) *) p))
++ if (rn != sector[i])
+ error_count++;
+ }
+
+- sectors_read = fread(sector, SECTOR_SIZE, 1, f);
+- final_errno = errno;
+- expected_offset += SECTOR_SIZE;
+-
+- if (offset_match) {
++ if (expected_offset == sector[0]) {
+ if (error_count == 0)
+ (*ptr_ok)++;
+ else if (error_count <= TOLERANCE)
+@@ -121,6 +113,10 @@ static void validate_file(const char *path, int number,
+ else
+ (*ptr_corrupted)++;
+
++ sectors_read = fread(sector, SECTOR_SIZE, 1, f);
++ final_errno = errno;
++ expected_offset += SECTOR_SIZE;
++
+ if (progress) {
+ struct timeval pt2;
+ assert(!gettimeofday(&pt2, NULL));
diff --git a/sys-block/f3/files/f3-6.0-respect-ldflags.patch b/sys-block/f3/files/f3-6.0-respect-ldflags.patch
new file mode 100644
index 000000000000..4d42ea8318d4
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-respect-ldflags.patch
@@ -0,0 +1,40 @@
+From 70962dcfaa41ca390f6f077cc64312fb879b7eb4 Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Sat, 12 Mar 2016 17:39:05 +0200
+Subject: [PATCH] allow users to specify linker flags
+
+Traditionally LDFLAGS is used for this, it's what I've tried first
+but it wasn't accepted.
+---
+ Makefile | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 404bc17..46853f5 100644
+--- a/Makefile
++++ b/Makefile
+@@ -23,19 +23,19 @@ install-experimental: experimental
+ $(INSTALL) -oroot -groot -m755 $(EXPERIMENTAL_TARGETS) $(PREFIX)/bin
+
+ f3write: utils.o f3write.o
+- $(CC) -o $@ $^ -lm
++ $(CC) -o $@ $^ $(LDFLAGS) -lm
+
+ f3read: utils.o f3read.o
+- $(CC) -o $@ $^
++ $(CC) -o $@ $^ $(LDFLAGS)
+
+ f3probe: libutils.o libdevs.o libprobe.o f3probe.o
+- $(CC) -o $@ $^ -lm -ludev
++ $(CC) -o $@ $^ $(LDFLAGS) -lm -ludev
+
+ f3brew: libutils.o libdevs.o f3brew.o
+- $(CC) -o $@ $^ -lm -ludev
++ $(CC) -o $@ $^ $(LDFLAGS) -lm -ludev
+
+ f3fix: libutils.o f3fix.o
+- $(CC) -o $@ $^ -lparted
++ $(CC) -o $@ $^ $(LDFLAGS) -lparted
+
+ -include *.d
+
diff --git a/sys-block/f3/files/f3-6.0-upstream-issue-44.patch b/sys-block/f3/files/f3-6.0-upstream-issue-44.patch
new file mode 100644
index 000000000000..605b6b3ea663
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-upstream-issue-44.patch
@@ -0,0 +1,25 @@
+From a754e9cf29415d110c4fe6fb1fe0d060d765a73e Mon Sep 17 00:00:00 2001
+From: Michel Machado <michel@digirati.com.br>
+Date: Thu, 19 May 2016 08:39:36 -0400
+Subject: [PATCH] f3read: add "#include <limits.h>" to f3read.c
+
+This addresses a compiling issue on Macs.
+
+@jksinton found and solved this problem:
+https://github.com/AltraMayor/f3/issues/44
+---
+ f3read.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/f3read.c b/f3read.c
+index 0842071..c5c20d2 100644
+--- a/f3read.c
++++ b/f3read.c
+@@ -5,6 +5,7 @@
+ #include <stdint.h>
+ #include <inttypes.h>
+ #include <stdio.h>
++#include <limits.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <errno.h>
diff --git a/sys-block/f3/files/f3-6.0-use-argp_parse.patch b/sys-block/f3/files/f3-6.0-use-argp_parse.patch
new file mode 100644
index 000000000000..b73fbff8c7a2
--- /dev/null
+++ b/sys-block/f3/files/f3-6.0-use-argp_parse.patch
@@ -0,0 +1,417 @@
+From fb187b4c710714a56d74af8a50adccd6118445e7 Mon Sep 17 00:00:00 2001
+From: zwpwjwtz <zwpwjwtz@126.com>
+Date: Tue, 29 Mar 2016 15:36:04 +0800
+Subject: [PATCH] Replace parse_args() with argp_parse() from argp.h
+
+---
+ f3read.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ f3write.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ utils.c | 92 ----------------------------------------------------
+ utils.h | 5 ---
+ 4 files changed, 200 insertions(+), 113 deletions(-)
+
+diff --git a/f3read.c b/f3read.c
+index 2dc6942..683232d 100644
+--- a/f3read.c
++++ b/f3read.c
+@@ -12,8 +12,100 @@
+ #include <unistd.h>
+ #include <err.h>
+ #include <sys/time.h>
++#include <limits.h>
++#include <argp.h>
+
+ #include "utils.h"
++#include "version.h"
++
++/* Argp's global variables. */
++const char *argp_program_version = "F3 Read " F3_STR_VERSION;
++
++/* Arguments. */
++static char adoc[] = "<PATH>";
++
++static char doc[] = "F3 Read -- test real flash memory capacity\n"
++ "Copyright (C) 2010 Digirati Internet LTDA.\n"
++ "This is free software; see the source for copying conditions.\n";
++
++static struct argp_option options[] = {
++ {"start-at", 's', "NUM", 0,
++ "Disk type of the partition table", 0},
++ {"end-at", 'e', "NUM", 0,
++ "Type of the file system of the partition", 0},
++ {"progress", 'p', NULL, 0,
++ "Show progress of the operation (default)", 0},
++ { 0 }
++};
++
++struct args {
++ long start_at;
++ long end_at;
++ int show_progress;
++ const char *dev_path;
++};
++
++static error_t parse_opt(int key, char *arg, struct argp_state *state)
++{
++ struct args *args = state->input;
++ char *endptr;
++
++ switch (key) {
++ case 's':
++ args->start_at = strtol(arg, &endptr, 10);
++ if (*endptr != '\0')
++ argp_error(state, "Option --start-at must be a number");
++ break;
++
++ case 'e':
++ args->end_at = strtol(arg, &endptr, 10);
++ if (*endptr != '\0')
++ argp_error(state, "Option --end-at must be a number");
++ break;
++
++ case 'p':
++ args->show_progress = 1;
++ break;
++
++ case ARGP_KEY_INIT:
++ args->dev_path = NULL;
++ args->start_at = 0;
++ args->end_at = LONG_MAX;
++ args->show_progress = 0;
++ break;
++
++ case ARGP_KEY_ARG:
++ if (args->dev_path)
++ argp_error(state,
++ "Wrong number of arguments; only one is allowed");
++ args->dev_path = arg;
++ break;
++
++ case ARGP_KEY_END:
++ if (!args->dev_path)
++ argp_error(state,
++ "The disk path was not specified");
++
++ if (args->start_at < 0)
++ argp_error(state,
++ "Option --start-at must be greater than 0");
++
++ if (args->end_at < 0)
++ argp_error(state,
++ "Option --end-at must be greater than 0");
++
++ if (args->start_at > args->end_at)
++ argp_error(state,
++ "Option --start-at must be less or equal to option --end-at");
++ break;
++
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
++ return 0;
++}
++
++static struct argp argp = {options, parse_opt, adoc, doc, NULL, NULL, NULL};
+
+ static inline void update_dt(struct timeval *dt, const struct timeval *t1,
+ const struct timeval *t2)
+@@ -228,20 +320,21 @@ static void iterate_files(const char *path, const long *files,
+
+ int main(int argc, char **argv)
+ {
+- long start_at, end_at;
+- const char *path;
+ const long *files;
+- int progress;
++ struct args args;
+ int rc;
+-
+- rc = parse_args("read", argc, argv, &start_at, &end_at, &path);
++ rc = argp_parse(&argp, argc, argv, 0, NULL, &args);
+ if (rc)
+ return rc;
+
+- files = ls_my_files(path, start_at, end_at);
+ /* If stdout isn't a terminal, supress progress. */
+- progress = isatty(STDOUT_FILENO);
+- iterate_files(path, files, start_at, end_at, progress);
++ if (!args.show_progress)
++ args.show_progress = isatty(STDOUT_FILENO);
++
++ files = ls_my_files(args.dev_path, args.start_at, args.end_at);
++ /* If stdout isn't a terminal, supress progress. */
++
++ iterate_files(args.dev_path, files, args.start_at, args.end_at, args.show_progress);
+ free((void *)files);
+ return 0;
+ }
+diff --git a/f3write.c b/f3write.c
+index b964059..bfef27e 100644
+--- a/f3write.c
++++ b/f3write.c
+@@ -15,8 +15,99 @@
+ #include <unistd.h>
+ #include <err.h>
+ #include <math.h>
++#include <argp.h>
+
+ #include "utils.h"
++#include "version.h"
++
++/* Argp's global variables. */
++const char *argp_program_version = "F3 Write " F3_STR_VERSION;
++
++/* Arguments. */
++static char adoc[] = "<PATH>";
++
++static char doc[] = "F3 Write -- test real flash memory capacity\n"
++ "Copyright (C) 2010 Digirati Internet LTDA.\n"
++ "This is free software; see the source for copying conditions.\n";
++
++static struct argp_option options[] = {
++ {"start-at", 's', "NUM", 0,
++ "Disk type of the partition table", 0},
++ {"end-at", 'e', "NUM", 0,
++ "Type of the file system of the partition", 0},
++ {"progress", 'p', NULL, 0,
++ "Show progress of the operation (default)", 0},
++ { 0 }
++};
++
++struct args {
++ long start_at;
++ long end_at;
++ int show_progress;
++ const char *dev_path;
++};
++
++static error_t parse_opt(int key, char *arg, struct argp_state *state)
++{
++ struct args *args = state->input;
++ char *endptr;
++
++ switch (key) {
++ case 's':
++ args->start_at = strtol(arg, &endptr, 10);
++ if (*endptr != '\0')
++ argp_error(state, "Option --start-at must be a number");
++ break;
++
++ case 'e':
++ args->end_at = strtol(arg, &endptr, 10);
++ if (*endptr != '\0')
++ argp_error(state, "Option --end-at must be a number");
++ break;
++
++ case 'p':
++ args->show_progress = 1;
++ break;
++
++ case ARGP_KEY_INIT:
++ args->dev_path = NULL;
++ args->start_at = 0;
++ args->end_at = LONG_MAX;
++ args->show_progress = 0;
++ break;
++
++ case ARGP_KEY_ARG:
++ if (args->dev_path)
++ argp_error(state,
++ "Wrong number of arguments; only one is allowed");
++ args->dev_path = arg;
++ break;
++
++ case ARGP_KEY_END:
++ if (!args->dev_path)
++ argp_error(state,
++ "The disk path was not specified");
++
++ if (args->start_at < 0)
++ argp_error(state,
++ "Option --start-at must be greater than 0");
++
++ if (args->end_at < 0)
++ argp_error(state,
++ "Option --end-at must be greater than 0");
++
++ if (args->start_at > args->end_at)
++ argp_error(state,
++ "Option --start-at must be less or equal to option --end-at");
++ break;
++
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
++ return 0;
++}
++
++static struct argp argp = {options, parse_opt, adoc, doc, NULL, NULL, NULL};
+
+ static uint64_t fill_buffer(void *buf, size_t size, uint64_t offset)
+ {
+@@ -464,17 +555,17 @@ static void unlink_old_files(const char *path, long start_at, long end_at)
+
+ int main(int argc, char **argv)
+ {
+- long start_at, end_at;
+- const char *path;
+- int progress;
++ struct args args;
+ int rc;
+-
+- rc = parse_args("write", argc, argv, &start_at, &end_at, &path);
++ rc = argp_parse(&argp, argc, argv, 0, NULL, &args);
+ if (rc)
+ return rc;
+
+- unlink_old_files(path, start_at, end_at);
++ unlink_old_files(args.dev_path, args.start_at, args.end_at);
++
+ /* If stdout isn't a terminal, supress progress. */
+- progress = isatty(STDOUT_FILENO);
+- return fill_fs(path, start_at, end_at, progress);
++ if (!args.show_progress)
++ args.show_progress = isatty(STDOUT_FILENO);
++
++ return fill_fs(args.dev_path, args.start_at, args.end_at, args.show_progress);
+ }
+diff --git a/utils.c b/utils.c
+index a30ea3b..6aaceff 100644
+--- a/utils.c
++++ b/utils.c
+@@ -13,13 +13,11 @@
+ #include <string.h>
+ #include <ctype.h>
+ #include <assert.h>
+-#include <limits.h>
+ #include <sys/types.h>
+ #include <dirent.h>
+ #include <errno.h>
+ #include <err.h>
+
+-#include "version.h"
+ #include "utils.h"
+
+ const char *adjust_unit(double *ptr_bytes)
+@@ -60,87 +58,6 @@ char *full_fn_from_number(const char **filename, const char *path, long num)
+ return str;
+ }
+
+-/* Parse @param and return the start-at parameter.
+- * The string must be of the format "--start-at=NUM"; otherwise it returns -1.
+- */
+-#define START_AT_TEXT "--start-at="
+-#define END_AT_TEXT "--end-at="
+-
+-static inline int is_param(const char *text, const char *param)
+-{
+- return !strncmp(param, text, strlen(text));
+-}
+-
+-static long parse_long_param(const char *param)
+-{
+- char *endptr;
+- long value;
+-
+- /* Skip text. */
+- while (*param != '=') {
+- if (*param == '\0')
+- return -1;
+- param++;
+- }
+- param++; /* Skip '='. */
+-
+- value = strtol(param, &endptr, 10);
+- if (*endptr != '\0')
+- return -1;
+-
+- return (value <= 0 || value == LONG_MAX) ? -1 : value - 1;
+-}
+-
+-static int parse_param(const char *param, long *pstart_at, long *pend_at)
+-{
+- if (is_param(START_AT_TEXT, param))
+- *pstart_at = parse_long_param(param);
+- else if (is_param(END_AT_TEXT, param))
+- *pend_at = parse_long_param(param);
+- else
+- return 1;
+- return 0;
+-}
+-
+-int parse_args(const char *name, int argc, char **argv,
+- long *pstart_at, long *pend_at, const char **ppath)
+-{
+- *pstart_at = 0;
+- *pend_at = LONG_MAX - 1;
+-
+- switch (argc) {
+- case 2:
+- *ppath = argv[1];
+- break;
+-
+- case 3:
+- if (parse_param(argv[1], pstart_at, pend_at))
+- goto error;
+- *ppath = argv[2];
+- break;
+-
+- case 4:
+- if (parse_param(argv[1], pstart_at, pend_at))
+- goto error;
+- if (parse_param(argv[2], pstart_at, pend_at))
+- goto error;
+- *ppath = argv[3];
+- break;
+-
+- default:
+- goto error;
+- }
+-
+- if (*pstart_at >= 0 && *pend_at >= 0 && *pstart_at <= *pend_at)
+- return 0;
+-
+-error:
+- print_header(stderr, name);
+- fprintf(stderr, "Usage: f3%s [%sNUM] [%sNUM] <PATH>\n",
+- name, START_AT_TEXT, END_AT_TEXT);
+- return 1;
+-}
+-
+ static long number_from_filename(const char *filename)
+ {
+ const char *p;
+@@ -218,15 +135,6 @@ const long *ls_my_files(const char *path, long start_at, long end_at)
+ return ret;
+ }
+
+-void print_header(FILE *f, const char *name)
+-{
+- fprintf(f,
+- "F3 %s " F3_STR_VERSION "\n"
+- "Copyright (C) 2010 Digirati Internet LTDA.\n"
+- "This is free software; see the source for copying conditions.\n"
+- "\n", name);
+-}
+-
+ #if __APPLE__ && __MACH__
+
+ /* This function is a _rough_ approximation of fdatasync(2). */
+diff --git a/utils.h b/utils.h
+index 6b7c92f..4fdbce2 100644
+--- a/utils.h
++++ b/utils.h
+@@ -22,13 +22,8 @@ static inline long delay_ms(const struct timeval *t1, const struct timeval *t2)
+ (t2->tv_usec - t1->tv_usec) / 1000;
+ }
+
+-int parse_args(const char *name, int argc, char **argv,
+- long *pstart_at, long *pend_at, const char **ppath);
+-
+ const long *ls_my_files(const char *path, long start_at, long end_at);
+
+-void print_header(FILE *f, const char *name);
+-
+ static inline uint64_t random_number(uint64_t prv_number)
+ {
+ return prv_number * 4294967311ULL + 17;
diff --git a/sys-block/f3/metadata.xml b/sys-block/f3/metadata.xml
new file mode 100644
index 000000000000..2313fa6014ca
--- /dev/null
+++ b/sys-block/f3/metadata.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="person">
+ <email>whissi@gentoo.org</email>
+ <name>Thomas Deutschmann</name>
+ </maintainer>
+ <longdescription lang="en">
+ F3 - an alternative to h2testw
+
+ The "Fight Flash Fraud" or "Fight Fake Flash" tool represents
+ a GPLv3 implementation of the algorithm of h2testw and further
+ improvements to speed up the identification of fake drives
+ as well as making them usable.
+
+ You can also use these utilities if you want to test the
+ integrity of your USB/flash medium.
+ </longdescription>
+ <upstream>
+ <bugs-to>https://github.com/AltraMayor/f3/issues</bugs-to>
+ <remote-id type="github">AltraMayor/f3</remote-id>
+ </upstream>
+ <use>
+ <flag name="extra">Build the additional f3probe, f3brew and f3fix utility (requires <pkg>sys-block/parted</pkg> and <pkg>virtual/udev</pkg>)</flag>
+ </use>
+</pkgmetadata>