blob: 690f37096e41917b29d2a8a1ee808836ce13c946 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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
27void printOom(void)
28{
29 fprintf(stderr, "Out of memory error");
30}
31
32char *get_homedir(void)
33{
34#ifndef OS_mingw32msvc
35 struct passwd *pw;
36 uid_t uid;
37 char *homedir;
38 char *username;
Yi Kong39bbd962022-01-09 19:41:38 +080039
40 homedir = getenv ("HOME");
41 /*
42 * first we call getlogin.
43 * There might be several accounts sharing one uid
Alistair Delvabeaee832021-02-24 11:27:23 -080044 */
45 if ( homedir )
46 return homedir;
Yi Kong39bbd962022-01-09 19:41:38 +080047
Alistair Delvabeaee832021-02-24 11:27:23 -080048 pw = 0;
Yi Kong39bbd962022-01-09 19:41:38 +080049
Alistair Delvabeaee832021-02-24 11:27:23 -080050 username = getenv("LOGNAME");
51 if ( !username )
52 username = getlogin();
53 if ( username )
54 pw = getpwnam( username);
Yi Kong39bbd962022-01-09 19:41:38 +080055
Alistair Delvabeaee832021-02-24 11:27:23 -080056 if ( pw == 0 ){
57 /* if we can't getlogin, look up the pwent by uid */
58 uid = geteuid();
59 pw = getpwuid(uid);
60 }
Yi Kong39bbd962022-01-09 19:41:38 +080061
Alistair Delvabeaee832021-02-24 11:27:23 -080062 /* 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
72static 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
91void unlink_mcwd(void)
92{
93 char file[MAXPATHLEN+1];
94 get_mcwd_file_name(file);
95 unlink(file);
96}
97
98FILE *open_mcwd(const char *mode)
99{
100 struct MT_STAT sbuf;
101 char file[MAXPATHLEN+1];
102 time_t now;
Yi Kong39bbd962022-01-09 19:41:38 +0800103
Alistair Delvabeaee832021-02-24 11:27:23 -0800104 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 }
Yi Kong39bbd962022-01-09 19:41:38 +0800120
Alistair Delvabeaee832021-02-24 11:27:23 -0800121 return fopen(file, mode);
122}
Yi Kong39bbd962022-01-09 19:41:38 +0800123
Alistair Delvabeaee832021-02-24 11:27:23 -0800124
125
126void *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
138void print_sector(const char *message, unsigned char *data, int size)
139{
140 int col;
141 int row;
142
143 printf("%s:\n", message);
Yi Kong39bbd962022-01-09 19:41:38 +0800144
Alistair Delvabeaee832021-02-24 11:27:23 -0800145 for(row = 0; row * 16 < size; row++){
146 printf("%03x ", row * 16);
Yi Kong39bbd962022-01-09 19:41:38 +0800147 for(col = 0; col < 16; col++)
Alistair Delvabeaee832021-02-24 11:27:23 -0800148 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
165time_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 }
Yi Kong39bbd962022-01-09 19:41:38 +0800196
Alistair Delvabeaee832021-02-24 11:27:23 -0800197 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) */
Yi Kong39bbd962022-01-09 19:41:38 +0800209off_t str_to_offset_with_end(const char *str, char **endp) {
210 char s;
Alistair Delvabeaee832021-02-24 11:27:23 -0800211 off_t ofs;
212
Yi Kong39bbd962022-01-09 19:41:38 +0800213 *endp = NULL;
214 ofs = strtol(str, endp, 0);
215 s = **endp;
216 /* trailing char, see if it is a size specifier */
217 if (s == 's' || s == 'S') /* sector */
218 ofs <<= 9;
219 else if (s == 'k' || s == 'K') /* kb */
220 ofs <<= 10;
221 else if (s == 'm' || s == 'M') /* Mb */
222 ofs <<= 20;
223 else if (s == 'g' || s == 'G') /* Gb */
224 ofs <<= 30;
225 else
226 return ofs; /* invalid character */
227 (*endp)++;
Alistair Delvabeaee832021-02-24 11:27:23 -0800228 return ofs;
229}
230
Yi Kong39bbd962022-01-09 19:41:38 +0800231/* Convert a string to a size. The string should be a number,
232 optionally followed by S (sectors), K (K-Bytes), M (Megabytes), G
233 (Gigabytes) */
234mt_off_t str_to_off_with_end(const char *str, char **endp) {
235 char s;
236 mt_off_t siz;
237
238 *endp = NULL;
239 siz = strtol(str, endp, 0);
240 s = **endp;
241 /* trailing char, see if it is a size specifier */
242 if (s == 's' || s == 'S') /* sector */
243 siz <<= 9;
244 else if (s == 'k' || s == 'K') /* kb */
245 siz <<= 10;
246 else if (s == 'm' || s == 'M') /* Mb */
247 siz <<= 20;
248 else if (s == 'g' || s == 'G') /* Gb */
249 siz <<= 30;
250 else
251 return siz; /* invalid character */
252 (*endp)++;
253 return siz;
254}
255
256off_t str_to_offset(char *str) {
257 char *end;
258 off_t ofs = str_to_offset_with_end(str, &end);
259 if (ofs <= 0)
260 return 0; /* invalid or missing offset */
261 if (*end)
262 return 0; /* extra char, invalid */
263 return ofs;
264}
265
266
267
Alistair Delvabeaee832021-02-24 11:27:23 -0800268#if 0
269
270#undef free
271#undef malloc
272
273static int total=0;
274
275void myfree(void *ptr)
276{
277 int *size = ((int *) ptr)-1;
278 total -= *size;
279 fprintf(stderr, "freeing %d bytes at %p total allocated=%d\n",
280 *size, ptr, total);
281 free(size);
282}
283
284void *mymalloc(size_t size)
285{
286 int *ptr;
287 ptr = (int *)malloc(size+sizeof(int));
288 if(!ptr)
289 return 0;
290 *ptr = size;
291 ptr++;
292 total += size;
293 fprintf(stderr, "allocating %d bytes at %p total allocated=%d\n",
294 size, ptr, total);
295 return (void *) ptr;
296}
297
298void *mycalloc(size_t nmemb, size_t size)
299{
300 void *ptr = mymalloc(nmemb * size);
301 if(!ptr)
302 return 0;
303 memset(ptr, 0, size);
304 return ptr;
305}
306
307void *myrealloc(void *ptr, size_t size)
308{
309 int oldsize = ((int *)ptr) [-1];
310 void *new = mymalloc(size);
311 if(!new)
312 return 0;
313 memcpy(new, ptr, oldsize);
314 myfree(ptr);
315 return new;
316}
317
318char *mystrdup(char *src)
319{
320 char *dest;
321 dest = mymalloc(strlen(src)+1);
322 if(!dest)
323 return 0;
324 strcpy(dest, src);
325 return dest;
326}
327
328#endif