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 
printOom(void)27 void printOom(void)
28 {
29 	fprintf(stderr, "Out of memory error");
30 }
31 
get_homedir(void)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 
get_mcwd_file_name(char * file)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 
unlink_mcwd(void)91 void unlink_mcwd(void)
92 {
93 	char file[MAXPATHLEN+1];
94 	get_mcwd_file_name(file);
95 	unlink(file);
96 }
97 
open_mcwd(const char * mode)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 
safe_malloc(size_t size)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 
print_sector(const char * message,unsigned char * data,int size)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 
getTimeNow(time_t * now)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) */
str_to_offset(char * str)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
295