diff --git a/Makefile b/Makefile index 0d5ff24..efcd456 100644 --- a/Makefile +++ b/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) \ No newline at end of file + rm $(OUT) \ No newline at end of file diff --git a/bscopy.c b/bscopy.c index b2b3625..170d03f 100644 --- a/bscopy.c +++ b/bscopy.c @@ -12,9 +12,17 @@ #include // errno #include // 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; } diff --git a/bscopy.txt b/bscopy.txt new file mode 100644 index 0000000..5c9819c --- /dev/null +++ b/bscopy.txt @@ -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 \ No newline at end of file