Alistair Delva | beaee83 | 2021-02-24 11:27:23 -0800 | [diff] [blame] | 1 | /* Copyright 1996-2002,2005,2007,2009,2011 Alain Knaff. |
| 2 | * This file is part of mtools. |
| 3 | * |
| 4 | * Mtools is free software: you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by |
| 6 | * the Free Software Foundation, either version 3 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * Mtools is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with Mtools. If not, see <http://www.gnu.org/licenses/>. |
| 16 | * |
| 17 | * Miscellaneous routines. |
| 18 | */ |
| 19 | |
| 20 | #include "sysincludes.h" |
| 21 | #include "msdos.h" |
| 22 | #include "stream.h" |
| 23 | #include "vfat.h" |
| 24 | #include "mtools.h" |
| 25 | |
| 26 | |
| 27 | void printOom(void) |
| 28 | { |
| 29 | fprintf(stderr, "Out of memory error"); |
| 30 | } |
| 31 | |
| 32 | char *get_homedir(void) |
| 33 | { |
| 34 | #ifndef OS_mingw32msvc |
| 35 | struct passwd *pw; |
| 36 | uid_t uid; |
| 37 | char *homedir; |
| 38 | char *username; |
| 39 | |
| 40 | homedir = getenv ("HOME"); |
| 41 | /* |
| 42 | * first we call getlogin. |
| 43 | * There might be several accounts sharing one uid |
| 44 | */ |
| 45 | if ( homedir ) |
| 46 | return homedir; |
| 47 | |
| 48 | pw = 0; |
| 49 | |
| 50 | username = getenv("LOGNAME"); |
| 51 | if ( !username ) |
| 52 | username = getlogin(); |
| 53 | if ( username ) |
| 54 | pw = getpwnam( username); |
| 55 | |
| 56 | if ( pw == 0 ){ |
| 57 | /* if we can't getlogin, look up the pwent by uid */ |
| 58 | uid = geteuid(); |
| 59 | pw = getpwuid(uid); |
| 60 | } |
| 61 | |
| 62 | /* we might still get no entry */ |
| 63 | if ( pw ) |
| 64 | return pw->pw_dir; |
| 65 | return 0; |
| 66 | #else |
| 67 | return getenv("HOME"); |
| 68 | #endif |
| 69 | } |
| 70 | |
| 71 | |
| 72 | static void get_mcwd_file_name(char *file) |
| 73 | { |
| 74 | char *mcwd_path; |
| 75 | const char *homedir; |
| 76 | |
| 77 | mcwd_path = getenv("MCWD"); |
| 78 | if (mcwd_path == NULL || *mcwd_path == '\0'){ |
| 79 | homedir= get_homedir(); |
| 80 | if(!homedir) |
| 81 | homedir="/tmp"; |
| 82 | strncpy(file, homedir, MAXPATHLEN-6); |
| 83 | file[MAXPATHLEN-6]='\0'; |
| 84 | strcat( file, "/.mcwd"); |
| 85 | } else { |
| 86 | strncpy(file, mcwd_path, MAXPATHLEN); |
| 87 | file[MAXPATHLEN]='\0'; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | void unlink_mcwd(void) |
| 92 | { |
| 93 | char file[MAXPATHLEN+1]; |
| 94 | get_mcwd_file_name(file); |
| 95 | unlink(file); |
| 96 | } |
| 97 | |
| 98 | FILE *open_mcwd(const char *mode) |
| 99 | { |
| 100 | struct MT_STAT sbuf; |
| 101 | char file[MAXPATHLEN+1]; |
| 102 | time_t now; |
| 103 | |
| 104 | get_mcwd_file_name(file); |
| 105 | if (*mode == 'r'){ |
| 106 | if (MT_STAT(file, &sbuf) < 0) |
| 107 | return NULL; |
| 108 | /* |
| 109 | * Ignore the info, if the file is more than 6 hours old |
| 110 | */ |
| 111 | getTimeNow(&now); |
| 112 | if (now - sbuf.st_mtime > 6 * 60 * 60) { |
| 113 | fprintf(stderr, |
| 114 | "Warning: \"%s\" is out of date, removing it\n", |
| 115 | file); |
| 116 | unlink(file); |
| 117 | return NULL; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | return fopen(file, mode); |
| 122 | } |
| 123 | |
| 124 | |
| 125 | |
| 126 | void *safe_malloc(size_t size) |
| 127 | { |
| 128 | void *p; |
| 129 | |
| 130 | p = malloc(size); |
| 131 | if(!p){ |
| 132 | printOom(); |
| 133 | exit(1); |
| 134 | } |
| 135 | return p; |
| 136 | } |
| 137 | |
| 138 | void print_sector(const char *message, unsigned char *data, int size) |
| 139 | { |
| 140 | int col; |
| 141 | int row; |
| 142 | |
| 143 | printf("%s:\n", message); |
| 144 | |
| 145 | for(row = 0; row * 16 < size; row++){ |
| 146 | printf("%03x ", row * 16); |
| 147 | for(col = 0; col < 16; col++) |
| 148 | printf("%02x ", data [row*16+col]); |
| 149 | for(col = 0; col < 16; col++) { |
| 150 | if(isprint(data [row*16+col])) |
| 151 | printf("%c", data [row*16+col]); |
| 152 | else |
| 153 | printf("."); |
| 154 | } |
| 155 | printf("\n"); |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | #if (SIZEOF_TIME_T > SIZEOF_LONG) && defined (HAVE_STRTOLL) |
| 160 | # define STRTOTIME strtoll |
| 161 | #else |
| 162 | # define STRTOTIME strtol |
| 163 | #endif |
| 164 | |
| 165 | time_t getTimeNow(time_t *now) |
| 166 | { |
| 167 | static int haveTime = 0; |
| 168 | static time_t sharedNow; |
| 169 | |
| 170 | if(!haveTime) { |
| 171 | const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); |
| 172 | if (source_date_epoch) { |
| 173 | char *endptr; |
| 174 | time_t epoch = |
| 175 | STRTOTIME(source_date_epoch, &endptr, 10); |
| 176 | errno = 0; |
| 177 | |
| 178 | if (endptr == source_date_epoch) |
| 179 | fprintf(stderr, |
| 180 | "SOURCE_DATE_EPOCH \"%s\" invalid\n", |
| 181 | source_date_epoch); |
| 182 | else if (errno != 0) |
| 183 | fprintf(stderr, |
| 184 | "SOURCE_DATE_EPOCH: strtoll: %s: %s\n", |
| 185 | strerror(errno), source_date_epoch); |
| 186 | else if (*endptr != '\0') |
| 187 | fprintf(stderr, |
| 188 | "SOURCE_DATE_EPOCH has trailing garbage \"%s\"\n", |
| 189 | endptr); |
| 190 | else { |
| 191 | sharedNow = epoch; |
| 192 | haveTime = 1; |
| 193 | } |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | if(!haveTime) { |
| 198 | time(&sharedNow); |
| 199 | haveTime = 1; |
| 200 | } |
| 201 | if(now) |
| 202 | *now = sharedNow; |
| 203 | return sharedNow; |
| 204 | } |
| 205 | |
| 206 | /* Convert a string to an offset. The string should be a number, |
| 207 | optionally followed by S (sectors), K (K-Bytes), M (Megabytes), G |
| 208 | (Gigabytes) */ |
| 209 | off_t str_to_offset(char *str) { |
| 210 | char s, *endp = NULL; |
| 211 | off_t ofs; |
| 212 | |
| 213 | ofs = strtol(str, &endp, 0); |
| 214 | if (ofs <= 0) |
| 215 | return 0; /* invalid or missing offset */ |
| 216 | s = *endp++; |
| 217 | if (s) { /* trailing char, see if it is a size specifier */ |
| 218 | if (s == 's' || s == 'S') /* sector */ |
| 219 | ofs <<= 9; |
| 220 | else if (s == 'k' || s == 'K') /* kb */ |
| 221 | ofs <<= 10; |
| 222 | else if (s == 'm' || s == 'M') /* Mb */ |
| 223 | ofs <<= 20; |
| 224 | else if (s == 'g' || s == 'G') /* Gb */ |
| 225 | ofs <<= 30; |
| 226 | else |
| 227 | return 0; /* invalid character */ |
| 228 | if (*endp) |
| 229 | return 0; /* extra char, invalid */ |
| 230 | } |
| 231 | return ofs; |
| 232 | } |
| 233 | |
| 234 | #if 0 |
| 235 | |
| 236 | #undef free |
| 237 | #undef malloc |
| 238 | |
| 239 | static int total=0; |
| 240 | |
| 241 | void myfree(void *ptr) |
| 242 | { |
| 243 | int *size = ((int *) ptr)-1; |
| 244 | total -= *size; |
| 245 | fprintf(stderr, "freeing %d bytes at %p total allocated=%d\n", |
| 246 | *size, ptr, total); |
| 247 | free(size); |
| 248 | } |
| 249 | |
| 250 | void *mymalloc(size_t size) |
| 251 | { |
| 252 | int *ptr; |
| 253 | ptr = (int *)malloc(size+sizeof(int)); |
| 254 | if(!ptr) |
| 255 | return 0; |
| 256 | *ptr = size; |
| 257 | ptr++; |
| 258 | total += size; |
| 259 | fprintf(stderr, "allocating %d bytes at %p total allocated=%d\n", |
| 260 | size, ptr, total); |
| 261 | return (void *) ptr; |
| 262 | } |
| 263 | |
| 264 | void *mycalloc(size_t nmemb, size_t size) |
| 265 | { |
| 266 | void *ptr = mymalloc(nmemb * size); |
| 267 | if(!ptr) |
| 268 | return 0; |
| 269 | memset(ptr, 0, size); |
| 270 | return ptr; |
| 271 | } |
| 272 | |
| 273 | void *myrealloc(void *ptr, size_t size) |
| 274 | { |
| 275 | int oldsize = ((int *)ptr) [-1]; |
| 276 | void *new = mymalloc(size); |
| 277 | if(!new) |
| 278 | return 0; |
| 279 | memcpy(new, ptr, oldsize); |
| 280 | myfree(ptr); |
| 281 | return new; |
| 282 | } |
| 283 | |
| 284 | char *mystrdup(char *src) |
| 285 | { |
| 286 | char *dest; |
| 287 | dest = mymalloc(strlen(src)+1); |
| 288 | if(!dest) |
| 289 | return 0; |
| 290 | strcpy(dest, src); |
| 291 | return dest; |
| 292 | } |
| 293 | |
| 294 | #endif |