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
CFLAGS =
EXEC := syscalls bscopy
SRC := syscalls bscopy
OUT := syscalls.out bscopy.out
.PHONY: all clean
all: $(EXEC)
all: $(SRC)
%: %.c
$(CC) $(CFLAGS) -o $@ $^
$(CC) $(CFLAGS) -o $@.out $^
clean:
rm $(EXEC)
rm $(OUT)

163
bscopy.c
View File

@ -12,9 +12,17 @@
#include <errno.h> // errno
#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
#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
args:
@ -43,41 +51,79 @@ int fcreate(size_t size, char* filename);
*/
int dircreate(char* path);
// Tests in the first batch
#define FILESIZES_LEN 8
#define BLOCKSIZES_LEN 4
// {block size, file size}
const int tests_filesize[FILESIZES_LEN + 1] =
{1 MB, 2 MB, 4 MB, 8 MB, 16 MB, 32 MB, 64 MB, 128 MB, 0};
const int tests_blocksize[BLOCKSIZES_LEN + 1] =
{1 B, 4 B, 64 B, 1024 B, 0};
/* -----------------------------------------------------------*/
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
clock_t time = clock();
// perform the copy
int size = fcopy(bsize, in, out);
// stop the clock
time = clock() - time;
ret[bs][fs] = (double)time / CLOCKS_PER_SEC;
bs++;
}
fs++;
}
return EXIT_SUCCESS;
}
/* main */
int main (int argc, char** argv) {
int block_size = 1;
char *in = "/tmp/A", *out = "/tmp/B";
int block_size;
char dir[MAX_PATH_SIZE] = {0};
// get argument "block size", "in", "out" from args
switch (argc) {
case 4:
out = argv[3];
case 3:
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;
PATHCAT(dir, argv[1]);
break;
case 1:
PATHCAT(dir, "/tmp/jab0910");
break;
default:
printf ("Usage: %s block_size [in [out]]\n", argv[0]);
printf ("Usage: %s [directory]\n", argv[0]);
exit (EXIT_FAILURE);
}
/*
printf ("Copy %s to %s with blocksize of %d.\n", in, out, block_size);
// start the clock
clock_t time = clock();
// perform the copy
int size = fcopy (block_size, in, out);
// stop the clock
time = clock() - time;
printf ("Copy of %.3f MBytes took %f seconds\n", (double)size / (1024*1024), (double) time / CLOCKS_PER_SEC);
exit (EXIT_SUCCESS);
*/
// Test dircreate
printf("dircreate returned %d\n",dircreate(out));
// TODO: test
double results[BLOCKSIZES_LEN][FILESIZES_LEN] = {0};
test((double(*)[8])results, dir, tests_blocksize, tests_filesize);
/*
Size, 1, 4, 64, 1024
*/
printf("Size (B),\tblock = %d,\tblock = %d,\tblock = %d,\tblock = %d\n", tests_blocksize[0], tests_blocksize[1], tests_blocksize[2], tests_blocksize[3]);
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) {
@ -91,15 +137,14 @@ size_t fcopy (size_t block, char *in_filename, char *out_filename) {
// until end of file,
while (!feof(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
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
if (bytes_read == bytes_written) {
bytes_copied += bytes_read;
} else {
// Something's gone wrong
printf ("Copy: %ld not equal %ld! Aborting!\n", bytes_read, bytes_written);
bytes_copied = -bytes_copied;
break;
}
@ -111,8 +156,13 @@ size_t fcopy (size_t block, char *in_filename, char *out_filename) {
return bytes_copied;
}
// min
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
@ -120,23 +170,30 @@ int dircreate_recurse(char* path, int depth) {
if (depth == 2) {
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)) {
// handle errors
switch (errno){
//* path exists. Success!
case EEXIST:
// path exists. Success!
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;
// get the length of the substring
last_slash = strrchr(path, '/');
l = (last_slash == NULL ? path : last_slash) - path;
strncpy(subpath, path, min(l, 0x1000)); // construct the substring
depth++;
// if at first you don't succeed, try and try again
depth = dircreate_recurse(subpath, depth); // recurse
l = (char *)pmax(strrchr(path, '/'), path) - path;
// construct the substring
strncpy(subpath, path, min(l, MAX_PATH_SIZE));
depth = dircreate_recurse(subpath, ++depth); // recurse
// If an error occured, propagate it backwards immediately
if (depth < 0)
return depth;
break;
}
//! If at first you don't succeed, you fail
default:
printf("Could not create directory %s: Error %d (%s)\n", path, errno, strerror(errno));
return -1;
@ -150,25 +207,29 @@ int dircreate(char* path) {
}
int fcreate(size_t size, char* filename) {
// First, check if the directory exists
//* First, check if the directory exists {
char* last_slash = strrchr(filename,'/');
// find the length of the substring
int l = filename - (last_slash==NULL?filename:last_slash);
char path[0x1000] = {0};
strncpy(path, filename, l); // construct the substring
// find the length of the substring
int l = (char *)pmax(strrchr(filename, '/'), filename) - filename;
char path[MAX_PATH_SIZE] = {0};
// construct the substring
strncpy(path, filename, min(l, MAX_PATH_SIZE));
dircreate(path); // recursively create new directories until satisfied
// then, try to create a file in that directory
uint8_t buffer[0x400] = {0}; // Assemble a buffer
//* }
// then, try to create a file in that directory
uint8_t buffer[1 KB] = {0}; // Assemble a buffer
FILE *file = fopen(filename, "w"); // Open for writing
F_ERROR(file, -1); // abort if error
// Copy 1024-byte chunks up until the desired filesize < 1024 bytes away
while (size > 0x400) {
size -= fwrite(buffer, 0x400, size/0x400, file);
// Copy 1 KB chunks up until the desired filesize < 1024 bytes away
while (size > 1 KB) {
size -= 1 KB * fwrite(buffer, 1 KB, 1, file);
}
// Copy the rest of the file
if (size > 0) {
size -= fwrite(buffer, size, 1, file);
}
fclose(file);
// Return the number of unwritten bytes, if any
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