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