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