commit: b5ec27b88c9b729e08f49b748d7b8728d9f2496c
parent b5b2501370c212422a542a36e6e849e684c15cfa
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Tue, 15 Feb 2022 01:09:14 +0100
bin/xcd: Check for write errors
Diffstat:
M | bin/xcd.c | 127 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
M | test-bin/xcd | 10 | ++++++++++ |
2 files changed, 111 insertions(+), 26 deletions(-)
diff --git a/bin/xcd.c b/bin/xcd.c
@@ -10,14 +10,12 @@
#include <stdio.h> /* printf(), fread(), fopen(), fclose() */
#include <string.h> /* memset(), strerror() */
-#define LANODAN_XCD_RESET printf("[0m[48;2;0;0;0m");
-
-struct rgb
+static struct rgb
{
double red, green, blue;
};
-struct rgb
+static struct rgb
rgb_char(unsigned char i)
{
double freq = 0.018;
@@ -39,31 +37,65 @@ rgb_char(unsigned char i)
}
}
-void
+static int
print_hex_rgb(unsigned char c)
{
struct rgb color = rgb_char(c);
- printf("[38;2;%d;%d;%dm%02hhx ", (int)color.red, (int)color.green, (int)color.blue, c);
+
+ int ret = printf("[38;2;%d;%d;%dm%02hhx ", (int)color.red, (int)color.green, (int)color.blue, c);
+
+ return (ret <= 0) ? 1 : 0;
+}
+
+static int
+print_xcd_reset()
+{
+ int ret = printf("[0m[48;2;0;0;0m");
+
+ return (ret <= 0) ? 1 : 0;
}
-void
+static int
print_plain_rgb(char *line, size_t len)
{
- LANODAN_XCD_RESET
- printf(" >");
+ if(print_xcd_reset() != 0)
+ {
+ return 1;
+ }
+
+ if(printf(" >") <= 0)
+ {
+ return 1;
+ }
for(size_t i = 0; i < len; i++)
{
struct rgb color = rgb_char((unsigned char)line[i]);
- printf("[38;2;%d;%d;%dm%c",
- (int)color.red,
- (int)color.green,
- (int)color.blue,
- isprint(line[i]) ? line[i] : '.');
+ int ret = 0;
+
+ ret = printf("[38;2;%d;%d;%dm%c",
+ (int)color.red,
+ (int)color.green,
+ (int)color.blue,
+ isprint(line[i]) ? line[i] : '.');
+
+ if(ret <= 0)
+ {
+ return 1;
+ }
+ }
+
+ if(print_xcd_reset() != 0)
+ {
+ return 1;
+ }
+
+ if(printf("<") <= 0)
+ {
+ return 1;
}
- LANODAN_XCD_RESET
- printf("<");
+ return 0;
}
#define WIDTH 16
@@ -76,14 +108,25 @@ concat(FILE *stream)
char c;
unsigned int bytes = 0;
struct rgb pos_rgb;
- errno = 0;
+ int ret = 0;
+ errno = 0;
memset(&line, 0, WIDTH);
- LANODAN_XCD_RESET
+ if(print_xcd_reset() != 0)
+ {
+ return 1;
+ }
pos_rgb = rgb_char((unsigned char)bytes);
- printf("[38;2;%d;%d;%dm%06x ", (int)pos_rgb.red, (int)pos_rgb.green, (int)pos_rgb.blue, bytes);
+
+ ret = printf(
+ "[38;2;%d;%d;%dm%06x ", (int)pos_rgb.red, (int)pos_rgb.green, (int)pos_rgb.blue, bytes);
+ if(ret <= 0)
+ {
+ goto werr;
+ }
+
while(fread(&c, 1, 1, stream) > 0)
{
if(cols >= WIDTH)
@@ -101,7 +144,12 @@ concat(FILE *stream)
cols = 0;
}
- print_hex_rgb((unsigned char)c);
+ ret = print_hex_rgb((unsigned char)c);
+ if(ret != 0)
+ {
+ goto werr;
+ }
+
line[cols] = c;
cols++;
@@ -110,17 +158,44 @@ concat(FILE *stream)
// Fill the rest of the hex space with spaces
for(; cols < WIDTH; cols++)
- printf(" ");
+ {
+ ret = printf(" ");
+
+ if(ret <= 0)
+ {
+ goto werr;
+ }
+ }
+
+ if(print_xcd_reset() != 0)
+ {
+ goto werr;
+ }
- LANODAN_XCD_RESET
- print_plain_rgb(line, (size_t)cols);
+ ret = print_plain_rgb(line, (size_t)cols);
+ if(ret != 0)
+ {
+ goto werr;
+ }
pos_rgb = rgb_char((unsigned char)bytes);
- printf(
- "\n[38;2;%d;%d;%dm%06x\n", (int)pos_rgb.red, (int)pos_rgb.green, (int)pos_rgb.blue, bytes);
- LANODAN_XCD_RESET
+ ret = printf(
+ "\n[38;2;%d;%d;%dm%06x\n", (int)pos_rgb.red, (int)pos_rgb.green, (int)pos_rgb.blue, bytes);
+ if(ret <= 0)
+ {
+ goto werr;
+ }
+
+ if(print_xcd_reset() != 0)
+ {
+ goto werr;
+ }
return 0;
+
+werr:
+ fprintf(stderr, "\n[0mWrite error: %s\n", strerror(errno));
+ return 1;
}
int
diff --git a/test-bin/xcd b/test-bin/xcd
@@ -7,6 +7,7 @@ openfile_body() {
atf_test_case stdinput
stdinput_body() {
atf_check -o file:outputs/xcd/all_bytes ../bin/xcd <inputs/all_bytes
+ atf_check -o file:outputs/xcd/all_bytes ../bin/xcd - <inputs/all_bytes
}
atf_test_case nullfile
@@ -31,6 +32,14 @@ noperm_cleanup() {
rm inputs/chmod_000 || atf_fail "rm chmod_000"
}
+atf_test_case devfull
+devfull_body() {
+ # shellcheck disable=SC1112
+ atf_check -s 'exit:1' -e 'inline:\n[0mWrite error: No space left on device\n\n[0mError closing ‘inputs/strings/true’: No space left on device\n' sh -c '../bin/xcd inputs/strings/true >/dev/full'
+ atf_check -s 'exit:1' -e 'inline:\n[0mWrite error: No space left on device\n' sh -c '../bin/xcd <inputs/strings/true >/dev/full'
+ atf_check -s 'exit:1' -e 'inline:\n[0mWrite error: No space left on device\n' sh -c '../bin/xcd - <inputs/strings/true >/dev/full'
+}
+
atf_init_test_cases() {
cd "$(atf_get_srcdir)" || exit 1
atf_add_test_case openfile
@@ -38,4 +47,5 @@ atf_init_test_cases() {
atf_add_test_case nullfile
atf_add_test_case nullinput
atf_add_test_case noperm
+ atf_add_test_case devfull
}