Changeset 988 for vendor/current/lib/util/util.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/lib/util/util.c
r740 r988 4 4 Copyright (C) Andrew Tridgell 1992-1998 5 5 Copyright (C) Jeremy Allison 2001-2002 6 Copyright (C) Simo Sorce 2001 6 Copyright (C) Simo Sorce 2001-2011 7 7 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. 8 8 Copyright (C) James J Myers 2003 9 Copyright (C) Volker Lendecke 2010 9 10 10 11 This program is free software; you can redistribute it and/or modify … … 22 23 */ 23 24 24 #include "includes.h" 25 #include "replace.h" 26 #include <talloc.h> 25 27 #include "system/network.h" 26 28 #include "system/filesys.h" 27 29 #include "system/locale.h" 28 30 #include "system/shmem.h" 31 #include "system/passwd.h" 32 #include "system/time.h" 33 #include "system/wait.h" 34 #include "debug.h" 35 #include "samba_util.h" 29 36 30 37 #undef malloc … … 33 40 #undef strdup 34 41 #undef realloc 35 36 #if defined(UID_WRAPPER) 37 #if !defined(UID_WRAPPER_REPLACE) && !defined(UID_WRAPPER_NOT_REPLACE) 38 #define UID_WRAPPER_REPLACE 39 #include "../uid_wrapper/uid_wrapper.h" 40 #endif 41 #else 42 #define uwrap_enabled() 0 43 #endif 42 #undef calloc 44 43 45 44 /** … … 62 61 63 62 /** 63 Create a tmp file, open it and immediately unlink it. 64 If dir is NULL uses tmpdir() 65 Returns the file descriptor or -1 on error. 66 **/ 67 int create_unlink_tmp(const char *dir) 68 { 69 size_t len = strlen(dir); 70 char fname[len+25]; 71 int fd; 72 mode_t mask; 73 74 if (!dir) { 75 dir = tmpdir(); 76 } 77 78 len = snprintf(fname, sizeof(fname), "%s/listenerlock_XXXXXX", dir); 79 if (len >= sizeof(fname)) { 80 errno = ENOMEM; 81 return -1; 82 } 83 mask = umask(S_IRWXO | S_IRWXG); 84 fd = mkstemp(fname); 85 umask(mask); 86 if (fd == -1) { 87 return -1; 88 } 89 if (unlink(fname) == -1) { 90 int sys_errno = errno; 91 close(fd); 92 errno = sys_errno; 93 return -1; 94 } 95 return fd; 96 } 97 98 99 /** 64 100 Check if a file exists - call vfs_file_exist for samba files. 65 101 **/ … … 90 126 91 127 /** 128 Check file permissions. 129 **/ 130 131 _PUBLIC_ bool file_check_permissions(const char *fname, 132 uid_t uid, 133 mode_t file_perms, 134 struct stat *pst) 135 { 136 int ret; 137 struct stat st; 138 139 if (pst == NULL) { 140 pst = &st; 141 } 142 143 ZERO_STRUCTP(pst); 144 145 ret = stat(fname, pst); 146 if (ret != 0) { 147 DEBUG(0, ("stat failed on file '%s': %s\n", 148 fname, strerror(errno))); 149 return false; 150 } 151 152 if (pst->st_uid != uid && !uid_wrapper_enabled()) { 153 DEBUG(0, ("invalid ownership of file '%s': " 154 "owned by uid %u, should be %u\n", 155 fname, (unsigned int)pst->st_uid, 156 (unsigned int)uid)); 157 return false; 158 } 159 160 if ((pst->st_mode & 0777) != file_perms) { 161 DEBUG(0, ("invalid permissions on file " 162 "'%s': has 0%o should be 0%o\n", fname, 163 (unsigned int)(pst->st_mode & 0777), 164 (unsigned int)file_perms)); 165 return false; 166 } 167 168 return true; 169 } 170 171 /** 92 172 Check if a directory exists. 93 173 **/ … … 111 191 * Try to create the specified directory if it didn't exist. 112 192 * 113 * @retval true if the directory already existed and has the right permissions193 * @retval true if the directory already existed 114 194 * or was successfully created. 115 195 */ 116 _PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, 117 mode_t dir_perms) 118 { 196 _PUBLIC_ bool directory_create_or_exist(const char *dname, 197 mode_t dir_perms) 198 { 199 int ret; 200 struct stat st; 119 201 mode_t old_umask; 120 struct stat st; 121 202 203 ret = lstat(dname, &st); 204 if (ret == 0) { 205 return true; 206 } 207 208 if (errno != ENOENT) { 209 DEBUG(0, ("lstat failed on directory %s: %s\n", 210 dname, strerror(errno))); 211 return false; 212 } 213 214 /* Create directory */ 122 215 old_umask = umask(0); 123 if (lstat(dname, &st) == -1) { 124 if (errno == ENOENT) { 125 /* Create directory */ 126 if (mkdir(dname, dir_perms) == -1) { 127 DEBUG(0, ("error creating directory " 128 "%s: %s\n", dname, 129 strerror(errno))); 130 umask(old_umask); 131 return false; 132 } 133 } else { 134 DEBUG(0, ("lstat failed on directory %s: %s\n", 135 dname, strerror(errno))); 136 umask(old_umask); 137 return false; 138 } 139 } else { 140 /* Check ownership and permission on existing directory */ 141 if (!S_ISDIR(st.st_mode)) { 142 DEBUG(0, ("directory %s isn't a directory\n", 143 dname)); 144 umask(old_umask); 145 return false; 146 } 147 if (st.st_uid != uid && !uwrap_enabled()) { 148 DEBUG(0, ("invalid ownership on directory " 149 "%s\n", dname)); 150 umask(old_umask); 151 return false; 152 } 153 if ((st.st_mode & 0777) != dir_perms) { 154 DEBUG(0, ("invalid permissions on directory " 155 "%s\n", dname)); 156 umask(old_umask); 157 return false; 158 } 159 } 216 ret = mkdir(dname, dir_perms); 217 if (ret == -1 && errno != EEXIST) { 218 DEBUG(0, ("mkdir failed on directory " 219 "%s: %s\n", dname, 220 strerror(errno))); 221 umask(old_umask); 222 return false; 223 } 224 umask(old_umask); 225 226 ret = lstat(dname, &st); 227 if (ret == -1) { 228 DEBUG(0, ("lstat failed on created directory %s: %s\n", 229 dname, strerror(errno))); 230 return false; 231 } 232 160 233 return true; 161 } 234 } 235 236 /** 237 * @brief Try to create a specified directory if it doesn't exist. 238 * 239 * The function creates a directory with the given uid and permissions if it 240 * doesn't exist. If it exists it makes sure the uid and permissions are 241 * correct and it will fail if they are different. 242 * 243 * @param[in] dname The directory to create. 244 * 245 * @param[in] uid The uid the directory needs to belong too. 246 * 247 * @param[in] dir_perms The expected permissions of the directory. 248 * 249 * @return True on success, false on error. 250 */ 251 _PUBLIC_ bool directory_create_or_exist_strict(const char *dname, 252 uid_t uid, 253 mode_t dir_perms) 254 { 255 struct stat st; 256 bool ok; 257 int rc; 258 259 ok = directory_create_or_exist(dname, dir_perms); 260 if (!ok) { 261 return false; 262 } 263 264 rc = lstat(dname, &st); 265 if (rc == -1) { 266 DEBUG(0, ("lstat failed on created directory %s: %s\n", 267 dname, strerror(errno))); 268 return false; 269 } 270 271 /* Check ownership and permission on existing directory */ 272 if (!S_ISDIR(st.st_mode)) { 273 DEBUG(0, ("directory %s isn't a directory\n", 274 dname)); 275 return false; 276 } 277 if (st.st_uid != uid && !uid_wrapper_enabled()) { 278 DBG_NOTICE("invalid ownership on directory " 279 "%s\n", dname); 280 return false; 281 } 282 if ((st.st_mode & 0777) != dir_perms) { 283 DEBUG(0, ("invalid permissions on directory " 284 "'%s': has 0%o should be 0%o\n", dname, 285 (unsigned int)(st.st_mode & 0777), (unsigned int)dir_perms)); 286 return false; 287 } 288 289 return true; 290 } 162 291 163 292 … … 247 376 /* Doing kill with a non-positive pid causes messages to be 248 377 * sent to places we don't want. */ 249 SMB_ASSERT(pid > 0); 378 if (pid <= 0) { 379 return false; 380 } 250 381 return(kill(pid,0) == 0 || errno != ESRCH); 251 382 } … … 299 430 300 431 return true; 432 } 433 434 struct debug_channel_level { 435 int channel; 436 int level; 437 }; 438 439 static void debugadd_channel_cb(const char *buf, void *private_data) 440 { 441 struct debug_channel_level *dcl = 442 (struct debug_channel_level *)private_data; 443 444 DEBUGADDC(dcl->channel, dcl->level,("%s", buf)); 301 445 } 302 446 … … 387 531 int n; 388 532 n = 16 - (i%16); 389 cb(" ", private_data);533 cb(" ", private_data); 390 534 if (n>8) { 391 535 cb(" ", private_data); … … 422 566 * Write dump of binary data to the log file. 423 567 * 568 * The data is only written if the log level is at least level for 569 * debug class dbgc_class. 570 */ 571 _PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len) 572 { 573 struct debug_channel_level dcl = { dbgc_class, level }; 574 575 if (!DEBUGLVLC(dbgc_class, level)) { 576 return; 577 } 578 dump_data_cb(buf, len, false, debugadd_channel_cb, &dcl); 579 } 580 581 /** 582 * Write dump of binary data to the log file. 583 * 424 584 * The data is only written if the log level is at least level. 425 585 * 16 zero bytes in a row are omitted … … 433 593 } 434 594 595 static void fprintf_cb(const char *buf, void *private_data) 596 { 597 FILE *f = (FILE *)private_data; 598 fprintf(f, "%s", buf); 599 } 600 601 void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes, 602 FILE *f) 603 { 604 dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f); 605 } 435 606 436 607 /** … … 526 697 **/ 527 698 528 _PUBLIC_ void * memdup(const void *p, size_t size)699 _PUBLIC_ void *smb_memdup(const void *p, size_t size) 529 700 { 530 701 void *p2; … … 562 733 _PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size) 563 734 { 564 int i;735 size_t i; 565 736 if (!ptr) return true; 566 737 for (i=0;i<size;i++) { … … 595 766 { 596 767 return realloc_array(NULL, el_size, count, false); 768 } 769 770 /**************************************************************************** 771 Type-safe memalign 772 ****************************************************************************/ 773 774 void *memalign_array(size_t el_size, size_t align, unsigned int count) 775 { 776 if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) { 777 return NULL; 778 } 779 780 return memalign(align, el_size*count); 781 } 782 783 /**************************************************************************** 784 Type-safe calloc. 785 ****************************************************************************/ 786 787 void *calloc_array(size_t size, size_t nmemb) 788 { 789 if (nmemb >= MAX_MALLOC_SIZE/size) { 790 return NULL; 791 } 792 if (size == 0 || nmemb == 0) { 793 return NULL; 794 } 795 return calloc(nmemb, size); 597 796 } 598 797 … … 652 851 653 852 /** 654 Routine to get hex characters and turn them into a 16byte array.655 the array can be variable length, and any non-hex-numeric656 characters are skipped. "0xnn" or "0Xnn" is specially catered657 for.658 659 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"660 661 662 **/853 * Routine to get hex characters and turn them into a byte array. 854 * the array can be variable length. 855 * - "0xnn" or "0Xnn" is specially catered for. 856 * - The first non-hex-digit character (apart from possibly leading "0x" 857 * finishes the conversion and skips the rest of the input. 858 * - A single hex-digit character at the end of the string is skipped. 859 * 860 * valid examples: "0A5D15"; "0x123456" 861 */ 663 862 _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len) 664 863 { … … 674 873 } 675 874 676 for (; i < strhex_len && strhex[i] != 0; i++) { 677 if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) 875 for (; i+1 < strhex_len && strhex[i] != 0 && strhex[i+1] != 0; i++) { 876 p1 = strchr(hexchars, toupper((unsigned char)strhex[i])); 877 if (p1 == NULL) { 678 878 break; 879 } 679 880 680 881 i++; /* next hex digit */ 681 882 682 if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i])))) 883 p2 = strchr(hexchars, toupper((unsigned char)strhex[i])); 884 if (p2 == NULL) { 683 885 break; 886 } 684 887 685 888 /* get the two nybbles */ … … 714 917 } 715 918 716 717 /** 718 * Routine to print a buffer as HEX digits, into an allocated string. 719 */ 720 _PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) 721 { 722 int i; 723 char *hex_buffer; 724 725 *out_hex_buffer = malloc_array_p(char, (len*2)+1); 726 hex_buffer = *out_hex_buffer; 727 728 for (i = 0; i < len; i++) 729 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); 730 } 731 732 /** 733 * talloc version of hex_encode() 919 /** 920 * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large. 921 */ 922 _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen) 923 { 924 size_t i; 925 for (i=0; i<srclen; i++) { 926 snprintf(dst + i*2, 3, "%02X", src[i]); 927 } 928 /* 929 * Ensure 0-termination for 0-length buffers 930 */ 931 dst[srclen*2] = '\0'; 932 } 933 934 /** 935 * talloc version of hex_encode_buf() 734 936 */ 735 937 _PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len) 736 938 { 737 int i;738 939 char *hex_buffer; 739 940 … … 742 943 return NULL; 743 944 } 744 745 for (i = 0; i < len; i++) 746 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); 747 945 hex_encode_buf(hex_buffer, buff_in, len); 748 946 talloc_set_name_const(hex_buffer, hex_buffer); 749 947 return hex_buffer; … … 780 978 781 979 return len; 782 }783 784 /**785 Set a boolean variable from the text value stored in the passed string.786 Returns true in success, false if the passed string does not correctly787 represent a boolean.788 **/789 790 _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)791 {792 if (strwicmp(boolean_string, "yes") == 0 ||793 strwicmp(boolean_string, "true") == 0 ||794 strwicmp(boolean_string, "on") == 0 ||795 strwicmp(boolean_string, "1") == 0) {796 *boolean = true;797 return true;798 } else if (strwicmp(boolean_string, "no") == 0 ||799 strwicmp(boolean_string, "false") == 0 ||800 strwicmp(boolean_string, "off") == 0 ||801 strwicmp(boolean_string, "0") == 0) {802 *boolean = false;803 return true;804 }805 return false;806 }807 808 /**809 return the number of bytes occupied by a buffer in CH_UTF16 format810 the result includes the null termination811 **/812 _PUBLIC_ size_t utf16_len(const void *buf)813 {814 size_t len;815 816 for (len = 0; SVAL(buf,len); len += 2) ;817 818 return len + 2;819 }820 821 /**822 return the number of bytes occupied by a buffer in CH_UTF16 format823 the result includes the null termination824 limited by 'n' bytes825 **/826 _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)827 {828 size_t len;829 830 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;831 832 if (len+2 <= n) {833 len += 2;834 }835 836 return len;837 }838 839 /**840 * @file841 * @brief String utilities.842 **/843 844 static bool next_token_internal_talloc(TALLOC_CTX *ctx,845 const char **ptr,846 char **pp_buff,847 const char *sep,848 bool ltrim)849 {850 const char *s;851 const char *saved_s;852 char *pbuf;853 bool quoted;854 size_t len=1;855 856 *pp_buff = NULL;857 if (!ptr) {858 return(false);859 }860 861 s = *ptr;862 863 /* default to simple separators */864 if (!sep) {865 sep = " \t\n\r";866 }867 868 /* find the first non sep char, if left-trimming is requested */869 if (ltrim) {870 while (*s && strchr_m(sep,*s)) {871 s++;872 }873 }874 875 /* nothing left? */876 if (!*s) {877 return false;878 }879 880 /* When restarting we need to go from here. */881 saved_s = s;882 883 /* Work out the length needed. */884 for (quoted = false; *s &&885 (quoted || !strchr_m(sep,*s)); s++) {886 if (*s == '\"') {887 quoted = !quoted;888 } else {889 len++;890 }891 }892 893 /* We started with len = 1 so we have space for the nul. */894 *pp_buff = talloc_array(ctx, char, len);895 if (!*pp_buff) {896 return false;897 }898 899 /* copy over the token */900 pbuf = *pp_buff;901 s = saved_s;902 for (quoted = false; *s &&903 (quoted || !strchr_m(sep,*s)); s++) {904 if ( *s == '\"' ) {905 quoted = !quoted;906 } else {907 *pbuf++ = *s;908 }909 }910 911 *ptr = (*s) ? s+1 : s;912 *pbuf = 0;913 914 return true;915 }916 917 bool next_token_talloc(TALLOC_CTX *ctx,918 const char **ptr,919 char **pp_buff,920 const char *sep)921 {922 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);923 }924 925 /*926 * Get the next token from a string, return false if none found. Handles927 * double-quotes. This version does not trim leading separator characters928 * before looking for a token.929 */930 931 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,932 const char **ptr,933 char **pp_buff,934 const char *sep)935 {936 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);937 }938 939 /**940 * Get the next token from a string, return False if none found.941 * Handles double-quotes.942 *943 * Based on a routine by GJC@VILLAGE.COM.944 * Extensively modified by Andrew.Tridgell@anu.edu.au945 **/946 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)947 {948 const char *s;949 bool quoted;950 size_t len=1;951 952 if (!ptr)953 return false;954 955 s = *ptr;956 957 /* default to simple separators */958 if (!sep)959 sep = " \t\n\r";960 961 /* find the first non sep char */962 while (*s && strchr_m(sep,*s))963 s++;964 965 /* nothing left? */966 if (!*s)967 return false;968 969 /* copy over the token */970 for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {971 if (*s == '\"') {972 quoted = !quoted;973 } else {974 len++;975 *buff++ = *s;976 }977 }978 979 *ptr = (*s) ? s+1 : s;980 *buff = 0;981 982 return true;983 980 } 984 981 … … 1020 1017 -1 /* fd */, 0 /* offset */); 1021 1018 #else 1019 { 1020 int saved_errno; 1021 int fd; 1022 1023 fd = open("/dev/zero", O_RDWR); 1024 if (fd == -1) { 1025 return NULL; 1026 } 1027 1022 1028 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 1023 open("/dev/zero", O_RDWR), 0 /* offset */); 1029 fd, 0 /* offset */); 1030 saved_errno = errno; 1031 close(fd); 1032 errno = saved_errno; 1033 } 1024 1034 #endif 1025 1035 … … 1034 1044 1035 1045 return ptr; 1046 } 1047 1048 void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove) 1049 { 1050 #ifdef HAVE_MREMAP 1051 void *buf; 1052 size_t pagesz = getpagesize(); 1053 size_t pagecnt; 1054 size_t bufsz; 1055 struct anonymous_shared_header *hdr; 1056 int flags = 0; 1057 1058 if (ptr == NULL) { 1059 errno = EINVAL; 1060 return NULL; 1061 } 1062 1063 hdr = (struct anonymous_shared_header *)ptr; 1064 hdr--; 1065 if (hdr->u.length > (new_size + sizeof(*hdr))) { 1066 errno = EINVAL; 1067 return NULL; 1068 } 1069 1070 bufsz = new_size + sizeof(*hdr); 1071 1072 /* round up to full pages */ 1073 pagecnt = bufsz / pagesz; 1074 if (bufsz % pagesz) { 1075 pagecnt += 1; 1076 } 1077 bufsz = pagesz * pagecnt; 1078 1079 if (new_size >= bufsz) { 1080 /* integer wrap */ 1081 errno = ENOSPC; 1082 return NULL; 1083 } 1084 1085 if (bufsz <= hdr->u.length) { 1086 return ptr; 1087 } 1088 1089 if (maymove) { 1090 flags = MREMAP_MAYMOVE; 1091 } 1092 1093 buf = mremap(hdr, hdr->u.length, bufsz, flags); 1094 1095 if (buf == MAP_FAILED) { 1096 errno = ENOSPC; 1097 return NULL; 1098 } 1099 1100 hdr = (struct anonymous_shared_header *)buf; 1101 hdr->u.length = bufsz; 1102 1103 ptr = (void *)(&hdr[1]); 1104 1105 return ptr; 1106 #else 1107 errno = ENOSPC; 1108 return NULL; 1109 #endif 1036 1110 } 1037 1111
Note:
See TracChangeset
for help on using the changeset viewer.