draw the rest of the f*cking owl
This commit is contained in:
		
							
								
								
									
										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 | ||||
		Reference in New Issue
	
	Block a user