Compare commits
8 commits
117d01fcbe
...
f37e28c4ef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f37e28c4ef | ||
|
|
4127ad6333 | ||
|
|
d1d3b3cd45 | ||
|
|
36a98b2630 | ||
|
|
9723924222 | ||
|
|
d0a3db77e9 | ||
|
|
078ba792f0 | ||
|
|
734c1c10ec |
3 changed files with 99 additions and 32 deletions
6
Makefile
6
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
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.2.1"
|
VERSION ?= "$(shell git describe --tags --always --abbrev=0 2>/dev/null || git rev-parse --short HEAD)"
|
||||||
|
|
||||||
CFLAGS ?= -Wall -Wextra -Wpedantic -O2 -std=gnu99
|
CFLAGS ?= -Wall -Wextra -Wpedantic -O2 -std=gnu99
|
||||||
CFLAGS += -DGITREV='"$(GITREV)"'
|
CFLAGS += -DGITREV='"$(GITREV)"'
|
||||||
|
|
@ -10,10 +10,6 @@ CFLAGS += -DCR_YEAR='"$(CR_YEAR)"'
|
||||||
CFLAGS += -DVERSION='$(VERSION)'
|
CFLAGS += -DVERSION='$(VERSION)'
|
||||||
CFLAGS += $(EXTRA_CFLAGS)
|
CFLAGS += $(EXTRA_CFLAGS)
|
||||||
|
|
||||||
# Soon...
|
|
||||||
# CFLAGS += $(shell pkg-config --cflags libudev)
|
|
||||||
# LIBS += $(shell pkg-config --libs libudev)
|
|
||||||
|
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
DESTDIR ?=
|
DESTDIR ?=
|
||||||
|
|
||||||
|
|
|
||||||
65
test.sh
Normal file
65
test.sh
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/env/bin bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
# set -x # For debugging
|
||||||
|
|
||||||
|
# If you ever mess this up:
|
||||||
|
# $ sudo mknod /dev/loop-control c 10 237
|
||||||
|
# $ sudo chmod 600 /dev/loop-control
|
||||||
|
# $ sudo chown root:root /dev/loop-control
|
||||||
|
#
|
||||||
|
# For cleanup:
|
||||||
|
# $ sudo find /dev -maxdepth 1 -type b -name 'loop[0-9]*' -exec rm -f {} \;
|
||||||
|
|
||||||
|
|
||||||
|
DISKFILE="/tmp/disk.img"
|
||||||
|
BINFILE="/tmp/file.bin"
|
||||||
|
LOOPNUM=$((RANDOM % 156 + 100))
|
||||||
|
LOOPDEV="/dev/loop${LOOPNUM}"
|
||||||
|
|
||||||
|
echo "Using device: ${LOOPDEV}"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "Cleaning up..."
|
||||||
|
set +e -x
|
||||||
|
sudo losetup -d ${LOOPDEV}
|
||||||
|
sudo rm ${LOOPDEV}
|
||||||
|
sudo rm ${BINFILE} ${DISKFILE}
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
if losetup ${LOOPDEV} >/dev/null 2>&1; then
|
||||||
|
echo "${LOOPDEV} already in use" >&2
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f ${DISKFILE} ]; then
|
||||||
|
dd if=/dev/zero of=${DISKFILE} bs=1M count=256
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f ${BINFILE} ]; then
|
||||||
|
dd if=/dev/urandom of=${BINFILE} bs=1M count=64
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ${LOOPDEV} ]; then
|
||||||
|
sudo losetup ${LOOPDEV} ${DISKFILE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo ./writeimg -nd ${LOOPDEV} ${BINFILE}
|
||||||
|
sudo ./writeimg -vnd ${LOOPDEV} ${BINFILE}
|
||||||
|
|
||||||
|
sudo ./writeimg -nd ${LOOPDEV} ./writeimg
|
||||||
|
sudo ./writeimg -vnd ${LOOPDEV} ./writeimg
|
||||||
|
|
||||||
|
sudo ./writeimg -nd ${LOOPDEV} ./LICENSE
|
||||||
|
sudo ./writeimg -vnd ${LOOPDEV} ./LICENSE
|
||||||
|
|
||||||
|
# Redirect this to avoid confusion
|
||||||
|
! sudo ./writeimg -vnd ${LOOPDEV} ./crc32.h 2>/dev/null
|
||||||
|
|
||||||
|
GREEN="\e[32m"
|
||||||
|
RESET="\e[0m"
|
||||||
|
|
||||||
|
echo -e "\n\n${GREEN}Looks good!${RESET}"
|
||||||
60
writeimg.c
60
writeimg.c
|
|
@ -32,6 +32,10 @@
|
||||||
#define BLOCKSIZE (1024 * 1024)
|
#define BLOCKSIZE (1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WI_VERIFY (1 << 0)
|
||||||
|
#define WI_WRITE (1 << 1)
|
||||||
|
#define WI_ASK (1 << 2)
|
||||||
|
|
||||||
#define BYTES_TO_MIB(bts) ((double)bts / (1024 * 1024))
|
#define BYTES_TO_MIB(bts) ((double)bts / (1024 * 1024))
|
||||||
|
|
||||||
#define BAR_WIDTH 50
|
#define BAR_WIDTH 50
|
||||||
|
|
@ -69,14 +73,14 @@ const char help[] =
|
||||||
const char copyright[] = "Copyright (C) %s Imbus, BSD-2-Clause\n";
|
const char copyright[] = "Copyright (C) %s Imbus, BSD-2-Clause\n";
|
||||||
|
|
||||||
struct write_job {
|
struct write_job {
|
||||||
char *filename;
|
char *iname;
|
||||||
char *dev_name;
|
char *oname;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
char *buffer2; /* For memcmp integrity checks */
|
char *buffer2; /* For memcmp integrity checks */
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
size_t block_size;
|
size_t block_size;
|
||||||
size_t total_bytes;
|
size_t total_bytes;
|
||||||
char verify_only;
|
char flags;
|
||||||
} wjob = {0};
|
} wjob = {0};
|
||||||
|
|
||||||
typedef struct write_job write_job_t;
|
typedef struct write_job write_job_t;
|
||||||
|
|
@ -94,8 +98,8 @@ void int_handler(int signum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int perform_write(write_job_t *job) {
|
int perform_write(write_job_t *job) {
|
||||||
int block_fd = open(job->dev_name, O_RDWR);
|
int block_fd = open(job->oname, O_RDWR);
|
||||||
int file_fd = open(job->filename, O_RDONLY);
|
int file_fd = open(job->iname, O_RDONLY);
|
||||||
|
|
||||||
assert(block_fd >= 0);
|
assert(block_fd >= 0);
|
||||||
assert(file_fd >= 0);
|
assert(file_fd >= 0);
|
||||||
|
|
@ -114,7 +118,7 @@ int perform_write(write_job_t *job) {
|
||||||
if (read_bytes == 0) {
|
if (read_bytes == 0) {
|
||||||
crc = crc32_finalize(crc);
|
crc = crc32_finalize(crc);
|
||||||
|
|
||||||
if (!job->verify_only) {
|
if (job->flags & WI_WRITE) {
|
||||||
printf("\nWriting done...\n");
|
printf("\nWriting done...\n");
|
||||||
assert(job->total_bytes == b_written);
|
assert(job->total_bytes == b_written);
|
||||||
} else
|
} else
|
||||||
|
|
@ -124,17 +128,17 @@ int perform_write(write_job_t *job) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_bytes < 0) {
|
if (read_bytes < 0) {
|
||||||
fprintf(stderr, "%s: Read error\n", job->filename);
|
fprintf(stderr, "%s: Read error\n", job->iname);
|
||||||
perror("Read");
|
perror("Read");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
crc = crc32_update(crc, job->buffer, read_bytes);
|
crc = crc32_update(crc, job->buffer, read_bytes);
|
||||||
|
|
||||||
if (!job->verify_only) {
|
if (job->flags & WI_WRITE) {
|
||||||
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->oname);
|
||||||
perror("Write");
|
perror("Write");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +199,7 @@ static const struct option longopts[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
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", "WriteIMG", VERSION, GITREV);
|
||||||
|
|
||||||
/* Line buffering, system allocated */
|
/* Line buffering, system allocated */
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
@ -206,14 +210,18 @@ 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;
|
wjob.flags = WI_VERIFY | WI_WRITE | WI_ASK;
|
||||||
|
|
||||||
int c = {0};
|
int c = {0};
|
||||||
while ((c = getopt_long(argc, argv, "vd:hnV", 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':
|
||||||
case 'd': wjob.dev_name = optarg; continue;
|
wjob.flags |= WI_VERIFY;
|
||||||
|
wjob.flags &= ~WI_WRITE;
|
||||||
|
continue;
|
||||||
|
case 'd': wjob.oname = optarg; continue;
|
||||||
case 'h': break;
|
case 'h': break;
|
||||||
case 'n': --ask_permission; continue;
|
case 'n': wjob.flags &= ~WI_ASK; continue;
|
||||||
case 'V': exit(EXIT_SUCCESS);
|
case 'V': exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
printf("In honor of SwePwnage - the OG disk destroyer\n");
|
printf("In honor of SwePwnage - the OG disk destroyer\n");
|
||||||
|
|
@ -236,27 +244,27 @@ int main(int argc, char *argv[]) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
wjob.filename = argv[0];
|
wjob.iname = argv[0];
|
||||||
struct stat file_stat = {0};
|
struct stat file_stat = {0};
|
||||||
if (0 != stat(wjob.filename, &file_stat)) {
|
if (0 != stat(wjob.iname, &file_stat)) {
|
||||||
printf("File does not exist...\n");
|
printf("File does not exist...\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == wjob.dev_name) {
|
if (NULL == wjob.oname) {
|
||||||
printf("You need to specify a device.\n");
|
printf("You need to specify a device.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != strncmp(wjob.dev_name, "/dev/", 4)) {
|
if (0 != strncmp(wjob.oname, "/dev/", 4)) {
|
||||||
printf("\"%s\" does not appear to be a block device...\n", wjob.dev_name);
|
printf("\"%s\" does not appear to be a block device...\n", wjob.oname);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Seems to be the cleanest way to check for write perm on a blockdev */
|
/* Seems to be the cleanest way to check for write perm on a blockdev */
|
||||||
int fd = open(wjob.dev_name, O_WRONLY);
|
int fd = open(wjob.oname, O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printf("Cannot write to \"%s\", do you have write permissions?\n", wjob.dev_name);
|
printf("Cannot write to \"%s\", do you have write permissions?\n", wjob.oname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
@ -264,13 +272,11 @@ int main(int argc, char *argv[]) {
|
||||||
wjob.total_bytes = file_stat.st_size;
|
wjob.total_bytes = file_stat.st_size;
|
||||||
assert(file_stat.st_size >= 0);
|
assert(file_stat.st_size >= 0);
|
||||||
|
|
||||||
if (!wjob.verify_only)
|
if (wjob.flags & WI_WRITE)
|
||||||
printf("Writing \"%s\" (%.1f MiB) to \"%s\"\n",
|
printf(
|
||||||
basename(wjob.filename),
|
"Writing \"%s\" (%.1f MiB) to \"%s\"\n", basename(wjob.iname), BYTES_TO_MIB(wjob.total_bytes), wjob.oname);
|
||||||
BYTES_TO_MIB(wjob.total_bytes),
|
|
||||||
wjob.dev_name);
|
|
||||||
|
|
||||||
if (ask_permission && !wjob.verify_only) {
|
if ((wjob.flags & WI_ASK) && (wjob.flags & WI_WRITE)) {
|
||||||
printf("Is this okay? (y/N): ");
|
printf("Is this okay? (y/N): ");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if ('y' != getchar()) {
|
if ('y' != getchar()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue