From 490a7cc97393807bf8a7229648ff2abee8e78a11 Mon Sep 17 00:00:00 2001 From: Odweta Date: Sat, 23 Dec 2023 19:51:54 +0100 Subject: [PATCH] made work: copy a file, move a file, check if a file exists, delete a file --- Makefile | 3 +- README.md | 13 ++++----- demo.c | 57 +++++++++++++++++++++++------------- examples/file/filedemo.c | 26 +++++++++++++++++ examples/list/listdemo.c | 2 +- include/file.h | 20 +++++++++---- src/file.c | 63 +++++++++++++++++++++++++++++++++++++++- test.txt | 1 + 8 files changed, 150 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 7739fd1..d0a8e28 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ libfile.so: src/file.c liblist.so: src/list.c sudo $(CC) -c -fpic $< -o /usr/lib/odweta/list.o sudo $(CC) -shared -o /usr/lib/odweta/$@ /usr/lib/odweta/list.o + install: sudo mkdir -p /usr/include/odweta/ sudo mkdir -p /usr/lib/odweta/ @@ -34,4 +35,4 @@ clean: sudo rm -f main /usr/lib/odweta/vector.o /usr/lib/odweta/file.o /usr/lib/odweta/libvector.so /usr/lib/odweta/libfile.so /usr/lib/odweta/list.o /usr/lib/odweta/liblist.so cleanrepo: - rm -fr ./demo + rm -fr ./demo ./moved_copy_of_test.txt ./copy_of_test.txt diff --git a/README.md b/README.md index 5a7249d..2117b12 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,15 @@ Examples of this work of art are in the `/examples/` directory of this repo. 1. Reading files into a 2D vector 2. Converting a file into a string +3. File writing logic +4. Copying a file to another file +5. Moving (renaming) a file to another file +6. Deleting a file +7. Checking if a file exists #### TODO: -1. File writing logic -2. File appending logic -3. Copy a file to another file -4. Move a file to another file -5. Rename a file -6. Delete a file? -8. Add line numbers at the beggining of each line in a file +1. Add line numbers at the beggining of each line in a file + You tell me diff --git a/demo.c b/demo.c index 585d12a..c7040a3 100644 --- a/demo.c +++ b/demo.c @@ -1,31 +1,48 @@ -#include -#include +#include #include int main() { - printf("creating a list using 'listInit()' (returns a list_t*)\n"); - list_t* l = listInit(); + printf("creating a file using 'fileInit()' (returns a file_t*)\n"); + file_t* f = fileInit("test.txt"); - printf("pushing an integer value into the list\nnote the kind of unusual way of passing the number argument: if you want to pass an expression (e.g. the value '1' or '4*4'), something not stored in a variable, you follow this syntax - &(type){value} (e.g. &(int){1 + 1})\nalso, the type of the variable must be given as the second argument to the function\n->'listPush(list_t*, INT, &(int){123})'\n"); - listPush(l, INT, &(int){123}); - listPrint(l); + printf("printing the file contents\n\n"); + filePrint(f); - printf("popping the last value of the list; in this case, it is an integer, so you type: 'int poppedValue = *((int *)listPop(list_t*))'\n"); - int poppedValue = *((int *)listPop(l)); - printf("popped: %d\n", poppedValue); - listPrint(l); + printf("\nconvering the file contents into a string (char*)\n"); + char* string = fileToString(f); + printf("\"%s\"\n", string); - printf("more examples with diferrent types\nnote that the vector_t* is a pointer, so there is no need to write the special syntax!\n"); - listPush(l, FLOAT, &(float){3.14}); - listPush(l, CHAR, &(char){'x'}); - vector_t* int_vec = vectorInit(INT); - vectorPush(int_vec, &(int){456}); - listPush(l, VECTOR, int_vec); + printf("writing is quite simple, just call the 'fileWrite(file_t*, char*)' or 'fileWriteln(file_t*, char*)' function, where the second argument is the string you want to write into a file\nthe 'fileWriteln()' function writes the specified string AND a '\\n' after it, whereas the 'fileWrite()' function does not append the '\\n'\n"); + fileWrite(f, "'this will not end with a \"\\n\"' "); + fileWriteln(f, "this line was appended"); + filePrint(f); - listPrint(l); + printf("if you are finished working with the file BEFORE the immediate end of the program, run 'fileCleanup(file_t*)', otherwise it is not strictly necessary\nit will, though, append a '\\n' at the end of the file if you have not done so, making writing into files more consistent, so for this reason, I recommend you use it with every file_t*\n"); + fileCleanup(f); - printf("if you are finished working with the list BEFORE the immediate end of the program, run 'listCleanup(list_t*)', otherwise it is not strictly necessary\n"); - listCleanup(l); + printf("copying and moving\nafter this block of code, the contents of test.txt will have been copied into copy_of_test.txt and moved to moved_copy_of_test.txt, which means that copy_of_test.txt is deleted and the contents of test.txt are only in test.txt and moved_copy_of_test.txt\n"); + + file_t* src = fileInit("test.txt"); + + fileCopy(src, "copy_of_test.txt"); + + printf("src:\n"); + filePrint(src); + + printf("\ndst:\n"); + file_t* dst = fileInit("copy_of_test.txt"); + filePrint(dst); + + fileMove(dst, "moved_copy_of_test.txt"); + + printf("moved file:\n"); + file_t* move_dst = fileInit("moved_copy_of_test.txt"); + filePrint(move_dst); + + fileCleanup(src); + printf("DO NOT cleanup a deleted file! (dst, in this case) it is already done for you by the 'fileMove(file_t*)' function\n"); + // fileCleanup(dst); + fileCleanup(move_dst); return 0; } diff --git a/examples/file/filedemo.c b/examples/file/filedemo.c index 091313b..4a223c6 100644 --- a/examples/file/filedemo.c +++ b/examples/file/filedemo.c @@ -20,5 +20,31 @@ int main() { printf("if you are finished working with the file BEFORE the immediate end of the program, run 'fileCleanup(file_t*)', otherwise it is not strictly necessary\nit will, though, append a '\\n' at the end of the file if you have not done so, making writing into files more consistent, so for this reason, I recommend you use it with every file_t*\n"); fileCleanup(f); + printf("copying and moving\nafter this block of code, the contents of test.txt will have been copied into copy_of_test.txt and moved to moved_copy_of_test.txt, which means that copy_of_test.txt is deleted and the contents of test.txt are only in test.txt and moved_copy_of_test.txt\n"); + + file_t* src = fileInit("test.txt"); + + fileCopy(src, "copy_of_test.txt"); + + printf("src:\n"); + filePrint(src); + + printf("\ndst:\n"); + file_t* dst = fileInit("copy_of_test.txt"); + filePrint(dst); + + fileMove(dst, "moved_copy_of_test.txt"); + + printf("moved file:\n"); + file_t* move_dst = fileInit("moved_copy_of_test.txt"); + filePrint(move_dst); + + fileCleanup(src); + printf("DO NOT cleanup a deleted file! (dst, in this case) it is already done for you by the 'fileMove(file_t*, char*)' function\n"); + // fileCleanup(dst); + fileCleanup(move_dst); + + printf("when copying and moving files, the first argument is a file_t* (source file) and the second argument is a char* (the path of the destination file), not a file_t*!\n"); + return 0; } diff --git a/examples/list/listdemo.c b/examples/list/listdemo.c index 585d12a..5881fa5 100644 --- a/examples/list/listdemo.c +++ b/examples/list/listdemo.c @@ -12,7 +12,7 @@ int main() { printf("popping the last value of the list; in this case, it is an integer, so you type: 'int poppedValue = *((int *)listPop(list_t*))'\n"); int poppedValue = *((int *)listPop(l)); - printf("popped: %d\n", poppedValue); + printf("popped: %d\n", poppedValue); listPrint(l); printf("more examples with diferrent types\nnote that the vector_t* is a pointer, so there is no need to write the special syntax!\n"); diff --git a/include/file.h b/include/file.h index a034aa2..c228af8 100644 --- a/include/file.h +++ b/include/file.h @@ -12,14 +12,24 @@ typedef struct { file_t* fileInit(char* path); // initialization function -void fileCleanup(file_t* f); // just to be memory safe... +void fileCleanup(file_t* f); // just to be memory safe... -void filePrint(file_t* f); // prints the file as a string +void filePrint(file_t* f); // prints the file as a string -char* fileToString(file_t* f); // returns a string with the file contents +char* fileToString(file_t* f); // returns a string with the file contents -void fileWriteln(file_t* f, char* payload); // appends a given string to the file on a newline +void fileWriteln(file_t* f, char* payload); // appends a given string to the file on a newline -void fileWrite(file_t* f, char* payload); // appends a given string to the file (not on a newline!) +void fileWrite(file_t* f, char* payload); // appends a given string to the file (not on a newline!) + +void fileCopy(file_t* src, char* dst); // copy file src into file dst + +void fileDelete(file_t* f); // deletes a file + +void fileMove(file_t* src, char* dst); // moves/renames a file + +int fileExists(file_t* f); // 1 = yes, 0 = no + +void fileCreateEmpty(char* path); // create an empty file with the given name #endif diff --git a/src/file.c b/src/file.c index 432720a..6627322 100644 --- a/src/file.c +++ b/src/file.c @@ -10,7 +10,7 @@ fileCountLines(file_t* f) { int lines = 0; FILE* fd = fopen(f->path, "r"); if (!fd) { - fprintf(stderr, "unable to open file"); + fprintf(stderr, "unable to count lines in file %s\n", f->path); exit(EXIT_FAILURE); } @@ -70,6 +70,22 @@ fileToString(file_t* f) { return (char *)vectorToString(f->lines); } +int +fileExists(file_t* f) { + FILE* fd = fopen(f->path, "r"); + if (!fd) { + return 0; // file does not exist + } else { + return 1; // file exists + } + fclose(fd); +} + +void +fileCreateEmpty(char* path) { + fclose(fopen(path, "w")); +} + file_t* fileInit(char* path) { file_t* f = malloc(sizeof(file_t)); @@ -80,6 +96,12 @@ fileInit(char* path) { f->path = path; + if (fileExists(f) == 0) { + // if file 'f' does not exist + fileCreateEmpty(f->path); + return fileInit(f->path); + } + f->length = fileCountLines(f); f->lines = vectorInit(VECTOR); // vector of vectors of chars = vector of strings @@ -161,3 +183,42 @@ fileWrite(file_t* f, char* payload) { f->length++; f->not_newline_terminated = 1; } + +void +fileCopy(file_t* src, char* dst) { + FILE* fd = fopen(dst, "w"); + if (!fd) { + fprintf(stderr, "could not open file for writing\n"); + exit(EXIT_FAILURE); + } + + char ch; + for (int i = 0; i < src->length; i++) { + for (int j = 0; j < ((vector_t *)vectorGetAt(src->lines, i))->size; j++) { + ch = *((char *)vectorGetAt((vector_t *)vectorGetAt(src->lines, i), j)); + fprintf(fd, "%c", ch); + } + fprintf(fd, "\n"); + } + + fclose(fd); +} + +void +fileDelete(file_t* f) { + int retval = remove(f->path); // try to remove/delete a file + + if (retval != 0) { // if it could not do so, raise an error + fprintf(stderr, "could not delete file\n"); + // fileCleanup(f); // don't know if this is necessary... :shrug: + // exit(EXIT_FAILURE); + } + fileCleanup(f); +} + +void +fileMove(file_t* src, char* dst) { + fileCopy(src, dst); + + fileDelete(src); +} diff --git a/test.txt b/test.txt index 9985556..99b8c1e 100644 --- a/test.txt +++ b/test.txt @@ -4,3 +4,4 @@ and this was an empty line !#%!@# <- symbols! +'this will not end with a "\n"' this line was appended