bscopy: Implement recursive mkdir (mkdir -p)

This commit is contained in:
John 2022-02-23 18:25:06 -06:00
parent 2d892495d6
commit e91bbc1ff7

View File

@ -28,7 +28,6 @@ size_t fcopy (size_t block, char* in_filename, char* out_filename);
/* fcreate: create a new file at filename, if it doesn't exist. /* fcreate: create a new file at filename, if it doesn't exist.
If file is attempted to be created in a nonexistent directory, If file is attempted to be created in a nonexistent directory,
recursively create directories until the error is resolved. recursively create directories until the error is resolved.
I have no time for grading mistakes due to user error.
args: args:
size: size of file in bytes size: size of file in bytes
filename: path to file filename: path to file
@ -36,6 +35,13 @@ size_t fcopy (size_t block, char* in_filename, char* out_filename);
size_t: difference between number of bytes requested and actually created (should be zero) size_t: difference between number of bytes requested and actually created (should be zero)
*/ */
int fcreate(size_t size, char* filename); int fcreate(size_t size, char* filename);
/* dircreate: recursive mkdir (aka mkdir -p)
args:
path: path to directory
returns:
depth: number of directories created
*/
int dircreate(char* path);
int main (int argc, char** argv) { int main (int argc, char** argv) {
int block_size = 1; int block_size = 1;
@ -59,7 +65,7 @@ int main (int argc, char** argv) {
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
/*
printf ("Copy %s to %s with blocksize of %d.\n", in, out, block_size); printf ("Copy %s to %s with blocksize of %d.\n", in, out, block_size);
// start the clock // start the clock
clock_t time = clock(); clock_t time = clock();
@ -69,6 +75,9 @@ int main (int argc, char** argv) {
time = clock() - time; time = clock() - time;
printf ("Copy of %.3f MBytes took %f seconds\n", (double)size / (1024*1024), (double) time / CLOCKS_PER_SEC); printf ("Copy of %.3f MBytes took %f seconds\n", (double)size / (1024*1024), (double) time / CLOCKS_PER_SEC);
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
*/
// Test dircreate
printf("dircreate returned %d\n",dircreate(out));
} }
size_t fcopy (size_t block, char *in_filename, char *out_filename) { size_t fcopy (size_t block, char *in_filename, char *out_filename) {
@ -107,25 +116,37 @@ int min(int a, int b) {
} }
// Recursive mkdir // Recursive mkdir
int dircreate(char* path) { 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");
}
while (mkdir(path, 0700)) { while (mkdir(path, 0700)) {
switch (errno){ switch (errno){
case EEXIST: case EEXIST:
return 0; // path exists. Success!
return depth;
case ENOENT: { case ENOENT: {
char subpath[0x1000] = {0}, *last_slash; char subpath[0x1000] = {0}, *last_slash;
size_t l = 0; size_t l = 0;
// get the length of the substring
last_slash = strrchr(path, '/'); last_slash = strrchr(path, '/');
l = path - (last_slash == NULL ? path : last_slash); l = (last_slash == NULL ? path : last_slash) - path;
strncpy(subpath, path, min(l, 0x1000)); // construct the substring strncpy(subpath, path, min(l, 0x1000)); // construct the substring
dircreate(subpath); // recurse depth++;
// if at first you don't succeed, try and try again
depth = dircreate_recurse(subpath, depth); // recurse
break;
} }
default: default:
printf("Could not create directory: %s\n", strerror(errno)); printf("Could not create directory %s: Error %d (%s)\n", path, errno, strerror(errno));
return -1; return -1;
} }
} }
return 0; return depth;
}
// wrap dircreate_recurse
int dircreate(char* path) {
return dircreate_recurse(path, 0);
} }
int fcreate(size_t size, char* filename) { int fcreate(size_t size, char* filename) {
@ -148,5 +169,6 @@ int fcreate(size_t size, char* filename) {
if (size > 0) { if (size > 0) {
size -= fwrite(buffer, size, 1, file); size -= fwrite(buffer, size, 1, file);
} }
// Return the number of unwritten bytes, if any
return size; return size;
} }