Compare commits

...

8 commits

Author SHA1 Message Date
Imbus
ab43512e42 Bump to v0.2.0 2026-02-07 17:36:37 +01:00
Imbus
3bfbfd46fa Move noisy metadata info into help section 2026-02-07 17:36:29 +01:00
Imbus
c67c68615a Add noconfirm flag 2026-02-07 17:24:31 +01:00
Imbus
13e27bbcc1 Flush block device with ioctl before reading it back 2026-02-07 17:24:16 +01:00
Imbus
c08ee6a738 Guard for verify only 2026-02-07 17:23:27 +01:00
Imbus
19bf88b2e6 Block size set to 1MiB 2026-02-07 17:22:06 +01:00
Imbus
824f975510 Include EXTRA_CFLAGS for optional extras 2026-02-07 17:21:48 +01:00
Imbus
be2f00b91c Clang-format 2026-02-07 17:20:00 +01:00
3 changed files with 78 additions and 33 deletions

20
.clang-format Normal file
View file

@ -0,0 +1,20 @@
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 120
AllowShortLoopsOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializers: BeforeComma
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveMacros: true
AllowShortCaseLabelsOnASingleLine: true
SeparateDefinitionBlocks: Always
BinPackArguments: false

View file

@ -1,13 +1,14 @@
GITREV ?= $(shell git describe --dirty --always) GITREV ?= $(shell git describe --dirty --always)
BLDDATE ?= $(shell date -I) BLDDATE ?= $(shell date -I)
CR_YEAR ?= $(shell date +%Y) CR_YEAR ?= $(shell date +%Y)
VERSION ?= "v0.1.2" VERSION ?= "v0.2.0"
CFLAGS ?= -Wall -Wextra -Wpedantic -O2 -std=gnu99 CFLAGS ?= -Wall -Wextra -Wpedantic -O2 -std=gnu99
CFLAGS += -DGITREV='"$(GITREV)"' CFLAGS += -DGITREV='"$(GITREV)"'
CFLAGS += -DBLDDATE='"$(BLDDATE)"' CFLAGS += -DBLDDATE='"$(BLDDATE)"'
CFLAGS += -DCR_YEAR='"$(CR_YEAR)"' CFLAGS += -DCR_YEAR='"$(CR_YEAR)"'
CFLAGS += -DVERSION='$(VERSION)' CFLAGS += -DVERSION='$(VERSION)'
CFLAGS += $(EXTRA_CFLAGS)
# Soon... # Soon...
# CFLAGS += $(shell pkg-config --cflags libudev) # CFLAGS += $(shell pkg-config --cflags libudev)

View file

