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