r15191: Avoid uint_t as it's not standard.
[ab/samba.git/.git] / source / lib / util / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2002
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
8    Copyright (C) James J Myers 2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "system/network.h"
27 #include "system/iconv.h"
28 #include "system/filesys.h"
29
30 /**
31  * @file
32  * @brief Misc utility functions
33  */
34
35 /**
36  Find a suitable temporary directory. The result should be copied immediately
37  as it may be overwritten by a subsequent call.
38 **/
39 _PUBLIC_ const char *tmpdir(void)
40 {
41         char *p;
42         if ((p = getenv("TMPDIR")))
43                 return p;
44         return "/tmp";
45 }
46
47
48 /**
49  Check if a file exists - call vfs_file_exist for samba files.
50 **/
51 _PUBLIC_ BOOL file_exist(const char *fname)
52 {
53         struct stat st;
54
55         if (stat(fname, &st) != 0) {
56                 return False;
57         }
58
59         return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
60 }
61
62 /**
63  Check a files mod time.
64 **/
65
66 _PUBLIC_ time_t file_modtime(const char *fname)
67 {
68         struct stat st;
69   
70         if (stat(fname,&st) != 0) 
71                 return(0);
72
73         return(st.st_mtime);
74 }
75
76 /**
77  Check if a directory exists.
78 **/
79
80 _PUBLIC_ BOOL directory_exist(const char *dname)
81 {
82         struct stat st;
83         BOOL ret;
84
85         if (stat(dname,&st) != 0) {
86                 return False;
87         }
88
89         ret = S_ISDIR(st.st_mode);
90         if(!ret)
91                 errno = ENOTDIR;
92         return ret;
93 }
94
95 /**
96  * Try to create the specified directory if it didn't exist.
97  *
98  * @retval True if the directory already existed and has the right permissions 
99  * or was successfully created.
100  */
101 _PUBLIC_ BOOL directory_create_or_exist(const char *dname, uid_t uid, 
102                                mode_t dir_perms)
103 {
104         mode_t old_umask;
105         struct stat st;
106       
107         old_umask = umask(0);
108         if (lstat(dname, &st) == -1) {
109                 if (errno == ENOENT) {
110                         /* Create directory */
111                         if (mkdir(dname, dir_perms) == -1) {
112                                 DEBUG(0, ("error creating directory "
113                                           "%s: %s\n", dname, 
114                                           strerror(errno)));
115                                 umask(old_umask);
116                                 return False;
117                         }
118                 } else {
119                         DEBUG(0, ("lstat failed on directory %s: %s\n",
120                                   dname, strerror(errno)));
121                         umask(old_umask);
122                         return False;
123                 }
124         } else {
125                 /* Check ownership and permission on existing directory */
126                 if (!S_ISDIR(st.st_mode)) {
127                         DEBUG(0, ("directory %s isn't a directory\n",
128                                 dname));
129                         umask(old_umask);
130                         return False;
131                 }
132                 if ((st.st_uid != uid) || 
133                     ((st.st_mode & 0777) != dir_perms)) {
134                         DEBUG(0, ("invalid permissions on directory "
135                                   "%s\n", dname));
136                         umask(old_umask);
137                         return False;
138                 }
139         }
140         return True;
141 }       
142
143
144 /*******************************************************************
145  Close the low 3 fd's and open dev/null in their place.
146 ********************************************************************/
147 static void close_low_fds(BOOL stderr_too)
148 {
149 #ifndef VALGRIND
150         int fd;
151         int i;
152
153         close(0);
154         close(1); 
155
156         if (stderr_too)
157                 close(2);
158
159         /* try and use up these file descriptors, so silly
160                 library routines writing to stdout etc won't cause havoc */
161         for (i=0;i<3;i++) {
162                 if (i == 2 && !stderr_too)
163                         continue;
164
165                 fd = open("/dev/null",O_RDWR,0);
166                 if (fd < 0)
167                         fd = open("/dev/null",O_WRONLY,0);
168                 if (fd < 0) {
169                         DEBUG(0,("Can't open /dev/null\n"));
170                         return;
171                 }
172                 if (fd != i) {
173                         DEBUG(0,("Didn't get file descriptor %d\n",i));
174                         return;
175                 }
176         }
177 #endif
178 }
179
180 /**
181  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
182  else
183   if SYSV use O_NDELAY
184   if BSD use FNDELAY
185 **/
186
187 _PUBLIC_ int set_blocking(int fd, BOOL set)
188 {
189         int val;
190 #ifdef O_NONBLOCK
191 #define FLAG_TO_SET O_NONBLOCK
192 #else
193 #ifdef SYSV
194 #define FLAG_TO_SET O_NDELAY
195 #else /* BSD */
196 #define FLAG_TO_SET FNDELAY
197 #endif
198 #endif
199
200         if((val = fcntl(fd, F_GETFL, 0)) == -1)
201                 return -1;
202         if(set) /* Turn blocking on - ie. clear nonblock flag */
203                 val &= ~FLAG_TO_SET;
204         else
205                 val |= FLAG_TO_SET;
206         return fcntl( fd, F_SETFL, val);
207 #undef FLAG_TO_SET
208 }
209
210
211 /**
212  Sleep for a specified number of milliseconds.
213 **/
214
215 _PUBLIC_ void msleep(unsigned int t)
216 {
217         struct timeval tval;  
218
219         tval.tv_sec = t/1000;
220         tval.tv_usec = 1000*(t%1000);
221         /* this should be the real select - do NOT replace
222            with sys_select() */
223         select(0,NULL,NULL,NULL,&tval);
224 }
225
226 /**
227  Become a daemon, discarding the controlling terminal.
228 **/
229
230 _PUBLIC_ void become_daemon(BOOL Fork)
231 {
232         if (Fork) {
233                 if (fork()) {
234                         _exit(0);
235                 }
236         }
237
238   /* detach from the terminal */
239 #ifdef HAVE_SETSID
240         setsid();
241 #elif defined(TIOCNOTTY)
242         {
243                 int i = open("/dev/tty", O_RDWR, 0);
244                 if (i != -1) {
245                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
246                         close(i);
247                 }
248         }
249 #endif /* HAVE_SETSID */
250
251         /* Close fd's 0,1,2. Needed if started by rsh */
252         close_low_fds(False);  /* Don't close stderr, let the debug system
253                                   attach it to the logfile */
254 }
255
256
257 /**
258  Free memory, checks for NULL.
259  Use directly SAFE_FREE()
260  Exists only because we need to pass a function pointer somewhere --SSS
261 **/
262
263 _PUBLIC_ void safe_free(void *p)
264 {
265         SAFE_FREE(p);
266 }
267
268
269 /**
270  Get my own name, return in malloc'ed storage.
271 **/
272
273 _PUBLIC_ char* get_myname(void)
274 {
275         char *hostname;
276         const int host_name_max = 255;
277         char *p;
278
279         hostname = malloc(host_name_max+1);
280         *hostname = 0;
281
282         /* get my host name */
283         if (gethostname(hostname, host_name_max+1) == -1) {
284                 DEBUG(0,("gethostname failed\n"));
285                 return NULL;
286         } 
287
288         /* Ensure null termination. */
289         hostname[host_name_max] = '\0';
290
291         /* split off any parts after an initial . */
292         p = strchr_m(hostname,'.');
293
294         if (p)
295                 *p = 0;
296         
297         return hostname;
298 }
299
300 /**
301  Return true if a string could be a pure IP address.
302 **/
303
304 _PUBLIC_ BOOL is_ipaddress(const char *str)
305 {
306         BOOL pure_address = True;
307         int i;
308   
309         for (i=0; pure_address && str[i]; i++)
310                 if (!(isdigit((int)str[i]) || str[i] == '.'))
311                         pure_address = False;
312
313         /* Check that a pure number is not misinterpreted as an IP */
314         pure_address = pure_address && (strchr_m(str, '.') != NULL);
315
316         return pure_address;
317 }
318
319 /**
320  Interpret an internet address or name into an IP address in 4 byte form.
321 **/
322 _PUBLIC_ uint32_t interpret_addr(const char *str)
323 {
324         struct hostent *hp;
325         uint32_t res;
326
327         if (str == NULL || *str == 0 ||
328             strcmp(str,"0.0.0.0") == 0) {
329                 return 0;
330         }
331         if (strcmp(str,"255.255.255.255") == 0) {
332                 return 0xFFFFFFFF;
333         }
334         /* recognise 'localhost' as a special name. This fixes problems with
335            some hosts that don't have localhost in /etc/hosts */
336         if (strcasecmp(str,"localhost") == 0) {
337                 str = "127.0.0.1";
338         }
339
340         /* if it's in the form of an IP address then get the lib to interpret it */
341         if (is_ipaddress(str)) {
342                 res = inet_addr(str);
343         } else {
344                 /* otherwise assume it's a network name of some sort and use 
345                         sys_gethostbyname */
346                 if ((hp = sys_gethostbyname(str)) == 0) {
347                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
348                         return 0;
349                 }
350
351                 if(hp->h_addr == NULL) {
352                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
353                         return 0;
354                 }
355                 memcpy((char *)&res,(char *)hp->h_addr, 4);
356         }
357
358         if (res == (uint32_t)-1)
359                 return(0);
360
361         return(res);
362 }
363
364 /**
365  A convenient addition to interpret_addr().
366 **/
367 _PUBLIC_ struct ipv4_addr interpret_addr2(const char *str)
368 {
369         struct ipv4_addr ret;
370         uint32_t a = interpret_addr(str);
371         ret.addr = a;
372         return ret;
373 }
374
375 /**
376  Check if an IP is the 0.0.0.0.
377 **/
378
379 _PUBLIC_ BOOL is_zero_ip(struct ipv4_addr ip)
380 {
381         return ip.addr == 0;
382 }
383
384 /**
385  Are two IPs on the same subnet?
386 **/
387
388 _PUBLIC_ BOOL same_net(struct ipv4_addr ip1,struct ipv4_addr ip2,struct ipv4_addr mask)
389 {
390         uint32_t net1,net2,nmask;
391
392         nmask = ntohl(mask.addr);
393         net1  = ntohl(ip1.addr);
394         net2  = ntohl(ip2.addr);
395             
396         return((net1 & nmask) == (net2 & nmask));
397 }
398
399
400 /**
401  Check if a process exists. Does this work on all unixes?
402 **/
403
404 _PUBLIC_ BOOL process_exists(pid_t pid)
405 {
406         /* Doing kill with a non-positive pid causes messages to be
407          * sent to places we don't want. */
408         SMB_ASSERT(pid > 0);
409         return(kill(pid,0) == 0 || errno != ESRCH);
410 }
411
412 /**
413  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
414  is dealt with in posix.c
415 **/
416
417 _PUBLIC_ BOOL fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
418 {
419         struct flock lock;
420         int ret;
421
422         DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
423
424         lock.l_type = type;
425         lock.l_whence = SEEK_SET;
426         lock.l_start = offset;
427         lock.l_len = count;
428         lock.l_pid = 0;
429
430         ret = fcntl(fd,op,&lock);
431
432         if (ret == -1 && errno != 0)
433                 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
434
435         /* a lock query */
436         if (op == F_GETLK) {
437                 if ((ret != -1) &&
438                                 (lock.l_type != F_UNLCK) && 
439                                 (lock.l_pid != 0) && 
440                                 (lock.l_pid != getpid())) {
441                         DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
442                         return(True);
443                 }
444
445                 /* it must be not locked or locked by me */
446                 return(False);
447         }
448
449         /* a lock set or unset */
450         if (ret == -1) {
451                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
452                         (double)offset,(double)count,op,type,strerror(errno)));
453                 return(False);
454         }
455
456         /* everything went OK */
457         DEBUG(8,("fcntl_lock: Lock call successful\n"));
458
459         return(True);
460 }
461
462
463 static void print_asc(int level, const uint8_t *buf,int len)
464 {
465         int i;
466         for (i=0;i<len;i++)
467                 DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
468 }
469
470 /**
471  * Write dump of binary data to the log file.
472  *
473  * The data is only written if the log level is at least level.
474  */
475 _PUBLIC_ void dump_data(int level, const uint8_t *buf,int len)
476 {
477         int i=0;
478         if (len<=0) return;
479
480         if (!DEBUGLVL(level)) return;
481         
482         DEBUGADD(level,("[%03X] ",i));
483         for (i=0;i<len;) {
484                 DEBUGADD(level,("%02X ",(int)buf[i]));
485                 i++;
486                 if (i%8 == 0) DEBUGADD(level,(" "));
487                 if (i%16 == 0) {      
488                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
489                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
490                         if (i<len) DEBUGADD(level,("[%03X] ",i));
491                 }
492         }
493         if (i%16) {
494                 int n;
495                 n = 16 - (i%16);
496                 DEBUGADD(level,(" "));
497                 if (n>8) DEBUGADD(level,(" "));
498                 while (n--) DEBUGADD(level,("   "));
499                 n = MIN(8,i%16);
500                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
501                 n = (i%16) - n;
502                 if (n>0) print_asc(level,&buf[i-n],n); 
503                 DEBUGADD(level,("\n"));    
504         }       
505 }
506
507 /**
508  malloc that aborts with smb_panic on fail or zero size.
509 **/
510
511 _PUBLIC_ void *smb_xmalloc(size_t size)
512 {
513         void *p;
514         if (size == 0)
515                 smb_panic("smb_xmalloc: called with zero size.\n");
516         if ((p = malloc(size)) == NULL)
517                 smb_panic("smb_xmalloc: malloc fail.\n");
518         return p;
519 }
520
521 /**
522  Memdup with smb_panic on fail.
523 **/
524
525 _PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
526 {
527         void *p2;
528         p2 = smb_xmalloc(size);
529         memcpy(p2, p, size);
530         return p2;
531 }
532
533 /**
534  strdup that aborts on malloc fail.
535 **/
536
537 _PUBLIC_ char *smb_xstrdup(const char *s)
538 {
539         char *s1 = strdup(s);
540         if (!s1)
541                 smb_panic("smb_xstrdup: malloc fail\n");
542         return s1;
543 }
544
545
546 /**
547  Like strdup but for memory.
548 **/
549
550 _PUBLIC_ void *memdup(const void *p, size_t size)
551 {
552         void *p2;
553         if (size == 0)
554                 return NULL;
555         p2 = malloc(size);
556         if (!p2)
557                 return NULL;
558         memcpy(p2, p, size);
559         return p2;
560 }
561
562 /**
563  * Write a password to the log file.
564  *
565  * @note Only actually does something if DEBUG_PASSWORD was defined during 
566  * compile-time.
567  */
568 _PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
569 {
570 #ifdef DEBUG_PASSWORD
571         DEBUG(11, ("%s", msg));
572         if (data != NULL && len > 0)
573         {
574                 dump_data(11, data, len);
575         }
576 #endif
577 }
578
579
580 /**
581  * see if a range of memory is all zero. A NULL pointer is considered
582  * to be all zero 
583  */
584 _PUBLIC_ BOOL all_zero(const uint8_t *ptr, size_t size)
585 {
586         int i;
587         if (!ptr) return True;
588         for (i=0;i<size;i++) {
589                 if (ptr[i]) return False;
590         }
591         return True;
592 }
593
594 /**
595   realloc an array, checking for integer overflow in the array size
596 */
597 _PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count)
598 {
599 #define MAX_MALLOC_SIZE 0x7fffffff
600         if (count == 0 ||
601             count >= MAX_MALLOC_SIZE/el_size) {
602                 return NULL;
603         }
604         if (!ptr) {
605                 return malloc(el_size * count);
606         }
607         return realloc(ptr, el_size * count);
608 }
609