@ -11,6 +11,11 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#if __linux__
#include <linux/fs.h> /* IOTCL flush number */
#include <sys/ioctl.h> /* IOCTL */
#endif
#ifndef GITREV #ifndef GITREV
#define GITREV "unknown" #define GITREV "unknown"
#endif #endif
@ -24,7 +29,7 @@
#endif #endif
#ifndef BLOCKSIZE #ifndef BLOCKSIZE
#define BLOCKSIZE (4 * 1024 * 1024) #define BLOCKSIZE (1024 * 1024)
#endif #endif
#define BYTES_TO_MIB(bts) ((double)bts / (1024 * 1024)) #define BYTES_TO_MIB(bts) ((double)bts / (1024 * 1024))
@ -56,6 +61,7 @@ const char help[] =
" -v Verify only\n" " -v Verify only\n"
" -d device Target block device\n" " -d device Target block device\n"
" -h, --help Print this help message\n" " -h, --help Print this help message\n"
" -n, --noconfirm Do not ask for premission\n"
" -V, --version Print version\n" " -V, --version Print version\n"
"\0"; "\0";
// clang-format on // clang-format on
@ -100,15 +106,20 @@ int perform_write(write_job_t *job) {
int crc = crc32_init(); int crc = crc32_init();
size_t b_written = 0; size_t b_written = 0;
while (!job->verify_only) { while (42) {
fsync(block_fd);
ssize_t read_bytes = read(file_fd, job->buffer, job->block_size); ssize_t read_bytes = read(file_fd, job->buffer, job->block_size);
assert(read_bytes >= 0); assert(read_bytes >= 0);
if (read_bytes == 0) { if (read_bytes == 0) {
fsync(block_fd);
crc = crc32_finalize(crc); crc = crc32_finalize(crc);
if (!job->verify_only) {
printf("\nWriting done...\n"); printf("\nWriting done...\n");
assert(job->total_bytes == b_written); assert(job->total_bytes == b_written);
} else
assert(0 == b_written);
break; /* Finished */ break; /* Finished */
} }
@ -120,6 +131,7 @@ int perform_write(write_job_t *job) {
crc = crc32_update(crc, job->buffer, read_bytes); crc = crc32_update(crc, job->buffer, read_bytes);
if (!job->verify_only) {
ssize_t written_bytes = write(block_fd, job->buffer, read_bytes); ssize_t written_bytes = write(block_fd, job->buffer, read_bytes);
if (written_bytes < 0) { if (written_bytes < 0) {
fprintf(stderr, "%s: Write error\n", job->dev_name); fprintf(stderr, "%s: Write error\n", job->dev_name);
@ -127,6 +139,7 @@ int perform_write(write_job_t *job) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
print_progress(b_written += written_bytes, job->total_bytes); print_progress(b_written += written_bytes, job->total_bytes);
} /* Else maybe give some helpful insights? */
} }
lseek(block_fd, 0, SEEK_SET); lseek(block_fd, 0, SEEK_SET);
@ -135,6 +148,9 @@ int perform_write(write_job_t *job) {
memset(job->buffer, 0, BLOCKSIZE); memset(job->buffer, 0, BLOCKSIZE);
memset(job->buffer2, 0, BLOCKSIZE); memset(job->buffer2, 0, BLOCKSIZE);
/* This is essentially $ blockdev --flushbufs */
ioctl(block_fd, BLKFLSBUF);
int crc_back = crc32_init(); int crc_back = crc32_init();
b_written = 0; b_written = 0;
@ -173,16 +189,12 @@ static const struct option longopts[] = {
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"version", 0, 0, 'V'}, {"version", 0, 0, 'V'},
{"device", 1, 0, 'd'}, {"device", 1, 0, 'd'},
{"noconfirm", 0, 0, 'n'},
{NULL, 0, 0, 0}, {NULL, 0, 0, 0},
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
printf("%s %s, Rev. %s\n", basename(argv[0]), VERSION, GITREV); printf("%s %s, Rev. %s\n", basename(argv[0]), VERSION, GITREV);
fprintf(stdout, copyright, CR_YEAR);
#ifdef BLDDATE
printf("Build date: %s\n", BLDDATE);
#endif
printf("\n");
/* Line buffering, system allocated */ /* Line buffering, system allocated */
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
@ -193,14 +205,22 @@ int main(int argc, char *argv[]) {
signal(SIGHUP, int_handler); signal(SIGHUP, int_handler);
signal(SIGTERM, int_handler); signal(SIGTERM, int_handler);
int ask_permission = 1;
int c = {0}; int c = {0};
while ((c = getopt_long(argc, argv, "vd:hV", longopts, 0)) != -1) { while ((c = getopt_long(argc, argv, "vd:hnV", longopts, 0)) != -1) {
switch (c) { switch (c) {
case 'v': ++wjob.verify_only; continue; case 'v': ++wjob.verify_only; continue;
case 'd': wjob.dev_name = optarg; continue; case 'd': wjob.dev_name = optarg; continue;
case 'h': break; case 'h': break;
case 'n': --ask_permission; continue;
case 'V': exit(EXIT_SUCCESS); case 'V': exit(EXIT_SUCCESS);
} }
printf("In honor of SwePwnage - the OG disk destroyer\n");
fprintf(stdout, copyright, CR_YEAR);
#ifdef BLDDATE
printf("Build date: %s\n", BLDDATE);
#endif
printf("\n");
printf("%s\n", help); printf("%s\n", help);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -223,7 +243,7 @@ int main(int argc, char *argv[]) {
} }
if (NULL == wjob.dev_name) { if (NULL == wjob.dev_name) {
printf("Device required...\n"); printf("You need to specify a device.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -240,12 +260,16 @@ int main(int argc, char *argv[]) {
} }
close(fd); close(fd);
if (!wjob.verify_only)
printf("Writing %s to %s\n", wjob.filename, wjob.dev_name); printf("Writing %s to %s\n", wjob.filename, wjob.dev_name);
if (ask_permission && !wjob.verify_only) {
printf("Is this okay? (y/n): "); printf("Is this okay? (y/n): ");
fflush(stdout); fflush(stdout);
if ('y' != getchar()) { if ('y' != getchar()) {
exit(0); printf("Aborting...\n");
exit(EXIT_SUCCESS);
}
} }
wjob.buffer = malloc(BLOCKSIZE); wjob.buffer = malloc(BLOCKSIZE);
@ -266,7 +290,7 @@ int main(int argc, char *argv[]) {
if (wjob.buffer2) if (wjob.buffer2)
free(wjob.buffer2); free(wjob.buffer2);
printf("\n%.1f MiB's written and verified.\nAll good!\n", BYTES_TO_MIB(wjob.total_bytes)); printf("\n%.1f MiB's verified.\nAll good!\n", BYTES_TO_MIB(wjob.total_bytes));
exit(0);
return 0; exit(EXIT_SUCCESS);
} }