draw the rest of the f*cking owl
This commit is contained in:
parent
e91bbc1ff7
commit
565abb83ef
9
Makefile
9
Makefile
@ -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
163
bscopy.c
@ -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
9
bscopy.txt
Normal 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
|
Loading…
Reference in New Issue
Block a user