helpers.c (4700B)
1 /* 2 * Copyright (c) 2020 Paco Esteban <paco@e1e0.net> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <sys/stat.h> 18 #include <sys/syslimits.h> 19 20 #include <errno.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include "ssnail_error.h" 26 #include "helpers.h" 27 28 char * 29 build_full_path(char *dir, char *file) 30 { 31 size_t n = 0; 32 char *fullpath = NULL, separator[2] = ""; 33 34 /* if user input does not have trailing slash, add it */ 35 if (dir[strlen(dir)-1] != '/') 36 n = strlcpy(separator, "/", sizeof(separator)); 37 if (n >= sizeof(separator)) 38 return NULL; 39 40 n = asprintf(&fullpath, "%s%s%s", dir, separator, file); 41 if ((n < 0) || (n > PATH_MAX)) { 42 return NULL; 43 } 44 45 return fullpath; 46 } 47 48 const struct ssnail_error * 49 copy_file(const char *source_file, const char *dest_file, int force) 50 { 51 FILE *src, *dst; 52 struct stat st; 53 long long src_mtime, dst_mtime; 54 55 if (stat(source_file, &st) == -1) 56 return ssnail_error_from_errno("cp stat src"); 57 src_mtime = st.st_mtim.tv_sec; 58 59 if (stat(dest_file, &st) == -1) { /* dst file does not have to exist */ 60 if (errno != ENOENT) 61 return ssnail_error_from_errno("cp stat dst"); 62 dst_mtime = 0; 63 } else { 64 dst_mtime = st.st_mtim.tv_sec; 65 } 66 67 if ((src_mtime > dst_mtime) || force) { 68 if ((src = fopen(source_file, "rb")) == NULL) 69 return ssnail_error_from_errno("cp fopen src"); 70 if ((dst = fopen(dest_file, "wb")) == NULL) 71 return ssnail_error_from_errno("cp fopen dst"); 72 73 printf("copying %s --> %s\n", source_file, dest_file); 74 size_t rcnt, wcnt; 75 unsigned char buff[4096]; 76 do { 77 rcnt = fread(buff, 1, sizeof(buff), src); 78 if (rcnt) { 79 wcnt = fwrite(buff, 1, rcnt, dst); 80 } else { 81 wcnt = 0; 82 } 83 } while ((rcnt > 0) && (rcnt == wcnt)); 84 if (wcnt) 85 return ssnail_error_msg(2, "cp"); 86 87 if (fclose(src) != 0) 88 return ssnail_error_from_errno("close src"); 89 if (fclose(dst) != 0) 90 return ssnail_error_from_errno("close dst"); 91 } 92 93 return NULL; 94 } 95 96 const char * 97 get_filename_ext(const char *filename) 98 { 99 const char *dot = strrchr(filename, '.'); 100 if(!dot || dot == filename) 101 return ""; 102 return dot + 1; 103 } 104 105 int 106 load_from_file(char **buffer, char *path) 107 { 108 long length = -1; 109 FILE *f = NULL; 110 111 if ((f = fopen(path, "r")) == NULL) 112 return 0; 113 114 if (f) { 115 /* Go to the end of the file. Record it's length, and return to 116 * the start 117 */ 118 if (fseek(f, 0, SEEK_END) == -1) 119 return 0; 120 if ((length = ftell(f)) == -1) 121 return 0; 122 if (fseek(f, 0, SEEK_SET) == -1) 123 return 0; 124 125 *buffer = malloc(length + 1); 126 if (*buffer == NULL) 127 return 0; 128 fread(*buffer, 1, length, f); 129 if (ferror(f) != 0) 130 return 0; 131 132 if (fclose(f) != 0) 133 return 0; 134 /* add null terminator to string. 135 * apparently this is not the same as: 136 * *buffer[length] = '\0'; 137 * but I do not know why ... 138 */ 139 *(*buffer + length) = '\0'; 140 } 141 142 return length + 1; 143 } 144 145 int 146 str_rep(char **str, const char *old, const char *new) 147 { 148 char *r, *s = *str; 149 int i, cnt = 0; 150 int new_len = strlen(new); 151 int old_len = strlen(old); 152 153 if (new_len == 0 || old_len == 0) 154 return -1; 155 156 /* Counting the number of times old word 157 * occur in the string 158 */ 159 for (i = 0; s[i] != '\0'; i++) { 160 if (strstr(&s[i], old) == &s[i]) { 161 cnt++; 162 /* Jumping to index after the old word. */ 163 i += old_len - 1; 164 } 165 } 166 167 /* Making new string long enough */ 168 r = (char *)malloc(i + cnt * (new_len - old_len) + 1); 169 if (!r) return -1; 170 171 i = 0; 172 while (*s) { 173 /* 174 * compare the substring the old word 175 * if found (pointers are equal), copy new word in 'i' position 176 * of result. Then increment by the lenght so we do not check 177 * unnecessarily. 178 */ 179 if (strstr(s, old) == s) { 180 /* 181 * On the original example it was done like this: 182 * strcpy(&r[i], new); 183 * I think there's no need to dereference and reference 184 * again. 185 */ 186 strcpy(r+i, new); 187 i += new_len; 188 s += old_len; 189 } else /* if not copy the char and increment pointers */ 190 r[i++] = *s++; 191 } 192 193 r[i] = '\0'; 194 195 free(*str); 196 s = NULL; 197 198 *str = r; 199 200 return 0; 201 }