Imported Upstream version 4.0.30
[platform/upstream/mtools.git] / misc.c
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_with_end(const char *str, char **endp) {
210         char s;
211         off_t ofs;
212
213         *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)++;
228         return ofs;
229 }
230
231 /* 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) */
234 size_t str_to_size_with_end(const char *str, char **endp) {
235         char s;
236         size_t siz;
237
238         *endp = NULL;
239         siz = strtoul(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
256 off_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
268 #if 0
269
270 #undef free
271 #undef malloc
272
273 static int total=0;
274
275 void 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
284 void *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
298 void *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
307 void *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
318 char *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