draw the rest of the f*cking owl

This commit is contained in:
John 2022-02-23 21:59:14 -06:00
parent e91bbc1ff7
commit 565abb83ef
3 changed files with 126 additions and 55 deletions

View File

@ -2,15 +2,16 @@
CC = gcc CC = gcc
CFLAGS = CFLAGS =
EXEC := syscalls bscopy SRC := syscalls bscopy
OUT := syscalls.out bscopy.out
.PHONY: all clean .PHONY: all clean
all: $(EXEC) all: $(SRC)
%: %.c %: %.c
$(CC) $(CFLAGS) -o $@ $^ $(CC) $(CFLAGS) -o $@.out $^
clean: clean:
rm $(EXEC) rm $(OUT)

161
bscopy.c
View File

@ -12,9 +12,17 @@
#include <errno.h> // errno #include <errno.h> // errno
#include <time.h> // clock() #include <time.h> // clock()
// Bytes, Kilobytes, and Megabytes
#define B *1
#define KB *1024 B
#define MB *1024 KB
#define MAX_BLOCK_SIZE 2 KB
#define MAX_PATH_SIZE 4 KB
// F_ERROR: check file stream for errors; if error, print // F_ERROR: check file stream for errors; if error, print
#define F_ERROR(file_obj, ret) if (!file_obj) { printf ("%s: %s\n", #file_obj, strerror(ferror(file_obj)) ); return ret; } #define F_ERROR(file_obj, ret) if (!file_obj) { printf ("%s: %s\n", #file_obj, strerror(ferror(file_obj)) ); return ret; }
#define MAX_BLOCK_SIZE 0x800 // PATHCAT: concatenate paths
#define PATHCAT(dest, src) strncat(dest, src, MAX_PATH_SIZE - strlen(dest))
/* fcopy: copy in_filename to out_filename /* fcopy: copy in_filename to out_filename
args: args:
@ -43,41 +51,79 @@ int fcreate(size_t size, char* filename);
*/ */
int dircreate(char* path); int dircreate(char* path);
int main (int argc, char** argv) { // Tests in the first batch
int block_size = 1; #define FILESIZES_LEN 8
char *in = "/tmp/A", *out = "/tmp/B"; #define BLOCKSIZES_LEN 4
// get argument "block size", "in", "out" from args // {block size, file size}
switch (argc) { const int tests_filesize[FILESIZES_LEN + 1] =
case 4: {1 MB, 2 MB, 4 MB, 8 MB, 16 MB, 32 MB, 64 MB, 128 MB, 0};
out = argv[3]; const int tests_blocksize[BLOCKSIZES_LEN + 1] =
case 3: {1 B, 4 B, 64 B, 1024 B, 0};
in = argv[2];
case 2:
block_size = atoi(argv[1]);
if (block_size > MAX_BLOCK_SIZE) {
printf ("%d too long (must not exceed %d)\n", block_size, MAX_BLOCK_SIZE);
block_size = MAX_BLOCK_SIZE;
}
break;
case 1:
default:
printf ("Usage: %s block_size [in [out]]\n", argv[0]);
exit (EXIT_FAILURE);
}
/* /* -----------------------------------------------------------*/
printf ("Copy %s to %s with blocksize of %d.\n", in, out, block_size);
int test(double ret[BLOCKSIZES_LEN][FILESIZES_LEN], char* dir, const int bstests[BLOCKSIZES_LEN], const int fstests[FILESIZES_LEN]) {
// Create the directory dir
dircreate(dir);
char in[MAX_PATH_SIZE] = {0}, out[MAX_PATH_SIZE] = {0};
// Construct the input and output filenames
PATHCAT(in, dir);
PATHCAT(in, "/A");
PATHCAT(out, dir);
PATHCAT(out, "/B");
int fsize = -1, fs = 0;
while (fsize = fstests[fs]) {
// create the file (expensive, we only want to do this once per size)
fcreate(fsize, in);
// prepare to test with all 4 block sizes
int bsize = -1, bs = 0;
while (bsize = bstests[bs]) {
// start the clock // start the clock
clock_t time = clock(); clock_t time = clock();
// perform the copy // perform the copy
int size = fcopy (block_size, in, out); int size = fcopy(bsize, in, out);
// stop the clock // stop the clock
time = clock() - time; time = clock() - time;
printf ("Copy of %.3f MBytes took %f seconds\n", (double)size / (1024*1024), (double) time / CLOCKS_PER_SEC); ret[bs][fs] = (double)time / CLOCKS_PER_SEC;
exit (EXIT_SUCCESS); bs++;
}
fs++;
}
return EXIT_SUCCESS;
}
/* main */
int main (int argc, char** argv) {
int block_size;
char dir[MAX_PATH_SIZE] = {0};
// get argument "block size", "in", "out" from args
switch (argc) {
case 2:
PATHCAT(dir, argv[1]);
break;
case 1:
PATHCAT(dir, "/tmp/jab0910");
break;
default:
printf ("Usage: %s [directory]\n", argv[0]);
exit (EXIT_FAILURE);
}
// TODO: test
double results[BLOCKSIZES_LEN][FILESIZES_LEN] = {0};
test((double(*)[8])results, dir, tests_blocksize, tests_filesize);
/*
Size, 1, 4, 64, 1024
*/ */
// Test dircreate printf("Size (B),\tblock = %d,\tblock = %d,\tblock = %d,\tblock = %d\n", tests_blocksize[0], tests_blocksize[1], tests_blocksize[2], tests_blocksize[3]);
printf("dircreate returned %d\n",dircreate(out)); for (int fs = 0; fs < FILESIZES_LEN; fs++)
{
printf("%9d", tests_filesize[fs]);
for (int bs = 0; bs < BLOCKSIZES_LEN; bs++) {
printf(",\t%2.6f", results[bs][fs]);
}
printf("\n");
}
} }
size_t fcopy (size_t block, char *in_filename, char *out_filename) { size_t fcopy (size_t block, char *in_filename, char *out_filename) {
@ -91,15 +137,14 @@ size_t fcopy (size_t block, char *in_filename, char *out_filename) {
// until end of file, // until end of file,
while (!feof(in)) { while (!feof(in)) {
// Read data from in // Read data from in
size_t bytes_read = fread(&buffer, block, 1, in); size_t bytes_read = fread(&buffer, block, 1, in) * block;
// Write data to out // Write data to out
size_t bytes_written = fwrite(&buffer, bytes_read, 1, out); size_t bytes_written = fwrite(&buffer, block, bytes_read/block, out) * block;
// Make sure wrote same number of bytes as read // Make sure wrote same number of bytes as read
if (bytes_read == bytes_written) { if (bytes_read == bytes_written) {
bytes_copied += bytes_read; bytes_copied += bytes_read;
} else { } else {
// Something's gone wrong // Something's gone wrong
printf ("Copy: %ld not equal %ld! Aborting!\n", bytes_read, bytes_written);
bytes_copied = -bytes_copied; bytes_copied = -bytes_copied;
break; break;
} }
@ -111,8 +156,13 @@ size_t fcopy (size_t block, char *in_filename, char *out_filename) {
return bytes_copied; return bytes_copied;
} }
// min
int min(int a, int b) { int min(int a, int b) {
return (b-a >= 0)? a: b; return (a < b)? a: b;
}
// max of two pointers
void* pmax(void* a, void* b) {
return (a > b)? a: b;
} }
// Recursive mkdir // Recursive mkdir
@ -120,23 +170,30 @@ int dircreate_recurse(char* path, int depth) {
if (depth == 2) { if (depth == 2) {
printf("If you see this message, you've asked to create an awful lot of directories.\n"); printf("If you see this message, you've asked to create an awful lot of directories.\n");
} }
// Try to create the directory
while (mkdir(path, 0700)) { while (mkdir(path, 0700)) {
// handle errors
switch (errno){ switch (errno){
//* path exists. Success!
case EEXIST: case EEXIST:
// path exists. Success!
return depth; return depth;
case ENOENT: {
char subpath[0x1000] = {0}, *last_slash; //? if at first you don't succeed, try and try again
case ENOENT: { // scope
char subpath[MAX_PATH_SIZE] = {0};
size_t l = 0; size_t l = 0;
// get the length of the substring // get the length of the substring
last_slash = strrchr(path, '/'); l = (char *)pmax(strrchr(path, '/'), path) - path;
l = (last_slash == NULL ? path : last_slash) - path; // construct the substring
strncpy(subpath, path, min(l, 0x1000)); // construct the substring strncpy(subpath, path, min(l, MAX_PATH_SIZE));
depth++; depth = dircreate_recurse(subpath, ++depth); // recurse
// if at first you don't succeed, try and try again // If an error occured, propagate it backwards immediately
depth = dircreate_recurse(subpath, depth); // recurse if (depth < 0)
return depth;
break; break;
} }
//! If at first you don't succeed, you fail
default: default:
printf("Could not create directory %s: Error %d (%s)\n", path, errno, strerror(errno)); printf("Could not create directory %s: Error %d (%s)\n", path, errno, strerror(errno));
return -1; return -1;
@ -150,25 +207,29 @@ int dircreate(char* path) {
} }
int fcreate(size_t size, char* filename) { int fcreate(size_t size, char* filename) {
// First, check if the directory exists //* First, check if the directory exists {
char* last_slash = strrchr(filename,'/'); char* last_slash = strrchr(filename,'/');
// find the length of the substring // find the length of the substring
int l = filename - (last_slash==NULL?filename:last_slash); int l = (char *)pmax(strrchr(filename, '/'), filename) - filename;
char path[0x1000] = {0}; char path[MAX_PATH_SIZE] = {0};
strncpy(path, filename, l); // construct the substring // construct the substring
strncpy(path, filename, min(l, MAX_PATH_SIZE));
dircreate(path); // recursively create new directories until satisfied dircreate(path); // recursively create new directories until satisfied
//* }
// then, try to create a file in that directory // then, try to create a file in that directory
uint8_t buffer[0x400] = {0}; // Assemble a buffer uint8_t buffer[1 KB] = {0}; // Assemble a buffer
FILE *file = fopen(filename, "w"); // Open for writing FILE *file = fopen(filename, "w"); // Open for writing
F_ERROR(file, -1); // abort if error F_ERROR(file, -1); // abort if error
// Copy 1024-byte chunks up until the desired filesize < 1024 bytes away // Copy 1 KB chunks up until the desired filesize < 1024 bytes away
while (size > 0x400) { while (size > 1 KB) {
size -= fwrite(buffer, 0x400, size/0x400, file); size -= 1 KB * fwrite(buffer, 1 KB, 1, file);
} }
// Copy the rest of the file // Copy the rest of the file
if (size > 0) { if (size > 0) {
size -= fwrite(buffer, size, 1, file); size -= fwrite(buffer, size, 1, file);
} }
fclose(file);
// Return the number of unwritten bytes, if any // Return the number of unwritten bytes, if any
return size; return size;
} }

9
bscopy.txt Normal file
View File

@ -0,0 +1,9 @@
Size (B), block = 1, block = 4, block = 64, block = 1024
1048576, 0.094970, 0.020879, 0.003186, 0.002128
2097152, 0.190275, 0.040352, 0.006260, 0.004120
4194304, 0.378950, 0.081005, 0.013132, 0.008688
8388608, 0.758710, 0.162465, 0.026368, 0.018048
16777216, 1.520598, 0.328735, 0.052860, 0.038057
33554432, 3.040905, 0.651854, 0.106033, 0.075358
67108864, 6.071026, 1.292299, 0.208520, 0.139785
134217728, 12.149918, 2.599616, 0.403936, 0.281994