Changeset 740 for vendor/current/lib
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- Location:
- vendor/current/lib
- Files:
-
- 379 added
- 66 deleted
- 189 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/lib/README
r414 r740 1 1 compression - Various compression algorithms (MSZIP, lzxpress) 2 dnspython - Python module for working with DNS. 2 3 nss_wrapper - Wrapper for the user and group NSS API allowing the use 3 4 of other data sources. … … 7 8 socket_wrapper - Wrapper library allowing TCP/IP traffic to be redirected 8 9 over Unix domain sockets. 10 subunit - Utilities and bindings for working with the Subunit test result 11 reporting protocol. 9 12 talloc - Hierarchical pool based memory allocator 10 13 tdb - Simple but fast key/value database library, supporting multiple writers -
vendor/current/lib/async_req/async_sock.c
r414 r740 37 37 #endif 38 38 39 struct async_send_state {39 struct sendto_state { 40 40 int fd; 41 41 const void *buf; 42 42 size_t len; 43 43 int flags; 44 const struct sockaddr_storage *addr; 45 socklen_t addr_len; 44 46 ssize_t sent; 45 47 }; 46 48 47 static void async_send_handler(struct tevent_context *ev,49 static void sendto_handler(struct tevent_context *ev, 48 50 struct tevent_fd *fde, 49 51 uint16_t flags, void *private_data); 50 52 51 struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, 52 struct tevent_context *ev, 53 int fd, const void *buf, size_t len, 54 int flags) 53 struct tevent_req *sendto_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, 54 int fd, const void *buf, size_t len, int flags, 55 const struct sockaddr_storage *addr) 55 56 { 56 57 struct tevent_req *result; 57 struct async_send_state *state;58 struct sendto_state *state; 58 59 struct tevent_fd *fde; 59 60 60 result = tevent_req_create(mem_ctx, &state, struct async_send_state);61 result = tevent_req_create(mem_ctx, &state, struct sendto_state); 61 62 if (result == NULL) { 62 63 return result; … … 66 67 state->len = len; 67 68 state->flags = flags; 68 69 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, async_send_handler, 69 state->addr = addr; 70 71 switch (addr->ss_family) { 72 case AF_INET: 73 state->addr_len = sizeof(struct sockaddr_in); 74 break; 75 #if defined(HAVE_IPV6) 76 case AF_INET6: 77 state->addr_len = sizeof(struct sockaddr_in6); 78 break; 79 #endif 80 case AF_UNIX: 81 state->addr_len = sizeof(struct sockaddr_un); 82 break; 83 default: 84 state->addr_len = sizeof(struct sockaddr_storage); 85 break; 86 } 87 88 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, sendto_handler, 70 89 result); 71 90 if (fde == NULL) { … … 76 95 } 77 96 78 static void async_send_handler(struct tevent_context *ev,97 static void sendto_handler(struct tevent_context *ev, 79 98 struct tevent_fd *fde, 80 99 uint16_t flags, void *private_data) … … 82 101 struct tevent_req *req = talloc_get_type_abort( 83 102 private_data, struct tevent_req); 84 struct async_send_state *state = 85 tevent_req_data(req, struct async_send_state); 86 87 state->sent = send(state->fd, state->buf, state->len, state->flags); 103 struct sendto_state *state = 104 tevent_req_data(req, struct sendto_state); 105 106 state->sent = sendto(state->fd, state->buf, state->len, state->flags, 107 (struct sockaddr *)state->addr, state->addr_len); 88 108 if ((state->sent == -1) && (errno == EINTR)) { 89 109 /* retry */ … … 97 117 } 98 118 99 ssize_t async_send_recv(struct tevent_req *req, int *perrno)100 { 101 struct async_send_state *state =102 tevent_req_data(req, struct async_send_state);119 ssize_t sendto_recv(struct tevent_req *req, int *perrno) 120 { 121 struct sendto_state *state = 122 tevent_req_data(req, struct sendto_state); 103 123 104 124 if (tevent_req_is_unix_error(req, perrno)) { … … 108 128 } 109 129 110 struct async_recv_state {130 struct recvfrom_state { 111 131 int fd; 112 132 void *buf; 113 133 size_t len; 114 134 int flags; 135 struct sockaddr_storage *addr; 136 socklen_t *addr_len; 115 137 ssize_t received; 116 138 }; 117 139 118 static void async_recv_handler(struct tevent_context *ev,140 static void recvfrom_handler(struct tevent_context *ev, 119 141 struct tevent_fd *fde, 120 142 uint16_t flags, void *private_data); 121 143 122 struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx, 123 struct tevent_context *ev, 124 int fd, void *buf, size_t len, int flags) 144 struct tevent_req *recvfrom_send(TALLOC_CTX *mem_ctx, 145 struct tevent_context *ev, 146 int fd, void *buf, size_t len, int flags, 147 struct sockaddr_storage *addr, 148 socklen_t *addr_len) 125 149 { 126 150 struct tevent_req *result; 127 struct async_recv_state *state;151 struct recvfrom_state *state; 128 152 struct tevent_fd *fde; 129 153 130 result = tevent_req_create(mem_ctx, &state, struct async_recv_state);154 result = tevent_req_create(mem_ctx, &state, struct recvfrom_state); 131 155 if (result == NULL) { 132 156 return result; … … 136 160 state->len = len; 137 161 state->flags = flags; 138 139 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, async_recv_handler, 162 state->addr = addr; 163 state->addr_len = addr_len; 164 165 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, recvfrom_handler, 140 166 result); 141 167 if (fde == NULL) { … … 146 172 } 147 173 148 static void async_recv_handler(struct tevent_context *ev,174 static void recvfrom_handler(struct tevent_context *ev, 149 175 struct tevent_fd *fde, 150 176 uint16_t flags, void *private_data) … … 152 178 struct tevent_req *req = talloc_get_type_abort( 153 179 private_data, struct tevent_req); 154 struct async_recv_state *state = 155 tevent_req_data(req, struct async_recv_state); 156 157 state->received = recv(state->fd, state->buf, state->len, 158 state->flags); 180 struct recvfrom_state *state = 181 tevent_req_data(req, struct recvfrom_state); 182 183 state->received = recvfrom(state->fd, state->buf, state->len, 184 state->flags, (struct sockaddr *)state->addr, 185 state->addr_len); 159 186 if ((state->received == -1) && (errno == EINTR)) { 160 187 /* retry */ … … 172 199 } 173 200 174 ssize_t async_recv_recv(struct tevent_req *req, int *perrno)175 { 176 struct async_recv_state *state =177 tevent_req_data(req, struct async_recv_state);201 ssize_t recvfrom_recv(struct tevent_req *req, int *perrno) 202 { 203 struct recvfrom_state *state = 204 tevent_req_data(req, struct recvfrom_state); 178 205 179 206 if (tevent_req_is_unix_error(req, perrno)) { … … 359 386 size_t total_size; 360 387 uint16_t flags; 388 bool err_on_readability; 361 389 }; 362 390 … … 386 414 goto fail; 387 415 } 388 state->flags = TEVENT_FD_WRITE; 389 if (err_on_readability) { 390 state->flags |= TEVENT_FD_READ; 391 } 416 state->flags = TEVENT_FD_WRITE|TEVENT_FD_READ; 417 state->err_on_readability = err_on_readability; 392 418 393 419 if (queue == NULL) { … … 435 461 436 462 if ((state->flags & TEVENT_FD_READ) && (flags & TEVENT_FD_READ)) { 437 tevent_req_error(req, EPIPE); 438 return; 463 int ret, value; 464 465 if (state->err_on_readability) { 466 /* Readable and the caller wants an error on read. */ 467 tevent_req_error(req, EPIPE); 468 return; 469 } 470 471 /* Might be an error. Check if there are bytes to read */ 472 ret = ioctl(state->fd, FIONREAD, &value); 473 /* FIXME - should we also check 474 for ret == 0 and value == 0 here ? */ 475 if (ret == -1) { 476 /* There's an error. */ 477 tevent_req_error(req, EPIPE); 478 return; 479 } 480 /* A request for TEVENT_FD_READ will succeed from now and 481 forevermore until the bytes are read so if there was 482 an error we'll wait until we do read, then get it in 483 the read callback function. Until then, remove TEVENT_FD_READ 484 from the flags we're waiting for. */ 485 state->flags &= ~TEVENT_FD_READ; 486 TEVENT_FD_NOT_READABLE(fde); 487 488 /* If not writable, we're done. */ 489 if (!(flags & TEVENT_FD_WRITE)) { 490 return; 491 } 439 492 } 440 493 -
vendor/current/lib/async_req/async_sock.h
r414 r740 28 28 #include <tevent.h> 29 29 30 struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, 31 struct tevent_context *ev, 32 int fd, const void *buf, size_t len, 33 int flags); 34 ssize_t async_send_recv(struct tevent_req *req, int *perrno); 30 struct tevent_req *sendto_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, 31 int fd, const void *buf, size_t len, int flags, 32 const struct sockaddr_storage *addr); 33 ssize_t sendto_recv(struct tevent_req *req, int *perrno); 35 34 36 struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx, 37 struct tevent_context *ev, 38 int fd, void *buf, size_t len, int flags); 39 ssize_t async_recv_recv(struct tevent_req *req, int *perrno); 35 struct tevent_req *recvfrom_send(TALLOC_CTX *mem_ctx, 36 struct tevent_context *ev, 37 int fd, void *buf, size_t len, int flags, 38 struct sockaddr_storage *addr, 39 socklen_t *addr_len); 40 ssize_t recvfrom_recv(struct tevent_req *req, int *perrno); 40 41 41 42 struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, -
vendor/current/lib/compression/lzxpress.c
r414 r740 35 35 #include "replace.h" 36 36 #include "lzxpress.h" 37 #include "../lib/util/byteorder.h" 37 38 38 39 … … 81 82 uncompressed_pos = 0; 82 83 indic = 0; 84 *(uint32_t *)compressed = 0; 83 85 compressed_pos = sizeof(uint32_t); 84 86 indic_pos = &compressed[0]; … … 130 132 /* Classical meta-data */ 131 133 metadata = (uint16_t)(((best_offset - 1) << 3) | (best_len - 3)); 132 dest[metadata_size / sizeof(uint16_t)] = metadata;134 SSVAL(dest, metadata_size / sizeof(uint16_t), metadata); 133 135 metadata_size += sizeof(uint16_t); 134 136 } else { 135 137 metadata = (uint16_t)(((best_offset - 1) << 3) | 7); 136 dest[metadata_size / sizeof(uint16_t)] = metadata;138 SSVAL(dest, metadata_size / sizeof(uint16_t), metadata); 137 139 metadata_size = sizeof(uint16_t); 138 140 … … 156 158 } 157 159 158 /* Addition nal best_len */160 /* Additional best_len */ 159 161 compressed[compressed_pos + metadata_size] = (best_len - (3 + 7 + 15)) & 0xFF; 160 162 metadata_size += sizeof(uint8_t); … … 168 170 } 169 171 170 /* Addition nal best_len */172 /* Additional best_len */ 171 173 compressed[compressed_pos + metadata_size] = 255; 172 174 … … 199 201 200 202 if ((indic_bit - 1) % 32 > (indic_bit % 32)) { 201 *(uint32_t *)indic_pos = indic;203 SIVAL(indic_pos, 0, indic); 202 204 indic = 0; 203 205 indic_pos = &compressed[compressed_pos]; … … 213 215 compressed_pos++; 214 216 if (((indic_bit - 1) % 32) > (indic_bit % 32)){ 215 *(uint32_t *)indic_pos = indic;217 SIVAL(indic_pos, 0, indic); 216 218 indic = 0; 217 219 indic_pos = &compressed[compressed_pos]; … … 224 226 indic |= 0 << (32 - ((indic_bit % 32) + 1)); 225 227 226 *(uint32_t *)indic_pos = indic; 228 *(uint32_t *)&compressed[compressed_pos] = 0; 229 SIVAL(indic_pos, 0, indic); 227 230 compressed_pos += sizeof(uint32_t); 228 231 } -
vendor/current/lib/compression/testsuite.c
r414 r740 21 21 #include "includes.h" 22 22 #include "torture/torture.h" 23 #include "../compression/mszip.h" 23 #include "talloc.h" 24 #include "mszip.h" 25 #include "lzxpress.h" 26 27 /* 28 test lzxpress 29 */ 30 static bool test_lzxpress(struct torture_context *test) 31 { 32 TALLOC_CTX *tmp_ctx = talloc_new(test); 33 uint8_t *data; 34 const char *fixed_data = "this is a test. and this is a test too"; 35 const uint8_t fixed_out[] = { 0x00, 0x20, 0x00, 0x04, 0x74, 0x68, 0x69, 0x73, 36 0x20, 0x10, 0x00, 0x61, 0x20, 0x74, 0x65, 0x73, 37 0x74, 0x2E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x9F, 38 0x00, 0x04, 0x20, 0x74, 0x6F, 0x6F, 0x00, 0x00, 39 0x00, 0x00 }; 40 ssize_t c_size; 41 uint8_t *out, *out2; 42 43 data = talloc_size(tmp_ctx, 1023); 44 out = talloc_size(tmp_ctx, 2048); 45 memset(out, 0x42, talloc_get_size(out)); 46 47 torture_comment(test, "lzxpress fixed compression\n"); 48 c_size = lzxpress_compress((const uint8_t *)fixed_data, 49 strlen(fixed_data), 50 out, 51 talloc_get_size(out)); 52 53 torture_assert_int_equal(test, c_size, sizeof(fixed_out), "fixed lzxpress_compress size"); 54 torture_assert_mem_equal(test, out, fixed_out, c_size, "fixed lzxpress_compress data"); 55 56 torture_comment(test, "lzxpress fixed decompression\n"); 57 out2 = talloc_size(tmp_ctx, strlen(fixed_data)); 58 c_size = lzxpress_decompress(out, 59 sizeof(fixed_out), 60 out2, 61 talloc_get_size(out2)); 62 63 torture_assert_int_equal(test, c_size, strlen(fixed_data), "fixed lzxpress_decompress size"); 64 torture_assert_mem_equal(test, out2, fixed_data, c_size, "fixed lzxpress_decompress data"); 65 66 return true; 67 } 68 24 69 25 70 struct torture_suite *torture_local_compression(TALLOC_CTX *mem_ctx) 26 71 { 27 struct torture_suite *suite = torture_suite_create(mem_ctx, "COMPRESSION"); 72 struct torture_suite *suite = torture_suite_create(mem_ctx, "compression"); 73 74 torture_suite_add_simple_test(suite, "lzxpress", test_lzxpress); 28 75 29 76 return suite; -
vendor/current/lib/crypto/aes.c
r414 r740 113 113 } 114 114 } 115 116 void aes_cfb8_encrypt(const uint8_t *in, uint8_t *out, 117 size_t length, const AES_KEY *key, 118 uint8_t *iv, int forward) 119 { 120 size_t i; 121 122 for (i=0; i < length; i++) { 123 uint8_t tiv[AES_BLOCK_SIZE*2]; 124 125 memcpy(tiv, iv, AES_BLOCK_SIZE); 126 AES_encrypt(iv, iv, key); 127 if (!forward) { 128 tiv[AES_BLOCK_SIZE] = in[i]; 129 } 130 out[i] = in[i] ^ iv[0]; 131 if (forward) { 132 tiv[AES_BLOCK_SIZE] = out[i]; 133 } 134 memcpy(iv, tiv+1, AES_BLOCK_SIZE); 135 } 136 } -
vendor/current/lib/crypto/aes.h
r414 r740 73 73 unsigned char *, int); 74 74 75 void aes_cfb8_encrypt(const uint8_t *in, uint8_t *out, 76 size_t length, const AES_KEY *key, 77 uint8_t *iv, int forward); 78 75 79 #ifdef __cplusplus 76 80 } -
vendor/current/lib/crypto/arcfour.c
r414 r740 20 20 */ 21 21 22 #include " includes.h"22 #include "replace.h" 23 23 #include "../lib/crypto/arcfour.h" 24 24 -
vendor/current/lib/crypto/arcfour.h
r414 r740 1 1 #ifndef ARCFOUR_HEADER_H 2 2 #define ARCFOUR_HEADER_H 3 4 #include "../lib/util/data_blob.h" 3 5 4 6 struct arcfour_state { -
vendor/current/lib/crypto/crc32.c
r414 r740 41 41 */ 42 42 43 #include " includes.h"43 #include "replace.h" 44 44 #include "../lib/crypto/crc32.h" 45 45 -
vendor/current/lib/crypto/hmacmd5.c
r414 r740 23 23 */ 24 24 25 #include " includes.h"25 #include "replace.h" 26 26 #include "../lib/crypto/hmacmd5.h" 27 27 -
vendor/current/lib/crypto/hmacmd5test.c
r414 r740 17 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 18 */ 19 #include "includes.h" 19 #include "replace.h" 20 #include "../lib/util/util.h" 20 21 #include "../lib/crypto/crypto.h" 21 22 -
vendor/current/lib/crypto/hmacsha256.c
r414 r740 27 27 */ 28 28 29 #include " includes.h"29 #include "replace.h" 30 30 #include "../lib/crypto/crypto.h" 31 31 -
vendor/current/lib/crypto/md4.c
r414 r740 18 18 */ 19 19 20 #include " includes.h"20 #include "replace.h" 21 21 #include "../lib/crypto/md4.h" 22 22 -
vendor/current/lib/crypto/md4test.c
r414 r740 18 18 */ 19 19 20 #include "includes.h" 20 #include "replace.h" 21 #include "../lib/util/util.h" 21 22 #include "../lib/crypto/crypto.h" 22 23 … … 26 27 This uses the test values from rfc1320 27 28 */ 28 bool torture_local_crypto_md4(struct torture_context *torture) 29 bool torture_local_crypto_md4(struct torture_context *torture) 29 30 { 30 31 bool ret = true; -
vendor/current/lib/crypto/md5.c
r414 r740 19 19 abartlet@samba.org Jun 2001 */ 20 20 21 #include " includes.h"21 #include "replace.h" 22 22 23 23 #include "md5.h" … … 29 29 * Note: this code is harmless on little-endian machines. 30 30 */ 31 static void byteReverse(uint8_t *buf, u int_t longs)31 static void byteReverse(uint8_t *buf, unsigned int longs) 32 32 { 33 33 uint32_t t; 34 34 do { 35 t = (uint32_t) ((u int_t) buf[3] << 8 | buf[2]) << 16 |36 ((u int_t) buf[1] << 8 | buf[0]);35 t = (uint32_t) ((unsigned int) buf[3] << 8 | buf[2]) << 16 | 36 ((unsigned int) buf[1] << 8 | buf[0]); 37 37 *(uint32_t *) buf = t; 38 38 buf += 4; … … 109 109 _PUBLIC_ void MD5Final(uint8_t digest[16], struct MD5Context *ctx) 110 110 { 111 u int_t count;111 unsigned int count; 112 112 uint8_t *p; 113 113 … … 145 145 byteReverse((uint8_t *) ctx->buf, 4); 146 146 memmove(digest, ctx->buf, 16); 147 memset(ctx, 0, sizeof( ctx)); /* In case it's sensitive */147 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ 148 148 } 149 149 -
vendor/current/lib/crypto/md5test.c
r414 r740 18 18 */ 19 19 20 #include "includes.h" 20 #include "replace.h" 21 #include "../lib/util/util.h" 21 22 #include "../lib/crypto/crypto.h" 22 23 -
vendor/current/lib/crypto/sha256.c
r414 r740 39 39 */ 40 40 41 #include " includes.h"41 #include "replace.h" 42 42 #include "sha256.h" 43 43 -
vendor/current/lib/nss_wrapper/nss_wrapper.c
r414 r740 34 34 35 35 #ifdef _SAMBA_BUILD_ 36 37 /* defining this gives us the posix getpwnam_r() calls on solaris 38 Thanks to heimdal for this */ 39 #define _POSIX_PTHREAD_SEMANTICS 36 40 37 41 #define NSS_WRAPPER_NOT_REPLACE … … 208 212 }; 209 213 210 /* proto ypes for files backend */214 /* prototypes for files backend */ 211 215 212 216 … … 246 250 static void nwrap_files_endgrent(struct nwrap_backend *b); 247 251 248 /* proto ypes for module backend */252 /* prototypes for module backend */ 249 253 250 254 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b); … … 461 465 struct nwrap_backend **backends) 462 466 { 467 struct nwrap_backend *b; 468 463 469 *backends = (struct nwrap_backend *)realloc(*backends, 464 470 sizeof(struct nwrap_backend) * ((*num_backends) + 1)); … … 469 475 } 470 476 471 (*backends)[*num_backends].name = name; 472 (*backends)[*num_backends].ops = ops; 473 (*backends)[*num_backends].so_path = so_path; 474 (*backends)[*num_backends].so_handle = nwrap_load_module(so_path); 475 (*backends)[*num_backends].fns = nwrap_load_module_fns(&((*backends)[*num_backends])); 477 b = &((*backends)[*num_backends]); 478 479 b->name = name; 480 b->ops = ops; 481 b->so_path = so_path; 482 483 if (so_path != NULL) { 484 b->so_handle = nwrap_load_module(so_path); 485 b->fns = nwrap_load_module_fns(b); 486 if (b->fns == NULL) { 487 return false; 488 } 489 } else { 490 b->so_handle = NULL; 491 b->fns = NULL; 492 } 476 493 477 494 (*num_backends)++; … … 2169 2186 gid_t *groups_tmp; 2170 2187 int count = 1; 2171 const char *name_of_group = NULL;2188 const char *name_of_group = ""; 2172 2189 2173 2190 if (!nwrap_enabled()) { -
vendor/current/lib/nss_wrapper/nss_wrapper.pl
r414 r740 14 14 my $opt_name = undef; 15 15 my $opt_member = undef; 16 my $opt_gid = 65534;# nogroup gid 16 17 17 18 my $passwdfn = undef; … … 20 21 my $actionfn = undef; 21 22 22 sub passwd_add($$$$ );23 sub passwd_delete($$$$ );24 sub group_add($$$$ );25 sub group_delete($$$$ );26 sub member_add($$$$ );27 sub member_delete($$$$ );23 sub passwd_add($$$$$); 24 sub passwd_delete($$$$$); 25 sub group_add($$$$$); 26 sub group_delete($$$$$); 27 sub member_add($$$$$); 28 sub member_delete($$$$$); 28 29 29 30 sub check_path($$); … … 36 37 'type=s' => \$opt_type, 37 38 'name=s' => \$opt_name, 38 'member=s' => \$opt_member 39 'member=s' => \$opt_member, 40 'gid=i' => \$opt_gid 39 41 ); 40 42 … … 59 61 60 62 --member <member> The name of the member. 63 64 --gid <gid> Primary Group ID for new users. 61 65 "; 62 66 exit($ret); … … 111 115 } 112 116 113 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name );117 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid); 114 118 115 119 sub check_path($$) … … 389 393 } 390 394 391 sub passwd_add($$$$ )392 { 393 my ($path, $dummy, $dummy2, $name ) = @_;395 sub passwd_add($$$$$) 396 { 397 my ($path, $dummy, $dummy2, $name, $gid) = @_; 394 398 395 399 #print "passwd_add: '$name' in '$path'\n"; … … 401 405 402 406 my $uid = passwd_get_free_uid($passwd); 403 my $gid = 65534;# nogroup gid404 407 405 408 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false"; … … 412 415 } 413 416 414 sub passwd_delete($$$$ )415 { 416 my ($path, $dummy, $dummy2, $name ) = @_;417 sub passwd_delete($$$$$) 418 { 419 my ($path, $dummy, $dummy2, $name, $dummy3) = @_; 417 420 418 421 #print "passwd_delete: '$name' in '$path'\n"; … … 430 433 } 431 434 432 sub group_add($$$$ )433 { 434 my ($dummy, $dummy2, $path, $name ) = @_;435 sub group_add($$$$$) 436 { 437 my ($dummy, $dummy2, $path, $name, $dummy3) = @_; 435 438 436 439 #print "group_add: '$name' in '$path'\n"; … … 454 457 } 455 458 456 sub group_delete($$$$ )457 { 458 my ($dummy, $dummy2, $path, $name ) = @_;459 sub group_delete($$$$$) 460 { 461 my ($dummy, $dummy2, $path, $name, $dummy3) = @_; 459 462 460 463 #print "group_delete: '$name' in '$path'\n"; … … 472 475 } 473 476 474 sub member_add($$$$ )475 { 476 my ($passwd_path, $username, $group_path, $groupname ) = @_;477 sub member_add($$$$$) 478 { 479 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; 477 480 478 481 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n"; … … 495 498 } 496 499 497 sub member_delete($$$$ )498 { 499 my ($passwd_path, $username, $group_path, $groupname ) = @_;500 sub member_delete($$$$$) 501 { 502 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; 500 503 501 504 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n"; -
vendor/current/lib/nss_wrapper/testsuite.c
r414 r740 4 4 local testing of the nss wrapper 5 5 6 Copyright (C) Guenther Deschner 2009 6 Copyright (C) Guenther Deschner 2009-2010 7 7 8 8 This program is free software; you can redistribute it and/or modify … … 21 21 22 22 #include "includes.h" 23 24 #ifndef NSS_WRAPPER 25 #define NSS_WRAPPER 26 #endif 27 23 28 #include "torture/torture.h" 24 29 #include "lib/replace/system/passwd.h" 25 #include "lib/nss_wrapper/nss_wrapper.h"26 30 27 31 static bool copy_passwd(struct torture_context *tctx, … … 176 180 (unsigned long)grp->gr_gid); 177 181 178 if ( !grp->gr_mem[0]) {182 if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) { 179 183 printf("\n"); 180 184 return; … … 773 777 774 778 if (!old_pwd || !old_group) { 779 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); 775 780 torture_skip(tctx, "nothing to test\n"); 776 return true;777 781 } 778 782 … … 798 802 799 803 if (!old_pwd || !old_group) { 804 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); 800 805 torture_skip(tctx, "nothing to test\n"); 801 return true;802 806 } 803 807 … … 816 820 817 821 if (!old_pwd || !old_group) { 822 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); 818 823 torture_skip(tctx, "nothing to test\n"); 819 return true;820 824 } 821 825 … … 836 840 837 841 if (!old_pwd || !old_group) { 842 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); 838 843 torture_skip(tctx, "nothing to test\n"); 839 return true;840 844 } 841 845 … … 850 854 } 851 855 856 static bool test_nwrap_passwd_duplicates(struct torture_context *tctx) 857 { 858 int i, d; 859 struct passwd *pwd; 860 size_t num_pwd; 861 int duplicates = 0; 862 863 torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), 864 "failed to enumerate passwd"); 865 866 for (i=0; i < num_pwd; i++) { 867 const char *current_name = pwd[i].pw_name; 868 for (d=0; d < num_pwd; d++) { 869 const char *dup_name = pwd[d].pw_name; 870 if (d == i) { 871 continue; 872 } 873 if (!strequal(current_name, dup_name)) { 874 continue; 875 } 876 877 torture_warning(tctx, "found duplicate names:"); 878 print_passwd(&pwd[d]); 879 print_passwd(&pwd[i]); 880 duplicates++; 881 } 882 } 883 884 if (duplicates) { 885 torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates)); 886 } 887 888 return true; 889 } 890 891 static bool test_nwrap_group_duplicates(struct torture_context *tctx) 892 { 893 int i, d; 894 struct group *grp; 895 size_t num_grp; 896 int duplicates = 0; 897 898 torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp), 899 "failed to enumerate group"); 900 901 for (i=0; i < num_grp; i++) { 902 const char *current_name = grp[i].gr_name; 903 for (d=0; d < num_grp; d++) { 904 const char *dup_name = grp[d].gr_name; 905 if (d == i) { 906 continue; 907 } 908 if (!strequal(current_name, dup_name)) { 909 continue; 910 } 911 912 torture_warning(tctx, "found duplicate names:"); 913 print_group(&grp[d]); 914 print_group(&grp[i]); 915 duplicates++; 916 } 917 } 918 919 if (duplicates) { 920 torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates)); 921 } 922 923 return true; 924 } 925 926 927 static bool test_nwrap_duplicates(struct torture_context *tctx) 928 { 929 const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); 930 const char *old_group = getenv("NSS_WRAPPER_GROUP"); 931 932 if (!old_pwd || !old_group) { 933 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); 934 torture_skip(tctx, "nothing to test\n"); 935 } 936 937 torture_assert(tctx, test_nwrap_passwd_duplicates(tctx), 938 "failed to test users"); 939 torture_assert(tctx, test_nwrap_group_duplicates(tctx), 940 "failed to test groups"); 941 942 return true; 943 } 944 945 852 946 struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx) 853 947 { 854 struct torture_suite *suite = torture_suite_create(mem_ctx, " NSS-WRAPPER");948 struct torture_suite *suite = torture_suite_create(mem_ctx, "nss-wrapper"); 855 949 856 950 torture_suite_add_simple_test(suite, "enumeration", test_nwrap_enumeration); … … 858 952 torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_nwrap_reentrant_enumeration_crosschecks); 859 953 torture_suite_add_simple_test(suite, "membership", test_nwrap_membership); 954 torture_suite_add_simple_test(suite, "duplicates", test_nwrap_duplicates); 860 955 861 956 return suite; -
vendor/current/lib/popt/popt.h
r414 r740 459 459 * Print detailed description of options. 460 460 * @param con context 461 * @param fp ou put file handle461 * @param fp output file handle 462 462 * @param flags (unused) 463 463 */ … … 469 469 * Print terse description of options. 470 470 * @param con context 471 * @param fp ou put file handle471 * @param fp output file handle 472 472 * @param flags (unused) 473 473 */ -
vendor/current/lib/replace/README
r414 r740 34 34 telldir 35 35 seekdir 36 clock_gettime 36 37 closedir 37 38 dlopen … … 76 77 bool 77 78 socklen_t 78 uint_t79 79 uint{8,16,32,64}_t 80 80 int{8,16,32,64}_t -
vendor/current/lib/replace/autoconf-2.60.m4
r414 r740 182 182 m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[ 183 183 AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS], 184 [ 185 AC_BEFORE([$0], [AC_COMPILE_IFELSE]) 186 AC_BEFORE([$0], [AC_RUN_IFELSE]) 187 188 AC_REQUIRE([AC_GNU_SOURCE]) 189 AC_REQUIRE([AC_AIX]) 190 AC_REQUIRE([AC_MINIX]) 184 [AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl 185 AC_BEFORE([$0], [AC_RUN_IFELSE])dnl 186 187 AC_CHECK_HEADER([minix/config.h], [MINIX=yes], [MINIX=]) 188 if test "$MINIX" = yes; then 189 AC_DEFINE([_POSIX_SOURCE], [1], 190 [Define to 1 if you need to in order for `stat' and other 191 things to work.]) 192 AC_DEFINE([_POSIX_1_SOURCE], [2], 193 [Define to 2 if the system does not provide POSIX.1 features 194 except with this defined.]) 195 AC_DEFINE([_MINIX], [1], 196 [Define to 1 if on MINIX.]) 197 fi 191 198 192 199 AH_VERBATIM([__EXTENSIONS__], 193 [/* Enable extensions on Solaris. */ 200 [/* Enable extensions on AIX 3, Interix. */ 201 #ifndef _ALL_SOURCE 202 # undef _ALL_SOURCE 203 #endif 204 /* Enable GNU extensions on systems that have them. */ 205 #ifndef _GNU_SOURCE 206 # undef _GNU_SOURCE 207 #endif 208 /* Enable threading extensions on Solaris. */ 209 #ifndef _POSIX_PTHREAD_SEMANTICS 210 # undef _POSIX_PTHREAD_SEMANTICS 211 #endif 212 /* Enable extensions on HP NonStop. */ 213 #ifndef _TANDEM_SOURCE 214 # undef _TANDEM_SOURCE 215 #endif 216 /* Enable general extensions on Solaris. */ 194 217 #ifndef __EXTENSIONS__ 195 218 # undef __EXTENSIONS__ 196 219 #endif 197 #ifndef _POSIX_PTHREAD_SEMANTICS 198 # undef _POSIX_PTHREAD_SEMANTICS 199 #endif]) 220 ]) 200 221 AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__], 201 222 [ac_cv_safe_to_define___extensions__], 202 223 [AC_COMPILE_IFELSE( 203 [AC_LANG_PROGRAM([ 224 [AC_LANG_PROGRAM([[ 204 225 # define __EXTENSIONS__ 1 205 AC_INCLUDES_DEFAULT])],226 ]AC_INCLUDES_DEFAULT])], 206 227 [ac_cv_safe_to_define___extensions__=yes], 207 228 [ac_cv_safe_to_define___extensions__=no])]) 208 229 test $ac_cv_safe_to_define___extensions__ = yes && 209 230 AC_DEFINE([__EXTENSIONS__]) 231 AC_DEFINE([_ALL_SOURCE]) 232 AC_DEFINE([_GNU_SOURCE]) 210 233 AC_DEFINE([_POSIX_PTHREAD_SEMANTICS]) 211 ]) 212 ]) 234 AC_DEFINE([_TANDEM_SOURCE]) 235 ])# AC_USE_SYSTEM_EXTENSIONS 236 ]) -
vendor/current/lib/replace/crypt.c
r414 r740 47 47 48 48 #ifndef long32 49 #define long32 int32 49 #define long32 int32_t 50 50 #endif 51 51 52 52 #ifndef long64 53 #define long64 int64 53 #define long64 int64_t 54 54 #endif 55 55 … … 666 666 */ 667 667 clearmem(ktab, sizeof ktab); 668 StrnCpy(ktab, key, 8);668 strncpy(ktab, key, 8); 669 669 ufc_mk_keytab(ktab); 670 670 -
vendor/current/lib/replace/getifaddrs.c
r414 r740 283 283 284 284 while (i > 0) { 285 u int_t inc;285 unsigned int inc; 286 286 287 287 inc = ifr->ifr_addr.sa_len; -
vendor/current/lib/replace/getpass.c
r414 r740 35 35 #endif 36 36 37 #ifndef SIGNAL_CAST38 #define SIGNAL_CAST (RETSIGTYPE (*)(int))39 #endif40 41 37 #ifdef SYSV_TERMIO 42 38 … … 100 96 #endif /* SYSV_TERMIO */ 101 97 102 static void catch_signal(int signum, void (*handler)(int ))98 static void catch_signal(int signum, void (*handler)(int )) 103 99 { 104 100 #ifdef HAVE_SIGACTION … … 132 128 ****************************************************************/ 133 129 134 static void gotintr_sig( void)130 static void gotintr_sig(int signum) 135 131 { 136 132 gotintr = 1; … … 149 145 150 146 /* Catch problematic signals */ 151 catch_signal(SIGINT, SIGNAL_CASTgotintr_sig);147 catch_signal(SIGINT, gotintr_sig); 152 148 153 149 /* Try to write to and read from the terminal if we can. … … 212 208 213 209 /* Catch problematic signals */ 214 catch_signal(SIGINT, SIG NAL_CAST SIG_DFL);210 catch_signal(SIGINT, SIG_DFL); 215 211 216 212 if (gotintr) { 217 printf("Inter upted by signal.\n");213 printf("Interrupted by signal.\n"); 218 214 fflush(stdout); 219 215 exit(1); -
vendor/current/lib/replace/libreplace.m4
r414 r740 52 52 LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/snprintf.o" 53 53 54 AC_TYPE_SIGNAL55 54 AC_TYPE_UID_T 56 55 AC_TYPE_MODE_T … … 91 90 ) 92 91 92 AC_CHECK_HEADERS(linux/types.h) 93 93 94 AC_CACHE_CHECK([for working mmap],libreplace_cv_HAVE_MMAP,[ 94 95 AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"], … … 106 107 AC_CHECK_HEADERS(unix.h) 107 108 108 AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror )109 AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror strerror_r) 109 110 AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) 110 111 AC_CHECK_FUNCS(waitpid wait4 strlcpy strlcat initgroups memmove strdup) 111 AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2 )112 AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2 dprintf vdprintf) 112 113 AC_CHECK_FUNCS(isatty chown lchown link readlink symlink realpath) 114 AC_CHECK_FUNCS(fdatasync,,[ 115 # if we didn't find it, look in librt (Solaris hides it there...) 116 AC_CHECK_LIB(rt, fdatasync, 117 [libreplace_cv_HAVE_FDATASYNC_IN_LIBRT=yes 118 AC_DEFINE(HAVE_FDATASYNC, 1, Define to 1 if there is support for fdatasync)]) 119 ]) 120 AC_HAVE_DECL(fdatasync, [#include <unistd.h>]) 121 AC_CHECK_FUNCS(clock_gettime,libreplace_cv_have_clock_gettime=yes,[ 122 AC_CHECK_LIB(rt, clock_gettime, 123 [libreplace_cv_HAVE_CLOCK_GETTIME_IN_LIBRT=yes 124 libreplace_cv_have_clock_gettime=yes 125 AC_DEFINE(HAVE_CLOCK_GETTIME, 1, Define to 1 if there is support for clock_gettime)]) 126 ]) 127 AC_CHECK_FUNCS(get_current_dir_name) 113 128 AC_HAVE_DECL(setresuid, [#include <unistd.h>]) 114 129 AC_HAVE_DECL(setresgid, [#include <unistd.h>]) … … 229 244 AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) 230 245 246 AC_CHECK_FUNCS(memmem) 247 231 248 # this test disabled as we don't actually need __VA_ARGS__ yet 232 249 AC_TRY_CPP([ … … 281 298 m4_include(crypt.m4) 282 299 300 if test x$libreplace_cv_have_clock_gettime = xyes ; then 301 SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC) 302 SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID) 303 SMB_CHECK_CLOCK_ID(CLOCK_REALTIME) 304 fi 305 306 AC_CACHE_CHECK([for struct timespec type],libreplace_cv_struct_timespec, [ 307 AC_TRY_COMPILE([ 308 #include <sys/types.h> 309 #if STDC_HEADERS 310 #include <stdlib.h> 311 #include <stddef.h> 312 #endif 313 #if TIME_WITH_SYS_TIME 314 # include <sys/time.h> 315 # include <time.h> 316 #else 317 # if HAVE_SYS_TIME_H 318 # include <sys/time.h> 319 # else 320 # include <time.h> 321 # endif 322 #endif 323 ],[struct timespec ts;], 324 libreplace_cv_struct_timespec=yes,libreplace_cv_struct_timespec=no)]) 325 if test x"$libreplace_cv_struct_timespec" = x"yes"; then 326 AC_DEFINE(HAVE_STRUCT_TIMESPEC,1,[Whether we have struct timespec]) 327 fi 328 283 329 AC_CHECK_FUNCS([printf memset memcpy],,[AC_MSG_ERROR([Required function not found])]) 284 330 … … 309 355 m4_include(libreplace_macros.m4) 310 356 357 358 dnl SMB_CHECK_CLOCK_ID(clockid) 359 dnl Test whether the specified clock_gettime clock ID is available. If it 360 dnl is, we define HAVE_clockid 361 AC_DEFUN([SMB_CHECK_CLOCK_ID], 362 [ 363 AC_MSG_CHECKING(for $1) 364 AC_TRY_LINK([ 365 #if TIME_WITH_SYS_TIME 366 # include <sys/time.h> 367 # include <time.h> 368 #else 369 # if HAVE_SYS_TIME_H 370 # include <sys/time.h> 371 # else 372 # include <time.h> 373 # endif 374 #endif 375 ], 376 [ 377 clockid_t clk = $1; 378 ], 379 [ 380 AC_MSG_RESULT(yes) 381 AC_DEFINE(HAVE_$1, 1, 382 [Whether the clock_gettime clock ID $1 is available]) 383 ], 384 [ 385 AC_MSG_RESULT(no) 386 ]) 387 ]) 311 388 m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[m4_include(autoconf-2.60.m4)]) -
vendor/current/lib/replace/libreplace_cc.m4
r414 r740 116 116 AC_CHECK_SIZEOF(long long) 117 117 118 AC_CHECK_TYPE(uint_t, unsigned int)119 118 AC_CHECK_TYPE(int8_t, char) 120 119 AC_CHECK_TYPE(uint8_t, unsigned char) -
vendor/current/lib/replace/libreplace_macros.m4
r414 r740 294 294 } 295 295 ])],[ 296 AS_TR_SH([ac_cv_c_prototype_$1])=yes296 eval AS_TR_SH([ac_cv_c_prototype_$1])=yes 297 297 ],[ 298 AS_TR_SH([ac_cv_c_prototype_$1])=no298 eval AS_TR_SH([ac_cv_c_prototype_$1])=no 299 299 ]) 300 300 ) -
vendor/current/lib/replace/libreplace_network.m4
r478 r740 115 115 fi 116 116 117 dnl The following test is roughl taken from the cvs sources.117 dnl The following test is roughly taken from the cvs sources. 118 118 dnl 119 119 dnl If we can't find connect, try looking in -lsocket, -lnsl, and -linet. … … 227 227 ], 228 228 libreplace_cv_HAVE_GETADDRINFO=yes,libreplace_cv_HAVE_GETADDRINFO=no)]) 229 230 if test x"$libreplace_cv_HAVE_GETADDRINFO" = x"yes"; then 231 # getaddrinfo is broken on some AIX systems 232 # see bug 5910, use our replacements if we detect 233 # a broken system. 234 AC_TRY_RUN([ 235 #include <stddef.h> 236 #include <sys/types.h> 237 #include <sys/socket.h> 238 #include <netdb.h> 239 int main(int argc, const char *argv[]) 240 { 241 struct addrinfo hints = {0,}; 242 struct addrinfo *ppres; 243 const char hostname1[] = "0.0.0.0"; 244 const char hostname2[] = "127.0.0.1"; 245 const char hostname3[] = "::"; 246 hints.ai_socktype = SOCK_STREAM; 247 hints.ai_family = AF_UNSPEC; 248 hints.ai_flags = 249 AI_NUMERICHOST|AI_PASSIVE|AI_ADDRCONFIG; 250 /* Test for broken flag combination on AIX. */ 251 if (getaddrinfo(hostname1, NULL, &hints, &ppres) == EAI_BADFLAGS) { 252 /* This fails on an IPv6-only box, but not with 253 the EAI_BADFLAGS error. */ 254 return 1; 255 } 256 if (getaddrinfo(hostname2, NULL, &hints, &ppres) == 0) { 257 /* IPv4 lookup works - good enough. */ 258 return 0; 259 } 260 /* Uh-oh, no IPv4. Are we IPv6-only ? */ 261 return getaddrinfo(hostname3, NULL, &hints, &ppres) != 0 ? 1 : 0; 262 }], 263 libreplace_cv_HAVE_GETADDRINFO=yes, 264 libreplace_cv_HAVE_GETADDRINFO=no) 265 fi 266 229 267 if test x"$libreplace_cv_HAVE_GETADDRINFO" = x"yes"; then 230 268 AC_DEFINE(HAVE_GETADDRINFO,1,[Whether the system has getaddrinfo]) -
vendor/current/lib/replace/replace.c
r414 r740 4 4 Copyright (C) Andrew Tridgell 1992-1998 5 5 Copyright (C) Jelmer Vernooij 2005-2008 6 Copyright (C) Matthieu Patou 2010 6 7 7 8 ** NOTE! The following LGPL license applies to the replace … … 410 411 { 411 412 /* have a reasonable go at emulating it. Hope that 412 the system mktemp() isn't complet ly hopeless */413 the system mktemp() isn't completely hopeless */ 413 414 char *p = mktemp(template); 414 415 if (!p) … … 503 504 #endif 504 505 506 505 507 #ifndef HAVE_STRTOLL 506 508 long long int rep_strtoll(const char *str, char **endptr, int base) … … 516 518 #endif 517 519 } 518 #endif 520 #else 521 #ifdef HAVE_BSD_STRTOLL 522 #ifdef HAVE_STRTOQ 523 long long int rep_strtoll(const char *str, char **endptr, int base) 524 { 525 long long int nb = strtoq(str, endptr, base); 526 /* In linux EINVAL is only returned if base is not ok */ 527 if (errno == EINVAL) { 528 if (base == 0 || (base >1 && base <37)) { 529 /* Base was ok so it's because we were not 530 * able to make the convertion. 531 * Let's reset errno. 532 */ 533 errno = 0; 534 } 535 } 536 return nb; 537 } 538 #else 539 #error "You need the strtoq function" 540 #endif /* HAVE_STRTOQ */ 541 #endif /* HAVE_BSD_STRTOLL */ 542 #endif /* HAVE_STRTOLL */ 519 543 520 544 … … 532 556 #endif 533 557 } 534 #endif 558 #else 559 #ifdef HAVE_BSD_STRTOLL 560 #ifdef HAVE_STRTOUQ 561 unsigned long long int rep_strtoull(const char *str, char **endptr, int base) 562 { 563 unsigned long long int nb = strtouq(str, endptr, base); 564 /* In linux EINVAL is only returned if base is not ok */ 565 if (errno == EINVAL) { 566 if (base == 0 || (base >1 && base <37)) { 567 /* Base was ok so it's because we were not 568 * able to make the convertion. 569 * Let's reset errno. 570 */ 571 errno = 0; 572 } 573 } 574 return nb; 575 } 576 #else 577 #error "You need the strtouq function" 578 #endif /* HAVE_STRTOUQ */ 579 #endif /* HAVE_BSD_STRTOLL */ 580 #endif /* HAVE_STRTOULL */ 535 581 536 582 #ifndef HAVE_SETENV … … 682 728 } 683 729 #endif 730 731 732 #ifndef HAVE_MEMMEM 733 void *rep_memmem(const void *haystack, size_t haystacklen, 734 const void *needle, size_t needlelen) 735 { 736 if (needlelen == 0) { 737 return discard_const(haystack); 738 } 739 while (haystacklen >= needlelen) { 740 char *p = (char *)memchr(haystack, *(const char *)needle, 741 haystacklen-(needlelen-1)); 742 if (!p) return NULL; 743 if (memcmp(p, needle, needlelen) == 0) { 744 return p; 745 } 746 haystack = p+1; 747 haystacklen -= (p - (const char *)haystack) + 1; 748 } 749 return NULL; 750 } 751 #endif 752 753 #ifndef HAVE_VDPRINTF 754 int rep_vdprintf(int fd, const char *format, va_list ap) 755 { 756 char *s = NULL; 757 int ret; 758 759 vasprintf(&s, format, ap); 760 if (s == NULL) { 761 errno = ENOMEM; 762 return -1; 763 } 764 ret = write(fd, s, strlen(s)); 765 free(s); 766 return ret; 767 } 768 #endif 769 770 #ifndef HAVE_DPRINTF 771 int rep_dprintf(int fd, const char *format, ...) 772 { 773 int ret; 774 va_list ap; 775 776 va_start(ap, format); 777 ret = vdprintf(fd, format, ap); 778 va_end(ap); 779 780 return ret; 781 } 782 #endif 783 784 #ifndef HAVE_GET_CURRENT_DIR_NAME 785 char *rep_get_current_dir_name(void) 786 { 787 char buf[PATH_MAX+1]; 788 char *p; 789 p = getcwd(buf, sizeof(buf)); 790 if (p == NULL) { 791 return NULL; 792 } 793 return strdup(p); 794 } 795 #endif 796 797 #if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE) 798 int rep_strerror_r(int errnum, char *buf, size_t buflen) 799 { 800 char *s = strerror(errnum); 801 if (strlen(s)+1 > buflen) { 802 errno = ERANGE; 803 return -1; 804 } 805 strncpy(buf, s, buflen); 806 return 0; 807 } 808 #endif 809 810 #ifndef HAVE_CLOCK_GETTIME 811 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp) 812 { 813 struct timeval tval; 814 switch (clk_id) { 815 case 0: /* CLOCK_REALTIME :*/ 816 #ifdef HAVE_GETTIMEOFDAY_TZ 817 gettimeofday(&tval,NULL); 818 #else 819 gettimeofday(&tval); 820 #endif 821 tp->tv_sec = tval.tv_sec; 822 tp->tv_nsec = tval.tv_usec * 1000; 823 break; 824 default: 825 errno = EINVAL; 826 return -1; 827 } 828 return 0; 829 } 830 #endif -
vendor/current/lib/replace/replace.h
r414 r740 82 82 # define PRIi8 "i" 83 83 #endif 84 #ifndef PRIi 884 #ifndef PRIi16 85 85 # define PRIi16 "i" 86 86 #endif 87 #ifndef PRIi 887 #ifndef PRIi32 88 88 # define PRIi32 "i" 89 89 #endif 90 #ifndef PRIi 890 #ifndef PRIi64 91 91 # define PRIi64 __PRI64_PREFIX "i" 92 92 #endif … … 122 122 #endif 123 123 124 #ifdef HAVE_LINUX_TYPES_H 125 /* 126 * This is needed as some broken header files require this to be included early 127 */ 128 #include <linux/types.h> 129 #endif 130 124 131 #ifndef HAVE_STRERROR 125 132 extern char *sys_errlist[]; … … 139 146 #define memmove rep_memmove 140 147 void *rep_memmove(void *dest,const void *src,int size); 148 #endif 149 150 #ifndef HAVE_MEMMEM 151 #define memmem rep_memmem 152 void *rep_memmem(const void *haystack, size_t haystacklen, 153 const void *needle, size_t needlelen); 141 154 #endif 142 155 … … 278 291 #endif 279 292 293 294 280 295 #ifndef HAVE_STRTOLL 281 296 #define strtoll rep_strtoll 282 297 long long int rep_strtoll(const char *str, char **endptr, int base); 298 #else 299 #ifdef HAVE_BSD_STRTOLL 300 #define strtoll rep_strtoll 301 long long int rep_strtoll(const char *str, char **endptr, int base); 302 #endif 283 303 #endif 284 304 … … 286 306 #define strtoull rep_strtoull 287 307 unsigned long long int rep_strtoull(const char *str, char **endptr, int base); 308 #else 309 #ifdef HAVE_BSD_STRTOLL /* yes, it's not HAVE_BSD_STRTOULL */ 310 #define strtoull rep_strtoull 311 unsigned long long int rep_strtoull(const char *str, char **endptr, int base); 312 #endif 288 313 #endif 289 314 … … 329 354 #define socketpair rep_socketpair 330 355 /* prototype is in system/network.h */ 356 #endif 357 358 #ifndef HAVE_VDPRINTF 359 #define vdprintf rep_vdprintf 360 int rep_vdprintf(int fd, const char *format, va_list ap); 361 #endif 362 363 #ifndef HAVE_DPRINTF 364 #define dprintf rep_dprintf 365 int rep_dprintf(int fd, const char *format, ...); 331 366 #endif 332 367 … … 490 525 #define freeifaddrs rep_freeifaddrs 491 526 /* prototype is in "system/network.h" */ 527 #endif 528 529 #ifndef HAVE_GET_CURRENT_DIR_NAME 530 #define get_current_dir_name rep_get_current_dir_name 531 char *rep_get_current_dir_name(void); 532 #endif 533 534 #if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE) 535 #undef strerror_r 536 #define strerror_r rep_strerror_r 537 int rep_strerror_r(int errnum, char *buf, size_t buflen); 538 #endif 539 540 #if !defined(HAVE_CLOCK_GETTIME) 541 #define clock_gettime rep_clock_gettime 492 542 #endif 493 543 … … 724 774 #endif 725 775 776 #ifndef HAVE_FDATASYNC 777 #define fdatasync(fd) fsync(fd) 778 #elif !defined(HAVE_DECL_FDATASYNC) 779 int fdatasync(int ); 780 #endif 781 782 /* these are used to mark symbols as local to a shared lib, or 783 * publicly available via the shared lib API */ 784 #ifndef _PUBLIC_ 785 #ifdef HAVE_VISIBILITY_ATTR 786 #define _PUBLIC_ __attribute__((visibility("default"))) 787 #else 788 #define _PUBLIC_ 789 #endif 790 #endif 791 792 #ifndef _PRIVATE_ 793 #ifdef HAVE_VISIBILITY_ATTR 794 # define _PRIVATE_ __attribute__((visibility("hidden"))) 795 #else 796 # define _PRIVATE_ 797 #endif 798 #endif 799 800 #ifndef HAVE_POLL 801 #define poll rep_poll 802 /* prototype is in "system/network.h" */ 803 #endif 804 726 805 #endif /* _LIBREPLACE_REPLACE_H */ -
vendor/current/lib/replace/system/config.m4
r618 r740 7 7 AC_CHECK_HEADERS(sys/select.h) 8 8 9 # poll 10 AC_CHECK_HEADERS(poll.h) 11 AC_CHECK_FUNCS(poll,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/poll.o"]) 12 9 13 # time 10 14 AC_CHECK_HEADERS(sys/time.h utime.h) 11 15 AC_HEADER_TIME 12 16 AC_CHECK_FUNCS(utime utimes) 17 18 AC_CACHE_CHECK([if gettimeofday takes TZ argument],libreplace_cv_HAVE_GETTIMEOFDAY_TZ,[ 19 AC_TRY_RUN([ 20 #include <sys/time.h> 21 #include <unistd.h> 22 main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}], 23 libreplace_cv_HAVE_GETTIMEOFDAY_TZ=yes,libreplace_cv_HAVE_GETTIMEOFDAY_TZ=no,libreplace_cv_HAVE_GETTIMEOFDAY_TZ=yes)]) 24 if test x"$libreplace_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then 25 AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) 26 fi 13 27 14 28 # wait -
vendor/current/lib/replace/system/network.h
r478 r740 308 308 #define ss_family sin6_family 309 309 #define HAVE_SS_FAMILY 1 310 #else 310 #else /*HAVE_STRUCT_SOCKADDR_IN6*/ 311 311 #define sockaddr_storage sockaddr_in 312 312 #define ss_family sin_family 313 313 #define HAVE_SS_FAMILY 1 314 #endif 315 #endif 314 #endif /*HAVE_STRUCT_SOCKADDR_IN6*/ 315 #endif /*HAVE_STRUCT_SOCKADDR_STORAGE*/ 316 316 317 317 #ifndef HAVE_SS_FAMILY … … 332 332 */ 333 333 # define IOV_MAX 512 334 # else335 # error IOV_MAX and UIO_MAXIOV undefined336 334 # endif 337 335 # endif -
vendor/current/lib/replace/system/passwd.h
r414 r740 102 102 103 103 #ifdef NSS_WRAPPER 104 #ifndef NSS_WRAPPER_DISABLE 104 105 #ifndef NSS_WRAPPER_NOT_REPLACE 105 106 #define NSS_WRAPPER_REPLACE 106 #endif 107 #endif /* NSS_WRAPPER_NOT_REPLACE */ 107 108 #include "../nss_wrapper/nss_wrapper.h" 108 #endif 109 #endif /* NSS_WRAPPER_DISABLE */ 110 #endif /* NSS_WRAPPER */ 109 111 110 112 #endif -
vendor/current/lib/replace/system/readline.h
r414 r740 44 44 45 45 #ifdef HAVE_NEW_LIBREADLINE 46 # define RL_COMPLETION_CAST (rl_completion_func_t *) 46 #ifdef HAVE_CPPFUNCTION 47 # define RL_COMPLETION_CAST (CPPFunction *) 48 #elif HAVE_RL_COMPLETION_T 49 # define RL_COMPLETION_CAST (rl_completion_t *) 50 #else 51 # define RL_COMPLETION_CAST 52 #endif 47 53 #else 48 54 /* This type is missing from libreadline<4.0 (approximately) */ -
vendor/current/lib/replace/system/select.h
r414 r740 39 39 #endif 40 40 41 #ifdef HAVE_POLL 42 43 #include <poll.h> 44 45 #else 46 47 /* Type used for the number of file descriptors. */ 48 typedef unsigned long int nfds_t; 49 50 /* Data structure describing a polling request. */ 51 struct pollfd 52 { 53 int fd; /* File descriptor to poll. */ 54 short int events; /* Types of events poller cares about. */ 55 short int revents; /* Types of events that actually occurred. */ 56 }; 57 58 /* Event types that can be polled for. These bits may be set in `events' 59 to indicate the interesting event types; they will appear in `revents' 60 to indicate the status of the file descriptor. */ 61 #define POLLIN 0x001 /* There is data to read. */ 62 #define POLLPRI 0x002 /* There is urgent data to read. */ 63 #define POLLOUT 0x004 /* Writing now will not block. */ 64 #define POLLRDNORM 0x040 /* Normal data may be read. */ 65 #define POLLRDBAND 0x080 /* Priority data may be read. */ 66 #define POLLWRNORM 0x100 /* Writing now will not block. */ 67 #define POLLWRBAND 0x200 /* Priority data may be written. */ 68 #define POLLERR 0x008 /* Error condition. */ 69 #define POLLHUP 0x010 /* Hung up. */ 70 #define POLLNVAL 0x020 /* Invalid polling request. */ 71 72 /* define is in "replace.h" */ 73 int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout); 74 41 75 #endif 76 77 #endif -
vendor/current/lib/replace/system/time.h
r414 r740 47 47 #endif 48 48 49 #ifndef HAVE_STRUCT_TIMESPEC 50 struct timespec { 51 time_t tv_sec; /* Seconds. */ 52 long tv_nsec; /* Nanoseconds. */ 53 }; 54 #endif 55 49 56 #ifndef HAVE_MKTIME 50 57 /* define is in "replace.h" */ … … 67 74 #endif 68 75 76 #ifndef HAVE_CLOCK_GETTIME 77 /* CLOCK_REALTIME is required by POSIX */ 78 #define CLOCK_REALTIME 0 79 typedef int clockid_t; 80 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp); 69 81 #endif 82 /* make sure we have a best effort CUSTOM_CLOCK_MONOTONIC we can rely on */ 83 #if defined(CLOCK_MONOTONIC) 84 #define CUSTOM_CLOCK_MONOTONIC CLOCK_MONOTONIC 85 #elif defined(CLOCK_HIGHRES) 86 #define CUSTOM_CLOCK_MONOTONIC CLOCK_HIGHRES 87 #else 88 #define CUSTOM_CLOCK_MONOTONIC CLOCK_REALTIME 89 #endif 90 91 #endif -
vendor/current/lib/replace/system/wait.h
r618 r740 37 37 #endif 38 38 39 #ifndef SIGNAL_CAST40 #define SIGNAL_CAST (RETSIGTYPE (*)(int))41 #endif42 43 39 #ifdef HAVE_SETJMP_H 44 40 #include <setjmp.h> -
vendor/current/lib/replace/test/os2_delete.c
r414 r740 47 47 char fname[40]; 48 48 int fd; 49 s printf(fname, TESTDIR "/test%u.txt", i);49 snprintf(fname, sizeof(fname), TESTDIR "/test%u.txt", i); 50 50 fd = open(fname, O_CREAT|O_RDWR, 0600); 51 51 if (fd < 0) { … … 80 80 for (j=0; j<MIN(i, DELETE_SIZE); j++) { 81 81 char fname[40]; 82 s printf(fname, TESTDIR "/%s", names[j]);82 snprintf(fname, sizeof(fname), TESTDIR "/%s", names[j]); 83 83 unlink(fname) == 0 || FAILED("unlink"); 84 84 } -
vendor/current/lib/replace/test/testsuite.c
r414 r740 752 752 bool 753 753 socklen_t 754 uint_t755 754 uint{8,16,32,64}_t 756 755 int{8,16,32,64}_t … … 773 772 printf("test: FUNCTION\n"); 774 773 if (strcmp(__FUNCTION__, "test_FUNCTION") != 0) { 775 printf("failure: F AILURE [\nFAILUREinvalid\n]\n");774 printf("failure: FUNCTION [\nFUNCTION invalid\n]\n"); 776 775 return false; 777 776 } … … 1015 1014 return true; 1016 1015 } 1016 1017 static int test_memmem(void) 1018 { 1019 char *s; 1020 1021 printf("test: memmem\n"); 1022 1023 s = (char *)memmem("foo", 3, "fo", 2); 1024 if (strcmp(s, "foo") != 0) { 1025 printf(__location__ ": Failed memmem\n"); 1026 return false; 1027 } 1028 1029 s = (char *)memmem("foo", 3, "", 0); 1030 /* it is allowable for this to return NULL (as happens on 1031 FreeBSD) */ 1032 if (s && strcmp(s, "foo") != 0) { 1033 printf(__location__ ": Failed memmem\n"); 1034 return false; 1035 } 1036 1037 s = (char *)memmem("foo", 4, "o", 1); 1038 if (strcmp(s, "oo") != 0) { 1039 printf(__location__ ": Failed memmem\n"); 1040 return false; 1041 } 1042 1043 s = (char *)memmem("foobarfodx", 11, "fod", 3); 1044 if (strcmp(s, "fodx") != 0) { 1045 printf(__location__ ": Failed memmem\n"); 1046 return false; 1047 } 1048 1049 printf("success: memmem\n"); 1050 1051 return true; 1052 } 1053 1017 1054 1018 1055 struct torture_context; … … 1066 1103 ret &= test_utime(); 1067 1104 ret &= test_utimes(); 1105 ret &= test_memmem(); 1068 1106 1069 1107 return ret; -
vendor/current/lib/smbconf/smbconf.c
r414 r740 28 28 **********************************************************************/ 29 29 30 static WERRORsmbconf_global_check(struct smbconf_ctx *ctx)30 static sbcErr smbconf_global_check(struct smbconf_ctx *ctx) 31 31 { 32 32 if (!smbconf_share_exists(ctx, GLOBAL_NAME)) { 33 33 return smbconf_create_share(ctx, GLOBAL_NAME); 34 34 } 35 return WERR_OK; 35 36 return SBC_ERR_OK; 36 37 } 37 38 … … 42 43 * 43 44 **********************************************************************/ 45 46 const char *sbcErrorString(sbcErr error) 47 { 48 switch (error) { 49 case SBC_ERR_OK: 50 return "SBC_ERR_OK"; 51 case SBC_ERR_NOT_IMPLEMENTED: 52 return "SBC_ERR_NOT_IMPLEMENTED"; 53 case SBC_ERR_NOT_SUPPORTED: 54 return "SBC_ERR_NOT_SUPPORTED"; 55 case SBC_ERR_UNKNOWN_FAILURE: 56 return "SBC_ERR_UNKNOWN_FAILURE"; 57 case SBC_ERR_NOMEM: 58 return "SBC_ERR_NOMEM"; 59 case SBC_ERR_INVALID_PARAM: 60 return "SBC_ERR_INVALID_PARAM"; 61 case SBC_ERR_BADFILE: 62 return "SBC_ERR_BADFILE"; 63 case SBC_ERR_NO_SUCH_SERVICE: 64 return "SBC_ERR_NO_SUCH_SERVICE"; 65 case SBC_ERR_IO_FAILURE: 66 return "SBC_ERR_IO_FAILURE"; 67 case SBC_ERR_CAN_NOT_COMPLETE: 68 return "SBC_ERR_CAN_NOT_COMPLETE"; 69 case SBC_ERR_NO_MORE_ITEMS: 70 return "SBC_ERR_NO_MORE_ITEMS"; 71 case SBC_ERR_FILE_EXISTS: 72 return "SBC_ERR_FILE_EXISTS"; 73 case SBC_ERR_ACCESS_DENIED: 74 return "SBC_ERR_ACCESS_DENIED"; 75 } 76 77 return "unknown sbcErr value"; 78 } 79 44 80 45 81 /** … … 92 128 * Drop the whole configuration (restarting empty). 93 129 */ 94 WERRORsmbconf_drop(struct smbconf_ctx *ctx)130 sbcErr smbconf_drop(struct smbconf_ctx *ctx) 95 131 { 96 132 return ctx->ops->drop(ctx); … … 106 142 * param_values : list of lists of parameter values for each share 107 143 */ 108 WERRORsmbconf_get_config(struct smbconf_ctx *ctx,144 sbcErr smbconf_get_config(struct smbconf_ctx *ctx, 109 145 TALLOC_CTX *mem_ctx, 110 146 uint32_t *num_shares, 111 147 struct smbconf_service ***services) 112 148 { 113 WERROR werr = WERR_OK;149 sbcErr err; 114 150 TALLOC_CTX *tmp_ctx = NULL; 115 151 uint32_t tmp_num_shares; … … 119 155 120 156 if ((num_shares == NULL) || (services == NULL)) { 121 werr = WERR_INVALID_PARAM;157 err = SBC_ERR_INVALID_PARAM; 122 158 goto done; 123 159 } … … 125 161 tmp_ctx = talloc_stackframe(); 126 162 127 werr = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,128 129 if (! W_ERROR_IS_OK(werr)) {163 err = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares, 164 &tmp_share_names); 165 if (!SBC_ERROR_IS_OK(err)) { 130 166 goto done; 131 167 } … … 133 169 tmp_services = talloc_array(tmp_ctx, struct smbconf_service *, 134 170 tmp_num_shares); 135 136 171 if (tmp_services == NULL) { 137 werr = WERR_NOMEM;172 err = SBC_ERR_NOMEM; 138 173 goto done; 139 174 } 140 175 141 176 for (count = 0; count < tmp_num_shares; count++) { 142 werr = smbconf_get_share(ctx, tmp_services,143 144 145 if (! W_ERROR_IS_OK(werr)) {177 err = smbconf_get_share(ctx, tmp_services, 178 tmp_share_names[count], 179 &tmp_services[count]); 180 if (!SBC_ERROR_IS_OK(err)) { 146 181 goto done; 147 182 } 148 183 } 149 184 150 werr = WERR_OK;185 err = SBC_ERR_OK; 151 186 152 187 *num_shares = tmp_num_shares; … … 159 194 done: 160 195 talloc_free(tmp_ctx); 161 return werr;196 return err; 162 197 } 163 198 … … 165 200 * get the list of share names defined in the configuration. 166 201 */ 167 WERRORsmbconf_get_share_names(struct smbconf_ctx *ctx,202 sbcErr smbconf_get_share_names(struct smbconf_ctx *ctx, 168 203 TALLOC_CTX *mem_ctx, 169 204 uint32_t *num_shares, … … 186 221 * Add a service if it does not already exist. 187 222 */ 188 WERRORsmbconf_create_share(struct smbconf_ctx *ctx,223 sbcErr smbconf_create_share(struct smbconf_ctx *ctx, 189 224 const char *servicename) 190 225 { 191 226 if ((servicename != NULL) && smbconf_share_exists(ctx, servicename)) { 192 return WERR_FILE_EXISTS;227 return SBC_ERR_FILE_EXISTS; 193 228 } 194 229 … … 199 234 * get a definition of a share (service) from configuration. 200 235 */ 201 WERRORsmbconf_get_share(struct smbconf_ctx *ctx,236 sbcErr smbconf_get_share(struct smbconf_ctx *ctx, 202 237 TALLOC_CTX *mem_ctx, 203 238 const char *servicename, … … 210 245 * delete a service from configuration 211 246 */ 212 WERRORsmbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)247 sbcErr smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename) 213 248 { 214 249 if (!smbconf_share_exists(ctx, servicename)) { 215 return WERR_NO_SUCH_SERVICE;250 return SBC_ERR_NO_SUCH_SERVICE; 216 251 } 217 252 … … 222 257 * set a configuration parameter to the value provided. 223 258 */ 224 WERRORsmbconf_set_parameter(struct smbconf_ctx *ctx,259 sbcErr smbconf_set_parameter(struct smbconf_ctx *ctx, 225 260 const char *service, 226 261 const char *param, … … 236 271 * This also creates [global] when it does not exist. 237 272 */ 238 WERRORsmbconf_set_global_parameter(struct smbconf_ctx *ctx,273 sbcErr smbconf_set_global_parameter(struct smbconf_ctx *ctx, 239 274 const char *param, const char *val) 240 275 { 241 WERROR werr; 242 243 werr = smbconf_global_check(ctx); 244 if (W_ERROR_IS_OK(werr)) { 245 werr = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val); 246 } 247 248 return werr; 276 sbcErr err; 277 278 err = smbconf_global_check(ctx); 279 if (!SBC_ERROR_IS_OK(err)) { 280 return err; 281 } 282 err = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val); 283 284 return err; 249 285 } 250 286 … … 252 288 * get the value of a configuration parameter as a string 253 289 */ 254 WERRORsmbconf_get_parameter(struct smbconf_ctx *ctx,290 sbcErr smbconf_get_parameter(struct smbconf_ctx *ctx, 255 291 TALLOC_CTX *mem_ctx, 256 292 const char *service, … … 259 295 { 260 296 if (valstr == NULL) { 261 return WERR_INVALID_PARAM;297 return SBC_ERR_INVALID_PARAM; 262 298 } 263 299 … … 270 306 * Create [global] if it does not exist. 271 307 */ 272 WERRORsmbconf_get_global_parameter(struct smbconf_ctx *ctx,308 sbcErr smbconf_get_global_parameter(struct smbconf_ctx *ctx, 273 309 TALLOC_CTX *mem_ctx, 274 310 const char *param, 275 311 char **valstr) 276 312 { 277 WERROR werr; 278 279 werr = smbconf_global_check(ctx); 280 if (W_ERROR_IS_OK(werr)) { 281 werr = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param, 282 valstr); 283 } 284 285 return werr; 313 sbcErr err; 314 315 err = smbconf_global_check(ctx); 316 if (!SBC_ERROR_IS_OK(err)) { 317 return err; 318 } 319 320 err = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param, 321 valstr); 322 323 return err; 286 324 } 287 325 … … 289 327 * delete a parameter from configuration 290 328 */ 291 WERRORsmbconf_delete_parameter(struct smbconf_ctx *ctx,329 sbcErr smbconf_delete_parameter(struct smbconf_ctx *ctx, 292 330 const char *service, const char *param) 293 331 { … … 300 338 * Create [global] if it does not exist. 301 339 */ 302 WERRORsmbconf_delete_global_parameter(struct smbconf_ctx *ctx,340 sbcErr smbconf_delete_global_parameter(struct smbconf_ctx *ctx, 303 341 const char *param) 304 342 { 305 WERROR werr; 306 307 werr = smbconf_global_check(ctx); 308 if (W_ERROR_IS_OK(werr)) { 309 werr = smbconf_delete_parameter(ctx, GLOBAL_NAME, param); 310 } 311 312 return werr; 313 } 314 315 WERROR smbconf_get_includes(struct smbconf_ctx *ctx, 343 sbcErr err; 344 345 err = smbconf_global_check(ctx); 346 if (!SBC_ERROR_IS_OK(err)) { 347 return err; 348 } 349 err = smbconf_delete_parameter(ctx, GLOBAL_NAME, param); 350 351 return err; 352 } 353 354 sbcErr smbconf_get_includes(struct smbconf_ctx *ctx, 316 355 TALLOC_CTX *mem_ctx, 317 356 const char *service, … … 322 361 } 323 362 324 WERRORsmbconf_get_global_includes(struct smbconf_ctx *ctx,363 sbcErr smbconf_get_global_includes(struct smbconf_ctx *ctx, 325 364 TALLOC_CTX *mem_ctx, 326 365 uint32_t *num_includes, char ***includes) 327 366 { 328 WERROR werr; 329 330 werr = smbconf_global_check(ctx); 331 if (W_ERROR_IS_OK(werr)) { 332 werr = smbconf_get_includes(ctx, mem_ctx, GLOBAL_NAME, 333 num_includes, includes); 334 } 335 336 return werr; 337 } 338 339 WERROR smbconf_set_includes(struct smbconf_ctx *ctx, 367 sbcErr err; 368 369 err = smbconf_global_check(ctx); 370 if (!SBC_ERROR_IS_OK(err)) { 371 return err; 372 } 373 err = smbconf_get_includes(ctx, mem_ctx, GLOBAL_NAME, 374 num_includes, includes); 375 376 return err; 377 } 378 379 sbcErr smbconf_set_includes(struct smbconf_ctx *ctx, 340 380 const char *service, 341 381 uint32_t num_includes, const char **includes) … … 344 384 } 345 385 346 WERRORsmbconf_set_global_includes(struct smbconf_ctx *ctx,386 sbcErr smbconf_set_global_includes(struct smbconf_ctx *ctx, 347 387 uint32_t num_includes, 348 388 const char **includes) 349 389 { 350 WERROR werr; 351 352 werr = smbconf_global_check(ctx); 353 if (W_ERROR_IS_OK(werr)) { 354 werr = smbconf_set_includes(ctx, GLOBAL_NAME, 355 num_includes, includes); 356 } 357 358 return werr; 359 } 360 361 362 WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service) 390 sbcErr err; 391 392 err = smbconf_global_check(ctx); 393 if (!SBC_ERROR_IS_OK(err)) { 394 return err; 395 } 396 err = smbconf_set_includes(ctx, GLOBAL_NAME, 397 num_includes, includes); 398 399 return err; 400 } 401 402 403 sbcErr smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service) 363 404 { 364 405 return ctx->ops->delete_includes(ctx, service); 365 406 } 366 407 367 WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx) 368 { 369 WERROR werr; 370 371 werr = smbconf_global_check(ctx); 372 if (W_ERROR_IS_OK(werr)) { 373 werr = smbconf_delete_includes(ctx, GLOBAL_NAME); 374 } 375 376 return werr; 377 } 378 379 WERROR smbconf_transaction_start(struct smbconf_ctx *ctx) 408 sbcErr smbconf_delete_global_includes(struct smbconf_ctx *ctx) 409 { 410 sbcErr err; 411 412 err = smbconf_global_check(ctx); 413 if (!SBC_ERROR_IS_OK(err)) { 414 return err; 415 } 416 err = smbconf_delete_includes(ctx, GLOBAL_NAME); 417 418 return err; 419 } 420 421 sbcErr smbconf_transaction_start(struct smbconf_ctx *ctx) 380 422 { 381 423 return ctx->ops->transaction_start(ctx); 382 424 } 383 425 384 WERRORsmbconf_transaction_commit(struct smbconf_ctx *ctx)426 sbcErr smbconf_transaction_commit(struct smbconf_ctx *ctx) 385 427 { 386 428 return ctx->ops->transaction_commit(ctx); 387 429 } 388 430 389 WERRORsmbconf_transaction_cancel(struct smbconf_ctx *ctx)431 sbcErr smbconf_transaction_cancel(struct smbconf_ctx *ctx) 390 432 { 391 433 return ctx->ops->transaction_cancel(ctx); -
vendor/current/lib/smbconf/smbconf.h
r414 r740 21 21 #define __LIBSMBCONF_H__ 22 22 23 /** 24 * @defgroup libsmbconf The smbconf API 25 * 26 * libsmbconf is a library to read or, based on the backend, modify the Samba 27 * configuration. 28 * 29 * @{ 30 */ 31 32 /** 33 * @brief Status codes returned from smbconf functions 34 */ 35 enum _sbcErrType { 36 SBC_ERR_OK = 0, /**< Successful completion **/ 37 SBC_ERR_NOT_IMPLEMENTED, /**< Function not implemented **/ 38 SBC_ERR_NOT_SUPPORTED, /**< Function not supported **/ 39 SBC_ERR_UNKNOWN_FAILURE, /**< General failure **/ 40 SBC_ERR_NOMEM, /**< Memory allocation error **/ 41 SBC_ERR_INVALID_PARAM, /**< An Invalid parameter was supplied **/ 42 SBC_ERR_BADFILE, /**< A bad file was supplied **/ 43 SBC_ERR_NO_SUCH_SERVICE, /**< There is no such service provided **/ 44 SBC_ERR_IO_FAILURE, /**< There was an IO error **/ 45 SBC_ERR_CAN_NOT_COMPLETE,/**< Can not complete action **/ 46 SBC_ERR_NO_MORE_ITEMS, /**< No more items left **/ 47 SBC_ERR_FILE_EXISTS, /**< File already exists **/ 48 SBC_ERR_ACCESS_DENIED, /**< Access has been denied **/ 49 }; 50 51 typedef enum _sbcErrType sbcErr; 52 53 #define SBC_ERROR_IS_OK(x) ((x) == SBC_ERR_OK) 54 #define SBC_ERROR_EQUAL(x,y) ((x) == (y)) 55 23 56 struct smbconf_ctx; 24 57 … … 28 61 }; 29 62 63 /** Information about a service */ 30 64 struct smbconf_service { 31 char *name; 32 uint32_t num_params; 33 char **param_names; 34 char **param_values; 65 char *name; /**< The name of the share */ 66 uint32_t num_params; /**< List of length num_shares of parameter counts for each share */ 67 char **param_names; /**< List of lists of parameter names for each share */ 68 char **param_values; /**< List of lists of parameter values for each share */ 35 69 }; 36 70 37 71 /* 38 * the smbconf API functions 72 * The smbconf API functions 73 */ 74 75 /** 76 * @brief Translate an error value into a string 77 * 78 * @param error 79 * 80 * @return a pointer to a static string 81 **/ 82 const char *sbcErrorString(sbcErr error); 83 84 /** 85 * @brief Check if the backend requires messaging to be set up. 86 * 87 * Tell whether the backend requires messaging to be set up 88 * for the backend to work correctly. 89 * 90 * @param[in] ctx The smbconf context to check. 91 * 92 * @return True if needed, false if not. 39 93 */ 40 94 bool smbconf_backend_requires_messaging(struct smbconf_ctx *ctx); 95 96 /** 97 * @brief Tell whether the source is writeable. 98 * 99 * @param[in] ctx The smbconf context to check. 100 * 101 * @return True if it is writeable, false if not. 102 */ 41 103 bool smbconf_is_writeable(struct smbconf_ctx *ctx); 104 105 /** 106 * @brief Close the configuration. 107 * 108 * @param[in] ctx The smbconf context to close. 109 */ 42 110 void smbconf_shutdown(struct smbconf_ctx *ctx); 111 112 /** 113 * @brief Detect changes in the configuration. 114 * 115 * Get the change sequence number of the given service/parameter. Service and 116 * parameter strings may be NULL. 117 * 118 * The given change sequence number (csn) struct is filled with the current 119 * csn. smbconf_changed() can also be used for initial retrieval of the csn. 120 * 121 * @param[in] ctx The smbconf context to check for changes. 122 * 123 * @param[inout] csn The smbconf csn to be filled. 124 * 125 * @param[in] service The service name to check or NULL. 126 * 127 * @param[in] param The param to check or NULL. 128 * 129 * @return True if it has been changed, false if not. 130 */ 43 131 bool smbconf_changed(struct smbconf_ctx *ctx, struct smbconf_csn *csn, 44 132 const char *service, const char *param); 45 WERROR smbconf_drop(struct smbconf_ctx *ctx); 46 WERROR smbconf_get_config(struct smbconf_ctx *ctx, 133 134 /** 135 * @brief Drop the whole configuration (restarting empty). 136 * 137 * @param[in] ctx The smbconf context to drop the config. 138 * 139 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 140 * error occured. 141 */ 142 sbcErr smbconf_drop(struct smbconf_ctx *ctx); 143 144 /** 145 * @brief Get the whole configuration as lists of strings with counts. 146 * 147 * @param[in] ctx The smbconf context to get the lists from. 148 * 149 * @param[in] mem_ctx The memory context to use. 150 * 151 * @param[in] num_shares A pointer to store the number of shares. 152 * 153 * @param[out] services A pointer to store the services. 154 * 155 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 156 * error occured. 157 * 158 * @see smbconf_service 159 */ 160 sbcErr smbconf_get_config(struct smbconf_ctx *ctx, 47 161 TALLOC_CTX *mem_ctx, 48 162 uint32_t *num_shares, 49 163 struct smbconf_service ***services); 50 WERROR smbconf_get_share_names(struct smbconf_ctx *ctx, 164 165 /** 166 * @brief Get the list of share names defined in the configuration. 167 * 168 * @param[in] ctx The smbconf context to use. 169 * 170 * @param[in] mem_ctx The memory context to use. 171 * 172 * @param[in] num_shares A pointer to store the number of shares. 173 * 174 * @param[in] share_names A pointer to store the share names. 175 * 176 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 177 * error occured. 178 */ 179 sbcErr smbconf_get_share_names(struct smbconf_ctx *ctx, 51 180 TALLOC_CTX *mem_ctx, 52 181 uint32_t *num_shares, 53 182 char ***share_names); 183 184 /** 185 * @brief Check if a share/service of a given name exists. 186 * 187 * @param[in] ctx The smbconf context to use. 188 * 189 * @param[in] servicename The service name to check if it exists. 190 * 191 * @return True if it exists, false if not. 192 */ 54 193 bool smbconf_share_exists(struct smbconf_ctx *ctx, const char *servicename); 55 WERROR smbconf_create_share(struct smbconf_ctx *ctx, const char *servicename); 56 WERROR smbconf_get_share(struct smbconf_ctx *ctx, 194 195 /** 196 * @brief Add a service if it does not already exist. 197 * 198 * @param[in] ctx The smbconf context to use. 199 * 200 * @param[in] servicename The name of the service to add. 201 * 202 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 203 * error occured. 204 */ 205 sbcErr smbconf_create_share(struct smbconf_ctx *ctx, const char *servicename); 206 207 /** 208 * @brief Get a definition of a share (service) from configuration. 209 * 210 * @param[in] ctx The smbconf context to use. 211 * 212 * @param[in] mem_ctx A memory context to allocate the result. 213 * 214 * @param[in] servicename The service name to get the information from. 215 * 216 * @param[out] service A pointer to store the service information about the 217 * share. 218 * 219 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 220 * error occured. 221 * 222 * @see smbconf_service 223 */ 224 sbcErr smbconf_get_share(struct smbconf_ctx *ctx, 57 225 TALLOC_CTX *mem_ctx, 58 226 const char *servicename, 59 227 struct smbconf_service **service); 60 WERROR smbconf_delete_share(struct smbconf_ctx *ctx, 228 229 /** 230 * @brief Delete a service from configuration. 231 * 232 * @param[in] ctx The smbconf context to use. 233 * 234 * @param[in] servicename The service name to delete. 235 * 236 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 237 * error occured. 238 */ 239 sbcErr smbconf_delete_share(struct smbconf_ctx *ctx, 61 240 const char *servicename); 62 WERROR smbconf_set_parameter(struct smbconf_ctx *ctx, 241 242 /** 243 * @brief Set a configuration parameter to the value provided. 244 * 245 * @param[in] ctx The smbconf context to use. 246 * 247 * @param[in] service The service name to set the parameter. 248 * 249 * @param[in] param The name of the parameter to set. 250 * 251 * @param[in] valstr The value to set. 252 * 253 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 254 * error occured. 255 */ 256 sbcErr smbconf_set_parameter(struct smbconf_ctx *ctx, 63 257 const char *service, 64 258 const char *param, 65 259 const char *valstr); 66 WERROR smbconf_set_global_parameter(struct smbconf_ctx *ctx, 260 261 /** 262 * @brief Set a global configuration parameter to the value provided. 263 * 264 * This adds a paramet in the [global] service. It also creates [global] if it 265 * does't exist. 266 * 267 * @param[in] ctx The smbconf context to use. 268 * 269 * @param[in] param The name of the parameter to set. 270 * 271 * @param[in] val The value to set. 272 * 273 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 274 * error occured. 275 */ 276 sbcErr smbconf_set_global_parameter(struct smbconf_ctx *ctx, 67 277 const char *param, const char *val); 68 WERROR smbconf_get_parameter(struct smbconf_ctx *ctx, 278 279 /** 280 * @brief Get the value of a configuration parameter as a string. 281 * 282 * @param[in] ctx The smbconf context to use. 283 * 284 * @param[in] mem_ctx The memory context to allocate the string on. 285 * 286 * @param[in] service The name of the service where to find the parameter. 287 * 288 * @param[in] param The parameter to get. 289 * 290 * @param[out] valstr A pointer to store the value as a string. 291 * 292 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 293 * error occured. 294 */ 295 sbcErr smbconf_get_parameter(struct smbconf_ctx *ctx, 69 296 TALLOC_CTX *mem_ctx, 70 297 const char *service, 71 298 const char *param, 72 299 char **valstr); 73 WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx, 300 301 /** 302 * @brief Get the value of a global configuration parameter as a string. 303 * 304 * It also creates [global] if it does't exist. 305 * 306 * @param[in] ctx The smbconf context to use. 307 * 308 * @param[in] mem_ctx The memory context to allocate the string on. 309 * 310 * @param[in] param The parameter to get. 311 * 312 * @param[out] valstr A pointer to store the value as a string. 313 * 314 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 315 * error occured. 316 */ 317 sbcErr smbconf_get_global_parameter(struct smbconf_ctx *ctx, 74 318 TALLOC_CTX *mem_ctx, 75 319 const char *param, 76 320 char **valstr); 77 WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx, 321 322 /** 323 * @brief Delete a parameter from the configuration. 324 * 325 * @param[in] ctx The smbconf context to use. 326 * 327 * @param[in] service The service where the parameter can be found. 328 * 329 * @param[in] param The name of the parameter to delete. 330 * 331 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 332 * error occured. 333 */ 334 sbcErr smbconf_delete_parameter(struct smbconf_ctx *ctx, 78 335 const char *service, const char *param); 79 WERROR smbconf_delete_global_parameter(struct smbconf_ctx *ctx, 336 337 /** 338 * @brief Delete a global parameter from the configuration. 339 * 340 * It also creates [global] if it does't exist. 341 * 342 * @param[in] ctx The smbconf context to use. 343 * 344 * @param[in] param The name of the parameter to delete. 345 * 346 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 347 * error occured. 348 */ 349 sbcErr smbconf_delete_global_parameter(struct smbconf_ctx *ctx, 80 350 const char *param); 81 WERROR smbconf_get_includes(struct smbconf_ctx *ctx, 351 352 /** 353 * @brief Get the list of names of included files. 354 * 355 * @param[in] ctx The smbconf context to use. 356 * 357 * @param[in] mem_ctx The memory context to allocate the names. 358 * 359 * @param[in] service The service name to get the include files. 360 * 361 * @param[out] num_includes A pointer to store the number of included files. 362 * 363 * @param[out] includes A pointer to store the paths of the included files. 364 * 365 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 366 * error occured. 367 */ 368 sbcErr smbconf_get_includes(struct smbconf_ctx *ctx, 82 369 TALLOC_CTX *mem_ctx, 83 370 const char *service, 84 371 uint32_t *num_includes, char ***includes); 85 WERROR smbconf_get_global_includes(struct smbconf_ctx *ctx, 372 373 /** 374 * @brief Get the list of globally included files. 375 * 376 * @param[in] ctx The smbconf context to use. 377 * 378 * @param[in] mem_ctx The memory context to allocate the names. 379 * 380 * @param[out] num_includes A pointer to store the number of included files. 381 * 382 * @param[out] includes A pointer to store the paths of the included files. 383 * 384 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 385 * error occured. 386 */ 387 sbcErr smbconf_get_global_includes(struct smbconf_ctx *ctx, 86 388 TALLOC_CTX *mem_ctx, 87 389 uint32_t *num_includes, char ***includes); 88 WERROR smbconf_set_includes(struct smbconf_ctx *ctx, 390 391 /** 392 * @brief Set a list of config files to include on the given service. 393 * 394 * @param[in] ctx The smbconf context to use. 395 * 396 * @param[in] service The service to add includes. 397 * 398 * @param[in] num_includes The number of includes to set. 399 * 400 * @param[in] includes A list of paths to include. 401 * 402 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 403 * error occured. 404 */ 405 sbcErr smbconf_set_includes(struct smbconf_ctx *ctx, 89 406 const char *service, 90 407 uint32_t num_includes, const char **includes); 91 WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx, 408 409 /** 410 * @brief Set a list of config files to include globally. 411 * 412 * @param[in] ctx The smbconf context to use. 413 * 414 * @param[in] num_includes The number of includes to set. 415 * 416 * @param[in] includes A list of paths to include. 417 * 418 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 419 * error occured. 420 */ 421 sbcErr smbconf_set_global_includes(struct smbconf_ctx *ctx, 92 422 uint32_t num_includes, 93 423 const char **includes); 94 WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service); 95 WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx); 96 97 WERROR smbconf_transaction_start(struct smbconf_ctx *ctx); 98 WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx); 99 WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx); 424 425 /** 426 * @brief Delete include parameter on the given service. 427 * 428 * @param[in] ctx The smbconf context to use. 429 * 430 * @param[in] service The name of the service to delete the includes from. 431 * 432 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 433 * error occured. 434 */ 435 sbcErr smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service); 436 437 /** 438 * @brief Delete include parameter from the global service. 439 * 440 * @param[in] ctx The smbconf context to use. 441 * 442 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 443 * error occured. 444 */ 445 sbcErr smbconf_delete_global_includes(struct smbconf_ctx *ctx); 446 447 /** 448 * @brief Start a transaction on the configuration backend. 449 * 450 * This is to speed up writes to the registry based backend. 451 * 452 * @param[in] ctx The smbconf context to start the transaction. 453 * 454 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 455 * error occured. 456 */ 457 sbcErr smbconf_transaction_start(struct smbconf_ctx *ctx); 458 459 /** 460 * @brief Commit a transaction on the configuration backend. 461 * 462 * This is to speed up writes to the registry based backend. 463 * 464 * @param[in] ctx The smbconf context to commit the transaction. 465 * 466 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 467 * error occured. 468 * 469 * @see smbconf_transaction_start() 470 */ 471 sbcErr smbconf_transaction_commit(struct smbconf_ctx *ctx); 472 473 /** 474 * @brief Cancel a transaction on the configuration backend. 475 * 476 * @param[in] ctx The smbconf context to cancel the transaction. 477 * 478 * @return SBC_ERR_OK on success, a corresponding sbcErr if an 479 * error occured. 480 * 481 * @see smbconf_transaction_start() 482 */ 483 sbcErr smbconf_transaction_cancel(struct smbconf_ctx *ctx); 484 485 /* @} ******************************************************************/ 100 486 101 487 #endif /* _LIBSMBCONF_H_ */ -
vendor/current/lib/smbconf/smbconf_private.h
r414 r740 28 28 29 29 struct smbconf_ops { 30 WERROR(*init)(struct smbconf_ctx *ctx, const char *path);30 sbcErr (*init)(struct smbconf_ctx *ctx, const char *path); 31 31 int (*shutdown)(struct smbconf_ctx *ctx); 32 32 bool (*requires_messaging)(struct smbconf_ctx *ctx); 33 33 bool (*is_writeable)(struct smbconf_ctx *ctx); 34 WERROR(*open_conf)(struct smbconf_ctx *ctx);34 sbcErr (*open_conf)(struct smbconf_ctx *ctx); 35 35 int (*close_conf)(struct smbconf_ctx *ctx); 36 36 void (*get_csn)(struct smbconf_ctx *ctx, struct smbconf_csn *csn, 37 37 const char *service, const char *param); 38 WERROR(*drop)(struct smbconf_ctx *ctx);39 WERROR(*get_share_names)(struct smbconf_ctx *ctx,38 sbcErr (*drop)(struct smbconf_ctx *ctx); 39 sbcErr (*get_share_names)(struct smbconf_ctx *ctx, 40 40 TALLOC_CTX *mem_ctx, 41 41 uint32_t *num_shares, 42 42 char ***share_names); 43 43 bool (*share_exists)(struct smbconf_ctx *ctx, const char *service); 44 WERROR(*create_share)(struct smbconf_ctx *ctx, const char *service);45 WERROR(*get_share)(struct smbconf_ctx *ctx,44 sbcErr (*create_share)(struct smbconf_ctx *ctx, const char *service); 45 sbcErr (*get_share)(struct smbconf_ctx *ctx, 46 46 TALLOC_CTX *mem_ctx, 47 47 const char *servicename, 48 48 struct smbconf_service **service); 49 WERROR(*delete_share)(struct smbconf_ctx *ctx,49 sbcErr (*delete_share)(struct smbconf_ctx *ctx, 50 50 const char *servicename); 51 WERROR(*set_parameter)(struct smbconf_ctx *ctx,51 sbcErr (*set_parameter)(struct smbconf_ctx *ctx, 52 52 const char *service, 53 53 const char *param, 54 54 const char *valstr); 55 WERROR(*get_parameter)(struct smbconf_ctx *ctx,55 sbcErr (*get_parameter)(struct smbconf_ctx *ctx, 56 56 TALLOC_CTX *mem_ctx, 57 57 const char *service, 58 58 const char *param, 59 59 char **valstr); 60 WERROR(*delete_parameter)(struct smbconf_ctx *ctx,60 sbcErr (*delete_parameter)(struct smbconf_ctx *ctx, 61 61 const char *service, const char *param); 62 WERROR(*get_includes)(struct smbconf_ctx *ctx,62 sbcErr (*get_includes)(struct smbconf_ctx *ctx, 63 63 TALLOC_CTX *mem_ctx, 64 64 const char *service, 65 65 uint32_t *num_includes, char ***includes); 66 WERROR(*set_includes)(struct smbconf_ctx *ctx,66 sbcErr (*set_includes)(struct smbconf_ctx *ctx, 67 67 const char *service, 68 68 uint32_t num_includes, const char **includes); 69 WERROR(*delete_includes)(struct smbconf_ctx *ctx,69 sbcErr (*delete_includes)(struct smbconf_ctx *ctx, 70 70 const char *service); 71 WERROR(*transaction_start)(struct smbconf_ctx *ctx);72 WERROR(*transaction_commit)(struct smbconf_ctx *ctx);73 WERROR(*transaction_cancel)(struct smbconf_ctx *ctx);71 sbcErr (*transaction_start)(struct smbconf_ctx *ctx); 72 sbcErr (*transaction_commit)(struct smbconf_ctx *ctx); 73 sbcErr (*transaction_cancel)(struct smbconf_ctx *ctx); 74 74 }; 75 75 … … 80 80 }; 81 81 82 WERRORsmbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,82 sbcErr smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx, 83 83 const char *path, struct smbconf_ops *ops); 84 84 85 WERRORsmbconf_add_string_to_array(TALLOC_CTX *mem_ctx,85 sbcErr smbconf_add_string_to_array(TALLOC_CTX *mem_ctx, 86 86 char ***array, 87 87 uint32_t count, -
vendor/current/lib/smbconf/smbconf_txt.c
r414 r740 28 28 #include "includes.h" 29 29 #include "smbconf_private.h" 30 #include "lib/smbconf/smbconf_txt.h" 30 31 31 32 struct txt_cache { … … 60 61 static bool smbconf_txt_do_section(const char *section, void *private_data) 61 62 { 62 WERROR werr;63 sbcErr err; 63 64 uint32_t idx; 64 65 struct txt_private_data *tpd = (struct txt_private_data *)private_data; … … 72 73 } 73 74 74 werr = smbconf_add_string_to_array(cache, &(cache->share_names),75 76 if (! W_ERROR_IS_OK(werr)) {75 err = smbconf_add_string_to_array(cache, &(cache->share_names), 76 cache->num_shares, section); 77 if (!SBC_ERROR_IS_OK(err)) { 77 78 return false; 78 79 } … … 114 115 void *private_data) 115 116 { 116 WERROR werr;117 sbcErr err; 117 118 char **param_names, **param_values; 118 119 uint32_t num_params; … … 146 147 return true; 147 148 } 148 werr = smbconf_add_string_to_array(cache,149 err = smbconf_add_string_to_array(cache, 149 150 &(cache->param_names[cache->current_share]), 150 151 num_params, param_name); 151 if (! W_ERROR_IS_OK(werr)) {152 if (!SBC_ERROR_IS_OK(err)) { 152 153 return false; 153 154 } 154 werr = smbconf_add_string_to_array(cache,155 err = smbconf_add_string_to_array(cache, 155 156 &(cache->param_values[cache->current_share]), 156 157 num_params, param_value); 157 158 cache->num_params[cache->current_share]++; 158 return W_ERROR_IS_OK(werr);159 return SBC_ERROR_IS_OK(err); 159 160 } 160 161 … … 165 166 } 166 167 167 static WERRORsmbconf_txt_init_cache(struct smbconf_ctx *ctx)168 static sbcErr smbconf_txt_init_cache(struct smbconf_ctx *ctx) 168 169 { 169 170 if (pd(ctx)->cache != NULL) { … … 174 175 175 176 if (pd(ctx)->cache == NULL) { 176 return WERR_NOMEM;177 } 178 179 return WERR_OK;180 } 181 182 static WERRORsmbconf_txt_load_file(struct smbconf_ctx *ctx)183 { 184 WERROR werr;177 return SBC_ERR_NOMEM; 178 } 179 180 return SBC_ERR_OK; 181 } 182 183 static sbcErr smbconf_txt_load_file(struct smbconf_ctx *ctx) 184 { 185 sbcErr err; 185 186 uint64_t new_csn; 186 187 187 188 if (!file_exist(ctx->path)) { 188 return WERR_BADFILE;189 return SBC_ERR_BADFILE; 189 190 } 190 191 191 192 new_csn = (uint64_t)file_modtime(ctx->path); 192 193 if (new_csn == pd(ctx)->csn) { 193 return WERR_OK;194 } 195 196 werr = smbconf_txt_init_cache(ctx);197 if (! W_ERROR_IS_OK(werr)) {198 return werr;194 return SBC_ERR_OK; 195 } 196 197 err = smbconf_txt_init_cache(ctx); 198 if (!SBC_ERROR_IS_OK(err)) { 199 return err; 199 200 } 200 201 … … 202 203 smbconf_txt_do_parameter, pd(ctx))) 203 204 { 204 return WERR_CAN_NOT_COMPLETE;205 return SBC_ERR_CAN_NOT_COMPLETE; 205 206 } 206 207 207 208 pd(ctx)->csn = new_csn; 208 209 209 return WERR_OK;210 return SBC_ERR_OK; 210 211 } 211 212 … … 220 221 * initialize the text based smbconf backend 221 222 */ 222 static WERRORsmbconf_txt_init(struct smbconf_ctx *ctx, const char *path)223 static sbcErr smbconf_txt_init(struct smbconf_ctx *ctx, const char *path) 223 224 { 224 225 if (path == NULL) { 225 return WERR_BADFILE;226 return SBC_ERR_BADFILE; 226 227 } 227 228 ctx->path = talloc_strdup(ctx, path); 228 229 if (ctx->path == NULL) { 229 return WERR_NOMEM;230 return SBC_ERR_NOMEM; 230 231 } 231 232 232 233 ctx->data = talloc_zero(ctx, struct txt_private_data); 233 234 if (ctx->data == NULL) { 234 return WERR_NOMEM;235 return SBC_ERR_NOMEM; 235 236 } 236 237 237 238 pd(ctx)->verbatim = true; 238 239 239 return WERR_OK;240 return SBC_ERR_OK; 240 241 } 241 242 … … 256 257 } 257 258 258 static WERRORsmbconf_txt_open(struct smbconf_ctx *ctx)259 static sbcErr smbconf_txt_open(struct smbconf_ctx *ctx) 259 260 { 260 261 return smbconf_txt_load_file(ctx); … … 285 286 * Drop the whole configuration (restarting empty) 286 287 */ 287 static WERRORsmbconf_txt_drop(struct smbconf_ctx *ctx)288 { 289 return WERR_NOT_SUPPORTED;288 static sbcErr smbconf_txt_drop(struct smbconf_ctx *ctx) 289 { 290 return SBC_ERR_NOT_SUPPORTED; 290 291 } 291 292 … … 293 294 * get the list of share names defined in the configuration. 294 295 */ 295 static WERRORsmbconf_txt_get_share_names(struct smbconf_ctx *ctx,296 static sbcErr smbconf_txt_get_share_names(struct smbconf_ctx *ctx, 296 297 TALLOC_CTX *mem_ctx, 297 298 uint32_t *num_shares, … … 301 302 uint32_t added_count = 0; 302 303 TALLOC_CTX *tmp_ctx = NULL; 303 WERROR werr = WERR_OK;304 sbcErr err = SBC_ERR_OK; 304 305 char **tmp_share_names = NULL; 305 306 306 307 if ((num_shares == NULL) || (share_names == NULL)) { 307 werr = WERR_INVALID_PARAM; 308 goto done; 309 } 310 311 werr = smbconf_txt_load_file(ctx); 312 if (!W_ERROR_IS_OK(werr)) { 313 return werr; 308 return SBC_ERR_INVALID_PARAM; 309 } 310 311 err = smbconf_txt_load_file(ctx); 312 if (!SBC_ERROR_IS_OK(err)) { 313 return err; 314 314 } 315 315 … … 320 320 321 321 if (smbconf_share_exists(ctx, NULL)) { 322 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,323 324 if (! W_ERROR_IS_OK(werr)) {322 err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, 323 0, NULL); 324 if (!SBC_ERROR_IS_OK(err)) { 325 325 goto done; 326 326 } … … 329 329 330 330 if (smbconf_share_exists(ctx, GLOBAL_NAME)) { 331 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,331 err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, 332 332 added_count, GLOBAL_NAME); 333 if (! W_ERROR_IS_OK(werr)) {333 if (!SBC_ERROR_IS_OK(err)) { 334 334 goto done; 335 335 } … … 344 344 } 345 345 346 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,346 err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, 347 347 added_count, 348 348 pd(ctx)->cache->share_names[count]); 349 if (! W_ERROR_IS_OK(werr)) {349 if (!SBC_ERROR_IS_OK(err)) { 350 350 goto done; 351 351 } … … 362 362 done: 363 363 talloc_free(tmp_ctx); 364 return werr;364 return err; 365 365 } 366 366 … … 371 371 const char *servicename) 372 372 { 373 WERROR werr;374 375 werr = smbconf_txt_load_file(ctx);376 if (! W_ERROR_IS_OK(werr)) {373 sbcErr err; 374 375 err = smbconf_txt_load_file(ctx); 376 if (!SBC_ERROR_IS_OK(err)) { 377 377 return false; 378 378 } … … 386 386 * Add a service if it does not already exist 387 387 */ 388 static WERRORsmbconf_txt_create_share(struct smbconf_ctx *ctx,388 static sbcErr smbconf_txt_create_share(struct smbconf_ctx *ctx, 389 389 const char *servicename) 390 390 { 391 return WERR_NOT_SUPPORTED;391 return SBC_ERR_NOT_SUPPORTED; 392 392 } 393 393 … … 395 395 * get a definition of a share (service) from configuration. 396 396 */ 397 static WERRORsmbconf_txt_get_share(struct smbconf_ctx *ctx,397 static sbcErr smbconf_txt_get_share(struct smbconf_ctx *ctx, 398 398 TALLOC_CTX *mem_ctx, 399 399 const char *servicename, 400 400 struct smbconf_service **service) 401 401 { 402 WERROR werr;402 sbcErr err; 403 403 uint32_t sidx, count; 404 404 bool found; … … 406 406 struct smbconf_service *tmp_service = NULL; 407 407 408 werr = smbconf_txt_load_file(ctx);409 if (! W_ERROR_IS_OK(werr)) {410 return werr;408 err = smbconf_txt_load_file(ctx); 409 if (!SBC_ERROR_IS_OK(err)) { 410 return err; 411 411 } 412 412 … … 416 416 &sidx); 417 417 if (!found) { 418 return WERR_NO_SUCH_SERVICE;418 return SBC_ERR_NO_SUCH_SERVICE; 419 419 } 420 420 … … 423 423 tmp_service = talloc_zero(tmp_ctx, struct smbconf_service); 424 424 if (tmp_service == NULL) { 425 werr = WERR_NOMEM;425 err = SBC_ERR_NOMEM; 426 426 goto done; 427 427 } … … 430 430 tmp_service->name = talloc_strdup(tmp_service, servicename); 431 431 if (tmp_service->name == NULL) { 432 werr = WERR_NOMEM;432 err = SBC_ERR_NOMEM; 433 433 goto done; 434 434 } … … 436 436 437 437 for (count = 0; count < pd(ctx)->cache->num_params[sidx]; count++) { 438 werr = smbconf_add_string_to_array(tmp_service,438 err = smbconf_add_string_to_array(tmp_service, 439 439 &(tmp_service->param_names), 440 440 count, 441 441 pd(ctx)->cache->param_names[sidx][count]); 442 if (! W_ERROR_IS_OK(werr)) {442 if (!SBC_ERROR_IS_OK(err)) { 443 443 goto done; 444 444 } 445 werr = smbconf_add_string_to_array(tmp_service,445 err = smbconf_add_string_to_array(tmp_service, 446 446 &(tmp_service->param_values), 447 447 count, 448 448 pd(ctx)->cache->param_values[sidx][count]); 449 if (! W_ERROR_IS_OK(werr)) {449 if (!SBC_ERROR_IS_OK(err)) { 450 450 goto done; 451 451 } … … 453 453 454 454 tmp_service->num_params = count; 455 if (count > 0) { 456 *service = talloc_move(mem_ctx, &tmp_service); 457 } else { 458 *service = NULL; 459 } 455 *service = talloc_move(mem_ctx, &tmp_service); 460 456 461 457 done: 462 458 talloc_free(tmp_ctx); 463 return werr;459 return err; 464 460 } 465 461 … … 467 463 * delete a service from configuration 468 464 */ 469 static WERRORsmbconf_txt_delete_share(struct smbconf_ctx *ctx,465 static sbcErr smbconf_txt_delete_share(struct smbconf_ctx *ctx, 470 466 const char *servicename) 471 467 { 472 return WERR_NOT_SUPPORTED;468 return SBC_ERR_NOT_SUPPORTED; 473 469 } 474 470 … … 476 472 * set a configuration parameter to the value provided. 477 473 */ 478 static WERRORsmbconf_txt_set_parameter(struct smbconf_ctx *ctx,474 static sbcErr smbconf_txt_set_parameter(struct smbconf_ctx *ctx, 479 475 const char *service, 480 476 const char *param, 481 477 const char *valstr) 482 478 { 483 return WERR_NOT_SUPPORTED;479 return SBC_ERR_NOT_SUPPORTED; 484 480 } 485 481 … … 487 483 * get the value of a configuration parameter as a string 488 484 */ 489 static WERRORsmbconf_txt_get_parameter(struct smbconf_ctx *ctx,485 static sbcErr smbconf_txt_get_parameter(struct smbconf_ctx *ctx, 490 486 TALLOC_CTX *mem_ctx, 491 487 const char *service, … … 493 489 char **valstr) 494 490 { 495 WERROR werr;491 sbcErr err; 496 492 bool found; 497 493 uint32_t share_index, param_index; 498 494 499 werr = smbconf_txt_load_file(ctx);500 if (! W_ERROR_IS_OK(werr)) {501 return werr;495 err = smbconf_txt_load_file(ctx); 496 if (!SBC_ERROR_IS_OK(err)) { 497 return err; 502 498 } 503 499 … … 507 503 &share_index); 508 504 if (!found) { 509 return WERR_NO_SUCH_SERVICE;505 return SBC_ERR_NO_SUCH_SERVICE; 510 506 } 511 507 … … 515 511 ¶m_index); 516 512 if (!found) { 517 return WERR_INVALID_PARAM;513 return SBC_ERR_INVALID_PARAM; 518 514 } 519 515 … … 522 518 523 519 if (*valstr == NULL) { 524 return WERR_NOMEM;525 } 526 527 return WERR_OK;520 return SBC_ERR_NOMEM; 521 } 522 523 return SBC_ERR_OK; 528 524 } 529 525 … … 531 527 * delete a parameter from configuration 532 528 */ 533 static WERRORsmbconf_txt_delete_parameter(struct smbconf_ctx *ctx,529 static sbcErr smbconf_txt_delete_parameter(struct smbconf_ctx *ctx, 534 530 const char *service, 535 531 const char *param) 536 532 { 537 return WERR_NOT_SUPPORTED;538 } 539 540 static WERRORsmbconf_txt_get_includes(struct smbconf_ctx *ctx,533 return SBC_ERR_NOT_SUPPORTED; 534 } 535 536 static sbcErr smbconf_txt_get_includes(struct smbconf_ctx *ctx, 541 537 TALLOC_CTX *mem_ctx, 542 538 const char *service, … … 544 540 char ***includes) 545 541 { 546 WERROR werr;542 sbcErr err; 547 543 bool found; 548 544 uint32_t sidx, count; … … 551 547 char **tmp_includes = NULL; 552 548 553 werr = smbconf_txt_load_file(ctx);554 if (! W_ERROR_IS_OK(werr)) {555 return werr;549 err = smbconf_txt_load_file(ctx); 550 if (!SBC_ERROR_IS_OK(err)) { 551 return err; 556 552 } 557 553 … … 561 557 &sidx); 562 558 if (!found) { 563 return WERR_NO_SUCH_SERVICE;559 return SBC_ERR_NO_SUCH_SERVICE; 564 560 } 565 561 … … 570 566 "include")) 571 567 { 572 werr = smbconf_add_string_to_array(tmp_ctx,568 err = smbconf_add_string_to_array(tmp_ctx, 573 569 &tmp_includes, 574 570 tmp_num_includes, 575 571 pd(ctx)->cache->param_values[sidx][count]); 576 if (! W_ERROR_IS_OK(werr)) {572 if (!SBC_ERROR_IS_OK(err)) { 577 573 goto done; 578 574 } … … 585 581 *includes = talloc_move(mem_ctx, &tmp_includes); 586 582 if (*includes == NULL) { 587 werr = WERR_NOMEM;583 err = SBC_ERR_NOMEM; 588 584 goto done; 589 585 } … … 592 588 } 593 589 594 werr = WERR_OK;590 err = SBC_ERR_OK; 595 591 596 592 done: 597 593 talloc_free(tmp_ctx); 598 return werr;599 } 600 601 static WERRORsmbconf_txt_set_includes(struct smbconf_ctx *ctx,594 return err; 595 } 596 597 static sbcErr smbconf_txt_set_includes(struct smbconf_ctx *ctx, 602 598 const char *service, 603 599 uint32_t num_includes, 604 600 const char **includes) 605 601 { 606 return WERR_NOT_SUPPORTED;607 } 608 609 static WERRORsmbconf_txt_delete_includes(struct smbconf_ctx *ctx,602 return SBC_ERR_NOT_SUPPORTED; 603 } 604 605 static sbcErr smbconf_txt_delete_includes(struct smbconf_ctx *ctx, 610 606 const char *service) 611 607 { 612 return WERR_NOT_SUPPORTED;613 } 614 615 static WERRORsmbconf_txt_transaction_start(struct smbconf_ctx *ctx)616 { 617 return WERR_OK;618 } 619 620 static WERRORsmbconf_txt_transaction_commit(struct smbconf_ctx *ctx)621 { 622 return WERR_OK;623 } 624 625 static WERRORsmbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)626 { 627 return WERR_OK;608 return SBC_ERR_NOT_SUPPORTED; 609 } 610 611 static sbcErr smbconf_txt_transaction_start(struct smbconf_ctx *ctx) 612 { 613 return SBC_ERR_OK; 614 } 615 616 static sbcErr smbconf_txt_transaction_commit(struct smbconf_ctx *ctx) 617 { 618 return SBC_ERR_OK; 619 } 620 621 static sbcErr smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx) 622 { 623 return SBC_ERR_OK; 628 624 } 629 625 … … 658 654 * the only function that is exported from this module 659 655 */ 660 WERRORsmbconf_init_txt(TALLOC_CTX *mem_ctx,656 sbcErr smbconf_init_txt(TALLOC_CTX *mem_ctx, 661 657 struct smbconf_ctx **conf_ctx, 662 658 const char *path) 663 659 { 664 WERROR werr;665 666 werr = smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_txt);667 if (! W_ERROR_IS_OK(werr)) {668 return werr;660 sbcErr err; 661 662 err = smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_txt); 663 if (!SBC_ERROR_IS_OK(err)) { 664 return err; 669 665 } 670 666 -
vendor/current/lib/smbconf/smbconf_txt.h
r414 r740 27 27 */ 28 28 29 WERRORsmbconf_init_txt(TALLOC_CTX *mem_ctx,29 sbcErr smbconf_init_txt(TALLOC_CTX *mem_ctx, 30 30 struct smbconf_ctx **conf_ctx, 31 31 const char *path); -
vendor/current/lib/smbconf/smbconf_util.c
r414 r740 40 40 * should be called. 41 41 */ 42 WERRORsmbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,42 sbcErr smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx, 43 43 const char *path, struct smbconf_ops *ops) 44 44 { 45 WERROR werr = WERR_OK;45 sbcErr err = SBC_ERR_OK; 46 46 struct smbconf_ctx *ctx; 47 47 48 48 if (conf_ctx == NULL) { 49 return WERR_INVALID_PARAM;49 return SBC_ERR_INVALID_PARAM; 50 50 } 51 51 52 52 ctx = talloc_zero(mem_ctx, struct smbconf_ctx); 53 53 if (ctx == NULL) { 54 return WERR_NOMEM;54 return SBC_ERR_NOMEM; 55 55 } 56 56 57 57 ctx->ops = ops; 58 58 59 werr = ctx->ops->init(ctx, path);60 if (! W_ERROR_IS_OK(werr)) {59 err = ctx->ops->init(ctx, path); 60 if (!SBC_ERROR_IS_OK(err)) { 61 61 goto fail; 62 62 } … … 65 65 66 66 *conf_ctx = ctx; 67 return werr;67 return err; 68 68 69 69 fail: 70 70 talloc_free(ctx); 71 return werr;71 return err; 72 72 } 73 73 … … 76 76 * add a string to a talloced array of strings. 77 77 */ 78 WERRORsmbconf_add_string_to_array(TALLOC_CTX *mem_ctx,78 sbcErr smbconf_add_string_to_array(TALLOC_CTX *mem_ctx, 79 79 char ***array, 80 80 uint32_t count, … … 84 84 85 85 if (array == NULL) { 86 return WERR_INVALID_PARAM;86 return SBC_ERR_INVALID_PARAM; 87 87 } 88 88 89 89 new_array = talloc_realloc(mem_ctx, *array, char *, count + 1); 90 90 if (new_array == NULL) { 91 return WERR_NOMEM;91 return SBC_ERR_NOMEM; 92 92 } 93 93 … … 98 98 if (new_array[count] == NULL) { 99 99 talloc_free(new_array); 100 return WERR_NOMEM;100 return SBC_ERR_NOMEM; 101 101 } 102 102 } … … 104 104 *array = new_array; 105 105 106 return WERR_OK;106 return SBC_ERR_OK; 107 107 } 108 108 -
vendor/current/lib/socket_wrapper/socket_wrapper.c
r414 r740 297 297 case SOCKET_TYPE_CHAR_TCP: 298 298 case SOCKET_TYPE_CHAR_UDP: { 299 struct sockaddr_in *in2 = (struct sockaddr_in *) in;300 299 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in; 300 301 301 if ((*len) < sizeof(*in2)) { 302 302 errno = EINVAL; … … 315 315 case SOCKET_TYPE_CHAR_TCP_V6: 316 316 case SOCKET_TYPE_CHAR_UDP_V6: { 317 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *) in;318 317 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in; 318 319 319 if ((*len) < sizeof(*in2)) { 320 320 errno = EINVAL; … … 353 353 case AF_INET: { 354 354 const struct sockaddr_in *in = 355 (const struct sockaddr_in *) inaddr;355 (const struct sockaddr_in *)(const void *)inaddr; 356 356 unsigned int addr = ntohl(in->sin_addr.s_addr); 357 357 char u_type = '\0'; … … 396 396 case AF_INET6: { 397 397 const struct sockaddr_in6 *in = 398 (const struct sockaddr_in6 *) inaddr;399 struct in6_addr cmp ;398 (const struct sockaddr_in6 *)(const void *)inaddr; 399 struct in6_addr cmp1, cmp2; 400 400 401 401 switch (si->type) { … … 412 412 prt = ntohs(in->sin6_port); 413 413 414 cmp = in->sin6_addr; 415 cmp.s6_addr[15] = 0; 416 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) { 414 cmp1 = *swrap_ipv6(); 415 cmp2 = in->sin6_addr; 416 cmp2.s6_addr[15] = 0; 417 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) { 417 418 iface = in->sin6_addr.s6_addr[15]; 418 419 } else { … … 461 462 case AF_INET: { 462 463 const struct sockaddr_in *in = 463 (const struct sockaddr_in *) inaddr;464 (const struct sockaddr_in *)(const void *)inaddr; 464 465 unsigned int addr = ntohl(in->sin_addr.s_addr); 465 466 char u_type = '\0'; … … 512 513 case AF_INET6: { 513 514 const struct sockaddr_in6 *in = 514 (const struct sockaddr_in6 *) inaddr;515 struct in6_addr cmp ;515 (const struct sockaddr_in6 *)(const void *)inaddr; 516 struct in6_addr cmp1, cmp2; 516 517 517 518 switch (si->type) { … … 528 529 prt = ntohs(in->sin6_port); 529 530 530 cmp = in->sin6_addr; 531 cmp.s6_addr[15] = 0; 531 cmp1 = *swrap_ipv6(); 532 cmp2 = in->sin6_addr; 533 cmp2.s6_addr[15] = 0; 532 534 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) { 533 535 iface = socket_wrapper_default_iface(); 534 } else if (IN6_ARE_ADDR_EQUAL( swrap_ipv6(), &cmp)) {536 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) { 535 537 iface = in->sin6_addr.s6_addr[15]; 536 538 } else { … … 585 587 struct sockaddr_un *out_addr, int alloc_sock, int *bcast) 586 588 { 589 struct sockaddr *out = (struct sockaddr *)(void *)out_addr; 587 590 if (!out_addr) 588 591 return 0; 589 592 590 out_addr->sun_family = AF_UNIX; 593 out->sa_family = AF_UNIX; 594 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 595 out->sa_len = sizeof(*out_addr); 596 #endif 591 597 592 598 switch (in_addr->sa_family) { … … 611 617 break; 612 618 } 613 619 614 620 errno = EAFNOSUPPORT; 615 621 return -1; … … 623 629 socklen_t *out_addrlen) 624 630 { 631 int ret; 632 625 633 if (out_addr == NULL || out_addrlen == NULL) 626 634 return 0; … … 644 652 return -1; 645 653 } 646 return convert_un_in(in_addr, out_addr, out_addrlen); 654 ret = convert_un_in(in_addr, out_addr, out_addrlen); 655 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 656 out_addr->sa_len = *out_addrlen; 657 #endif 658 return ret; 647 659 default: 648 660 break; … … 960 972 ip->v6.flow_label_high = 0x00; 961 973 ip->v6.flow_label_low = 0x0000; 962 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); //TODO974 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */ 963 975 ip->v6.next_header = protocol; 964 976 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16); … … 1010 1022 ip->v6.flow_label_high = 0x00; 1011 1023 ip->v6.flow_label_low = 0x0000; 1012 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); //TODO1024 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */ 1013 1025 ip->v6.next_header = protocol; 1014 1026 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16); … … 1495 1507 memset(&un_my_addr, 0, sizeof(un_my_addr)); 1496 1508 1497 ret = real_accept(s, (struct sockaddr *) &un_addr, &un_addrlen);1509 ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen); 1498 1510 if (ret == -1) { 1499 1511 free(my_addr); … … 1527 1539 1528 1540 if (addr != NULL && addrlen != NULL) { 1529 *addrlen = len; 1530 if (*addrlen >= len) 1531 memcpy(addr, my_addr, len); 1532 *addrlen = 0; 1533 } 1534 1535 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); 1541 size_t copy_len = MIN(*addrlen, len); 1542 if (copy_len > 0) { 1543 memcpy(addr, my_addr, copy_len); 1544 } 1545 *addrlen = len; 1546 } 1547 1548 ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr, 1549 &un_my_addrlen); 1536 1550 if (ret == -1) { 1537 1551 free(child_si); … … 1660 1674 type, socket_wrapper_default_iface(), port); 1661 1675 if (stat(un_addr.sun_path, &st) == 0) continue; 1662 1663 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); 1676 1677 ret = real_bind(si->fd, (struct sockaddr *)(void *)&un_addr, 1678 sizeof(un_addr)); 1664 1679 if (ret == -1) return ret; 1665 1680 … … 1686 1701 struct sockaddr_un un_addr; 1687 1702 struct socket_info *si = find_socket_info(s); 1703 int bcast = 0; 1688 1704 1689 1705 if (!si) { … … 1701 1717 } 1702 1718 1703 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); 1719 ret = sockaddr_convert_to_un(si, serv_addr, 1720 addrlen, &un_addr, 0, &bcast); 1704 1721 if (ret == -1) return -1; 1722 1723 if (bcast) { 1724 errno = ENETUNREACH; 1725 return -1; 1726 } 1705 1727 1706 1728 if (si->type == SOCK_DGRAM) { … … 1710 1732 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); 1711 1733 1712 ret = real_connect(s, (struct sockaddr *) &un_addr,1734 ret = real_connect(s, (struct sockaddr *)(void *)&un_addr, 1713 1735 sizeof(struct sockaddr_un)); 1714 1736 } … … 1746 1768 si->myname = sockaddr_dup(myaddr, addrlen); 1747 1769 1748 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);1770 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast); 1749 1771 if (ret == -1) return -1; 1750 1772 1751 1773 unlink(un_addr.sun_path); 1752 1774 1753 ret = real_bind(s, (struct sockaddr *) &un_addr,1775 ret = real_bind(s, (struct sockaddr *)(void *)&un_addr, 1754 1776 sizeof(struct sockaddr_un)); 1755 1777 … … 1848 1870 return -1; 1849 1871 } 1850 }1851 1852 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)1853 {1854 struct sockaddr_un un_addr;1855 socklen_t un_addrlen = sizeof(un_addr);1856 int ret;1857 struct socket_info *si = find_socket_info(s);1858 struct sockaddr_storage ss;1859 socklen_t ss_len = sizeof(ss);1860 1861 if (!si) {1862 return real_recvfrom(s, buf, len, flags, from, fromlen);1863 }1864 1865 if (!from) {1866 from = (struct sockaddr *)&ss;1867 fromlen = &ss_len;1868 }1869 1870 if (si->type == SOCK_STREAM) {1871 /* cut down to 1500 byte packets for stream sockets,1872 * which makes it easier to format PCAP capture files1873 * (as the caller will simply continue from here) */1874 len = MIN(len, 1500);1875 }1876 1877 /* irix 6.4 forgets to null terminate the sun_path string :-( */1878 memset(&un_addr, 0, sizeof(un_addr));1879 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);1880 if (ret == -1)1881 return ret;1882 1883 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,1884 si->family, from, fromlen) == -1) {1885 return -1;1886 }1887 1888 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);1889 1890 return ret;1891 }1892 1893 1894 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)1895 {1896 struct sockaddr_un un_addr;1897 int ret;1898 struct socket_info *si = find_socket_info(s);1899 int bcast = 0;1900 1901 if (!si) {1902 return real_sendto(s, buf, len, flags, to, tolen);1903 }1904 1905 if (si->connected) {1906 if (to) {1907 errno = EISCONN;1908 return -1;1909 }1910 1911 to = si->peername;1912 tolen = si->peername_len;1913 }1914 1915 switch (si->type) {1916 case SOCK_STREAM:1917 /* cut down to 1500 byte packets for stream sockets,1918 * which makes it easier to format PCAP capture files1919 * (as the caller will simply continue from here) */1920 len = MIN(len, 1500);1921 1922 ret = real_send(s, buf, len, flags);1923 break;1924 case SOCK_DGRAM:1925 if (si->bound == 0) {1926 ret = swrap_auto_bind(si, si->family);1927 if (ret == -1) return -1;1928 }1929 1930 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);1931 if (ret == -1) return -1;1932 1933 if (bcast) {1934 struct stat st;1935 unsigned int iface;1936 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);1937 char type;1938 1939 type = SOCKET_TYPE_CHAR_UDP;1940 1941 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {1942 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,1943 socket_wrapper_dir(), type, iface, prt);1944 if (stat(un_addr.sun_path, &st) != 0) continue;1945 1946 /* ignore the any errors in broadcast sends */1947 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));1948 }1949 1950 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);1951 1952 return len;1953 }1954 1955 if (si->defer_connect) {1956 ret = real_connect(s, (struct sockaddr *)&un_addr,1957 sizeof(un_addr));1958 1959 /* to give better errors */1960 if (ret == -1 && errno == ENOENT) {1961 errno = EHOSTUNREACH;1962 }1963 1964 if (ret == -1) {1965 return ret;1966 }1967 si->defer_connect = 0;1968 }1969 1970 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));1971 break;1972 default:1973 ret = -1;1974 errno = EHOSTUNREACH;1975 break;1976 }1977 1978 /* to give better errors */1979 if (ret == -1 && errno == ENOENT) {1980 errno = EHOSTUNREACH;1981 }1982 1983 if (ret == -1) {1984 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);1985 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);1986 } else {1987 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);1988 }1989 1990 return ret;1991 1872 } 1992 1873 … … 2017 1898 } 2018 1899 1900 static ssize_t swrap_sendmsg_before(struct socket_info *si, 1901 struct msghdr *msg, 1902 struct iovec *tmp_iov, 1903 struct sockaddr_un *tmp_un, 1904 const struct sockaddr_un **to_un, 1905 const struct sockaddr **to, 1906 int *bcast) 1907 { 1908 size_t i, len = 0; 1909 ssize_t ret; 1910 1911 if (to_un) { 1912 *to_un = NULL; 1913 } 1914 if (to) { 1915 *to = NULL; 1916 } 1917 if (bcast) { 1918 *bcast = 0; 1919 } 1920 1921 switch (si->type) { 1922 case SOCK_STREAM: 1923 if (!si->connected) { 1924 errno = ENOTCONN; 1925 return -1; 1926 } 1927 1928 if (msg->msg_iovlen == 0) { 1929 break; 1930 } 1931 1932 /* 1933 * cut down to 1500 byte packets for stream sockets, 1934 * which makes it easier to format PCAP capture files 1935 * (as the caller will simply continue from here) 1936 */ 1937 1938 for (i=0; i < msg->msg_iovlen; i++) { 1939 size_t nlen; 1940 nlen = len + msg->msg_iov[i].iov_len; 1941 if (nlen > 1500) { 1942 break; 1943 } 1944 } 1945 msg->msg_iovlen = i; 1946 if (msg->msg_iovlen == 0) { 1947 *tmp_iov = msg->msg_iov[0]; 1948 tmp_iov->iov_len = MIN(tmp_iov->iov_len, 1500); 1949 msg->msg_iov = tmp_iov; 1950 msg->msg_iovlen = 1; 1951 } 1952 break; 1953 1954 case SOCK_DGRAM: 1955 if (si->connected) { 1956 if (msg->msg_name) { 1957 errno = EISCONN; 1958 return -1; 1959 } 1960 } else { 1961 const struct sockaddr *msg_name; 1962 msg_name = (const struct sockaddr *)msg->msg_name; 1963 1964 if (msg_name == NULL) { 1965 errno = ENOTCONN; 1966 return -1; 1967 } 1968 1969 1970 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen, 1971 tmp_un, 0, bcast); 1972 if (ret == -1) return -1; 1973 1974 if (to_un) { 1975 *to_un = tmp_un; 1976 } 1977 if (to) { 1978 *to = msg_name; 1979 } 1980 msg->msg_name = tmp_un; 1981 msg->msg_namelen = sizeof(*tmp_un); 1982 } 1983 1984 if (si->bound == 0) { 1985 ret = swrap_auto_bind(si, si->family); 1986 if (ret == -1) return -1; 1987 } 1988 1989 if (!si->defer_connect) { 1990 break; 1991 } 1992 1993 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len, 1994 tmp_un, 0, NULL); 1995 if (ret == -1) return -1; 1996 1997 ret = real_connect(si->fd, (struct sockaddr *)(void *)tmp_un, 1998 sizeof(*tmp_un)); 1999 2000 /* to give better errors */ 2001 if (ret == -1 && errno == ENOENT) { 2002 errno = EHOSTUNREACH; 2003 } 2004 2005 if (ret == -1) { 2006 return ret; 2007 } 2008 2009 si->defer_connect = 0; 2010 break; 2011 default: 2012 errno = EHOSTUNREACH; 2013 return -1; 2014 } 2015 2016 return 0; 2017 } 2018 2019 static void swrap_sendmsg_after(struct socket_info *si, 2020 struct msghdr *msg, 2021 const struct sockaddr *to, 2022 ssize_t ret) 2023 { 2024 int saved_errno = errno; 2025 size_t i, len = 0; 2026 uint8_t *buf; 2027 off_t ofs = 0; 2028 size_t avail = 0; 2029 size_t remain; 2030 2031 /* to give better errors */ 2032 if (ret == -1 && saved_errno == ENOENT) { 2033 saved_errno = EHOSTUNREACH; 2034 } 2035 2036 for (i=0; i < msg->msg_iovlen; i++) { 2037 avail += msg->msg_iov[i].iov_len; 2038 } 2039 2040 if (ret == -1) { 2041 remain = MIN(80, avail); 2042 } else { 2043 remain = ret; 2044 } 2045 2046 /* we capture it as one single packet */ 2047 buf = (uint8_t *)malloc(remain); 2048 if (!buf) { 2049 /* we just not capture the packet */ 2050 errno = saved_errno; 2051 return; 2052 } 2053 2054 for (i=0; i < msg->msg_iovlen; i++) { 2055 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len); 2056 memcpy(buf + ofs, 2057 msg->msg_iov[i].iov_base, 2058 this_time); 2059 ofs += this_time; 2060 remain -= this_time; 2061 } 2062 len = ofs; 2063 2064 switch (si->type) { 2065 case SOCK_STREAM: 2066 if (ret == -1) { 2067 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); 2068 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); 2069 } else { 2070 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); 2071 } 2072 break; 2073 2074 case SOCK_DGRAM: 2075 if (si->connected) { 2076 to = si->peername; 2077 } 2078 if (ret == -1) { 2079 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 2080 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len); 2081 } else { 2082 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 2083 } 2084 break; 2085 } 2086 2087 free(buf); 2088 errno = saved_errno; 2089 } 2090 2091 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) 2092 { 2093 struct sockaddr_un un_addr; 2094 socklen_t un_addrlen = sizeof(un_addr); 2095 int ret; 2096 struct socket_info *si = find_socket_info(s); 2097 struct sockaddr_storage ss; 2098 socklen_t ss_len = sizeof(ss); 2099 2100 if (!si) { 2101 return real_recvfrom(s, buf, len, flags, from, fromlen); 2102 } 2103 2104 if (!from) { 2105 from = (struct sockaddr *)(void *)&ss; 2106 fromlen = &ss_len; 2107 } 2108 2109 if (si->type == SOCK_STREAM) { 2110 /* cut down to 1500 byte packets for stream sockets, 2111 * which makes it easier to format PCAP capture files 2112 * (as the caller will simply continue from here) */ 2113 len = MIN(len, 1500); 2114 } 2115 2116 /* irix 6.4 forgets to null terminate the sun_path string :-( */ 2117 memset(&un_addr, 0, sizeof(un_addr)); 2118 ret = real_recvfrom(s, buf, len, flags, 2119 (struct sockaddr *)(void *)&un_addr, &un_addrlen); 2120 if (ret == -1) 2121 return ret; 2122 2123 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, 2124 si->family, from, fromlen) == -1) { 2125 return -1; 2126 } 2127 2128 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret); 2129 2130 return ret; 2131 } 2132 2133 2134 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) 2135 { 2136 struct msghdr msg; 2137 struct iovec tmp; 2138 struct sockaddr_un un_addr; 2139 const struct sockaddr_un *to_un = NULL; 2140 ssize_t ret; 2141 struct socket_info *si = find_socket_info(s); 2142 int bcast = 0; 2143 2144 if (!si) { 2145 return real_sendto(s, buf, len, flags, to, tolen); 2146 } 2147 2148 tmp.iov_base = discard_const_p(char, buf); 2149 tmp.iov_len = len; 2150 2151 ZERO_STRUCT(msg); 2152 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */ 2153 msg.msg_namelen = tolen; /* size of address */ 2154 msg.msg_iov = &tmp; /* scatter/gather array */ 2155 msg.msg_iovlen = 1; /* # elements in msg_iov */ 2156 #if 0 /* not available on solaris */ 2157 msg.msg_control = NULL; /* ancillary data, see below */ 2158 msg.msg_controllen = 0; /* ancillary data buffer len */ 2159 msg.msg_flags = 0; /* flags on received message */ 2160 #endif 2161 2162 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); 2163 if (ret == -1) return -1; 2164 2165 buf = msg.msg_iov[0].iov_base; 2166 len = msg.msg_iov[0].iov_len; 2167 2168 if (bcast) { 2169 struct stat st; 2170 unsigned int iface; 2171 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); 2172 char type; 2173 2174 type = SOCKET_TYPE_CHAR_UDP; 2175 2176 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { 2177 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 2178 socket_wrapper_dir(), type, iface, prt); 2179 if (stat(un_addr.sun_path, &st) != 0) continue; 2180 2181 /* ignore the any errors in broadcast sends */ 2182 real_sendto(s, buf, len, flags, 2183 (struct sockaddr *)(void *)&un_addr, 2184 sizeof(un_addr)); 2185 } 2186 2187 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 2188 2189 return len; 2190 } 2191 2192 ret = real_sendto(s, buf, len, flags, msg.msg_name, msg.msg_namelen); 2193 2194 swrap_sendmsg_after(si, &msg, to, ret); 2195 2196 return ret; 2197 } 2198 2019 2199 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags) 2020 2200 { … … 2076 2256 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) 2077 2257 { 2078 int ret; 2258 struct msghdr msg; 2259 struct iovec tmp; 2260 struct sockaddr_un un_addr; 2261 ssize_t ret; 2079 2262 struct socket_info *si = find_socket_info(s); 2080 2263 … … 2083 2266 } 2084 2267 2085 if (si->type == SOCK_STREAM) { 2086 /* cut down to 1500 byte packets for stream sockets, 2087 * which makes it easier to format PCAP capture files 2088 * (as the caller will simply continue from here) */ 2089 len = MIN(len, 1500); 2090 } 2091 2092 if (si->defer_connect) { 2093 struct sockaddr_un un_addr; 2094 int bcast = 0; 2095 2096 if (si->bound == 0) { 2097 ret = swrap_auto_bind(si, si->family); 2098 if (ret == -1) return -1; 2099 } 2100 2101 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len, 2102 &un_addr, 0, &bcast); 2103 if (ret == -1) return -1; 2104 2105 ret = real_connect(s, (struct sockaddr *)&un_addr, 2106 sizeof(un_addr)); 2107 2108 /* to give better errors */ 2109 if (ret == -1 && errno == ENOENT) { 2110 errno = EHOSTUNREACH; 2111 } 2112 2113 if (ret == -1) { 2114 return ret; 2115 } 2116 si->defer_connect = 0; 2117 } 2268 tmp.iov_base = discard_const_p(char, buf); 2269 tmp.iov_len = len; 2270 2271 ZERO_STRUCT(msg); 2272 msg.msg_name = NULL; /* optional address */ 2273 msg.msg_namelen = 0; /* size of address */ 2274 msg.msg_iov = &tmp; /* scatter/gather array */ 2275 msg.msg_iovlen = 1; /* # elements in msg_iov */ 2276 #if 0 /* not available on solaris */ 2277 msg.msg_control = NULL; /* ancillary data, see below */ 2278 msg.msg_controllen = 0; /* ancillary data buffer len */ 2279 msg.msg_flags = 0; /* flags on received message */ 2280 #endif 2281 2282 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL); 2283 if (ret == -1) return -1; 2284 2285 buf = msg.msg_iov[0].iov_base; 2286 len = msg.msg_iov[0].iov_len; 2118 2287 2119 2288 ret = real_send(s, buf, len, flags); 2120 2289 2121 if (ret == -1) { 2122 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); 2123 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); 2124 } else { 2125 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); 2126 } 2290 swrap_sendmsg_after(si, &msg, NULL, ret); 2127 2291 2128 2292 return ret; 2129 2293 } 2130 2294 2131 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr * msg, int flags)2132 { 2133 int ret;2134 uint8_t *buf;2135 off_t ofs = 0;2136 size_t i;2137 size_t remain;2138 2295 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags) 2296 { 2297 struct msghdr msg; 2298 struct iovec tmp; 2299 struct sockaddr_un un_addr; 2300 const struct sockaddr_un *to_un = NULL; 2301 const struct sockaddr *to = NULL; 2302 ssize_t ret; 2139 2303 struct socket_info *si = find_socket_info(s); 2304 int bcast = 0; 2140 2305 2141 2306 if (!si) { 2142 return real_sendmsg(s, msg, flags); 2143 } 2144 2145 if (si->defer_connect) { 2146 struct sockaddr_un un_addr; 2147 int bcast = 0; 2148 2149 if (si->bound == 0) { 2150 ret = swrap_auto_bind(si, si->family); 2151 if (ret == -1) return -1; 2152 } 2153 2154 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len, 2155 &un_addr, 0, &bcast); 2156 if (ret == -1) return -1; 2157 2158 ret = real_connect(s, (struct sockaddr *)&un_addr, 2159 sizeof(un_addr)); 2160 2161 /* to give better errors */ 2162 if (ret == -1 && errno == ENOENT) { 2163 errno = EHOSTUNREACH; 2164 } 2165 2166 if (ret == -1) { 2167 return ret; 2168 } 2169 si->defer_connect = 0; 2170 } 2171 2172 ret = real_sendmsg(s, msg, flags); 2173 remain = ret; 2174 2175 /* we capture it as one single packet */ 2176 buf = (uint8_t *)malloc(ret); 2177 if (!buf) { 2178 /* we just not capture the packet */ 2179 errno = 0; 2180 return ret; 2181 } 2182 2183 for (i=0; i < msg->msg_iovlen; i++) { 2184 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len); 2185 memcpy(buf + ofs, 2186 msg->msg_iov[i].iov_base, 2187 this_time); 2188 ofs += this_time; 2189 remain -= this_time; 2190 } 2191 2192 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); 2193 free(buf); 2194 if (ret == -1) { 2195 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); 2196 } 2307 return real_sendmsg(s, omsg, flags); 2308 } 2309 2310 tmp.iov_base = NULL; 2311 tmp.iov_len = 0; 2312 2313 msg = *omsg; 2314 #if 0 2315 msg.msg_name = omsg->msg_name; /* optional address */ 2316 msg.msg_namelen = omsg->msg_namelen; /* size of address */ 2317 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */ 2318 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */ 2319 /* the following is not available on solaris */ 2320 msg.msg_control = omsg->msg_control; /* ancillary data, see below */ 2321 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */ 2322 msg.msg_flags = omsg->msg_flags; /* flags on received message */ 2323 #endif 2324 2325 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); 2326 if (ret == -1) return -1; 2327 2328 if (bcast) { 2329 struct stat st; 2330 unsigned int iface; 2331 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); 2332 char type; 2333 size_t i, len = 0; 2334 uint8_t *buf; 2335 off_t ofs = 0; 2336 size_t avail = 0; 2337 size_t remain; 2338 2339 for (i=0; i < msg.msg_iovlen; i++) { 2340 avail += msg.msg_iov[i].iov_len; 2341 } 2342 2343 len = avail; 2344 remain = avail; 2345 2346 /* we capture it as one single packet */ 2347 buf = (uint8_t *)malloc(remain); 2348 if (!buf) { 2349 return -1; 2350 } 2351 2352 for (i=0; i < msg.msg_iovlen; i++) { 2353 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len); 2354 memcpy(buf + ofs, 2355 msg.msg_iov[i].iov_base, 2356 this_time); 2357 ofs += this_time; 2358 remain -= this_time; 2359 } 2360 2361 type = SOCKET_TYPE_CHAR_UDP; 2362 2363 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { 2364 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 2365 socket_wrapper_dir(), type, iface, prt); 2366 if (stat(un_addr.sun_path, &st) != 0) continue; 2367 2368 msg.msg_name = &un_addr; /* optional address */ 2369 msg.msg_namelen = sizeof(un_addr); /* size of address */ 2370 2371 /* ignore the any errors in broadcast sends */ 2372 real_sendmsg(s, &msg, flags); 2373 } 2374 2375 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 2376 free(buf); 2377 2378 return len; 2379 } 2380 2381 ret = real_sendmsg(s, &msg, flags); 2382 2383 swrap_sendmsg_after(si, &msg, to, ret); 2197 2384 2198 2385 return ret; … … 2207 2394 if (!si) { 2208 2395 return real_readv(s, vector, count); 2396 } 2397 2398 if (!si->connected) { 2399 errno = ENOTCONN; 2400 return -1; 2209 2401 } 2210 2402 … … 2214 2406 * (as the caller will simply continue from here) */ 2215 2407 size_t i, len = 0; 2216 2408 2217 2409 for (i=0; i < count; i++) { 2218 2410 size_t nlen; … … 2268 2460 int swrap_writev(int s, const struct iovec *vector, size_t count) 2269 2461 { 2270 int ret; 2462 struct msghdr msg; 2463 struct iovec tmp; 2464 struct sockaddr_un un_addr; 2465 ssize_t ret; 2271 2466 struct socket_info *si = find_socket_info(s); 2272 struct iovec v;2273 2467 2274 2468 if (!si) { … … 2276 2470 } 2277 2471 2278 if (si->type == SOCK_STREAM && count > 0) { 2279 /* cut down to 1500 byte packets for stream sockets, 2280 * which makes it easier to format PCAP capture files 2281 * (as the caller will simply continue from here) */ 2282 size_t i, len = 0; 2283 2284 for (i=0; i < count; i++) { 2285 size_t nlen; 2286 nlen = len + vector[i].iov_len; 2287 if (nlen > 1500) { 2288 break; 2289 } 2290 } 2291 count = i; 2292 if (count == 0) { 2293 v = vector[0]; 2294 v.iov_len = MIN(v.iov_len, 1500); 2295 vector = &v; 2296 count = 1; 2297 } 2298 } 2299 2300 ret = real_writev(s, vector, count); 2301 if (ret == -1) { 2302 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); 2303 } else { 2304 uint8_t *buf; 2305 off_t ofs = 0; 2306 size_t i; 2307 size_t remain = ret; 2308 2309 /* we capture it as one single packet */ 2310 buf = (uint8_t *)malloc(ret); 2311 if (!buf) { 2312 /* we just not capture the packet */ 2313 errno = 0; 2314 return ret; 2315 } 2316 2317 for (i=0; i < count; i++) { 2318 size_t this_time = MIN(remain, vector[i].iov_len); 2319 memcpy(buf + ofs, 2320 vector[i].iov_base, 2321 this_time); 2322 ofs += this_time; 2323 remain -= this_time; 2324 } 2325 2326 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); 2327 free(buf); 2328 } 2472 tmp.iov_base = NULL; 2473 tmp.iov_len = 0; 2474 2475 ZERO_STRUCT(msg); 2476 msg.msg_name = NULL; /* optional address */ 2477 msg.msg_namelen = 0; /* size of address */ 2478 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */ 2479 msg.msg_iovlen = count; /* # elements in msg_iov */ 2480 #if 0 /* not available on solaris */ 2481 msg.msg_control = NULL; /* ancillary data, see below */ 2482 msg.msg_controllen = 0; /* ancillary data buffer len */ 2483 msg.msg_flags = 0; /* flags on received message */ 2484 #endif 2485 2486 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL); 2487 if (ret == -1) return -1; 2488 2489 ret = real_writev(s, msg.msg_iov, msg.msg_iovlen); 2490 2491 swrap_sendmsg_after(si, &msg, NULL, ret); 2329 2492 2330 2493 return ret; -
vendor/current/lib/socket_wrapper/socket_wrapper.h
r414 r740 51 51 ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); 52 52 ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags); 53 ssize_t swrap_recvmsg(int s, struct msghdr *msg, int flags); 53 54 int swrap_ioctl(int s, int req, void *ptr); 54 55 ssize_t swrap_recv(int s, void *buf, size_t len, int flags); … … 116 117 #define sendmsg(s,msg,flags) swrap_sendmsg(s,msg,flags) 117 118 119 #ifdef recvmsg 120 #undef recvmsg 121 #endif 122 #define recvmsg(s,msg,flags) swrap_recvmsg(s,msg,flags) 123 118 124 #ifdef ioctl 119 125 #undef ioctl -
vendor/current/lib/socket_wrapper/testsuite.c
r414 r740 96 96 { 97 97 struct torture_suite *suite = torture_suite_create(mem_ctx, 98 " SOCKET-WRAPPER");98 "socket-wrapper"); 99 99 100 100 torture_suite_add_simple_test(suite, "socket_wrapper_dir", test_socket_wrapper_dir); -
vendor/current/lib/subunit/python/subunit/__init__.py
r414 r740 1 1 # 2 # subunit: extensions to python unittest to get test results from subprocesses.2 # subunit: extensions to Python unittest to get test results from subprocesses. 3 3 # Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> 4 # Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>5 4 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; either version 3 of the License, or 9 # (at your option) any later version. 5 # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause 6 # license at the users choice. A copy of both licenses are available in the 7 # project source as Apache-2.0 and BSD. You may not use this file except in 8 # compliance with one of these two licences. 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT 12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 # license you chose for the specific language governing permissions and 14 # limitations under that license. 10 15 # 11 # This program is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 # GNU General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 # 20 16 17 """Subunit - a streaming test protocol 18 19 Overview 20 ++++++++ 21 22 The ``subunit`` Python package provides a number of ``unittest`` extensions 23 which can be used to cause tests to output Subunit, to parse Subunit streams 24 into test activity, perform seamless test isolation within a regular test 25 case and variously sort, filter and report on test runs. 26 27 28 Key Classes 29 ----------- 30 31 The ``subunit.TestProtocolClient`` class is a ``unittest.TestResult`` 32 extension which will translate a test run into a Subunit stream. 33 34 The ``subunit.ProtocolTestCase`` class is an adapter between the Subunit wire 35 protocol and the ``unittest.TestCase`` object protocol. It is used to translate 36 a stream into a test run, which regular ``unittest.TestResult`` objects can 37 process and report/inspect. 38 39 Subunit has support for non-blocking usage too, for use with asyncore or 40 Twisted. See the ``TestProtocolServer`` parser class for more details. 41 42 Subunit includes extensions to the Python ``TestResult`` protocol. These are 43 all done in a compatible manner: ``TestResult`` objects that do not implement 44 the extension methods will not cause errors to be raised, instead the extension 45 will either lose fidelity (for instance, folding expected failures to success 46 in Python versions < 2.7 or 3.1), or discard the extended data (for extra 47 details, tags, timestamping and progress markers). 48 49 The test outcome methods ``addSuccess``, ``addError``, ``addExpectedFailure``, 50 ``addFailure``, ``addSkip`` take an optional keyword parameter ``details`` 51 which can be used instead of the usual python unittest parameter. 52 When used the value of details should be a dict from ``string`` to 53 ``testtools.content.Content`` objects. This is a draft API being worked on with 54 the Python Testing In Python mail list, with the goal of permitting a common 55 way to provide additional data beyond a traceback, such as captured data from 56 disk, logging messages etc. The reference for this API is in testtools (0.9.0 57 and newer). 58 59 The ``tags(new_tags, gone_tags)`` method is called (if present) to add or 60 remove tags in the test run that is currently executing. If called when no 61 test is in progress (that is, if called outside of the ``startTest``, 62 ``stopTest`` pair), the the tags apply to all sebsequent tests. If called 63 when a test is in progress, then the tags only apply to that test. 64 65 The ``time(a_datetime)`` method is called (if present) when a ``time:`` 66 directive is encountered in a Subunit stream. This is used to tell a TestResult 67 about the time that events in the stream occured at, to allow reconstructing 68 test timing from a stream. 69 70 The ``progress(offset, whence)`` method controls progress data for a stream. 71 The offset parameter is an int, and whence is one of subunit.PROGRESS_CUR, 72 subunit.PROGRESS_SET, PROGRESS_PUSH, PROGRESS_POP. Push and pop operations 73 ignore the offset parameter. 74 75 76 Python test support 77 ------------------- 78 79 ``subunit.run`` is a convenience wrapper to run a Python test suite via 80 the command line, reporting via Subunit:: 81 82 $ python -m subunit.run mylib.tests.test_suite 83 84 The ``IsolatedTestSuite`` class is a TestSuite that forks before running its 85 tests, allowing isolation between the test runner and some tests. 86 87 Similarly, ``IsolatedTestCase`` is a base class which can be subclassed to get 88 tests that will fork() before that individual test is run. 89 90 `ExecTestCase`` is a convenience wrapper for running an external 91 program to get a Subunit stream and then report that back to an arbitrary 92 result object:: 93 94 class AggregateTests(subunit.ExecTestCase): 95 96 def test_script_one(self): 97 './bin/script_one' 98 99 def test_script_two(self): 100 './bin/script_two' 101 102 # Normally your normal test loading would take of this automatically, 103 # It is only spelt out in detail here for clarity. 104 suite = unittest.TestSuite([AggregateTests("test_script_one"), 105 AggregateTests("test_script_two")]) 106 # Create any TestResult class you like. 107 result = unittest._TextTestResult(sys.stdout) 108 # And run your suite as normal, Subunit will exec each external script as 109 # needed and report to your result object. 110 suite.run(result) 111 112 Utility modules 113 --------------- 114 115 * subunit.chunked contains HTTP chunked encoding/decoding logic. 116 * subunit.test_results contains TestResult helper classes. 117 """ 118 119 import datetime 21 120 import os 121 import re 22 122 from StringIO import StringIO 123 import subprocess 23 124 import sys 24 125 import unittest 126 127 import iso8601 128 from testtools import content, content_type, ExtendedToOriginalDecorator 129 try: 130 from testtools.testresult.real import _StringException 131 RemoteException = _StringException 132 _remote_exception_str = '_StringException' # For testing. 133 except ImportError: 134 raise ImportError ("testtools.testresult.real does not contain " 135 "_StringException, check your version.") 136 from testtools import testresult 137 138 import chunked, details, test_results 139 140 141 PROGRESS_SET = 0 142 PROGRESS_CUR = 1 143 PROGRESS_PUSH = 2 144 PROGRESS_POP = 3 145 25 146 26 147 def test_suite(): … … 43 164 44 165 166 def tags_to_new_gone(tags): 167 """Split a list of tags into a new_set and a gone_set.""" 168 new_tags = set() 169 gone_tags = set() 170 for tag in tags: 171 if tag[0] == '-': 172 gone_tags.add(tag[1:]) 173 else: 174 new_tags.add(tag) 175 return new_tags, gone_tags 176 177 178 class DiscardStream(object): 179 """A filelike object which discards what is written to it.""" 180 181 def write(self, bytes): 182 pass 183 184 185 class _ParserState(object): 186 """State for the subunit parser.""" 187 188 def __init__(self, parser): 189 self.parser = parser 190 191 def addError(self, offset, line): 192 """An 'error:' directive has been read.""" 193 self.parser.stdOutLineReceived(line) 194 195 def addExpectedFail(self, offset, line): 196 """An 'xfail:' directive has been read.""" 197 self.parser.stdOutLineReceived(line) 198 199 def addFailure(self, offset, line): 200 """A 'failure:' directive has been read.""" 201 self.parser.stdOutLineReceived(line) 202 203 def addSkip(self, offset, line): 204 """A 'skip:' directive has been read.""" 205 self.parser.stdOutLineReceived(line) 206 207 def addSuccess(self, offset, line): 208 """A 'success:' directive has been read.""" 209 self.parser.stdOutLineReceived(line) 210 211 def lineReceived(self, line): 212 """a line has been received.""" 213 parts = line.split(None, 1) 214 if len(parts) == 2 and line.startswith(parts[0]): 215 cmd, rest = parts 216 offset = len(cmd) + 1 217 cmd = cmd.rstrip(':') 218 if cmd in ('test', 'testing'): 219 self.startTest(offset, line) 220 elif cmd == 'error': 221 self.addError(offset, line) 222 elif cmd == 'failure': 223 self.addFailure(offset, line) 224 elif cmd == 'progress': 225 self.parser._handleProgress(offset, line) 226 elif cmd == 'skip': 227 self.addSkip(offset, line) 228 elif cmd in ('success', 'successful'): 229 self.addSuccess(offset, line) 230 elif cmd in ('tags',): 231 self.parser._handleTags(offset, line) 232 self.parser.subunitLineReceived(line) 233 elif cmd in ('time',): 234 self.parser._handleTime(offset, line) 235 self.parser.subunitLineReceived(line) 236 elif cmd == 'xfail': 237 self.addExpectedFail(offset, line) 238 else: 239 self.parser.stdOutLineReceived(line) 240 else: 241 self.parser.stdOutLineReceived(line) 242 243 def lostConnection(self): 244 """Connection lost.""" 245 self.parser._lostConnectionInTest(u'unknown state of ') 246 247 def startTest(self, offset, line): 248 """A test start command received.""" 249 self.parser.stdOutLineReceived(line) 250 251 252 class _InTest(_ParserState): 253 """State for the subunit parser after reading a test: directive.""" 254 255 def _outcome(self, offset, line, no_details, details_state): 256 """An outcome directive has been read. 257 258 :param no_details: Callable to call when no details are presented. 259 :param details_state: The state to switch to for details 260 processing of this outcome. 261 """ 262 if self.parser.current_test_description == line[offset:-1]: 263 self.parser._state = self.parser._outside_test 264 self.parser.current_test_description = None 265 no_details() 266 self.parser.client.stopTest(self.parser._current_test) 267 self.parser._current_test = None 268 self.parser.subunitLineReceived(line) 269 elif self.parser.current_test_description + " [" == line[offset:-1]: 270 self.parser._state = details_state 271 details_state.set_simple() 272 self.parser.subunitLineReceived(line) 273 elif self.parser.current_test_description + " [ multipart" == \ 274 line[offset:-1]: 275 self.parser._state = details_state 276 details_state.set_multipart() 277 self.parser.subunitLineReceived(line) 278 else: 279 self.parser.stdOutLineReceived(line) 280 281 def _error(self): 282 self.parser.client.addError(self.parser._current_test, 283 details={}) 284 285 def addError(self, offset, line): 286 """An 'error:' directive has been read.""" 287 self._outcome(offset, line, self._error, 288 self.parser._reading_error_details) 289 290 def _xfail(self): 291 self.parser.client.addExpectedFailure(self.parser._current_test, 292 details={}) 293 294 def addExpectedFail(self, offset, line): 295 """An 'xfail:' directive has been read.""" 296 self._outcome(offset, line, self._xfail, 297 self.parser._reading_xfail_details) 298 299 def _failure(self): 300 self.parser.client.addFailure(self.parser._current_test, details={}) 301 302 def addFailure(self, offset, line): 303 """A 'failure:' directive has been read.""" 304 self._outcome(offset, line, self._failure, 305 self.parser._reading_failure_details) 306 307 def _skip(self): 308 self.parser.client.addSkip(self.parser._current_test, details={}) 309 310 def addSkip(self, offset, line): 311 """A 'skip:' directive has been read.""" 312 self._outcome(offset, line, self._skip, 313 self.parser._reading_skip_details) 314 315 def _succeed(self): 316 self.parser.client.addSuccess(self.parser._current_test, details={}) 317 318 def addSuccess(self, offset, line): 319 """A 'success:' directive has been read.""" 320 self._outcome(offset, line, self._succeed, 321 self.parser._reading_success_details) 322 323 def lostConnection(self): 324 """Connection lost.""" 325 self.parser._lostConnectionInTest(u'') 326 327 328 class _OutSideTest(_ParserState): 329 """State for the subunit parser outside of a test context.""" 330 331 def lostConnection(self): 332 """Connection lost.""" 333 334 def startTest(self, offset, line): 335 """A test start command received.""" 336 self.parser._state = self.parser._in_test 337 self.parser._current_test = RemotedTestCase(line[offset:-1]) 338 self.parser.current_test_description = line[offset:-1] 339 self.parser.client.startTest(self.parser._current_test) 340 self.parser.subunitLineReceived(line) 341 342 343 class _ReadingDetails(_ParserState): 344 """Common logic for readin state details.""" 345 346 def endDetails(self): 347 """The end of a details section has been reached.""" 348 self.parser._state = self.parser._outside_test 349 self.parser.current_test_description = None 350 self._report_outcome() 351 self.parser.client.stopTest(self.parser._current_test) 352 353 def lineReceived(self, line): 354 """a line has been received.""" 355 self.details_parser.lineReceived(line) 356 self.parser.subunitLineReceived(line) 357 358 def lostConnection(self): 359 """Connection lost.""" 360 self.parser._lostConnectionInTest(u'%s report of ' % 361 self._outcome_label()) 362 363 def _outcome_label(self): 364 """The label to describe this outcome.""" 365 raise NotImplementedError(self._outcome_label) 366 367 def set_simple(self): 368 """Start a simple details parser.""" 369 self.details_parser = details.SimpleDetailsParser(self) 370 371 def set_multipart(self): 372 """Start a multipart details parser.""" 373 self.details_parser = details.MultipartDetailsParser(self) 374 375 376 class _ReadingFailureDetails(_ReadingDetails): 377 """State for the subunit parser when reading failure details.""" 378 379 def _report_outcome(self): 380 self.parser.client.addFailure(self.parser._current_test, 381 details=self.details_parser.get_details()) 382 383 def _outcome_label(self): 384 return "failure" 385 386 387 class _ReadingErrorDetails(_ReadingDetails): 388 """State for the subunit parser when reading error details.""" 389 390 def _report_outcome(self): 391 self.parser.client.addError(self.parser._current_test, 392 details=self.details_parser.get_details()) 393 394 def _outcome_label(self): 395 return "error" 396 397 398 class _ReadingExpectedFailureDetails(_ReadingDetails): 399 """State for the subunit parser when reading xfail details.""" 400 401 def _report_outcome(self): 402 self.parser.client.addExpectedFailure(self.parser._current_test, 403 details=self.details_parser.get_details()) 404 405 def _outcome_label(self): 406 return "xfail" 407 408 409 class _ReadingSkipDetails(_ReadingDetails): 410 """State for the subunit parser when reading skip details.""" 411 412 def _report_outcome(self): 413 self.parser.client.addSkip(self.parser._current_test, 414 details=self.details_parser.get_details("skip")) 415 416 def _outcome_label(self): 417 return "skip" 418 419 420 class _ReadingSuccessDetails(_ReadingDetails): 421 """State for the subunit parser when reading success details.""" 422 423 def _report_outcome(self): 424 self.parser.client.addSuccess(self.parser._current_test, 425 details=self.details_parser.get_details("success")) 426 427 def _outcome_label(self): 428 return "success" 429 430 45 431 class TestProtocolServer(object): 46 """A class for receiving results from a TestProtocol client."""47 48 OUTSIDE_TEST = 049 TEST_STARTED = 150 READING_FAILURE = 2 51 READING_ERROR = 352 53 def __init__(self, client, stream=sys.stdout): 54 """Create a TestProtocol server instance.55 56 client should be an object that provides57 - startTest58 - addSuccess59 - addFailure60 - addError61 - stopTest62 methods, i.e. a TestResult.432 """A parser for subunit. 433 434 :ivar tags: The current tags associated with the protocol stream. 435 """ 436 437 def __init__(self, client, stream=None, forward_stream=None): 438 """Create a TestProtocolServer instance. 439 440 :param client: An object meeting the unittest.TestResult protocol. 441 :param stream: The stream that lines received which are not part of the 442 subunit protocol should be written to. This allows custom handling 443 of mixed protocols. By default, sys.stdout will be used for 444 convenience. 445 :param forward_stream: A stream to forward subunit lines to. This 446 allows a filter to forward the entire stream while still parsing 447 and acting on it. By default forward_stream is set to 448 DiscardStream() and no forwarding happens. 63 449 """ 64 self.state = TestProtocolServer.OUTSIDE_TEST 65 self.client = client 450 self.client = ExtendedToOriginalDecorator(client) 451 if stream is None: 452 stream = sys.stdout 66 453 self._stream = stream 67 68 def _addError(self, offset, line): 69 if (self.state == TestProtocolServer.TEST_STARTED and 70 self.current_test_description == line[offset:-1]): 71 self.state = TestProtocolServer.OUTSIDE_TEST 72 self.current_test_description = None 73 self.client.addError(self._current_test, RemoteError("")) 74 self.client.stopTest(self._current_test) 75 self._current_test = None 76 elif (self.state == TestProtocolServer.TEST_STARTED and 77 self.current_test_description + " [" == line[offset:-1]): 78 self.state = TestProtocolServer.READING_ERROR 79 self._message = "" 454 self._forward_stream = forward_stream or DiscardStream() 455 # state objects we can switch too 456 self._in_test = _InTest(self) 457 self._outside_test = _OutSideTest(self) 458 self._reading_error_details = _ReadingErrorDetails(self) 459 self._reading_failure_details = _ReadingFailureDetails(self) 460 self._reading_skip_details = _ReadingSkipDetails(self) 461 self._reading_success_details = _ReadingSuccessDetails(self) 462 self._reading_xfail_details = _ReadingExpectedFailureDetails(self) 463 # start with outside test. 464 self._state = self._outside_test 465 466 def _handleProgress(self, offset, line): 467 """Process a progress directive.""" 468 line = line[offset:].strip() 469 if line[0] in '+-': 470 whence = PROGRESS_CUR 471 delta = int(line) 472 elif line == "push": 473 whence = PROGRESS_PUSH 474 delta = None 475 elif line == "pop": 476 whence = PROGRESS_POP 477 delta = None 80 478 else: 81 self.stdOutLineReceived(line) 82 83 def _addFailure(self, offset, line): 84 if (self.state == TestProtocolServer.TEST_STARTED and 85 self.current_test_description == line[offset:-1]): 86 self.state = TestProtocolServer.OUTSIDE_TEST 87 self.current_test_description = None 88 self.client.addFailure(self._current_test, RemoteError()) 89 self.client.stopTest(self._current_test) 90 elif (self.state == TestProtocolServer.TEST_STARTED and 91 self.current_test_description + " [" == line[offset:-1]): 92 self.state = TestProtocolServer.READING_FAILURE 93 self._message = "" 94 else: 95 self.stdOutLineReceived(line) 96 97 def _addSuccess(self, offset, line): 98 if (self.state == TestProtocolServer.TEST_STARTED and 99 self.current_test_description == line[offset:-1]): 100 self.client.addSuccess(self._current_test) 101 self.client.stopTest(self._current_test) 102 self.current_test_description = None 103 self._current_test = None 104 self.state = TestProtocolServer.OUTSIDE_TEST 105 else: 106 self.stdOutLineReceived(line) 107 108 def _appendMessage(self, line): 109 if line[0:2] == " ]": 110 # quoted ] start 111 self._message += line[1:] 112 else: 113 self._message += line 114 115 def endQuote(self, line): 116 if self.state == TestProtocolServer.READING_FAILURE: 117 self.state = TestProtocolServer.OUTSIDE_TEST 118 self.current_test_description = None 119 self.client.addFailure(self._current_test, 120 RemoteError(self._message)) 121 self.client.stopTest(self._current_test) 122 elif self.state == TestProtocolServer.READING_ERROR: 123 self.state = TestProtocolServer.OUTSIDE_TEST 124 self.current_test_description = None 125 self.client.addError(self._current_test, 126 RemoteError(self._message)) 127 self.client.stopTest(self._current_test) 128 else: 129 self.stdOutLineReceived(line) 479 whence = PROGRESS_SET 480 delta = int(line) 481 self.client.progress(delta, whence) 482 483 def _handleTags(self, offset, line): 484 """Process a tags command.""" 485 tags = line[offset:].split() 486 new_tags, gone_tags = tags_to_new_gone(tags) 487 self.client.tags(new_tags, gone_tags) 488 489 def _handleTime(self, offset, line): 490 # Accept it, but do not do anything with it yet. 491 try: 492 event_time = iso8601.parse_date(line[offset:-1]) 493 except TypeError, e: 494 raise TypeError("Failed to parse %r, got %r" % (line, e)) 495 self.client.time(event_time) 130 496 131 497 def lineReceived(self, line): 132 498 """Call the appropriate local method for the received line.""" 133 if line == "]\n": 134 self.endQuote(line) 135 elif (self.state == TestProtocolServer.READING_FAILURE or 136 self.state == TestProtocolServer.READING_ERROR): 137 self._appendMessage(line) 138 else: 139 parts = line.split(None, 1) 140 if len(parts) == 2: 141 cmd, rest = parts 142 offset = len(cmd) + 1 143 cmd = cmd.strip(':') 144 if cmd in ('test', 'testing'): 145 self._startTest(offset, line) 146 elif cmd == 'error': 147 self._addError(offset, line) 148 elif cmd == 'failure': 149 self._addFailure(offset, line) 150 elif cmd in ('success', 'successful'): 151 self._addSuccess(offset, line) 152 else: 153 self.stdOutLineReceived(line) 154 else: 155 self.stdOutLineReceived(line) 499 self._state.lineReceived(line) 500 501 def _lostConnectionInTest(self, state_string): 502 error_string = u"lost connection during %stest '%s'" % ( 503 state_string, self.current_test_description) 504 self.client.addError(self._current_test, RemoteError(error_string)) 505 self.client.stopTest(self._current_test) 156 506 157 507 def lostConnection(self): 158 508 """The input connection has finished.""" 159 if self.state == TestProtocolServer.TEST_STARTED: 160 self.client.addError(self._current_test, 161 RemoteError("lost connection during test '%s'" 162 % self.current_test_description)) 163 self.client.stopTest(self._current_test) 164 elif self.state == TestProtocolServer.READING_ERROR: 165 self.client.addError(self._current_test, 166 RemoteError("lost connection during " 167 "error report of test " 168 "'%s'" % 169 self.current_test_description)) 170 self.client.stopTest(self._current_test) 171 elif self.state == TestProtocolServer.READING_FAILURE: 172 self.client.addError(self._current_test, 173 RemoteError("lost connection during " 174 "failure report of test " 175 "'%s'" % 176 self.current_test_description)) 177 self.client.stopTest(self._current_test) 509 self._state.lostConnection() 178 510 179 511 def readFrom(self, pipe): 512 """Blocking convenience API to parse an entire stream. 513 514 :param pipe: A file-like object supporting readlines(). 515 :return: None. 516 """ 180 517 for line in pipe.readlines(): 181 518 self.lineReceived(line) … … 184 521 def _startTest(self, offset, line): 185 522 """Internal call to change state machine. Override startTest().""" 186 if self.state == TestProtocolServer.OUTSIDE_TEST: 187 self.state = TestProtocolServer.TEST_STARTED 188 self._current_test = RemotedTestCase(line[offset:-1]) 189 self.current_test_description = line[offset:-1] 190 self.client.startTest(self._current_test) 191 else: 192 self.stdOutLineReceived(line) 523 self._state.startTest(offset, line) 524 525 def subunitLineReceived(self, line): 526 self._forward_stream.write(line) 193 527 194 528 def stdOutLineReceived(self, line): … … 196 530 197 531 198 class RemoteException(Exception): 199 """An exception that occured remotely to python.""" 200 201 def __eq__(self, other): 202 try: 203 return self.args == other.args 204 except AttributeError: 205 return False 206 207 208 class TestProtocolClient(unittest.TestResult): 209 """A class that looks like a TestResult and informs a TestProtocolServer.""" 532 class TestProtocolClient(testresult.TestResult): 533 """A TestResult which generates a subunit stream for a test run. 534 535 # Get a TestSuite or TestCase to run 536 suite = make_suite() 537 # Create a stream (any object with a 'write' method) 538 stream = file('tests.log', 'wb') 539 # Create a subunit result object which will output to the stream 540 result = subunit.TestProtocolClient(stream) 541 # Optionally, to get timing data for performance analysis, wrap the 542 # serialiser with a timing decorator 543 result = subunit.test_results.AutoTimingTestResultDecorator(result) 544 # Run the test suite reporting to the subunit result object 545 suite.run(result) 546 # Close the stream. 547 stream.close() 548 """ 210 549 211 550 def __init__(self, stream): 212 super(TestProtocolClient, self).__init__()551 testresult.TestResult.__init__(self) 213 552 self._stream = stream 214 215 def addError(self, test, error): 216 """Report an error in test test.""" 217 self._stream.write("error: %s [\n" % (test.shortDescription() or str(test))) 218 for line in self._exc_info_to_string(error, test).splitlines(): 219 self._stream.write("%s\n" % line) 553 _make_stream_binary(stream) 554 555 def addError(self, test, error=None, details=None): 556 """Report an error in test test. 557 558 Only one of error and details should be provided: conceptually there 559 are two separate methods: 560 addError(self, test, error) 561 addError(self, test, details) 562 563 :param error: Standard unittest positional argument form - an 564 exc_info tuple. 565 :param details: New Testing-in-python drafted API; a dict from string 566 to subunit.Content objects. 567 """ 568 self._addOutcome("error", test, error=error, details=details) 569 570 def addExpectedFailure(self, test, error=None, details=None): 571 """Report an expected failure in test test. 572 573 Only one of error and details should be provided: conceptually there 574 are two separate methods: 575 addError(self, test, error) 576 addError(self, test, details) 577 578 :param error: Standard unittest positional argument form - an 579 exc_info tuple. 580 :param details: New Testing-in-python drafted API; a dict from string 581 to subunit.Content objects. 582 """ 583 self._addOutcome("xfail", test, error=error, details=details) 584 585 def addFailure(self, test, error=None, details=None): 586 """Report a failure in test test. 587 588 Only one of error and details should be provided: conceptually there 589 are two separate methods: 590 addFailure(self, test, error) 591 addFailure(self, test, details) 592 593 :param error: Standard unittest positional argument form - an 594 exc_info tuple. 595 :param details: New Testing-in-python drafted API; a dict from string 596 to subunit.Content objects. 597 """ 598 self._addOutcome("failure", test, error=error, details=details) 599 600 def _addOutcome(self, outcome, test, error=None, details=None): 601 """Report a failure in test test. 602 603 Only one of error and details should be provided: conceptually there 604 are two separate methods: 605 addOutcome(self, test, error) 606 addOutcome(self, test, details) 607 608 :param outcome: A string describing the outcome - used as the 609 event name in the subunit stream. 610 :param error: Standard unittest positional argument form - an 611 exc_info tuple. 612 :param details: New Testing-in-python drafted API; a dict from string 613 to subunit.Content objects. 614 """ 615 self._stream.write("%s: %s" % (outcome, test.id())) 616 if error is None and details is None: 617 raise ValueError 618 if error is not None: 619 self._stream.write(" [\n") 620 # XXX: this needs to be made much stricter, along the lines of 621 # Martin[gz]'s work in testtools. Perhaps subunit can use that? 622 for line in self._exc_info_to_unicode(error, test).splitlines(): 623 self._stream.write(("%s\n" % line).encode('utf8')) 624 else: 625 self._write_details(details) 220 626 self._stream.write("]\n") 221 super(TestProtocolClient, self).addError(test, error) 222 223 def addFailure(self, test, error):224 """Report a failure in test test."""225 self._stream.write("failure: %s [\n" % (test.shortDescription() or str(test)))226 for line in self._exc_info_to_string(error, test).splitlines():227 self._stream.write(" %s\n" % line)228 self._stream.write("]\n")229 super(TestProtocolClient, self).addFailure(test, error)230 231 def addSuccess(self, test ):627 628 def addSkip(self, test, reason=None, details=None): 629 """Report a skipped test.""" 630 if reason is None: 631 self._addOutcome("skip", test, error=None, details=details) 632 else: 633 self._stream.write("skip: %s [\n" % test.id()) 634 self._stream.write("%s\n" % reason) 635 self._stream.write("]\n") 636 637 def addSuccess(self, test, details=None): 232 638 """Report a success in a test.""" 233 self._stream.write("successful: %s\n" % (test.shortDescription() or str(test))) 234 super(TestProtocolClient, self).addSuccess(test) 639 self._stream.write("successful: %s" % test.id()) 640 if not details: 641 self._stream.write("\n") 642 else: 643 self._write_details(details) 644 self._stream.write("]\n") 645 addUnexpectedSuccess = addSuccess 235 646 236 647 def startTest(self, test): 237 648 """Mark a test as starting its test run.""" 238 self._stream.write("test: %s\n" % (test.shortDescription() or str(test)))239 649 super(TestProtocolClient, self).startTest(test) 240 241 242 def RemoteError(description=""): 243 if description == "": 244 description = "\n" 245 return (RemoteException, RemoteException(description), None) 650 self._stream.write("test: %s\n" % test.id()) 651 self._stream.flush() 652 653 def stopTest(self, test): 654 super(TestProtocolClient, self).stopTest(test) 655 self._stream.flush() 656 657 def progress(self, offset, whence): 658 """Provide indication about the progress/length of the test run. 659 660 :param offset: Information about the number of tests remaining. If 661 whence is PROGRESS_CUR, then offset increases/decreases the 662 remaining test count. If whence is PROGRESS_SET, then offset 663 specifies exactly the remaining test count. 664 :param whence: One of PROGRESS_CUR, PROGRESS_SET, PROGRESS_PUSH, 665 PROGRESS_POP. 666 """ 667 if whence == PROGRESS_CUR and offset > -1: 668 prefix = "+" 669 elif whence == PROGRESS_PUSH: 670 prefix = "" 671 offset = "push" 672 elif whence == PROGRESS_POP: 673 prefix = "" 674 offset = "pop" 675 else: 676 prefix = "" 677 self._stream.write("progress: %s%s\n" % (prefix, offset)) 678 679 def time(self, a_datetime): 680 """Inform the client of the time. 681 682 ":param datetime: A datetime.datetime object. 683 """ 684 time = a_datetime.astimezone(iso8601.Utc()) 685 self._stream.write("time: %04d-%02d-%02d %02d:%02d:%02d.%06dZ\n" % ( 686 time.year, time.month, time.day, time.hour, time.minute, 687 time.second, time.microsecond)) 688 689 def _write_details(self, details): 690 """Output details to the stream. 691 692 :param details: An extended details dict for a test outcome. 693 """ 694 self._stream.write(" [ multipart\n") 695 for name, content in sorted(details.iteritems()): 696 self._stream.write("Content-Type: %s/%s" % 697 (content.content_type.type, content.content_type.subtype)) 698 parameters = content.content_type.parameters 699 if parameters: 700 self._stream.write(";") 701 param_strs = [] 702 for param, value in parameters.iteritems(): 703 param_strs.append("%s=%s" % (param, value)) 704 self._stream.write(",".join(param_strs)) 705 self._stream.write("\n%s\n" % name) 706 encoder = chunked.Encoder(self._stream) 707 map(encoder.write, content.iter_bytes()) 708 encoder.close() 709 710 def done(self): 711 """Obey the testtools result.done() interface.""" 712 713 714 def RemoteError(description=u""): 715 return (_StringException, _StringException(description), None) 246 716 247 717 248 718 class RemotedTestCase(unittest.TestCase): 249 """A class to represent test cases run in child processes.""" 719 """A class to represent test cases run in child processes. 720 721 Instances of this class are used to provide the Python test API a TestCase 722 that can be printed to the screen, introspected for metadata and so on. 723 However, as they are a simply a memoisation of a test that was actually 724 run in the past by a separate process, they cannot perform any interactive 725 actions. 726 """ 250 727 251 728 def __eq__ (self, other): … … 273 750 274 751 def id(self): 275 return "%s .%s" % (self._strclass(), self.__description)752 return "%s" % (self.__description,) 276 753 277 754 def __str__(self): … … 285 762 if result is None: result = self.defaultTestResult() 286 763 result.startTest(self) 287 result.addError(self, RemoteError( "Cannot run RemotedTestCases.\n"))764 result.addError(self, RemoteError(u"Cannot run RemotedTestCases.\n")) 288 765 result.stopTest(self) 289 766 … … 315 792 def debug(self): 316 793 """Run the test without collecting errors in a TestResult""" 317 self._run( unittest.TestResult())794 self._run(testresult.TestResult()) 318 795 319 796 def _run(self, result): 320 797 protocol = TestProtocolServer(result) 321 output = os.popen(self.script, mode='r') 322 protocol.readFrom(output) 798 output = subprocess.Popen(self.script, shell=True, 799 stdout=subprocess.PIPE).communicate()[0] 800 protocol.readFrom(StringIO(output)) 323 801 324 802 325 803 class IsolatedTestCase(unittest.TestCase): 326 """A TestCase which runs its tests in a forked process.""" 804 """A TestCase which executes in a forked process. 805 806 Each test gets its own process, which has a performance overhead but will 807 provide excellent isolation from global state (such as django configs, 808 zope utilities and so on). 809 """ 327 810 328 811 def run(self, result=None): … … 332 815 333 816 class IsolatedTestSuite(unittest.TestSuite): 334 """A TestCase which runs its tests in a forked process.""" 817 """A TestSuite which runs its tests in a forked process. 818 819 This decorator that will fork() before running the tests and report the 820 results from the child process using a Subunit stream. This is useful for 821 handling tests that mutate global state, or are testing C extensions that 822 could crash the VM. 823 """ 335 824 336 825 def run(self, result=None): 337 if result is None: result = unittest.TestResult()826 if result is None: result = testresult.TestResult() 338 827 run_isolated(unittest.TestSuite, self, result) 339 828 … … 377 866 378 867 379 class SubunitTestRunner(object): 380 def __init__(self, stream=sys.stdout): 381 self.stream = stream 382 383 def run(self, test): 384 "Run the given test case or test suite." 385 result = TestProtocolClient(self.stream) 386 test(result) 387 return result 388 868 def TAP2SubUnit(tap, subunit): 869 """Filter a TAP pipe into a subunit pipe. 870 871 :param tap: A tap pipe/stream/file object. 872 :param subunit: A pipe/stream/file object to write subunit results to. 873 :return: The exit code to exit with. 874 """ 875 BEFORE_PLAN = 0 876 AFTER_PLAN = 1 877 SKIP_STREAM = 2 878 client = TestProtocolClient(subunit) 879 state = BEFORE_PLAN 880 plan_start = 1 881 plan_stop = 0 882 def _skipped_test(subunit, plan_start): 883 # Some tests were skipped. 884 subunit.write('test test %d\n' % plan_start) 885 subunit.write('error test %d [\n' % plan_start) 886 subunit.write('test missing from TAP output\n') 887 subunit.write(']\n') 888 return plan_start + 1 889 # Test data for the next test to emit 890 test_name = None 891 log = [] 892 result = None 893 def _emit_test(): 894 "write out a test" 895 if test_name is None: 896 return 897 subunit.write("test %s\n" % test_name) 898 if not log: 899 subunit.write("%s %s\n" % (result, test_name)) 900 else: 901 subunit.write("%s %s [\n" % (result, test_name)) 902 if log: 903 for line in log: 904 subunit.write("%s\n" % line) 905 subunit.write("]\n") 906 del log[:] 907 for line in tap: 908 if state == BEFORE_PLAN: 909 match = re.match("(\d+)\.\.(\d+)\s*(?:\#\s+(.*))?\n", line) 910 if match: 911 state = AFTER_PLAN 912 _, plan_stop, comment = match.groups() 913 plan_stop = int(plan_stop) 914 if plan_start > plan_stop and plan_stop == 0: 915 # skipped file 916 state = SKIP_STREAM 917 subunit.write("test file skip\n") 918 subunit.write("skip file skip [\n") 919 subunit.write("%s\n" % comment) 920 subunit.write("]\n") 921 continue 922 # not a plan line, or have seen one before 923 match = re.match("(ok|not ok)(?:\s+(\d+)?)?(?:\s+([^#]*[^#\s]+)\s*)?(?:\s+#\s+(TODO|SKIP|skip|todo)(?:\s+(.*))?)?\n", line) 924 if match: 925 # new test, emit current one. 926 _emit_test() 927 status, number, description, directive, directive_comment = match.groups() 928 if status == 'ok': 929 result = 'success' 930 else: 931 result = "failure" 932 if description is None: 933 description = '' 934 else: 935 description = ' ' + description 936 if directive is not None: 937 if directive.upper() == 'TODO': 938 result = 'xfail' 939 elif directive.upper() == 'SKIP': 940 result = 'skip' 941 if directive_comment is not None: 942 log.append(directive_comment) 943 if number is not None: 944 number = int(number) 945 while plan_start < number: 946 plan_start = _skipped_test(subunit, plan_start) 947 test_name = "test %d%s" % (plan_start, description) 948 plan_start += 1 949 continue 950 match = re.match("Bail out\!(?:\s*(.*))?\n", line) 951 if match: 952 reason, = match.groups() 953 if reason is None: 954 extra = '' 955 else: 956 extra = ' %s' % reason 957 _emit_test() 958 test_name = "Bail out!%s" % extra 959 result = "error" 960 state = SKIP_STREAM 961 continue 962 match = re.match("\#.*\n", line) 963 if match: 964 log.append(line[:-1]) 965 continue 966 subunit.write(line) 967 _emit_test() 968 while plan_start <= plan_stop: 969 # record missed tests 970 plan_start = _skipped_test(subunit, plan_start) 971 return 0 972 973 974 def tag_stream(original, filtered, tags): 975 """Alter tags on a stream. 976 977 :param original: The input stream. 978 :param filtered: The output stream. 979 :param tags: The tags to apply. As in a normal stream - a list of 'TAG' or 980 '-TAG' commands. 981 982 A 'TAG' command will add the tag to the output stream, 983 and override any existing '-TAG' command in that stream. 984 Specifically: 985 * A global 'tags: TAG' will be added to the start of the stream. 986 * Any tags commands with -TAG will have the -TAG removed. 987 988 A '-TAG' command will remove the TAG command from the stream. 989 Specifically: 990 * A 'tags: -TAG' command will be added to the start of the stream. 991 * Any 'tags: TAG' command will have 'TAG' removed from it. 992 Additionally, any redundant tagging commands (adding a tag globally 993 present, or removing a tag globally removed) are stripped as a 994 by-product of the filtering. 995 :return: 0 996 """ 997 new_tags, gone_tags = tags_to_new_gone(tags) 998 def write_tags(new_tags, gone_tags): 999 if new_tags or gone_tags: 1000 filtered.write("tags: " + ' '.join(new_tags)) 1001 if gone_tags: 1002 for tag in gone_tags: 1003 filtered.write("-" + tag) 1004 filtered.write("\n") 1005 write_tags(new_tags, gone_tags) 1006 # TODO: use the protocol parser and thus don't mangle test comments. 1007 for line in original: 1008 if line.startswith("tags:"): 1009 line_tags = line[5:].split() 1010 line_new, line_gone = tags_to_new_gone(line_tags) 1011 line_new = line_new - gone_tags 1012 line_gone = line_gone - new_tags 1013 write_tags(line_new, line_gone) 1014 else: 1015 filtered.write(line) 1016 return 0 1017 1018 1019 class ProtocolTestCase(object): 1020 """Subunit wire protocol to unittest.TestCase adapter. 1021 1022 ProtocolTestCase honours the core of ``unittest.TestCase`` protocol - 1023 calling a ProtocolTestCase or invoking the run() method will make a 'test 1024 run' happen. The 'test run' will simply be a replay of the test activity 1025 that has been encoded into the stream. The ``unittest.TestCase`` ``debug`` 1026 and ``countTestCases`` methods are not supported because there isn't a 1027 sensible mapping for those methods. 1028 1029 # Get a stream (any object with a readline() method), in this case the 1030 # stream output by the example from ``subunit.TestProtocolClient``. 1031 stream = file('tests.log', 'rb') 1032 # Create a parser which will read from the stream and emit 1033 # activity to a unittest.TestResult when run() is called. 1034 suite = subunit.ProtocolTestCase(stream) 1035 # Create a result object to accept the contents of that stream. 1036 result = unittest._TextTestResult(sys.stdout) 1037 # 'run' the tests - process the stream and feed its contents to result. 1038 suite.run(result) 1039 stream.close() 1040 1041 :seealso: TestProtocolServer (the subunit wire protocol parser). 1042 """ 1043 1044 def __init__(self, stream, passthrough=None, forward=False): 1045 """Create a ProtocolTestCase reading from stream. 1046 1047 :param stream: A filelike object which a subunit stream can be read 1048 from. 1049 :param passthrough: A stream pass non subunit input on to. If not 1050 supplied, the TestProtocolServer default is used. 1051 :param forward: A stream to pass subunit input on to. If not supplied 1052 subunit input is not forwarded. 1053 """ 1054 self._stream = stream 1055 _make_stream_binary(stream) 1056 self._passthrough = passthrough 1057 self._forward = forward 1058 _make_stream_binary(forward) 1059 1060 def __call__(self, result=None): 1061 return self.run(result) 1062 1063 def run(self, result=None): 1064 if result is None: 1065 result = self.defaultTestResult() 1066 protocol = TestProtocolServer(result, self._passthrough, self._forward) 1067 line = self._stream.readline() 1068 while line: 1069 protocol.lineReceived(line) 1070 line = self._stream.readline() 1071 protocol.lostConnection() 1072 1073 1074 class TestResultStats(testresult.TestResult): 1075 """A pyunit TestResult interface implementation for making statistics. 1076 1077 :ivar total_tests: The total tests seen. 1078 :ivar passed_tests: The tests that passed. 1079 :ivar failed_tests: The tests that failed. 1080 :ivar seen_tags: The tags seen across all tests. 1081 """ 1082 1083 def __init__(self, stream): 1084 """Create a TestResultStats which outputs to stream.""" 1085 testresult.TestResult.__init__(self) 1086 self._stream = stream 1087 self.failed_tests = 0 1088 self.skipped_tests = 0 1089 self.seen_tags = set() 1090 1091 @property 1092 def total_tests(self): 1093 return self.testsRun 1094 1095 def addError(self, test, err, details=None): 1096 self.failed_tests += 1 1097 1098 def addFailure(self, test, err, details=None): 1099 self.failed_tests += 1 1100 1101 def addSkip(self, test, reason, details=None): 1102 self.skipped_tests += 1 1103 1104 def formatStats(self): 1105 self._stream.write("Total tests: %5d\n" % self.total_tests) 1106 self._stream.write("Passed tests: %5d\n" % self.passed_tests) 1107 self._stream.write("Failed tests: %5d\n" % self.failed_tests) 1108 self._stream.write("Skipped tests: %5d\n" % self.skipped_tests) 1109 tags = sorted(self.seen_tags) 1110 self._stream.write("Seen tags: %s\n" % (", ".join(tags))) 1111 1112 @property 1113 def passed_tests(self): 1114 return self.total_tests - self.failed_tests - self.skipped_tests 1115 1116 def tags(self, new_tags, gone_tags): 1117 """Accumulate the seen tags.""" 1118 self.seen_tags.update(new_tags) 1119 1120 def wasSuccessful(self): 1121 """Tells whether or not this result was a success""" 1122 return self.failed_tests == 0 1123 1124 1125 def get_default_formatter(): 1126 """Obtain the default formatter to write to. 1127 1128 :return: A file-like object. 1129 """ 1130 formatter = os.getenv("SUBUNIT_FORMATTER") 1131 if formatter: 1132 return os.popen(formatter, "w") 1133 else: 1134 return sys.stdout 1135 1136 1137 def _make_stream_binary(stream): 1138 """Ensure that a stream will be binary safe. See _make_binary_on_windows.""" 1139 if getattr(stream, 'fileno', None) is not None: 1140 _make_binary_on_windows(stream.fileno()) 1141 1142 def _make_binary_on_windows(fileno): 1143 """Win32 mangles \r\n to \n and that breaks streams. See bug lp:505078.""" 1144 if sys.platform == "win32": 1145 import msvcrt 1146 msvcrt.setmode(fileno, os.O_BINARY) -
vendor/current/lib/subunit/python/subunit/tests/__init__.py
r414 r740 3 3 # Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> 4 4 # 5 # This program is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation; either version 2 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 5 # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause 6 # license at the users choice. A copy of both licenses are available in the 7 # project source as Apache-2.0 and BSD. You may not use this file except in 8 # compliance with one of these two licences. 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT 12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 # license you chose for the specific language governing permissions and 14 # limitations under that license. 18 15 # 19 16 20 from subunit.tests import TestUtil, test_test_protocol 17 from subunit.tests import ( 18 TestUtil, 19 test_chunked, 20 test_details, 21 test_progress_model, 22 test_subunit_filter, 23 test_subunit_stats, 24 test_subunit_tags, 25 test_tap2subunit, 26 test_test_protocol, 27 test_test_results, 28 ) 21 29 22 30 def test_suite(): 23 31 result = TestUtil.TestSuite() 32 result.addTest(test_chunked.test_suite()) 33 result.addTest(test_details.test_suite()) 34 result.addTest(test_progress_model.test_suite()) 35 result.addTest(test_test_results.test_suite()) 24 36 result.addTest(test_test_protocol.test_suite()) 37 result.addTest(test_tap2subunit.test_suite()) 38 result.addTest(test_subunit_filter.test_suite()) 39 result.addTest(test_subunit_tags.test_suite()) 40 result.addTest(test_subunit_stats.test_suite()) 25 41 return result -
vendor/current/lib/subunit/python/subunit/tests/sample-script.py
r414 r740 1 1 #!/usr/bin/env python 2 2 import sys 3 if len(sys.argv) == 2: 4 # subunit.tests.test_test_protocol.TestExecTestCase.test_sample_method_args 5 # uses this code path to be sure that the arguments were passed to 6 # sample-script.py 7 print "test fail" 8 print "error fail" 9 sys.exit(0) 3 10 print "test old mcdonald" 4 11 print "success old mcdonald" -
vendor/current/lib/subunit/python/subunit/tests/test_test_protocol.py
r414 r740 1 1 # 2 # subunit: extensions to python unittest to get test results from subprocesses.2 # subunit: extensions to Python unittest to get test results from subprocesses. 3 3 # Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> 4 4 # 5 # This program is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation; either version 2 of the License, or 8 # (at your option) any later version. 5 # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause 6 # license at the users choice. A copy of both licenses are available in the 7 # project source as Apache-2.0 and BSD. You may not use this file except in 8 # compliance with one of these two licences. 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT 12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 # license you chose for the specific language governing permissions and 14 # limitations under that license. 9 15 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 # 19 16 17 import datetime 20 18 import unittest 21 19 from StringIO import StringIO 22 20 import os 21 import sys 22 23 from testtools.content import Content, TracebackContent 24 from testtools.content_type import ContentType 25 from testtools.tests.helpers import ( 26 Python26TestResult, 27 Python27TestResult, 28 ExtendedTestResult, 29 ) 30 23 31 import subunit 24 import sys 25 26 try: 27 class MockTestProtocolServerClient(object): 28 """A mock protocol server client to test callbacks.""" 29 30 def __init__(self): 31 self.end_calls = [] 32 self.error_calls = [] 33 self.failure_calls = [] 34 self.start_calls = [] 35 self.success_calls = [] 36 super(MockTestProtocolServerClient, self).__init__() 37 38 def addError(self, test, error): 39 self.error_calls.append((test, error)) 40 41 def addFailure(self, test, error): 42 self.failure_calls.append((test, error)) 43 44 def addSuccess(self, test): 45 self.success_calls.append(test) 46 47 def stopTest(self, test): 48 self.end_calls.append(test) 49 50 def startTest(self, test): 51 self.start_calls.append(test) 52 53 except AttributeError: 54 MockTestProtocolServer = None 55 56 57 class TestMockTestProtocolServer(unittest.TestCase): 58 59 def test_start_test(self): 60 protocol = MockTestProtocolServerClient() 61 protocol.startTest(subunit.RemotedTestCase("test old mcdonald")) 62 self.assertEqual(protocol.start_calls, 63 [subunit.RemotedTestCase("test old mcdonald")]) 64 self.assertEqual(protocol.end_calls, []) 65 self.assertEqual(protocol.error_calls, []) 66 self.assertEqual(protocol.failure_calls, []) 67 self.assertEqual(protocol.success_calls, []) 68 69 def test_add_error(self): 70 protocol = MockTestProtocolServerClient() 71 protocol.addError(subunit.RemotedTestCase("old mcdonald"), 72 subunit.RemoteError("omg it works")) 73 self.assertEqual(protocol.start_calls, []) 74 self.assertEqual(protocol.end_calls, []) 75 self.assertEqual(protocol.error_calls, [( 76 subunit.RemotedTestCase("old mcdonald"), 77 subunit.RemoteError("omg it works"))]) 78 self.assertEqual(protocol.failure_calls, []) 79 self.assertEqual(protocol.success_calls, []) 80 81 def test_add_failure(self): 82 protocol = MockTestProtocolServerClient() 83 protocol.addFailure(subunit.RemotedTestCase("old mcdonald"), 84 subunit.RemoteError("omg it works")) 85 self.assertEqual(protocol.start_calls, []) 86 self.assertEqual(protocol.end_calls, []) 87 self.assertEqual(protocol.error_calls, []) 88 self.assertEqual(protocol.failure_calls, [ 89 (subunit.RemotedTestCase("old mcdonald"), 90 subunit.RemoteError("omg it works"))]) 91 self.assertEqual(protocol.success_calls, []) 92 93 def test_add_success(self): 94 protocol = MockTestProtocolServerClient() 95 protocol.addSuccess(subunit.RemotedTestCase("test old mcdonald")) 96 self.assertEqual(protocol.start_calls, []) 97 self.assertEqual(protocol.end_calls, []) 98 self.assertEqual(protocol.error_calls, []) 99 self.assertEqual(protocol.failure_calls, []) 100 self.assertEqual(protocol.success_calls, 101 [subunit.RemotedTestCase("test old mcdonald")]) 102 103 def test_end_test(self): 104 protocol = MockTestProtocolServerClient() 105 protocol.stopTest(subunit.RemotedTestCase("test old mcdonald")) 106 self.assertEqual(protocol.end_calls, 107 [subunit.RemotedTestCase("test old mcdonald")]) 108 self.assertEqual(protocol.error_calls, []) 109 self.assertEqual(protocol.failure_calls, []) 110 self.assertEqual(protocol.success_calls, []) 111 self.assertEqual(protocol.start_calls, []) 32 from subunit import _remote_exception_str 33 import subunit.iso8601 as iso8601 112 34 113 35 … … 115 37 116 38 def test_imports(self): 39 from subunit import DiscardStream 117 40 from subunit import TestProtocolServer 118 41 from subunit import RemotedTestCase … … 121 44 from subunit import IsolatedTestCase 122 45 from subunit import TestProtocolClient 123 46 from subunit import ProtocolTestCase 47 48 49 class TestDiscardStream(unittest.TestCase): 50 51 def test_write(self): 52 subunit.DiscardStream().write("content") 53 54 55 class TestProtocolServerForward(unittest.TestCase): 56 57 def test_story(self): 58 client = unittest.TestResult() 59 out = StringIO() 60 protocol = subunit.TestProtocolServer(client, forward_stream=out) 61 pipe = StringIO("test old mcdonald\n" 62 "success old mcdonald\n") 63 protocol.readFrom(pipe) 64 mcdonald = subunit.RemotedTestCase("old mcdonald") 65 self.assertEqual(client.testsRun, 1) 66 self.assertEqual(pipe.getvalue(), out.getvalue()) 67 68 def test_not_command(self): 69 client = unittest.TestResult() 70 out = StringIO() 71 protocol = subunit.TestProtocolServer(client, 72 stream=subunit.DiscardStream(), forward_stream=out) 73 pipe = StringIO("success old mcdonald\n") 74 protocol.readFrom(pipe) 75 self.assertEqual(client.testsRun, 0) 76 self.assertEqual("", out.getvalue()) 77 124 78 125 79 class TestTestProtocolServerPipe(unittest.TestCase): … … 141 95 an_error = subunit.RemotedTestCase("an error") 142 96 self.assertEqual(client.errors, 143 [(an_error, 'RemoteException: \n\n')])97 [(an_error, _remote_exception_str + '\n')]) 144 98 self.assertEqual( 145 99 client.failures, 146 [(bing, "RemoteException: foo.c:53:ERROR invalid state\n\n")]) 100 [(bing, _remote_exception_str + ": Text attachment: traceback\n" 101 "------------\nfoo.c:53:ERROR invalid state\n" 102 "------------\n\n")]) 147 103 self.assertEqual(client.testsRun, 3) 148 104 105 def test_non_test_characters_forwarded_immediately(self): 106 pass 107 149 108 150 109 class TestTestProtocolServerStartTest(unittest.TestCase): 151 110 152 111 def setUp(self): 153 self.client = MockTestProtocolServerClient()112 self.client = Python26TestResult() 154 113 self.protocol = subunit.TestProtocolServer(self.client) 155 114 156 115 def test_start_test(self): 157 116 self.protocol.lineReceived("test old mcdonald\n") 158 self.assertEqual(self.client. start_calls,159 [subunit.RemotedTestCase("old mcdonald")])117 self.assertEqual(self.client._events, 118 [('startTest', subunit.RemotedTestCase("old mcdonald"))]) 160 119 161 120 def test_start_testing(self): 162 121 self.protocol.lineReceived("testing old mcdonald\n") 163 self.assertEqual(self.client. start_calls,164 [subunit.RemotedTestCase("old mcdonald")])122 self.assertEqual(self.client._events, 123 [('startTest', subunit.RemotedTestCase("old mcdonald"))]) 165 124 166 125 def test_start_test_colon(self): 167 126 self.protocol.lineReceived("test: old mcdonald\n") 168 self.assertEqual(self.client.start_calls, 169 [subunit.RemotedTestCase("old mcdonald")]) 127 self.assertEqual(self.client._events, 128 [('startTest', subunit.RemotedTestCase("old mcdonald"))]) 129 130 def test_indented_test_colon_ignored(self): 131 self.protocol.lineReceived(" test: old mcdonald\n") 132 self.assertEqual([], self.client._events) 170 133 171 134 def test_start_testing_colon(self): 172 135 self.protocol.lineReceived("testing: old mcdonald\n") 173 self.assertEqual(self.client. start_calls,174 [subunit.RemotedTestCase("old mcdonald")])136 self.assertEqual(self.client._events, 137 [('startTest', subunit.RemotedTestCase("old mcdonald"))]) 175 138 176 139 … … 178 141 179 142 def setUp(self): 180 from StringIO import StringIO181 143 self.stdout = StringIO() 182 144 self.test = subunit.RemotedTestCase("old mcdonald") 183 self.client = MockTestProtocolServerClient()145 self.client = ExtendedTestResult() 184 146 self.protocol = subunit.TestProtocolServer(self.client, self.stdout) 185 147 … … 206 168 def test_keywords_before_test(self): 207 169 self.keywords_before_test() 208 self.assertEqual(self.client.start_calls, []) 209 self.assertEqual(self.client.error_calls, []) 210 self.assertEqual(self.client.failure_calls, []) 211 self.assertEqual(self.client.success_calls, []) 170 self.assertEqual(self.client._events, []) 212 171 213 172 def test_keywords_after_error(self): … … 215 174 self.protocol.lineReceived("error old mcdonald\n") 216 175 self.keywords_before_test() 217 self.assertEqual(self.client.start_calls, [self.test]) 218 self.assertEqual(self.client.end_calls, [self.test]) 219 self.assertEqual(self.client.error_calls, 220 [(self.test, subunit.RemoteError(""))]) 221 self.assertEqual(self.client.failure_calls, []) 222 self.assertEqual(self.client.success_calls, []) 176 self.assertEqual([ 177 ('startTest', self.test), 178 ('addError', self.test, {}), 179 ('stopTest', self.test), 180 ], self.client._events) 223 181 224 182 def test_keywords_after_failure(self): … … 226 184 self.protocol.lineReceived("failure old mcdonald\n") 227 185 self.keywords_before_test() 228 self.assertEqual(self.client.start_calls, [self.test]) 229 self.assertEqual(self.client.end_calls, [self.test]) 230 self.assertEqual(self.client.error_calls, []) 231 self.assertEqual(self.client.failure_calls, 232 [(self.test, subunit.RemoteError())]) 233 self.assertEqual(self.client.success_calls, []) 186 self.assertEqual(self.client._events, [ 187 ('startTest', self.test), 188 ('addFailure', self.test, {}), 189 ('stopTest', self.test), 190 ]) 234 191 235 192 def test_keywords_after_success(self): … … 237 194 self.protocol.lineReceived("success old mcdonald\n") 238 195 self.keywords_before_test() 239 self.assertEqual( self.client.start_calls, [self.test])240 self.assertEqual(self.client.end_calls, [self.test])241 self.assertEqual(self.client.error_calls, [])242 self.assertEqual(self.client.failure_calls, [])243 self.assertEqual(self.client.success_calls, [self.test])196 self.assertEqual([ 197 ('startTest', self.test), 198 ('addSuccess', self.test), 199 ('stopTest', self.test), 200 ], self.client._events) 244 201 245 202 def test_keywords_after_test(self): … … 266 223 "successful: a\n" 267 224 "]\n") 268 self.assertEqual(self.client.start_calls, [self.test]) 269 self.assertEqual(self.client.end_calls, [self.test]) 270 self.assertEqual(self.client.failure_calls, 271 [(self.test, subunit.RemoteError())]) 272 self.assertEqual(self.client.error_calls, []) 273 self.assertEqual(self.client.success_calls, []) 225 self.assertEqual(self.client._events, [ 226 ('startTest', self.test), 227 ('addFailure', self.test, {}), 228 ('stopTest', self.test), 229 ]) 274 230 275 231 def test_keywords_during_failure(self): 232 # A smoke test to make sure that the details parsers have control 233 # appropriately. 276 234 self.protocol.lineReceived("test old mcdonald\n") 277 235 self.protocol.lineReceived("failure: old mcdonald [\n") … … 288 246 self.protocol.lineReceived("]\n") 289 247 self.assertEqual(self.stdout.getvalue(), "") 290 self.assertEqual(self.client.start_calls, [self.test]) 291 self.assertEqual(self.client.failure_calls, 292 [(self.test, subunit.RemoteError("test old mcdonald\n" 293 "failure a\n" 294 "failure: a\n" 295 "error a\n" 296 "error: a\n" 297 "success a\n" 298 "success: a\n" 299 "successful a\n" 300 "successful: a\n" 301 "]\n"))]) 302 self.assertEqual(self.client.end_calls, [self.test]) 303 self.assertEqual(self.client.error_calls, []) 304 self.assertEqual(self.client.success_calls, []) 248 details = {} 249 details['traceback'] = Content(ContentType("text", "x-traceback", 250 {'charset': 'utf8'}), 251 lambda:[ 252 "test old mcdonald\n" 253 "failure a\n" 254 "failure: a\n" 255 "error a\n" 256 "error: a\n" 257 "success a\n" 258 "success: a\n" 259 "successful a\n" 260 "successful: a\n" 261 "]\n"]) 262 self.assertEqual(self.client._events, [ 263 ('startTest', self.test), 264 ('addFailure', self.test, details), 265 ('stopTest', self.test), 266 ]) 305 267 306 268 def test_stdout_passthrough(self): … … 316 278 317 279 def setUp(self): 318 self.client = MockTestProtocolServerClient()280 self.client = Python26TestResult() 319 281 self.protocol = subunit.TestProtocolServer(self.client) 320 282 self.test = subunit.RemotedTestCase("old mcdonald") … … 322 284 def test_lost_connection_no_input(self): 323 285 self.protocol.lostConnection() 324 self.assertEqual(self.client.start_calls, []) 325 self.assertEqual(self.client.error_calls, []) 326 self.assertEqual(self.client.failure_calls, []) 327 self.assertEqual(self.client.success_calls, []) 286 self.assertEqual([], self.client._events) 328 287 329 288 def test_lost_connection_after_start(self): 330 289 self.protocol.lineReceived("test old mcdonald\n") 331 290 self.protocol.lostConnection() 332 self.assertEqual(self.client.start_calls, [self.test])333 self.assertEqual(self.client.end_calls, [self.test])334 self.assertEqual( self.client.error_calls,[335 ( self.test, subunit.RemoteError("lost connection during "336 "test 'old mcdonald'"))])337 self.assertEqual(self.client.failure_calls, [])338 self.assertEqual(self.client.success_calls, [])291 failure = subunit.RemoteError( 292 u"lost connection during test 'old mcdonald'") 293 self.assertEqual([ 294 ('startTest', self.test), 295 ('addError', self.test, failure), 296 ('stopTest', self.test), 297 ], self.client._events) 339 298 340 299 def test_lost_connected_after_error(self): … … 342 301 self.protocol.lineReceived("error old mcdonald\n") 343 302 self.protocol.lostConnection() 344 self.assertEqual(self.client.start_calls, [self.test]) 345 self.assertEqual(self.client.failure_calls, []) 346 self.assertEqual(self.client.end_calls, [self.test]) 347 self.assertEqual(self.client.error_calls, [ 348 (self.test, subunit.RemoteError(""))]) 349 self.assertEqual(self.client.success_calls, []) 303 self.assertEqual([ 304 ('startTest', self.test), 305 ('addError', self.test, subunit.RemoteError(u"")), 306 ('stopTest', self.test), 307 ], self.client._events) 308 309 def do_connection_lost(self, outcome, opening): 310 self.protocol.lineReceived("test old mcdonald\n") 311 self.protocol.lineReceived("%s old mcdonald %s" % (outcome, opening)) 312 self.protocol.lostConnection() 313 failure = subunit.RemoteError( 314 u"lost connection during %s report of test 'old mcdonald'" % 315 outcome) 316 self.assertEqual([ 317 ('startTest', self.test), 318 ('addError', self.test, failure), 319 ('stopTest', self.test), 320 ], self.client._events) 350 321 351 322 def test_lost_connection_during_error(self): 352 self.protocol.lineReceived("test old mcdonald\n") 353 self.protocol.lineReceived("error old mcdonald [\n") 354 self.protocol.lostConnection() 355 self.assertEqual(self.client.start_calls, [self.test]) 356 self.assertEqual(self.client.end_calls, [self.test]) 357 self.assertEqual(self.client.error_calls, [ 358 (self.test, subunit.RemoteError("lost connection during error " 359 "report of test 'old mcdonald'"))]) 360 self.assertEqual(self.client.failure_calls, []) 361 self.assertEqual(self.client.success_calls, []) 323 self.do_connection_lost("error", "[\n") 324 325 def test_lost_connection_during_error_details(self): 326 self.do_connection_lost("error", "[ multipart\n") 362 327 363 328 def test_lost_connected_after_failure(self): … … 365 330 self.protocol.lineReceived("failure old mcdonald\n") 366 331 self.protocol.lostConnection() 367 test = subunit.RemotedTestCase("old mcdonald") 368 self.assertEqual(self.client.start_calls, [self.test]) 369 self.assertEqual(self.client.end_calls, [self.test]) 370 self.assertEqual(self.client.error_calls, []) 371 self.assertEqual(self.client.failure_calls, 372 [(self.test, subunit.RemoteError())]) 373 self.assertEqual(self.client.success_calls, []) 332 self.assertEqual([ 333 ('startTest', self.test), 334 ('addFailure', self.test, subunit.RemoteError(u"")), 335 ('stopTest', self.test), 336 ], self.client._events) 374 337 375 338 def test_lost_connection_during_failure(self): 376 self.protocol.lineReceived("test old mcdonald\n") 377 self.protocol.lineReceived("failure old mcdonald [\n") 378 self.protocol.lostConnection() 379 self.assertEqual(self.client.start_calls, [self.test]) 380 self.assertEqual(self.client.end_calls, [self.test]) 381 self.assertEqual(self.client.error_calls, 382 [(self.test, 383 subunit.RemoteError("lost connection during " 384 "failure report" 385 " of test 'old mcdonald'"))]) 386 self.assertEqual(self.client.failure_calls, []) 387 self.assertEqual(self.client.success_calls, []) 339 self.do_connection_lost("failure", "[\n") 340 341 def test_lost_connection_during_failure_details(self): 342 self.do_connection_lost("failure", "[ multipart\n") 388 343 389 344 def test_lost_connection_after_success(self): … … 391 346 self.protocol.lineReceived("success old mcdonald\n") 392 347 self.protocol.lostConnection() 393 self.assertEqual(self.client.start_calls, [self.test]) 394 self.assertEqual(self.client.end_calls, [self.test]) 395 self.assertEqual(self.client.error_calls, []) 396 self.assertEqual(self.client.failure_calls, []) 397 self.assertEqual(self.client.success_calls, [self.test]) 398 399 400 class TestTestProtocolServerAddError(unittest.TestCase): 348 self.assertEqual([ 349 ('startTest', self.test), 350 ('addSuccess', self.test), 351 ('stopTest', self.test), 352 ], self.client._events) 353 354 def test_lost_connection_during_success(self): 355 self.do_connection_lost("success", "[\n") 356 357 def test_lost_connection_during_success_details(self): 358 self.do_connection_lost("success", "[ multipart\n") 359 360 def test_lost_connection_during_skip(self): 361 self.do_connection_lost("skip", "[\n") 362 363 def test_lost_connection_during_skip_details(self): 364 self.do_connection_lost("skip", "[ multipart\n") 365 366 def test_lost_connection_during_xfail(self): 367 self.do_connection_lost("xfail", "[\n") 368 369 def test_lost_connection_during_xfail_details(self): 370 self.do_connection_lost("xfail", "[ multipart\n") 371 372 373 class TestInTestMultipart(unittest.TestCase): 401 374 402 375 def setUp(self): 403 self.client = MockTestProtocolServerClient()376 self.client = ExtendedTestResult() 404 377 self.protocol = subunit.TestProtocolServer(self.client) 405 378 self.protocol.lineReceived("test mcdonalds farm\n") 406 379 self.test = subunit.RemotedTestCase("mcdonalds farm") 407 380 381 def test__outcome_sets_details_parser(self): 382 self.protocol._reading_success_details.details_parser = None 383 self.protocol._state._outcome(0, "mcdonalds farm [ multipart\n", 384 None, self.protocol._reading_success_details) 385 parser = self.protocol._reading_success_details.details_parser 386 self.assertNotEqual(None, parser) 387 self.assertTrue(isinstance(parser, 388 subunit.details.MultipartDetailsParser)) 389 390 391 class TestTestProtocolServerAddError(unittest.TestCase): 392 393 def setUp(self): 394 self.client = ExtendedTestResult() 395 self.protocol = subunit.TestProtocolServer(self.client) 396 self.protocol.lineReceived("test mcdonalds farm\n") 397 self.test = subunit.RemotedTestCase("mcdonalds farm") 398 408 399 def simple_error_keyword(self, keyword): 409 400 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword) 410 self.assertEqual(self.client.start_calls, [self.test]) 411 self.assertEqual(self.client.end_calls, [self.test]) 412 self.assertEqual(self.client.error_calls, [ 413 (self.test, subunit.RemoteError(""))]) 414 self.assertEqual(self.client.failure_calls, []) 401 details = {} 402 self.assertEqual([ 403 ('startTest', self.test), 404 ('addError', self.test, details), 405 ('stopTest', self.test), 406 ], self.client._events) 415 407 416 408 def test_simple_error(self): … … 423 415 self.protocol.lineReceived("error mcdonalds farm [\n") 424 416 self.protocol.lineReceived("]\n") 425 self.assertEqual(self.client.start_calls, [self.test]) 426 self.assertEqual(self.client.end_calls, [self.test]) 427 self.assertEqual(self.client.error_calls, [ 428 (self.test, subunit.RemoteError(""))]) 429 self.assertEqual(self.client.failure_calls, []) 417 details = {} 418 details['traceback'] = Content(ContentType("text", "x-traceback", 419 {'charset': 'utf8'}), lambda:[""]) 420 self.assertEqual([ 421 ('startTest', self.test), 422 ('addError', self.test, details), 423 ('stopTest', self.test), 424 ], self.client._events) 430 425 431 426 def error_quoted_bracket(self, keyword): … … 433 428 self.protocol.lineReceived(" ]\n") 434 429 self.protocol.lineReceived("]\n") 435 self.assertEqual(self.client.start_calls, [self.test]) 436 self.assertEqual(self.client.end_calls, [self.test]) 437 self.assertEqual(self.client.error_calls, [ 438 (self.test, subunit.RemoteError("]\n"))]) 439 self.assertEqual(self.client.failure_calls, []) 430 details = {} 431 details['traceback'] = Content(ContentType("text", "x-traceback", 432 {'charset': 'utf8'}), lambda:["]\n"]) 433 self.assertEqual([ 434 ('startTest', self.test), 435 ('addError', self.test, details), 436 ('stopTest', self.test), 437 ], self.client._events) 440 438 441 439 def test_error_quoted_bracket(self): … … 449 447 450 448 def setUp(self): 451 self.client = MockTestProtocolServerClient()449 self.client = ExtendedTestResult() 452 450 self.protocol = subunit.TestProtocolServer(self.client) 453 451 self.protocol.lineReceived("test mcdonalds farm\n") 454 452 self.test = subunit.RemotedTestCase("mcdonalds farm") 455 453 454 def assertFailure(self, details): 455 self.assertEqual([ 456 ('startTest', self.test), 457 ('addFailure', self.test, details), 458 ('stopTest', self.test), 459 ], self.client._events) 460 456 461 def simple_failure_keyword(self, keyword): 457 462 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword) 458 self.assertEqual(self.client.start_calls, [self.test]) 459 self.assertEqual(self.client.end_calls, [self.test]) 460 self.assertEqual(self.client.error_calls, []) 461 self.assertEqual(self.client.failure_calls, 462 [(self.test, subunit.RemoteError())]) 463 details = {} 464 self.assertFailure(details) 463 465 464 466 def test_simple_failure(self): … … 471 473 self.protocol.lineReceived("failure mcdonalds farm [\n") 472 474 self.protocol.lineReceived("]\n") 473 self.assertEqual(self.client.start_calls, [self.test]) 474 self.assertEqual(self.client.end_calls, [self.test]) 475 self.assertEqual(self.client.error_calls, []) 476 self.assertEqual(self.client.failure_calls, 477 [(self.test, subunit.RemoteError())]) 475 details = {} 476 details['traceback'] = Content(ContentType("text", "x-traceback", 477 {'charset': 'utf8'}), lambda:[""]) 478 self.assertFailure(details) 478 479 479 480 def failure_quoted_bracket(self, keyword): … … 481 482 self.protocol.lineReceived(" ]\n") 482 483 self.protocol.lineReceived("]\n") 483 self.assertEqual(self.client.start_calls, [self.test]) 484 self.assertEqual(self.client.end_calls, [self.test]) 485 self.assertEqual(self.client.error_calls, []) 486 self.assertEqual(self.client.failure_calls, 487 [(self.test, subunit.RemoteError("]\n"))]) 484 details = {} 485 details['traceback'] = Content(ContentType("text", "x-traceback", 486 {'charset': 'utf8'}), lambda:["]\n"]) 487 self.assertFailure(details) 488 488 489 489 def test_failure_quoted_bracket(self): … … 494 494 495 495 496 class TestTestProtocolServerAddxFail(unittest.TestCase): 497 """Tests for the xfail keyword. 498 499 In Python this can thunk through to Success due to stdlib limitations (see 500 README). 501 """ 502 503 def capture_expected_failure(self, test, err): 504 self._events.append((test, err)) 505 506 def setup_python26(self): 507 """Setup a test object ready to be xfailed and thunk to success.""" 508 self.client = Python26TestResult() 509 self.setup_protocol() 510 511 def setup_python27(self): 512 """Setup a test object ready to be xfailed.""" 513 self.client = Python27TestResult() 514 self.setup_protocol() 515 516 def setup_python_ex(self): 517 """Setup a test object ready to be xfailed with details.""" 518 self.client = ExtendedTestResult() 519 self.setup_protocol() 520 521 def setup_protocol(self): 522 """Setup the protocol based on self.client.""" 523 self.protocol = subunit.TestProtocolServer(self.client) 524 self.protocol.lineReceived("test mcdonalds farm\n") 525 self.test = self.client._events[-1][-1] 526 527 def simple_xfail_keyword(self, keyword, as_success): 528 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword) 529 self.check_success_or_xfail(as_success) 530 531 def check_success_or_xfail(self, as_success, error_message=None): 532 if as_success: 533 self.assertEqual([ 534 ('startTest', self.test), 535 ('addSuccess', self.test), 536 ('stopTest', self.test), 537 ], self.client._events) 538 else: 539 details = {} 540 if error_message is not None: 541 details['traceback'] = Content( 542 ContentType("text", "x-traceback", {'charset': 'utf8'}), 543 lambda:[error_message]) 544 if isinstance(self.client, ExtendedTestResult): 545 value = details 546 else: 547 if error_message is not None: 548 value = subunit.RemoteError(u'Text attachment: traceback\n' 549 '------------\n' + error_message + '------------\n') 550 else: 551 value = subunit.RemoteError() 552 self.assertEqual([ 553 ('startTest', self.test), 554 ('addExpectedFailure', self.test, value), 555 ('stopTest', self.test), 556 ], self.client._events) 557 558 def test_simple_xfail(self): 559 self.setup_python26() 560 self.simple_xfail_keyword("xfail", True) 561 self.setup_python27() 562 self.simple_xfail_keyword("xfail", False) 563 self.setup_python_ex() 564 self.simple_xfail_keyword("xfail", False) 565 566 def test_simple_xfail_colon(self): 567 self.setup_python26() 568 self.simple_xfail_keyword("xfail:", True) 569 self.setup_python27() 570 self.simple_xfail_keyword("xfail:", False) 571 self.setup_python_ex() 572 self.simple_xfail_keyword("xfail:", False) 573 574 def test_xfail_empty_message(self): 575 self.setup_python26() 576 self.empty_message(True) 577 self.setup_python27() 578 self.empty_message(False) 579 self.setup_python_ex() 580 self.empty_message(False, error_message="") 581 582 def empty_message(self, as_success, error_message="\n"): 583 self.protocol.lineReceived("xfail mcdonalds farm [\n") 584 self.protocol.lineReceived("]\n") 585 self.check_success_or_xfail(as_success, error_message) 586 587 def xfail_quoted_bracket(self, keyword, as_success): 588 # This tests it is accepted, but cannot test it is used today, because 589 # of not having a way to expose it in Python so far. 590 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword) 591 self.protocol.lineReceived(" ]\n") 592 self.protocol.lineReceived("]\n") 593 self.check_success_or_xfail(as_success, "]\n") 594 595 def test_xfail_quoted_bracket(self): 596 self.setup_python26() 597 self.xfail_quoted_bracket("xfail", True) 598 self.setup_python27() 599 self.xfail_quoted_bracket("xfail", False) 600 self.setup_python_ex() 601 self.xfail_quoted_bracket("xfail", False) 602 603 def test_xfail_colon_quoted_bracket(self): 604 self.setup_python26() 605 self.xfail_quoted_bracket("xfail:", True) 606 self.setup_python27() 607 self.xfail_quoted_bracket("xfail:", False) 608 self.setup_python_ex() 609 self.xfail_quoted_bracket("xfail:", False) 610 611 612 class TestTestProtocolServerAddSkip(unittest.TestCase): 613 """Tests for the skip keyword. 614 615 In Python this meets the testtools extended TestResult contract. 616 (See https://launchpad.net/testtools). 617 """ 618 619 def setUp(self): 620 """Setup a test object ready to be skipped.""" 621 self.client = ExtendedTestResult() 622 self.protocol = subunit.TestProtocolServer(self.client) 623 self.protocol.lineReceived("test mcdonalds farm\n") 624 self.test = self.client._events[-1][-1] 625 626 def assertSkip(self, reason): 627 details = {} 628 if reason is not None: 629 details['reason'] = Content( 630 ContentType("text", "plain"), lambda:[reason]) 631 self.assertEqual([ 632 ('startTest', self.test), 633 ('addSkip', self.test, details), 634 ('stopTest', self.test), 635 ], self.client._events) 636 637 def simple_skip_keyword(self, keyword): 638 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword) 639 self.assertSkip(None) 640 641 def test_simple_skip(self): 642 self.simple_skip_keyword("skip") 643 644 def test_simple_skip_colon(self): 645 self.simple_skip_keyword("skip:") 646 647 def test_skip_empty_message(self): 648 self.protocol.lineReceived("skip mcdonalds farm [\n") 649 self.protocol.lineReceived("]\n") 650 self.assertSkip("") 651 652 def skip_quoted_bracket(self, keyword): 653 # This tests it is accepted, but cannot test it is used today, because 654 # of not having a way to expose it in Python so far. 655 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword) 656 self.protocol.lineReceived(" ]\n") 657 self.protocol.lineReceived("]\n") 658 self.assertSkip("]\n") 659 660 def test_skip_quoted_bracket(self): 661 self.skip_quoted_bracket("skip") 662 663 def test_skip_colon_quoted_bracket(self): 664 self.skip_quoted_bracket("skip:") 665 666 496 667 class TestTestProtocolServerAddSuccess(unittest.TestCase): 497 668 498 669 def setUp(self): 499 self.client = MockTestProtocolServerClient()670 self.client = ExtendedTestResult() 500 671 self.protocol = subunit.TestProtocolServer(self.client) 501 672 self.protocol.lineReceived("test mcdonalds farm\n") … … 504 675 def simple_success_keyword(self, keyword): 505 676 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword) 506 self.assertEqual(self.client.start_calls, [self.test]) 507 self.assertEqual(self.client.end_calls, [self.test]) 508 self.assertEqual(self.client.error_calls, []) 509 self.assertEqual(self.client.success_calls, [self.test]) 677 self.assertEqual([ 678 ('startTest', self.test), 679 ('addSuccess', self.test), 680 ('stopTest', self.test), 681 ], self.client._events) 510 682 511 683 def test_simple_success(self): … … 520 692 def test_simple_success_colon(self): 521 693 self.simple_success_keyword("successful:") 694 695 def assertSuccess(self, details): 696 self.assertEqual([ 697 ('startTest', self.test), 698 ('addSuccess', self.test, details), 699 ('stopTest', self.test), 700 ], self.client._events) 701 702 def test_success_empty_message(self): 703 self.protocol.lineReceived("success mcdonalds farm [\n") 704 self.protocol.lineReceived("]\n") 705 details = {} 706 details['message'] = Content(ContentType("text", "plain"), 707 lambda:[""]) 708 self.assertSuccess(details) 709 710 def success_quoted_bracket(self, keyword): 711 # This tests it is accepted, but cannot test it is used today, because 712 # of not having a way to expose it in Python so far. 713 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword) 714 self.protocol.lineReceived(" ]\n") 715 self.protocol.lineReceived("]\n") 716 details = {} 717 details['message'] = Content(ContentType("text", "plain"), 718 lambda:["]\n"]) 719 self.assertSuccess(details) 720 721 def test_success_quoted_bracket(self): 722 self.success_quoted_bracket("success") 723 724 def test_success_colon_quoted_bracket(self): 725 self.success_quoted_bracket("success:") 726 727 728 class TestTestProtocolServerProgress(unittest.TestCase): 729 """Test receipt of progress: directives.""" 730 731 def test_progress_accepted_stdlib(self): 732 self.result = Python26TestResult() 733 self.stream = StringIO() 734 self.protocol = subunit.TestProtocolServer(self.result, 735 stream=self.stream) 736 self.protocol.lineReceived("progress: 23") 737 self.protocol.lineReceived("progress: -2") 738 self.protocol.lineReceived("progress: +4") 739 self.assertEqual("", self.stream.getvalue()) 740 741 def test_progress_accepted_extended(self): 742 # With a progress capable TestResult, progress events are emitted. 743 self.result = ExtendedTestResult() 744 self.stream = StringIO() 745 self.protocol = subunit.TestProtocolServer(self.result, 746 stream=self.stream) 747 self.protocol.lineReceived("progress: 23") 748 self.protocol.lineReceived("progress: push") 749 self.protocol.lineReceived("progress: -2") 750 self.protocol.lineReceived("progress: pop") 751 self.protocol.lineReceived("progress: +4") 752 self.assertEqual("", self.stream.getvalue()) 753 self.assertEqual([ 754 ('progress', 23, subunit.PROGRESS_SET), 755 ('progress', None, subunit.PROGRESS_PUSH), 756 ('progress', -2, subunit.PROGRESS_CUR), 757 ('progress', None, subunit.PROGRESS_POP), 758 ('progress', 4, subunit.PROGRESS_CUR), 759 ], self.result._events) 760 761 762 class TestTestProtocolServerStreamTags(unittest.TestCase): 763 """Test managing tags on the protocol level.""" 764 765 def setUp(self): 766 self.client = ExtendedTestResult() 767 self.protocol = subunit.TestProtocolServer(self.client) 768 769 def test_initial_tags(self): 770 self.protocol.lineReceived("tags: foo bar:baz quux\n") 771 self.assertEqual([ 772 ('tags', set(["foo", "bar:baz", "quux"]), set()), 773 ], self.client._events) 774 775 def test_minus_removes_tags(self): 776 self.protocol.lineReceived("tags: -bar quux\n") 777 self.assertEqual([ 778 ('tags', set(["quux"]), set(["bar"])), 779 ], self.client._events) 780 781 def test_tags_do_not_get_set_on_test(self): 782 self.protocol.lineReceived("test mcdonalds farm\n") 783 test = self.client._events[0][-1] 784 self.assertEqual(None, getattr(test, 'tags', None)) 785 786 def test_tags_do_not_get_set_on_global_tags(self): 787 self.protocol.lineReceived("tags: foo bar\n") 788 self.protocol.lineReceived("test mcdonalds farm\n") 789 test = self.client._events[-1][-1] 790 self.assertEqual(None, getattr(test, 'tags', None)) 791 792 def test_tags_get_set_on_test_tags(self): 793 self.protocol.lineReceived("test mcdonalds farm\n") 794 test = self.client._events[-1][-1] 795 self.protocol.lineReceived("tags: foo bar\n") 796 self.protocol.lineReceived("success mcdonalds farm\n") 797 self.assertEqual(None, getattr(test, 'tags', None)) 798 799 800 class TestTestProtocolServerStreamTime(unittest.TestCase): 801 """Test managing time information at the protocol level.""" 802 803 def test_time_accepted_stdlib(self): 804 self.result = Python26TestResult() 805 self.stream = StringIO() 806 self.protocol = subunit.TestProtocolServer(self.result, 807 stream=self.stream) 808 self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n") 809 self.assertEqual("", self.stream.getvalue()) 810 811 def test_time_accepted_extended(self): 812 self.result = ExtendedTestResult() 813 self.stream = StringIO() 814 self.protocol = subunit.TestProtocolServer(self.result, 815 stream=self.stream) 816 self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n") 817 self.assertEqual("", self.stream.getvalue()) 818 self.assertEqual([ 819 ('time', datetime.datetime(2001, 12, 12, 12, 59, 59, 0, 820 iso8601.Utc())) 821 ], self.result._events) 522 822 523 823 … … 530 830 self.assertEqual("A test description", 531 831 test.shortDescription()) 532 self.assertEqual(" subunit.RemotedTestCase.A test description",832 self.assertEqual("A test description", 533 833 test.id()) 534 834 self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test) … … 537 837 result = unittest.TestResult() 538 838 test.run(result) 539 self.assertEqual([(test, "RemoteException: "839 self.assertEqual([(test, _remote_exception_str + ": " 540 840 "Cannot run RemotedTestCases.\n\n")], 541 841 result.errors) … … 551 851 552 852 def test_eq(self): 553 error = subunit.RemoteError( "Something went wrong")554 another_error = subunit.RemoteError( "Something went wrong")555 different_error = subunit.RemoteError( "boo!")853 error = subunit.RemoteError(u"Something went wrong") 854 another_error = subunit.RemoteError(u"Something went wrong") 855 different_error = subunit.RemoteError(u"boo!") 556 856 self.assertEqual(error, another_error) 557 857 self.assertNotEqual(error, different_error) … … 559 859 560 860 def test_empty_constructor(self): 561 self.assertEqual(subunit.RemoteError(), subunit.RemoteError( ""))861 self.assertEqual(subunit.RemoteError(), subunit.RemoteError(u"")) 562 862 563 863 … … 571 871 # that fails, errors and succeeds 572 872 873 def test_sample_method_args(self): 874 """sample-script.py foo""" 875 # sample that will run just one test. 573 876 574 877 def test_construct(self): … … 577 880 subunit.join_dir(__file__, 'sample-script.py')) 578 881 882 def test_args(self): 883 result = unittest.TestResult() 884 test = self.SampleExecTestCase("test_sample_method_args") 885 test.run(result) 886 self.assertEqual(1, result.testsRun) 887 579 888 def test_run(self): 580 r unner = MockTestProtocolServerClient()889 result = ExtendedTestResult() 581 890 test = self.SampleExecTestCase("test_sample_method") 582 test.run(r unner)891 test.run(result) 583 892 mcdonald = subunit.RemotedTestCase("old mcdonald") 584 893 bing = subunit.RemotedTestCase("bing crosby") 894 bing_details = {} 895 bing_details['traceback'] = Content(ContentType("text", "x-traceback", 896 {'charset': 'utf8'}), lambda:["foo.c:53:ERROR invalid state\n"]) 585 897 an_error = subunit.RemotedTestCase("an error") 586 self.assertEqual(runner.error_calls, 587 [(an_error, subunit.RemoteError())]) 588 self.assertEqual(runner.failure_calls, 589 [(bing, 590 subunit.RemoteError( 591 "foo.c:53:ERROR invalid state\n"))]) 592 self.assertEqual(runner.start_calls, [mcdonald, bing, an_error]) 593 self.assertEqual(runner.end_calls, [mcdonald, bing, an_error]) 898 error_details = {} 899 self.assertEqual([ 900 ('startTest', mcdonald), 901 ('addSuccess', mcdonald), 902 ('stopTest', mcdonald), 903 ('startTest', bing), 904 ('addFailure', bing, bing_details), 905 ('stopTest', bing), 906 ('startTest', an_error), 907 ('addError', an_error, error_details), 908 ('stopTest', an_error), 909 ], result._events) 594 910 595 911 def test_debug(self): … … 690 1006 self.protocol = subunit.TestProtocolClient(self.io) 691 1007 self.test = TestTestProtocolClient("test_start_test") 692 1008 self.sample_details = {'something':Content( 1009 ContentType('text', 'plain'), lambda:['serialised\nform'])} 1010 self.sample_tb_details = dict(self.sample_details) 1011 self.sample_tb_details['traceback'] = TracebackContent( 1012 subunit.RemoteError(u"boo qux"), self.test) 693 1013 694 1014 def test_start_test(self): … … 698 1018 699 1019 def test_stop_test(self): 700 """Test stopTest on a TestProtocolClient."""1020 # stopTest doesn't output anything. 701 1021 self.protocol.stopTest(self.test) 702 1022 self.assertEqual(self.io.getvalue(), "") … … 708 1028 self.io.getvalue(), "successful: %s\n" % self.test.id()) 709 1029 1030 def test_add_success_details(self): 1031 """Test addSuccess on a TestProtocolClient with details.""" 1032 self.protocol.addSuccess(self.test, details=self.sample_details) 1033 self.assertEqual( 1034 self.io.getvalue(), "successful: %s [ multipart\n" 1035 "Content-Type: text/plain\n" 1036 "something\n" 1037 "F\r\nserialised\nform0\r\n]\n" % self.test.id()) 1038 710 1039 def test_add_failure(self): 711 1040 """Test addFailure on a TestProtocolClient.""" 712 self.protocol.addFailure(self.test, subunit.RemoteError("boo")) 1041 self.protocol.addFailure( 1042 self.test, subunit.RemoteError(u"boo qux")) 713 1043 self.assertEqual( 714 1044 self.io.getvalue(), 715 'failure: %s [\nRemoteException: boo\n]\n' % self.test.id()) 1045 ('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n') 1046 % self.test.id()) 1047 1048 def test_add_failure_details(self): 1049 """Test addFailure on a TestProtocolClient with details.""" 1050 self.protocol.addFailure( 1051 self.test, details=self.sample_tb_details) 1052 self.assertEqual( 1053 self.io.getvalue(), 1054 ("failure: %s [ multipart\n" 1055 "Content-Type: text/plain\n" 1056 "something\n" 1057 "F\r\nserialised\nform0\r\n" 1058 "Content-Type: text/x-traceback;charset=utf8,language=python\n" 1059 "traceback\n" 1060 "1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n" 1061 "]\n") % self.test.id()) 716 1062 717 1063 def test_add_error(self): 718 1064 """Test stopTest on a TestProtocolClient.""" 719 self.protocol.addError(self.test, subunit.RemoteError("phwoar")) 1065 self.protocol.addError( 1066 self.test, subunit.RemoteError(u"phwoar crikey")) 720 1067 self.assertEqual( 721 1068 self.io.getvalue(), 722 'error: %s [\n' 723 "RemoteException: phwoar\n" 1069 ('error: %s [\n' + 1070 _remote_exception_str + ": phwoar crikey\n" 1071 "]\n") % self.test.id()) 1072 1073 def test_add_error_details(self): 1074 """Test stopTest on a TestProtocolClient with details.""" 1075 self.protocol.addError( 1076 self.test, details=self.sample_tb_details) 1077 self.assertEqual( 1078 self.io.getvalue(), 1079 ("error: %s [ multipart\n" 1080 "Content-Type: text/plain\n" 1081 "something\n" 1082 "F\r\nserialised\nform0\r\n" 1083 "Content-Type: text/x-traceback;charset=utf8,language=python\n" 1084 "traceback\n" 1085 "1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n" 1086 "]\n") % self.test.id()) 1087 1088 def test_add_expected_failure(self): 1089 """Test addExpectedFailure on a TestProtocolClient.""" 1090 self.protocol.addExpectedFailure( 1091 self.test, subunit.RemoteError(u"phwoar crikey")) 1092 self.assertEqual( 1093 self.io.getvalue(), 1094 ('xfail: %s [\n' + 1095 _remote_exception_str + ": phwoar crikey\n" 1096 "]\n") % self.test.id()) 1097 1098 def test_add_expected_failure_details(self): 1099 """Test addExpectedFailure on a TestProtocolClient with details.""" 1100 self.protocol.addExpectedFailure( 1101 self.test, details=self.sample_tb_details) 1102 self.assertEqual( 1103 self.io.getvalue(), 1104 ("xfail: %s [ multipart\n" 1105 "Content-Type: text/plain\n" 1106 "something\n" 1107 "F\r\nserialised\nform0\r\n" 1108 "Content-Type: text/x-traceback;charset=utf8,language=python\n" 1109 "traceback\n" 1110 "1A\r\n"+ _remote_exception_str + ": boo qux\n0\r\n" 1111 "]\n") % self.test.id()) 1112 1113 def test_add_skip(self): 1114 """Test addSkip on a TestProtocolClient.""" 1115 self.protocol.addSkip( 1116 self.test, "Has it really?") 1117 self.assertEqual( 1118 self.io.getvalue(), 1119 'skip: %s [\nHas it really?\n]\n' % self.test.id()) 1120 1121 def test_add_skip_details(self): 1122 """Test addSkip on a TestProtocolClient with details.""" 1123 details = {'reason':Content( 1124 ContentType('text', 'plain'), lambda:['Has it really?'])} 1125 self.protocol.addSkip( 1126 self.test, details=details) 1127 self.assertEqual( 1128 self.io.getvalue(), 1129 "skip: %s [ multipart\n" 1130 "Content-Type: text/plain\n" 1131 "reason\n" 1132 "E\r\nHas it really?0\r\n" 724 1133 "]\n" % self.test.id()) 1134 1135 def test_progress_set(self): 1136 self.protocol.progress(23, subunit.PROGRESS_SET) 1137 self.assertEqual(self.io.getvalue(), 'progress: 23\n') 1138 1139 def test_progress_neg_cur(self): 1140 self.protocol.progress(-23, subunit.PROGRESS_CUR) 1141 self.assertEqual(self.io.getvalue(), 'progress: -23\n') 1142 1143 def test_progress_pos_cur(self): 1144 self.protocol.progress(23, subunit.PROGRESS_CUR) 1145 self.assertEqual(self.io.getvalue(), 'progress: +23\n') 1146 1147 def test_progress_pop(self): 1148 self.protocol.progress(1234, subunit.PROGRESS_POP) 1149 self.assertEqual(self.io.getvalue(), 'progress: pop\n') 1150 1151 def test_progress_push(self): 1152 self.protocol.progress(1234, subunit.PROGRESS_PUSH) 1153 self.assertEqual(self.io.getvalue(), 'progress: push\n') 1154 1155 def test_time(self): 1156 # Calling time() outputs a time signal immediately. 1157 self.protocol.time( 1158 datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc())) 1159 self.assertEqual( 1160 "time: 2009-10-11 12:13:14.000015Z\n", 1161 self.io.getvalue()) 1162 1163 def test_add_unexpected_success(self): 1164 """Test addUnexpectedSuccess on a TestProtocolClient.""" 1165 self.protocol.addUnexpectedSuccess(self.test) 1166 self.assertEqual( 1167 self.io.getvalue(), "successful: %s\n" % self.test.id()) 1168 1169 def test_add_unexpected_success_details(self): 1170 """Test addUnexpectedSuccess on a TestProtocolClient with details.""" 1171 self.protocol.addUnexpectedSuccess(self.test, details=self.sample_details) 1172 self.assertEqual( 1173 self.io.getvalue(), "successful: %s [ multipart\n" 1174 "Content-Type: text/plain\n" 1175 "something\n" 1176 "F\r\nserialised\nform0\r\n]\n" % self.test.id()) 725 1177 726 1178 -
vendor/current/lib/talloc/pytalloc.c
r414 r740 1 1 /* 2 2 Unix SMB/CIFS implementation. 3 Python /Talloc glue4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 20 085 3 Python Talloc Module 4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010 5 6 6 This program is free software; you can redistribute it and/or modify 7 7 it under the terms of the GNU General Public License as published by 8 8 the Free Software Foundation; either version 3 of the License, or 9 9 (at your option) any later version. 10 10 11 11 This program is distributed in the hope that it will be useful, 12 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 14 GNU General Public License for more details. 15 15 16 16 You should have received a copy of the GNU General Public License 17 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 18 */ 19 19 20 #include "replace.h"20 #include <Python.h> 21 21 #include <talloc.h> 22 22 #include <pytalloc.h> 23 23 24 /** 25 * Simple dealloc for talloc-wrapping PyObjects 26 */27 void py_talloc_dealloc(PyObject* self)24 void inittalloc(void); 25 26 /* print a talloc tree report for a talloc python object */ 27 static PyObject *py_talloc_report_full(PyObject *self, PyObject *args) 28 28 { 29 py_talloc_Object *obj = (py_talloc_Object *)self; 30 talloc_free(obj->talloc_ctx); 31 obj->talloc_ctx = NULL; 32 self->ob_type->tp_free(self); 29 PyObject *py_obj = Py_None; 30 PyTypeObject *type; 31 32 if (!PyArg_ParseTuple(args, "|O", &py_obj)) 33 return NULL; 34 35 if (py_obj == Py_None) { 36 talloc_report_full(NULL, stdout); 37 } else { 38 type = (PyTypeObject*)PyObject_Type(py_obj); 39 talloc_report_full(py_talloc_get_mem_ctx(py_obj), stdout); 40 } 41 return Py_None; 33 42 } 34 43 35 /** 36 * Import an existing talloc pointer into a Python object. 37 */ 38 PyObject *py_talloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, 39 void *ptr) 44 /* enable null tracking */ 45 static PyObject *py_talloc_enable_null_tracking(PyObject *self) 40 46 { 41 py_talloc_Object *ret = (py_talloc_Object *)py_type->tp_alloc(py_type, 0); 42 ret->talloc_ctx = talloc_new(NULL); 43 if (ret->talloc_ctx == NULL) { 44 return NULL; 45 } 46 if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { 47 return NULL; 48 } 49 ret->ptr = ptr; 50 return (PyObject *)ret; 47 talloc_enable_null_tracking(); 48 return Py_None; 51 49 } 52 50 51 /* return the number of talloc blocks */ 52 static PyObject *py_talloc_total_blocks(PyObject *self, PyObject *args) 53 { 54 PyObject *py_obj = Py_None; 55 PyTypeObject *type; 56 57 if (!PyArg_ParseTuple(args, "|O", &py_obj)) 58 return NULL; 59 60 if (py_obj == Py_None) { 61 return PyLong_FromLong(talloc_total_blocks(NULL)); 62 } 63 64 type = (PyTypeObject*)PyObject_Type(py_obj); 65 66 return PyLong_FromLong(talloc_total_blocks(py_talloc_get_mem_ctx(py_obj))); 67 } 68 69 static PyMethodDef talloc_methods[] = { 70 { "report_full", (PyCFunction)py_talloc_report_full, METH_VARARGS, 71 "show a talloc tree for an object"}, 72 { "enable_null_tracking", (PyCFunction)py_talloc_enable_null_tracking, METH_NOARGS, 73 "enable tracking of the NULL object"}, 74 { "total_blocks", (PyCFunction)py_talloc_total_blocks, METH_VARARGS, 75 "return talloc block count"}, 76 { NULL } 77 }; 53 78 54 79 /** 55 * Import an existing talloc pointer into a Python object, leaving the 56 * original parent, and creating a reference to the object in the python 57 * object 80 * Default (but only slightly more useful than the default) implementation of Repr(). 58 81 */ 59 PyObject *py_talloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) 60 { 61 py_talloc_Object *ret = (py_talloc_Object *)py_type->tp_alloc(py_type, 0); 62 ret->talloc_ctx = talloc_new(NULL); 63 if (ret->talloc_ctx == NULL) { 64 return NULL; 65 } 66 if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) { 67 return NULL; 68 } 69 ret->ptr = ptr; 70 return (PyObject *)ret; 71 } 72 73 /** 74 * Default (but slightly more useful than the default) implementation of Repr(). 75 */ 76 PyObject *py_talloc_default_repr(PyObject *obj) 82 static PyObject *py_talloc_default_repr(PyObject *obj) 77 83 { 78 84 py_talloc_Object *talloc_obj = (py_talloc_Object *)obj; … … 83 89 } 84 90 85 static void py_cobject_talloc_free(void *ptr) 91 /** 92 * Simple dealloc for talloc-wrapping PyObjects 93 */ 94 static void py_talloc_dealloc(PyObject* self) 86 95 { 87 talloc_free(ptr); 96 py_talloc_Object *obj = (py_talloc_Object *)self; 97 assert(talloc_unlink(NULL, obj->talloc_ctx) != -1); 98 obj->talloc_ctx = NULL; 99 self->ob_type->tp_free(self); 88 100 } 89 101 90 PyObject *PyCObject_FromTallocPtr(void *ptr) 102 /** 103 * Default (but only slightly more useful than the default) implementation of cmp. 104 */ 105 static int py_talloc_default_cmp(PyObject *_obj1, PyObject *_obj2) 91 106 { 92 return PyCObject_FromVoidPtr(ptr, py_cobject_talloc_free); 107 py_talloc_Object *obj1 = (py_talloc_Object *)_obj1, 108 *obj2 = (py_talloc_Object *)_obj2; 109 if (obj1->ob_type != obj2->ob_type) 110 return (obj1->ob_type - obj2->ob_type); 111 112 return ((char *)py_talloc_get_ptr(obj1) - (char *)py_talloc_get_ptr(obj2)); 93 113 } 114 115 static PyTypeObject TallocObject_Type = { 116 .tp_name = "talloc.Object", 117 .tp_doc = "Python wrapper for a talloc-maintained object.", 118 .tp_basicsize = sizeof(py_talloc_Object), 119 .tp_dealloc = (destructor)py_talloc_dealloc, 120 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 121 .tp_repr = py_talloc_default_repr, 122 .tp_compare = py_talloc_default_cmp, 123 }; 124 125 void inittalloc(void) 126 { 127 PyObject *m; 128 129 if (PyType_Ready(&TallocObject_Type) < 0) 130 return; 131 132 m = Py_InitModule3("talloc", talloc_methods, 133 "Python wrapping of talloc-maintained objects."); 134 if (m == NULL) 135 return; 136 137 Py_INCREF(&TallocObject_Type); 138 PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type); 139 } -
vendor/current/lib/talloc/pytalloc.h
r414 r740 30 30 } py_talloc_Object; 31 31 32 /* Deallocate a py_talloc_Object */ 33 void py_talloc_dealloc(PyObject* self);32 PyTypeObject *PyTalloc_GetObjectType(void); 33 int PyTalloc_Check(PyObject *); 34 34 35 35 /* Retrieve the pointer for a py_talloc_object. Like talloc_get_type() … … 44 44 45 45 PyObject *py_talloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr); 46 PyObject *py_talloc_steal(PyTypeObject *py_type, void *ptr); 46 47 PyObject *py_talloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr); 47 #define py_talloc_steal(py_type, talloc_ptr) py_talloc_steal_ex(py_type, talloc_ptr, talloc_ptr)48 48 #define py_talloc_reference(py_type, talloc_ptr) py_talloc_reference_ex(py_type, talloc_ptr, talloc_ptr) 49 50 /* Sane default implementation of reprfunc. */51 PyObject *py_talloc_default_repr(PyObject *py_obj);52 49 53 50 #define py_talloc_new(type, typeobj) py_talloc_steal(typeobj, talloc_zero(NULL, type)) … … 55 52 PyObject *PyCObject_FromTallocPtr(void *); 56 53 54 PyObject *PyString_FromString_check_null(const char *ptr); 55 57 56 #endif /* _PY_TALLOC_H_ */ -
vendor/current/lib/talloc/script/mksigs.pl
r414 r740 28 28 29 29 my $in_comment = 0; 30 my $in_doxygen = 0; 30 31 my $extern_C_block = 0; 31 32 … … 40 41 next; 41 42 } 43 } 44 45 # find end of DOXYGEN section 46 if ($in_doxygen) { 47 if ($LINE =~ /^#\s*else(?:\s+.*)?$/) { 48 $in_doxygen = 0; 49 } 50 next; 42 51 } 43 52 … … 69 78 $LINE .= " " . $LINE2; 70 79 } 80 81 # remove DOXYGEN sections 82 if ($LINE =~ /^#\s*ifdef\s+DOXYGEN(?:\s+.*)?$/) { 83 $in_doxygen = 1; 84 next; 85 } 86 71 87 72 88 # remove all preprocessor directives -
vendor/current/lib/talloc/script/mksyms.awk
r414 r740 9 9 BEGIN { 10 10 inheader=0; 11 indoxygen=0; 11 12 } 12 13 … … 21 22 next; 22 23 } 24 if (indoxygen) { 25 if (match($0,"^#[ \t]*else[ \t]*.*$")) { 26 indoxygen = 0; 27 } 28 next; 29 } 23 30 } 24 31 25 /^static/ || /^[ \t]*typedef/ || !/^[a-zA-Z\_ ]/ {32 /^static/ || /^[ \t]*typedef/ || !/^[a-zA-Z\_\#]/ { 26 33 next; 27 34 } … … 34 41 } 35 42 43 /^#[ \t]*ifdef[ \t]*DOXYGEN[ \t]*.*$/ { 44 indoxygen=1; 45 next; 46 } 47 36 48 # look for function headers: 37 49 { 38 50 gotstart = 0; 39 51 if ($0 ~ /^[A-Za-z_][A-Za-z0-9_]+/) { 40 gotstart = 1;52 gotstart = 1; 41 53 } 42 54 if(!gotstart) { -
vendor/current/lib/talloc/script/release-script.sh
r414 r740 1 1 #!/bin/bash 2 3 LNAME=talloc 4 LINCLUDE=talloc.h 2 5 3 6 if [ "$1" = "" ]; then … … 6 9 fi 7 10 8 if [ ! -d "lib/ talloc" ]; then11 if [ ! -d "lib/${LNAME}" ]; then 9 12 echo "Run this script from the samba base directory." 10 13 exit 1 11 14 fi 12 13 # Check exports and signatures are up to date14 pushd lib/talloc15 ./script/abi_checks.sh talloc talloc.h16 abicheck=$?17 popd18 if [ ! "$abicheck" = "0" ]; then19 echo "ERROR: ABI Checks produced warnings!"20 exit 121 fi22 23 git clean -f -x -d lib/talloc24 git clean -f -x -d lib/replace25 15 26 16 curbranch=`git branch |grep "^*" | tr -d "* "` … … 30 20 31 21 # Checkout the release tag 32 git branch -f talloc-release-script-${strver} talloc-${strver}22 git branch -f ${LNAME}-release-script-${strver} ${LNAME}-${strver} 33 23 if [ ! "$?" = "0" ]; then 34 echo "Unable to checkout talloc-${strver} release"24 echo "Unable to checkout ${LNAME}-${strver} release" 35 25 exit 1 36 26 fi 37 27 38 git checkout talloc-release-script-${strver} 28 function cleanquit { 29 #Clean up 30 git checkout $curbranch 31 git branch -d ${LNAME}-release-script-${strver} 32 exit $1 33 } 34 35 # NOTE: use cleanquit after this point 36 git checkout ${LNAME}-release-script-${strver} 39 37 40 38 # Test configure agrees with us 41 confver=`grep "^AC_INIT" lib/ talloc/configure.ac | tr -d "AC_INIT(talloc, " | tr -d ")"`39 confver=`grep "^AC_INIT" lib/${LNAME}/configure.ac | tr -d "AC_INIT(${LNAME}, " | tr -d ")"` 42 40 if [ ! "$confver" = "$version" ]; then 43 41 echo "Wrong version, requested release for ${version}, found ${confver}" 44 exit 142 cleanquit 1 45 43 fi 46 44 45 # Check exports and signatures are up to date 46 pushd lib/${LNAME} 47 ./script/abi_checks.sh ${LNAME} ${LINCLUDE} 48 abicheck=$? 49 popd 50 if [ ! "$abicheck" = "0" ]; then 51 echo "ERROR: ABI Checks produced warnings!" 52 cleanquit 1 53 fi 54 55 git clean -f -x -d lib/${LNAME} 56 git clean -f -x -d lib/replace 57 47 58 # Now build tarball 48 cp -a lib/ talloc talloc-${version}49 cp -a lib/replace talloc-${version}/libreplace50 pushd talloc-${version}59 cp -a lib/${LNAME} ${LNAME}-${version} 60 cp -a lib/replace ${LNAME}-${version}/libreplace 61 pushd ${LNAME}-${version} 51 62 ./autogen.sh 52 63 popd 53 tar cvzf talloc-${version}.tar.gz talloc-${version}54 rm -fr talloc-${version}64 tar cvzf ${LNAME}-${version}.tar.gz ${LNAME}-${version} 65 rm -fr ${LNAME}-${version} 55 66 56 #Clean up 57 git checkout $curbranch 58 git branch -d talloc-release-script-${strver} 67 cleanquit 0 68 -
vendor/current/lib/talloc/talloc.3.xml
r414 r740 11 11 </refnamediv> 12 12 <refsynopsisdiv> 13 <synopsis>#include <talloc /talloc.h></synopsis>13 <synopsis>#include <talloc.h></synopsis> 14 14 </refsynopsisdiv> 15 15 <refsect1><title>DESCRIPTION</title> … … 363 363 <para> 364 364 This is a utility macro that creates a new memory context hanging 365 off an exi ting context, automatically naming it "talloc_new:365 off an existing context, automatically naming it "talloc_new: 366 366 __location__" where __location__ is the source line it is called 367 367 from. It is particularly useful for creating a new temporary … … 646 646 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 647 647 </refsect2> 648 <refsect2><title>char *talloc_ append_string(const void *<emphasis role="italic">t</emphasis>, char *<emphasis role="italic">orig</emphasis>, const char *<emphasis role="italic">append</emphasis>);</title>649 <para> 650 The talloc_ append_string() function appends the given formatted651 string to the given string.648 <refsect2><title>char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>);</title> 649 <para> 650 The talloc_vasprintf() function is the talloc equivalent of the C 651 library function vasprintf(3). 652 652 </para> 653 653 <para> … … 657 657 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 658 658 </refsect2> 659 <refsect2><title>char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>);</title> 660 <para> 661 The talloc_vasprintf() function is the talloc equivalent of the C 662 library function vasprintf(3). 659 <refsect2><title>char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title> 660 <para> 661 The talloc_asprintf() function is the talloc equivalent of the C 662 library function asprintf(3). 663 </para> 664 <para> 665 This function sets the name of the new pointer to the passed 666 string. This is equivalent to: 667 </para> 668 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 669 </refsect2> 670 <refsect2><title>char *talloc_asprintf_append(char *s, const char *fmt, ...);</title> 671 <para> 672 The talloc_asprintf_append() function appends the given formatted 673 string to the given string. 663 674 </para> 664 675 <para> … … 668 679 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 669 680 </refsect2> 670 <refsect2><title>char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title> 671 <para> 672 The talloc_asprintf() function is the talloc equivalent of the C 673 library function asprintf(3). 674 </para> 675 <para> 676 This function sets the name of the new pointer to the passed 677 string. This is equivalent to: 678 </para> 679 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 680 </refsect2> 681 <refsect2><title>char *talloc_asprintf_append(char *s, const char *fmt, ...);</title> 682 <para> 683 The talloc_asprintf_append() function appends the given formatted 684 string to the given string. 685 </para> 686 <para> 687 This function sets the name of the new pointer to the new 688 string. This is equivalent to: 689 </para> 690 <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> 691 </refsect2> 692 <refsect2><title>(type *)talloc_array(const void *ctx, type, uint_t count);</title> 681 <refsect2><title>(type *)talloc_array(const void *ctx, type, unsigned int count);</title> 693 682 <para> 694 683 The talloc_array() macro is equivalent to: … … 700 689 </para> 701 690 </refsect2> 702 <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, u int_t count);</title>691 <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, unsigned int count);</title> 703 692 <para> 704 693 The talloc_array_size() function is useful when the type is not … … 707 696 </para> 708 697 </refsect2> 709 <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, u int_t count);</title>698 <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);</title> 710 699 <para> 711 700 The talloc_ptrtype() macro should be used when you have a pointer to an array -
vendor/current/lib/talloc/talloc.c
r414 r740 46 46 #endif 47 47 48 /* Special macros that are no-ops except when run under Valgrind on 49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */ 50 #ifdef HAVE_VALGRIND_MEMCHECK_H 51 /* memcheck.h includes valgrind.h */ 52 #include <valgrind/memcheck.h> 53 #elif defined(HAVE_VALGRIND_H) 54 #include <valgrind.h> 55 #endif 56 48 57 /* use this to force every realloc to change the pointer, to stress test 49 58 code that might not cope */ … … 104 113 static void *null_context; 105 114 static void *autofree_context; 115 116 /* used to enable fill of memory on free, which can be useful for 117 * catching use after free errors when valgrind is too slow 118 */ 119 static struct { 120 bool initialised; 121 bool enabled; 122 uint8_t fill_value; 123 } talloc_fill; 124 125 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL" 126 127 /* 128 * do not wipe the header, to allow the 129 * double-free logic to still work 130 */ 131 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \ 132 if (unlikely(talloc_fill.enabled)) { \ 133 size_t _flen = (_tc)->size; \ 134 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ 135 memset(_fptr, talloc_fill.fill_value, _flen); \ 136 } \ 137 } while (0) 138 139 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 140 /* Mark the whole chunk as not accessable */ 141 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \ 142 size_t _flen = TC_HDR_SIZE + (_tc)->size; \ 143 char *_fptr = (char *)(_tc); \ 144 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ 145 } while(0) 146 #else 147 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0) 148 #endif 149 150 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \ 151 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \ 152 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \ 153 } while (0) 154 155 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ 156 if (unlikely(talloc_fill.enabled)) { \ 157 size_t _flen = (_tc)->size - (_new_size); \ 158 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ 159 _fptr += (_new_size); \ 160 memset(_fptr, talloc_fill.fill_value, _flen); \ 161 } \ 162 } while (0) 163 164 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 165 /* Mark the unused bytes not accessable */ 166 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ 167 size_t _flen = (_tc)->size - (_new_size); \ 168 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ 169 _fptr += (_new_size); \ 170 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ 171 } while (0) 172 #else 173 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 174 #endif 175 176 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \ 177 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \ 178 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ 179 } while (0) 180 181 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ 182 if (unlikely(talloc_fill.enabled)) { \ 183 size_t _flen = (_tc)->size - (_new_size); \ 184 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ 185 _fptr += (_new_size); \ 186 memset(_fptr, talloc_fill.fill_value, _flen); \ 187 } \ 188 } while (0) 189 190 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) 191 /* Mark the unused bytes as undefined */ 192 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ 193 size_t _flen = (_tc)->size - (_new_size); \ 194 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ 195 _fptr += (_new_size); \ 196 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ 197 } while (0) 198 #else 199 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 200 #endif 201 202 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \ 203 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \ 204 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ 205 } while (0) 206 207 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) 208 /* Mark the new bytes as undefined */ 209 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \ 210 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \ 211 size_t _new_used = TC_HDR_SIZE + (_new_size); \ 212 size_t _flen = _new_used - _old_used; \ 213 char *_fptr = _old_used + (char *)(_tc); \ 214 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ 215 } while (0) 216 #else 217 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 218 #endif 219 220 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \ 221 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \ 222 } while (0) 106 223 107 224 struct talloc_reference_handle { … … 137 254 138 255 /* 16 byte alignment seems to keep everyone happy */ 139 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) 256 #define TC_ALIGN16(s) (((s)+15)&~15) 257 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk)) 140 258 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) 141 259 142 int talloc_version_major(void)260 _PUBLIC_ int talloc_version_major(void) 143 261 { 144 262 return TALLOC_VERSION_MAJOR; 145 263 } 146 264 147 int talloc_version_minor(void)265 _PUBLIC_ int talloc_version_minor(void) 148 266 { 149 267 return TALLOC_VERSION_MINOR; … … 152 270 static void (*talloc_log_fn)(const char *message); 153 271 154 void talloc_set_log_fn(void (*log_fn)(const char *message))272 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message)) 155 273 { 156 274 talloc_log_fn = log_fn; … … 180 298 } 181 299 182 void talloc_set_log_stderr(void)300 _PUBLIC_ void talloc_set_log_stderr(void) 183 301 { 184 302 talloc_set_log_fn(talloc_log_stderr); … … 187 305 static void (*talloc_abort_fn)(const char *reason); 188 306 189 void talloc_set_abort_fn(void (*abort_fn)(const char *reason))307 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) 190 308 { 191 309 talloc_abort_fn = abort_fn; … … 214 332 } 215 333 216 static void talloc_abort_ double_free(void)217 { 218 talloc_abort("Bad talloc magic value - doublefree");334 static void talloc_abort_access_after_free(void) 335 { 336 talloc_abort("Bad talloc magic value - access after free"); 219 337 } 220 338 … … 236 354 237 355 if (tc->flags & TALLOC_FLAG_FREE) { 238 talloc_log("talloc: doublefree error - first free may be at %s\n", tc->name);239 talloc_abort_ double_free();356 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name); 357 talloc_abort_access_after_free(); 240 358 return NULL; 241 359 } else { … … 292 410 } 293 411 294 void *talloc_parent(const void *ptr)412 _PUBLIC_ void *talloc_parent(const void *ptr) 295 413 { 296 414 struct talloc_chunk *tc = talloc_parent_chunk(ptr); … … 301 419 find parents name 302 420 */ 303 const char *talloc_parent_name(const void *ptr)421 _PUBLIC_ const char *talloc_parent_name(const void *ptr) 304 422 { 305 423 struct talloc_chunk *tc = talloc_parent_chunk(ptr); … … 322 440 #define TALLOC_POOL_HDR_SIZE 16 323 441 442 #define TC_POOL_SPACE_LEFT(_pool_tc) \ 443 PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \ 444 (_pool_tc)->pool) 445 446 #define TC_POOL_FIRST_CHUNK(_pool_tc) \ 447 ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc))) 448 449 #define TC_POOLMEM_CHUNK_SIZE(_tc) \ 450 TC_ALIGN16(TC_HDR_SIZE + (_tc)->size) 451 452 #define TC_POOLMEM_NEXT_CHUNK(_tc) \ 453 ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc))) 454 455 /* Mark the whole remaining pool as not accessable */ 456 #define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \ 457 if (unlikely(talloc_fill.enabled)) { \ 458 size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ 459 char *_fptr = (char *)(_pool_tc)->pool; \ 460 memset(_fptr, talloc_fill.fill_value, _flen); \ 461 } \ 462 } while(0) 463 464 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 465 /* Mark the whole remaining pool as not accessable */ 466 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \ 467 size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ 468 char *_fptr = (char *)(_pool_tc)->pool; \ 469 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ 470 } while(0) 471 #else 472 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0) 473 #endif 474 475 #define TC_INVALIDATE_POOL(_pool_tc) do { \ 476 TC_INVALIDATE_FILL_POOL(_pool_tc); \ 477 TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \ 478 } while (0) 479 324 480 static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) 325 481 { 326 return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));482 return (unsigned int *)((char *)tc + TC_HDR_SIZE); 327 483 } 328 484 … … 354 510 } 355 511 356 space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) 357 - ((char *)pool_ctx->pool); 512 space_left = TC_POOL_SPACE_LEFT(pool_ctx); 358 513 359 514 /* 360 515 * Align size to 16 bytes 361 516 */ 362 chunk_size = ((size + 15) & ~15);517 chunk_size = TC_ALIGN16(size); 363 518 364 519 if (space_left < chunk_size) { … … 439 594 */ 440 595 441 void *talloc_pool(const void *context, size_t size)596 _PUBLIC_ void *talloc_pool(const void *context, size_t size) 442 597 { 443 598 void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); … … 451 606 452 607 tc->flags |= TALLOC_FLAG_POOL; 453 tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;608 tc->pool = TC_POOL_FIRST_CHUNK(tc); 454 609 455 610 *talloc_pool_objectcount(tc) = 1; 456 611 457 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 458 VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); 459 #endif 612 TC_INVALIDATE_POOL(tc); 460 613 461 614 return result; … … 468 621 be continued to be used 469 622 */ 470 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))623 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) 471 624 { 472 625 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 477 630 increase the reference count on a piece of memory. 478 631 */ 479 int talloc_increase_ref_count(const void *ptr)632 _PUBLIC_ int talloc_increase_ref_count(const void *ptr) 480 633 { 481 634 if (unlikely(!talloc_reference(null_context, ptr))) { … … 533 686 and in either order 534 687 */ 535 void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)688 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) 536 689 { 537 690 struct talloc_chunk *tc; … … 557 710 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); 558 711 712 static inline void _talloc_free_poolmem(struct talloc_chunk *tc, 713 const char *location) 714 { 715 struct talloc_chunk *pool; 716 void *next_tc; 717 unsigned int *pool_object_count; 718 719 pool = (struct talloc_chunk *)tc->pool; 720 next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 721 722 tc->flags |= TALLOC_FLAG_FREE; 723 724 /* we mark the freed memory with where we called the free 725 * from. This means on a double free error we can report where 726 * the first free came from 727 */ 728 tc->name = location; 729 730 TC_INVALIDATE_FULL_CHUNK(tc); 731 732 pool_object_count = talloc_pool_objectcount(pool); 733 734 if (unlikely(*pool_object_count == 0)) { 735 talloc_abort("Pool object count zero!"); 736 return; 737 } 738 739 *pool_object_count -= 1; 740 741 if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) { 742 /* 743 * if there is just one object left in the pool 744 * and pool->flags does not have TALLOC_FLAG_FREE, 745 * it means this is the pool itself and 746 * the rest is available for new objects 747 * again. 748 */ 749 pool->pool = TC_POOL_FIRST_CHUNK(pool); 750 TC_INVALIDATE_POOL(pool); 751 } else if (unlikely(*pool_object_count == 0)) { 752 /* 753 * we mark the freed memory with where we called the free 754 * from. This means on a double free error we can report where 755 * the first free came from 756 */ 757 pool->name = location; 758 759 TC_INVALIDATE_FULL_CHUNK(pool); 760 free(pool); 761 } else if (pool->pool == next_tc) { 762 /* 763 * if pool->pool still points to end of 764 * 'tc' (which is stored in the 'next_tc' variable), 765 * we can reclaim the memory of 'tc'. 766 */ 767 pool->pool = tc; 768 } 769 } 770 771 static inline void _talloc_free_children_internal(struct talloc_chunk *tc, 772 void *ptr, 773 const char *location); 774 559 775 /* 560 776 internal talloc_free call … … 568 784 } 569 785 786 /* possibly initialised the talloc fill value */ 787 if (unlikely(!talloc_fill.initialised)) { 788 const char *fill = getenv(TALLOC_FILL_ENV); 789 if (fill != NULL) { 790 talloc_fill.enabled = true; 791 talloc_fill.fill_value = strtoul(fill, NULL, 0); 792 } 793 talloc_fill.initialised = true; 794 } 795 570 796 tc = talloc_chunk_from_ptr(ptr); 571 797 572 798 if (unlikely(tc->refs)) { 573 799 int is_child; 574 /* check this is a reference from a child or grantchild575 * back to it's parent or grantparent800 /* check if this is a reference from a child or 801 * grandchild back to it's parent or grandparent 576 802 * 577 803 * in that case we need to remove the reference and … … 617 843 tc->flags |= TALLOC_FLAG_LOOP; 618 844 619 while (tc->child) { 620 /* we need to work out who will own an abandoned child 621 if it cannot be freed. In priority order, the first 622 choice is owner of any remaining reference to this 623 pointer, the second choice is our parent, and the 624 final choice is the null context. */ 625 void *child = TC_PTR_FROM_CHUNK(tc->child); 626 const void *new_parent = null_context; 627 if (unlikely(tc->child->refs)) { 628 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); 629 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 630 } 631 if (unlikely(_talloc_free_internal(child, location) == -1)) { 632 if (new_parent == null_context) { 633 struct talloc_chunk *p = talloc_parent_chunk(ptr); 634 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 635 } 636 _talloc_steal_internal(new_parent, child); 637 } 638 } 845 _talloc_free_children_internal(tc, ptr, location); 639 846 640 847 tc->flags |= TALLOC_FLAG_FREE; … … 646 853 tc->name = location; 647 854 648 if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { 649 struct talloc_chunk *pool; 855 if (tc->flags & TALLOC_FLAG_POOL) { 650 856 unsigned int *pool_object_count; 651 857 652 pool = (tc->flags & TALLOC_FLAG_POOL) 653 ? tc : (struct talloc_chunk *)tc->pool; 654 655 pool_object_count = talloc_pool_objectcount(pool); 656 657 if (*pool_object_count == 0) { 858 pool_object_count = talloc_pool_objectcount(tc); 859 860 if (unlikely(*pool_object_count == 0)) { 658 861 talloc_abort("Pool object count zero!"); 659 862 return 0; … … 662 865 *pool_object_count -= 1; 663 866 664 if (*pool_object_count == 0) { 665 free(pool); 666 } 667 } 668 else { 867 if (unlikely(*pool_object_count == 0)) { 868 TC_INVALIDATE_FULL_CHUNK(tc); 869 free(tc); 870 } 871 } else if (tc->flags & TALLOC_FLAG_POOLMEM) { 872 _talloc_free_poolmem(tc, location); 873 } else { 874 TC_INVALIDATE_FULL_CHUNK(tc); 669 875 free(tc); 670 876 } … … 734 940 passing NULL as ptr will always return NULL with no side effects. 735 941 */ 736 void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)942 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) 737 943 { 738 944 struct talloc_chunk *tc; … … 755 961 } 756 962 } 963 964 #if 0 965 /* this test is probably too expensive to have on in the 966 normal build, but it useful for debugging */ 967 if (talloc_is_parent(new_ctx, ptr)) { 968 talloc_log("WARNING: stealing into talloc child at %s\n", location); 969 } 970 #endif 757 971 758 972 return _talloc_steal_internal(new_ctx, ptr); … … 766 980 The old parent can be either a reference or a parent 767 981 */ 768 void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)982 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) 769 983 { 770 984 struct talloc_chunk *tc; … … 826 1040 controlled varient of talloc_free() 827 1041 */ 828 int talloc_unlink(const void *context, void *ptr)1042 _PUBLIC_ int talloc_unlink(const void *context, void *ptr) 829 1043 { 830 1044 struct talloc_chunk *tc_p, *new_p; … … 893 1107 add a name to an existing pointer 894 1108 */ 895 const char *talloc_set_name(const void *ptr, const char *fmt, ...)1109 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...) 896 1110 { 897 1111 const char *name; … … 909 1123 to name the pointer. 910 1124 */ 911 void *talloc_named(const void *context, size_t size, const char *fmt, ...)1125 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...) 912 1126 { 913 1127 va_list ap; … … 933 1147 return the name of a talloc ptr, or "UNNAMED" 934 1148 */ 935 const char *talloc_get_name(const void *ptr)1149 _PUBLIC_ const char *talloc_get_name(const void *ptr) 936 1150 { 937 1151 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 950 1164 otherwise return NULL 951 1165 */ 952 void *talloc_check_name(const void *ptr, const char *name)1166 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name) 953 1167 { 954 1168 const char *pname; … … 979 1193 } 980 1194 981 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)1195 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) 982 1196 { 983 1197 const char *pname; … … 1000 1214 this is for compatibility with older versions of talloc 1001 1215 */ 1002 void *talloc_init(const char *fmt, ...)1216 _PUBLIC_ void *talloc_init(const char *fmt, ...) 1003 1217 { 1004 1218 va_list ap; … … 1006 1220 const char *name; 1007 1221 1008 /*1009 * samba3 expects talloc_report_depth_cb(NULL, ...)1010 * reports all talloc'ed memory, so we need to enable1011 * null_tracking1012 */1013 talloc_enable_null_tracking();1014 1015 1222 ptr = __talloc(NULL, 0); 1016 1223 if (unlikely(ptr == NULL)) return NULL; … … 1028 1235 } 1029 1236 1030 /* 1031 this is a replacement for the Samba3 talloc_destroy_pool functionality. It 1032 should probably not be used in new code. It's in here to keep the talloc 1033 code consistent across Samba 3 and 4. 1034 */ 1035 void talloc_free_children(void *ptr) 1036 { 1037 struct talloc_chunk *tc; 1038 1039 if (unlikely(ptr == NULL)) { 1040 return; 1041 } 1042 1043 tc = talloc_chunk_from_ptr(ptr); 1044 1237 static inline void _talloc_free_children_internal(struct talloc_chunk *tc, 1238 void *ptr, 1239 const char *location) 1240 { 1045 1241 while (tc->child) { 1046 1242 /* we need to work out who will own an abandoned child … … 1051 1247 void *child = TC_PTR_FROM_CHUNK(tc->child); 1052 1248 const void *new_parent = null_context; 1249 struct talloc_chunk *old_parent = NULL; 1053 1250 if (unlikely(tc->child->refs)) { 1054 1251 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); 1055 1252 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 1056 1253 } 1057 if (unlikely(talloc_free(child) == -1)) { 1254 /* finding the parent here is potentially quite 1255 expensive, but the alternative, which is to change 1256 talloc to always have a valid tc->parent pointer, 1257 makes realloc more expensive where there are a 1258 large number of children. 1259 1260 The reason we need the parent pointer here is that 1261 if _talloc_free_internal() fails due to references 1262 or a failing destructor we need to re-parent, but 1263 the free call can invalidate the prev pointer. 1264 */ 1265 if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) { 1266 old_parent = talloc_parent_chunk(ptr); 1267 } 1268 if (unlikely(_talloc_free_internal(child, location) == -1)) { 1058 1269 if (new_parent == null_context) { 1059 struct talloc_chunk *p = talloc_parent_chunk(ptr);1270 struct talloc_chunk *p = old_parent; 1060 1271 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 1061 1272 } … … 1063 1274 } 1064 1275 } 1065 1066 if ((tc->flags & TALLOC_FLAG_POOL) 1067 && (*talloc_pool_objectcount(tc) == 1)) { 1068 tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE); 1069 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 1070 VALGRIND_MAKE_MEM_NOACCESS( 1071 tc->pool, tc->size - TALLOC_POOL_HDR_SIZE); 1072 #endif 1073 } 1276 } 1277 1278 /* 1279 this is a replacement for the Samba3 talloc_destroy_pool functionality. It 1280 should probably not be used in new code. It's in here to keep the talloc 1281 code consistent across Samba 3 and 4. 1282 */ 1283 _PUBLIC_ void talloc_free_children(void *ptr) 1284 { 1285 struct talloc_chunk *tc; 1286 1287 if (unlikely(ptr == NULL)) { 1288 return; 1289 } 1290 1291 tc = talloc_chunk_from_ptr(ptr); 1292 1293 _talloc_free_children_internal(tc, ptr, __location__); 1074 1294 } 1075 1295 … … 1077 1297 Allocate a bit of memory as a child of an existing pointer 1078 1298 */ 1079 void *_talloc(const void *context, size_t size)1299 _PUBLIC_ void *_talloc(const void *context, size_t size) 1080 1300 { 1081 1301 return __talloc(context, size); … … 1085 1305 externally callable talloc_set_name_const() 1086 1306 */ 1087 void talloc_set_name_const(const void *ptr, const char *name)1307 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name) 1088 1308 { 1089 1309 _talloc_set_name_const(ptr, name); … … 1095 1315 to name the pointer. 1096 1316 */ 1097 void *talloc_named_const(const void *context, size_t size, const char *name)1317 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name) 1098 1318 { 1099 1319 return _talloc_named_const(context, size, name); … … 1108 1328 any) returns non-zero 1109 1329 */ 1110 int _talloc_free(void *ptr, const char *location)1330 _PUBLIC_ int _talloc_free(void *ptr, const char *location) 1111 1331 { 1112 1332 struct talloc_chunk *tc; … … 1121 1341 struct talloc_reference_handle *h; 1122 1342 1343 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) { 1344 /* in this case we do know which parent should 1345 get this pointer, as there is really only 1346 one parent */ 1347 return talloc_unlink(null_context, ptr); 1348 } 1349 1123 1350 talloc_log("ERROR: talloc_free with references at %s\n", 1124 1351 location); … … 1140 1367 ptr is NULL 1141 1368 */ 1142 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)1369 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) 1143 1370 { 1144 1371 struct talloc_chunk *tc; 1145 1372 void *new_ptr; 1146 1373 bool malloced = false; 1374 struct talloc_chunk *pool_tc = NULL; 1147 1375 1148 1376 /* size zero is equivalent to free() */ … … 1173 1401 } 1174 1402 1403 /* don't let anybody try to realloc a talloc_pool */ 1404 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) { 1405 pool_tc = (struct talloc_chunk *)tc->pool; 1406 } 1407 1408 #if (ALWAYS_REALLOC == 0) 1175 1409 /* don't shrink if we have less than 1k to gain */ 1176 if ((size < tc->size) && ((tc->size - size) < 1024)) { 1177 tc->size = size; 1410 if (size < tc->size) { 1411 if (pool_tc) { 1412 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 1413 TC_INVALIDATE_SHRINK_CHUNK(tc, size); 1414 tc->size = size; 1415 if (next_tc == pool_tc->pool) { 1416 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); 1417 } 1418 return ptr; 1419 } else if ((tc->size - size) < 1024) { 1420 /* 1421 * if we call TC_INVALIDATE_SHRINK_CHUNK() here 1422 * we would need to call TC_UNDEFINE_GROW_CHUNK() 1423 * after each realloc call, which slows down 1424 * testing a lot :-(. 1425 * 1426 * That is why we only mark memory as undefined here. 1427 */ 1428 TC_UNDEFINE_SHRINK_CHUNK(tc, size); 1429 1430 /* do not shrink if we have less than 1k to gain */ 1431 tc->size = size; 1432 return ptr; 1433 } 1434 } else if (tc->size == size) { 1435 /* 1436 * do not change the pointer if it is exactly 1437 * the same size. 1438 */ 1178 1439 return ptr; 1179 1440 } 1441 #endif 1180 1442 1181 1443 /* by resetting magic we catch users of the old memory */ … … 1183 1445 1184 1446 #if ALWAYS_REALLOC 1185 new_ptr = malloc(size + TC_HDR_SIZE); 1186 if (new_ptr) { 1187 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); 1188 free(tc); 1189 } 1190 #else 1191 if (tc->flags & TALLOC_FLAG_POOLMEM) { 1192 1447 if (pool_tc) { 1193 1448 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); 1194 *talloc_pool_objectcount((struct talloc_chunk *) 1195 (tc->pool)) -= 1; 1449 *talloc_pool_objectcount(pool_tc) -= 1; 1196 1450 1197 1451 if (new_ptr == NULL) { … … 1202 1456 if (new_ptr) { 1203 1457 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); 1458 TC_INVALIDATE_FULL_CHUNK(tc); 1459 } 1460 } else { 1461 new_ptr = malloc(size + TC_HDR_SIZE); 1462 if (new_ptr) { 1463 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); 1464 free(tc); 1465 } 1466 } 1467 #else 1468 if (pool_tc) { 1469 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 1470 size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc); 1471 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size); 1472 size_t space_needed; 1473 size_t space_left; 1474 unsigned int chunk_count = *talloc_pool_objectcount(pool_tc); 1475 1476 if (!(pool_tc->flags & TALLOC_FLAG_FREE)) { 1477 chunk_count -= 1; 1478 } 1479 1480 if (chunk_count == 1) { 1481 /* 1482 * optimize for the case where 'tc' is the only 1483 * chunk in the pool. 1484 */ 1485 space_needed = new_chunk_size; 1486 space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE; 1487 1488 if (space_left >= space_needed) { 1489 size_t old_used = TC_HDR_SIZE + tc->size; 1490 size_t new_used = TC_HDR_SIZE + size; 1491 pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc); 1492 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) 1493 /* 1494 * we need to prepare the memmove into 1495 * the unaccessable area. 1496 */ 1497 { 1498 size_t diff = PTR_DIFF(tc, pool_tc->pool); 1499 size_t flen = MIN(diff, old_used); 1500 char *fptr = (char *)pool_tc->pool; 1501 VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen); 1502 } 1503 #endif 1504 memmove(pool_tc->pool, tc, old_used); 1505 new_ptr = pool_tc->pool; 1506 1507 tc = (struct talloc_chunk *)new_ptr; 1508 TC_UNDEFINE_GROW_CHUNK(tc, size); 1509 1510 /* 1511 * first we do not align the pool pointer 1512 * because we want to invalidate the padding 1513 * too. 1514 */ 1515 pool_tc->pool = new_used + (char *)new_ptr; 1516 TC_INVALIDATE_POOL(pool_tc); 1517 1518 /* now the aligned pointer */ 1519 pool_tc->pool = new_chunk_size + (char *)new_ptr; 1520 goto got_new_ptr; 1521 } 1522 1523 next_tc = NULL; 1524 } 1525 1526 if (new_chunk_size == old_chunk_size) { 1527 TC_UNDEFINE_GROW_CHUNK(tc, size); 1528 tc->flags &= ~TALLOC_FLAG_FREE; 1529 tc->size = size; 1530 return ptr; 1531 } 1532 1533 if (next_tc == pool_tc->pool) { 1534 /* 1535 * optimize for the case where 'tc' is the last 1536 * chunk in the pool. 1537 */ 1538 space_needed = new_chunk_size - old_chunk_size; 1539 space_left = TC_POOL_SPACE_LEFT(pool_tc); 1540 1541 if (space_left >= space_needed) { 1542 TC_UNDEFINE_GROW_CHUNK(tc, size); 1543 tc->flags &= ~TALLOC_FLAG_FREE; 1544 tc->size = size; 1545 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); 1546 return ptr; 1547 } 1548 } 1549 1550 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); 1551 1552 if (new_ptr == NULL) { 1553 new_ptr = malloc(TC_HDR_SIZE+size); 1554 malloced = true; 1555 } 1556 1557 if (new_ptr) { 1558 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); 1559 1560 _talloc_free_poolmem(tc, __location__ "_talloc_realloc"); 1204 1561 } 1205 1562 } … … 1207 1564 new_ptr = realloc(tc, size + TC_HDR_SIZE); 1208 1565 } 1566 got_new_ptr: 1209 1567 #endif 1210 1568 if (unlikely(!new_ptr)) { … … 1242 1600 between two structures, and want the old pointer to be set to NULL 1243 1601 */ 1244 void *_talloc_move(const void *new_ctx, const void *_pptr)1602 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr) 1245 1603 { 1246 1604 const void **pptr = discard_const_p(const void *,_pptr); … … 1253 1611 return the total size of a talloc pool (subtree) 1254 1612 */ 1255 size_t talloc_total_size(const void *ptr)1613 _PUBLIC_ size_t talloc_total_size(const void *ptr) 1256 1614 { 1257 1615 size_t total = 0; … … 1288 1646 return the total number of blocks in a talloc pool (subtree) 1289 1647 */ 1290 size_t talloc_total_blocks(const void *ptr)1648 _PUBLIC_ size_t talloc_total_blocks(const void *ptr) 1291 1649 { 1292 1650 size_t total = 0; … … 1321 1679 return the number of external references to a pointer 1322 1680 */ 1323 size_t talloc_reference_count(const void *ptr)1681 _PUBLIC_ size_t talloc_reference_count(const void *ptr) 1324 1682 { 1325 1683 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 1336 1694 report on memory usage by all children of a pointer, giving a full tree view 1337 1695 */ 1338 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,1696 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, 1339 1697 void (*callback)(const void *ptr, 1340 1698 int depth, int max_depth, … … 1420 1778 report on memory usage by all children of a pointer, giving a full tree view 1421 1779 */ 1422 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)1780 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) 1423 1781 { 1424 1782 if (f) { … … 1431 1789 report on memory usage by all children of a pointer, giving a full tree view 1432 1790 */ 1433 void talloc_report_full(const void *ptr, FILE *f)1791 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f) 1434 1792 { 1435 1793 talloc_report_depth_file(ptr, 0, -1, f); … … 1439 1797 report on memory usage by all children of a pointer 1440 1798 */ 1441 void talloc_report(const void *ptr, FILE *f)1799 _PUBLIC_ void talloc_report(const void *ptr, FILE *f) 1442 1800 { 1443 1801 talloc_report_depth_file(ptr, 0, 1, f); … … 1467 1825 enable tracking of the NULL context 1468 1826 */ 1469 void talloc_enable_null_tracking(void)1827 _PUBLIC_ void talloc_enable_null_tracking(void) 1470 1828 { 1471 1829 if (null_context == NULL) { … … 1481 1839 into the NULL context. This is needed for the talloc testsuite 1482 1840 */ 1483 void talloc_enable_null_tracking_no_autofree(void)1841 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void) 1484 1842 { 1485 1843 if (null_context == NULL) { … … 1491 1849 disable tracking of the NULL context 1492 1850 */ 1493 void talloc_disable_null_tracking(void)1851 _PUBLIC_ void talloc_disable_null_tracking(void) 1494 1852 { 1495 1853 if (null_context != NULL) { … … 1516 1874 enable leak reporting on exit 1517 1875 */ 1518 void talloc_enable_leak_report(void)1876 _PUBLIC_ void talloc_enable_leak_report(void) 1519 1877 { 1520 1878 talloc_enable_null_tracking(); … … 1525 1883 enable full leak reporting on exit 1526 1884 */ 1527 void talloc_enable_leak_report_full(void)1885 _PUBLIC_ void talloc_enable_leak_report_full(void) 1528 1886 { 1529 1887 talloc_enable_null_tracking(); … … 1534 1892 talloc and zero memory. 1535 1893 */ 1536 void *_talloc_zero(const void *ctx, size_t size, const char *name)1894 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name) 1537 1895 { 1538 1896 void *p = _talloc_named_const(ctx, size, name); … … 1548 1906 memdup with a talloc. 1549 1907 */ 1550 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)1908 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) 1551 1909 { 1552 1910 void *newp = _talloc_named_const(t, size, name); … … 1576 1934 strdup with a talloc 1577 1935 */ 1578 char *talloc_strdup(const void *t, const char *p)1936 _PUBLIC_ char *talloc_strdup(const void *t, const char *p) 1579 1937 { 1580 1938 if (unlikely(!p)) return NULL; … … 1585 1943 strndup with a talloc 1586 1944 */ 1587 char *talloc_strndup(const void *t, const char *p, size_t n)1945 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n) 1588 1946 { 1589 1947 if (unlikely(!p)) return NULL; … … 1610 1968 * Appends at the end of the string. 1611 1969 */ 1612 char *talloc_strdup_append(char *s, const char *a)1970 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a) 1613 1971 { 1614 1972 if (unlikely(!s)) { … … 1627 1985 * not the end of the string. 1628 1986 */ 1629 char *talloc_strdup_append_buffer(char *s, const char *a)1987 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a) 1630 1988 { 1631 1989 size_t slen; … … 1650 2008 * Appends at the end of the string. 1651 2009 */ 1652 char *talloc_strndup_append(char *s, const char *a, size_t n)2010 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n) 1653 2011 { 1654 2012 if (unlikely(!s)) { … … 1667 2025 * not the end of the string. 1668 2026 */ 1669 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)2027 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) 1670 2028 { 1671 2029 size_t slen; … … 1695 2053 #endif 1696 2054 1697 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)2055 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) 1698 2056 { 1699 2057 int len; … … 1726 2084 memory holding the result, inside a memory pool. 1727 2085 */ 1728 char *talloc_asprintf(const void *t, const char *fmt, ...)2086 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...) 1729 2087 { 1730 2088 va_list ap; … … 1779 2137 * of the string. 1780 2138 **/ 1781 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)2139 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) 1782 2140 { 1783 2141 if (unlikely(!s)) { … … 1793 2151 * end of the talloc'ed buffer, not the end of the string. 1794 2152 **/ 1795 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)2153 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) 1796 2154 { 1797 2155 size_t slen; … … 1814 2172 into a string buffer. 1815 2173 */ 1816 char *talloc_asprintf_append(char *s, const char *fmt, ...)2174 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...) 1817 2175 { 1818 2176 va_list ap; … … 1829 2187 into a buffer. 1830 2188 */ 1831 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)2189 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) 1832 2190 { 1833 2191 va_list ap; … … 1842 2200 alloc an array, checking for integer overflow in the array size 1843 2201 */ 1844 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)2202 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) 1845 2203 { 1846 2204 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1853 2211 alloc an zero array, checking for integer overflow in the array size 1854 2212 */ 1855 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)2213 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) 1856 2214 { 1857 2215 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1864 2222 realloc an array, checking for integer overflow in the array size 1865 2223 */ 1866 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)2224 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) 1867 2225 { 1868 2226 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1877 2235 all the basic capabilities of an allocation library, which is why this is useful) 1878 2236 */ 1879 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)2237 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) 1880 2238 { 1881 2239 return _talloc_realloc(context, ptr, size, NULL); … … 1898 2256 this is useful for reducing the noise in leak reports 1899 2257 */ 1900 void *talloc_autofree_context(void)2258 _PUBLIC_ void *talloc_autofree_context(void) 1901 2259 { 1902 2260 if (autofree_context == NULL) { … … 1908 2266 } 1909 2267 1910 size_t talloc_get_size(const void *context)2268 _PUBLIC_ size_t talloc_get_size(const void *context) 1911 2269 { 1912 2270 struct talloc_chunk *tc; … … 1927 2285 find a parent of this context that has the given name, if any 1928 2286 */ 1929 void *talloc_find_parent_byname(const void *context, const char *name)2287 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name) 1930 2288 { 1931 2289 struct talloc_chunk *tc; … … 1951 2309 show the parentage of a context 1952 2310 */ 1953 void talloc_show_parents(const void *context, FILE *file)2311 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file) 1954 2312 { 1955 2313 struct talloc_chunk *tc; … … 1975 2333 return 1 if ptr is a parent of context 1976 2334 */ 1977 int talloc_is_parent(const void *context, const void *ptr)2335 static int _talloc_is_parent(const void *context, const void *ptr, int depth) 1978 2336 { 1979 2337 struct talloc_chunk *tc; … … 1984 2342 1985 2343 tc = talloc_chunk_from_ptr(context); 1986 while (tc ) {2344 while (tc && depth > 0) { 1987 2345 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; 1988 2346 while (tc && tc->prev) tc = tc->prev; 1989 2347 if (tc) { 1990 2348 tc = tc->parent; 2349 depth--; 1991 2350 } 1992 2351 } 1993 2352 return 0; 1994 2353 } 2354 2355 /* 2356 return 1 if ptr is a parent of context 2357 */ 2358 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr) 2359 { 2360 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH); 2361 } -
vendor/current/lib/talloc/talloc.h
r414 r740 30 30 #include <stdarg.h> 31 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /** 37 * @defgroup talloc The talloc API 38 * 39 * talloc is a hierarchical, reference counted memory pool system with 40 * destructors. It is the core memory allocator used in Samba. 41 * 42 * @{ 43 */ 44 32 45 #define TALLOC_VERSION_MAJOR 2 33 46 #define TALLOC_VERSION_MINOR 0 … … 36 49 int talloc_version_minor(void); 37 50 38 /* this is only needed for compatibility with the old talloc */ 51 /** 52 * @brief Define a talloc parent type 53 * 54 * As talloc is a hierarchial memory allocator, every talloc chunk is a 55 * potential parent to other talloc chunks. So defining a separate type for a 56 * talloc chunk is not strictly necessary. TALLOC_CTX is defined nevertheless, 57 * as it provides an indicator for function arguments. You will frequently 58 * write code like 59 * 60 * @code 61 * struct foo *foo_create(TALLOC_CTX *mem_ctx) 62 * { 63 * struct foo *result; 64 * result = talloc(mem_ctx, struct foo); 65 * if (result == NULL) return NULL; 66 * ... initialize foo ... 67 * return result; 68 * } 69 * @endcode 70 * 71 * In this type of allocating functions it is handy to have a general 72 * TALLOC_CTX type to indicate which parent to put allocated structures on. 73 */ 39 74 typedef void TALLOC_CTX; 40 75 … … 65 100 #endif 66 101 102 #ifdef DOXYGEN 103 /** 104 * @brief Create a new talloc context. 105 * 106 * The talloc() macro is the core of the talloc library. It takes a memory 107 * context and a type, and returns a pointer to a new area of memory of the 108 * given type. 109 * 110 * The returned pointer is itself a talloc context, so you can use it as the 111 * context argument to more calls to talloc if you wish. 112 * 113 * The returned pointer is a "child" of the supplied context. This means that if 114 * you talloc_free() the context then the new child disappears as well. 115 * Alternatively you can free just the child. 116 * 117 * @param[in] ctx A talloc context to create a new reference on or NULL to 118 * create a new top level context. 119 * 120 * @param[in] type The type of memory to allocate. 121 * 122 * @return A type casted talloc context or NULL on error. 123 * 124 * @code 125 * unsigned int *a, *b; 126 * 127 * a = talloc(NULL, unsigned int); 128 * b = talloc(a, unsigned int); 129 * @endcode 130 * 131 * @see talloc_zero 132 * @see talloc_array 133 * @see talloc_steal 134 * @see talloc_free 135 */ 136 void *talloc(const void *ctx, #type); 137 #else 138 #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) 139 void *_talloc(const void *context, size_t size); 140 #endif 141 142 /** 143 * @brief Create a new top level talloc context. 144 * 145 * This function creates a zero length named talloc context as a top level 146 * context. It is equivalent to: 147 * 148 * @code 149 * talloc_named(NULL, 0, fmt, ...); 150 * @endcode 151 * @param[in] fmt Format string for the name. 152 * 153 * @param[in] ... Additional printf-style arguments. 154 * 155 * @return The allocated memory chunk, NULL on error. 156 * 157 * @see talloc_named() 158 */ 159 void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); 160 161 #ifdef DOXYGEN 162 /** 163 * @brief Free a chunk of talloc memory. 164 * 165 * The talloc_free() function frees a piece of talloc memory, and all its 166 * children. You can call talloc_free() on any pointer returned by 167 * talloc(). 168 * 169 * The return value of talloc_free() indicates success or failure, with 0 170 * returned for success and -1 for failure. A possible failure condition 171 * is if the pointer had a destructor attached to it and the destructor 172 * returned -1. See talloc_set_destructor() for details on 173 * destructors. Likewise, if "ptr" is NULL, then the function will make 174 * no modifications and return -1. 175 * 176 * If this pointer has an additional parent when talloc_free() is called 177 * then the memory is not actually released, but instead the most 178 * recently established parent is destroyed. See talloc_reference() for 179 * details on establishing additional parents. 180 * 181 * For more control on which parent is removed, see talloc_unlink() 182 * 183 * talloc_free() operates recursively on its children. 184 * 185 * From the 2.0 version of talloc, as a special case, talloc_free() is 186 * refused on pointers that have more than one parent, as talloc would 187 * have no way of knowing which parent should be removed. To free a 188 * pointer that has more than one parent please use talloc_unlink(). 189 * 190 * To help you find problems in your code caused by this behaviour, if 191 * you do try and free a pointer with more than one parent then the 192 * talloc logging function will be called to give output like this: 193 * 194 * @code 195 * ERROR: talloc_free with references at some_dir/source/foo.c:123 196 * reference at some_dir/source/other.c:325 197 * reference at some_dir/source/third.c:121 198 * @endcode 199 * 200 * Please see the documentation for talloc_set_log_fn() and 201 * talloc_set_log_stderr() for more information on talloc logging 202 * functions. 203 * 204 * @param[in] ptr The chunk to be freed. 205 * 206 * @return Returns 0 on success and -1 on error. A possible 207 * failure condition is if the pointer had a destructor 208 * attached to it and the destructor returned -1. Likewise, 209 * if "ptr" is NULL, then the function will make no 210 * modifications and returns -1. 211 * 212 * Example: 213 * @code 214 * unsigned int *a, *b; 215 * a = talloc(NULL, unsigned int); 216 * b = talloc(a, unsigned int); 217 * 218 * talloc_free(a); // Frees a and b 219 * @endcode 220 * 221 * @see talloc_set_destructor() 222 * @see talloc_unlink() 223 */ 224 int talloc_free(void *ptr); 225 #else 226 #define talloc_free(ctx) _talloc_free(ctx, __location__) 227 int _talloc_free(void *ptr, const char *location); 228 #endif 229 230 /** 231 * @brief Free a talloc chunk's children. 232 * 233 * The function walks along the list of all children of a talloc context and 234 * talloc_free()s only the children, not the context itself. 235 * 236 * @param[in] ptr The chunk that you want to free the children of. 237 */ 238 void talloc_free_children(void *ptr); 239 240 #ifdef DOXYGEN 241 /** 242 * @brief Assign a destructor function to be called when a chunk is freed. 243 * 244 * The function talloc_set_destructor() sets the "destructor" for the pointer 245 * "ptr". A destructor is a function that is called when the memory used by a 246 * pointer is about to be released. The destructor receives the pointer as an 247 * argument, and should return 0 for success and -1 for failure. 248 * 249 * The destructor can do anything it wants to, including freeing other pieces 250 * of memory. A common use for destructors is to clean up operating system 251 * resources (such as open file descriptors) contained in the structure the 252 * destructor is placed on. 253 * 254 * You can only place one destructor on a pointer. If you need more than one 255 * destructor then you can create a zero-length child of the pointer and place 256 * an additional destructor on that. 257 * 258 * To remove a destructor call talloc_set_destructor() with NULL for the 259 * destructor. 260 * 261 * If your destructor attempts to talloc_free() the pointer that it is the 262 * destructor for then talloc_free() will return -1 and the free will be 263 * ignored. This would be a pointless operation anyway, as the destructor is 264 * only called when the memory is just about to go away. 265 * 266 * @param[in] ptr The talloc chunk to add a destructor to. 267 * 268 * @param[in] destructor The destructor function to be called. NULL to remove 269 * it. 270 * 271 * Example: 272 * @code 273 * static int destroy_fd(int *fd) { 274 * close(*fd); 275 * return 0; 276 * } 277 * 278 * int *open_file(const char *filename) { 279 * int *fd = talloc(NULL, int); 280 * *fd = open(filename, O_RDONLY); 281 * if (*fd < 0) { 282 * talloc_free(fd); 283 * return NULL; 284 * } 285 * // Whenever they free this, we close the file. 286 * talloc_set_destructor(fd, destroy_fd); 287 * return fd; 288 * } 289 * @endcode 290 * 291 * @see talloc() 292 * @see talloc_free() 293 */ 294 void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); 295 296 /** 297 * @brief Change a talloc chunk's parent. 298 * 299 * The talloc_steal() function changes the parent context of a talloc 300 * pointer. It is typically used when the context that the pointer is 301 * currently a child of is going to be freed and you wish to keep the 302 * memory for a longer time. 303 * 304 * To make the changed hierarchy less error-prone, you might consider to use 305 * talloc_move(). 306 * 307 * If you try and call talloc_steal() on a pointer that has more than one 308 * parent then the result is ambiguous. Talloc will choose to remove the 309 * parent that is currently indicated by talloc_parent() and replace it with 310 * the chosen parent. You will also get a message like this via the talloc 311 * logging functions: 312 * 313 * @code 314 * WARNING: talloc_steal with references at some_dir/source/foo.c:123 315 * reference at some_dir/source/other.c:325 316 * reference at some_dir/source/third.c:121 317 * @endcode 318 * 319 * To unambiguously change the parent of a pointer please see the function 320 * talloc_reparent(). See the talloc_set_log_fn() documentation for more 321 * information on talloc logging. 322 * 323 * @param[in] new_ctx The new parent context. 324 * 325 * @param[in] ptr The talloc chunk to move. 326 * 327 * @return Returns the pointer that you pass it. It does not have 328 * any failure modes. 329 * 330 * @note It is possible to produce loops in the parent/child relationship 331 * if you are not careful with talloc_steal(). No guarantees are provided 332 * as to your sanity or the safety of your data if you do this. 333 */ 334 void *talloc_steal(const void *new_ctx, const void *ptr); 335 #else /* DOXYGEN */ 67 336 /* try to make talloc_set_destructor() and talloc_steal() type safe, 68 337 if we have a recent gcc */ … … 77 346 stupidity in gcc 4.1.x */ 78 347 #define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; }) 79 #else 348 #else /* __GNUC__ >= 3 */ 80 349 #define talloc_set_destructor(ptr, function) \ 81 350 _talloc_set_destructor((ptr), (int (*)(void *))(function)) 82 351 #define _TALLOC_TYPEOF(ptr) void * 83 352 #define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__) 84 #endif 85 86 #define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) 353 #endif /* __GNUC__ >= 3 */ 354 void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); 355 void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); 356 #endif /* DOXYGEN */ 357 358 /** 359 * @brief Assign a name to a talloc chunk. 360 * 361 * Each talloc pointer has a "name". The name is used principally for 362 * debugging purposes, although it is also possible to set and get the name on 363 * a pointer in as a way of "marking" pointers in your code. 364 * 365 * The main use for names on pointer is for "talloc reports". See 366 * talloc_report() and talloc_report_full() for details. Also see 367 * talloc_enable_leak_report() and talloc_enable_leak_report_full(). 368 * 369 * The talloc_set_name() function allocates memory as a child of the 370 * pointer. It is logically equivalent to: 371 * 372 * @code 373 * talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); 374 * @endcode 375 * 376 * @param[in] ptr The talloc chunk to assign a name to. 377 * 378 * @param[in] fmt Format string for the name. 379 * 380 * @param[in] ... Add printf-style additional arguments. 381 * 382 * @return The assigned name, NULL on error. 383 * 384 * @note Multiple calls to talloc_set_name() will allocate more memory without 385 * releasing the name. All of the memory is released when the ptr is freed 386 * using talloc_free(). 387 */ 388 const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 389 390 #ifdef DOXYGEN 391 /** 392 * @brief Change a talloc chunk's parent. 393 * 394 * This function has the same effect as talloc_steal(), and additionally sets 395 * the source pointer to NULL. You would use it like this: 396 * 397 * @code 398 * struct foo *X = talloc(tmp_ctx, struct foo); 399 * struct foo *Y; 400 * Y = talloc_move(new_ctx, &X); 401 * @endcode 402 * 403 * @param[in] new_ctx The new parent context. 404 * 405 * @param[in] ptr Pointer to the talloc chunk to move. 406 * 407 * @return The pointer of the talloc chunk it has been moved to, 408 * NULL on error. 409 */ 410 void *talloc_move(const void *new_ctx, const void *ptr); 411 #else 87 412 #define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) 88 89 /* useful macros for creating type checked pointers */ 90 #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) 413 void *_talloc_move(const void *new_ctx, const void *pptr); 414 #endif 415 416 /** 417 * @brief Assign a name to a talloc chunk. 418 * 419 * The function is just like talloc_set_name(), but it takes a string constant, 420 * and is much faster. It is extensively used by the "auto naming" macros, such 421 * as talloc_p(). 422 * 423 * This function does not allocate any memory. It just copies the supplied 424 * pointer into the internal representation of the talloc ptr. This means you 425 * must not pass a name pointer to memory that will disappear before the ptr 426 * is freed with talloc_free(). 427 * 428 * @param[in] ptr The talloc chunk to assign a name to. 429 * 430 * @param[in] name Format string for the name. 431 */ 432 void talloc_set_name_const(const void *ptr, const char *name); 433 434 /** 435 * @brief Create a named talloc chunk. 436 * 437 * The talloc_named() function creates a named talloc pointer. It is 438 * equivalent to: 439 * 440 * @code 441 * ptr = talloc_size(context, size); 442 * talloc_set_name(ptr, fmt, ....); 443 * @endcode 444 * 445 * @param[in] context The talloc context to hang the result off. 446 * 447 * @param[in] size Number of char's that you want to allocate. 448 * 449 * @param[in] fmt Format string for the name. 450 * 451 * @param[in] ... Additional printf-style arguments. 452 * 453 * @return The allocated memory chunk, NULL on error. 454 * 455 * @see talloc_set_name() 456 */ 457 void *talloc_named(const void *context, size_t size, 458 const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); 459 460 /** 461 * @brief Basic routine to allocate a chunk of memory. 462 * 463 * This is equivalent to: 464 * 465 * @code 466 * ptr = talloc_size(context, size); 467 * talloc_set_name_const(ptr, name); 468 * @endcode 469 * 470 * @param[in] context The parent context. 471 * 472 * @param[in] size The number of char's that we want to allocate. 473 * 474 * @param[in] name The name the talloc block has. 475 * 476 * @return The allocated memory chunk, NULL on error. 477 */ 478 void *talloc_named_const(const void *context, size_t size, const char *name); 479 480 #ifdef DOXYGEN 481 /** 482 * @brief Untyped allocation. 483 * 484 * The function should be used when you don't have a convenient type to pass to 485 * talloc(). Unlike talloc(), it is not type safe (as it returns a void *), so 486 * you are on your own for type checking. 487 * 488 * Best to use talloc() or talloc_array() instead. 489 * 490 * @param[in] ctx The talloc context to hang the result off. 491 * 492 * @param[in] size Number of char's that you want to allocate. 493 * 494 * @return The allocated memory chunk, NULL on error. 495 * 496 * Example: 497 * @code 498 * void *mem = talloc_size(NULL, 100); 499 * @endcode 500 */ 501 void *talloc_size(const void *ctx, size_t size); 502 #else 91 503 #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) 504 #endif 505 506 #ifdef DOXYGEN 507 /** 508 * @brief Allocate into a typed pointer. 509 * 510 * The talloc_ptrtype() macro should be used when you have a pointer and want 511 * to allocate memory to point at with this pointer. When compiling with 512 * gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() and 513 * talloc_get_name() will return the current location in the source file and 514 * not the type. 515 * 516 * @param[in] ctx The talloc context to hang the result off. 517 * 518 * @param[in] type The pointer you want to assign the result to. 519 * 520 * @return The properly casted allocated memory chunk, NULL on 521 * error. 522 * 523 * Example: 524 * @code 525 * unsigned int *a = talloc_ptrtype(NULL, a); 526 * @endcode 527 */ 528 void *talloc_ptrtype(const void *ctx, #type); 529 #else 92 530 #define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) 93 531 #endif 532 533 #ifdef DOXYGEN 534 /** 535 * @brief Allocate a new 0-sized talloc chunk. 536 * 537 * This is a utility macro that creates a new memory context hanging off an 538 * existing context, automatically naming it "talloc_new: __location__" where 539 * __location__ is the source line it is called from. It is particularly 540 * useful for creating a new temporary working context. 541 * 542 * @param[in] ctx The talloc parent context. 543 * 544 * @return A new talloc chunk, NULL on error. 545 */ 546 void *talloc_new(const void *ctx); 547 #else 94 548 #define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) 95 549 #endif 550 551 #ifdef DOXYGEN 552 /** 553 * @brief Allocate a 0-initizialized structure. 554 * 555 * The macro is equivalent to: 556 * 557 * @code 558 * ptr = talloc(ctx, type); 559 * if (ptr) memset(ptr, 0, sizeof(type)); 560 * @endcode 561 * 562 * @param[in] ctx The talloc context to hang the result off. 563 * 564 * @param[in] type The type that we want to allocate. 565 * 566 * @return Pointer to a piece of memory, properly cast to 'type *', 567 * NULL on error. 568 * 569 * Example: 570 * @code 571 * unsigned int *a, *b; 572 * a = talloc_zero(NULL, unsigned int); 573 * b = talloc_zero(a, unsigned int); 574 * @endcode 575 * 576 * @see talloc() 577 * @see talloc_zero_size() 578 * @see talloc_zero_array() 579 */ 580 void *talloc_zero(const void *ctx, #type); 581 582 /** 583 * @brief Allocate untyped, 0-initialized memory. 584 * 585 * @param[in] ctx The talloc context to hang the result off. 586 * 587 * @param[in] size Number of char's that you want to allocate. 588 * 589 * @return The allocated memory chunk. 590 */ 591 void *talloc_zero_size(const void *ctx, size_t size); 592 #else 96 593 #define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) 97 594 #define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) 98 99 #define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) 100 #define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) 101 #define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) 102 #define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) 103 #define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) 104 105 #define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) 106 #define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) 107 595 void *_talloc_zero(const void *ctx, size_t size, const char *name); 596 #endif 597 598 /** 599 * @brief Return the name of a talloc chunk. 600 * 601 * @param[in] ptr The talloc chunk. 602 * 603 * @return The current name for the given talloc pointer. 604 * 605 * @see talloc_set_name() 606 */ 607 const char *talloc_get_name(const void *ptr); 608 609 /** 610 * @brief Verify that a talloc chunk carries a specified name. 611 * 612 * This function checks if a pointer has the specified name. If it does 613 * then the pointer is returned. 614 * 615 * @param[in] ptr The talloc chunk to check. 616 * 617 * @param[in] name The name to check against. 618 * 619 * @return The pointer if the name matches, NULL if it doesn't. 620 */ 621 void *talloc_check_name(const void *ptr, const char *name); 622 623 /** 624 * @brief Get the parent chunk of a pointer. 625 * 626 * @param[in] ptr The talloc pointer to inspect. 627 * 628 * @return The talloc parent of ptr, NULL on error. 629 */ 630 void *talloc_parent(const void *ptr); 631 632 /** 633 * @brief Get a talloc chunk's parent name. 634 * 635 * @param[in] ptr The talloc pointer to inspect. 636 * 637 * @return The name of ptr's parent chunk. 638 */ 639 const char *talloc_parent_name(const void *ptr); 640 641 /** 642 * @brief Get the total size of a talloc chunk including its children. 643 * 644 * The function returns the total size in bytes used by this pointer and all 645 * child pointers. Mostly useful for debugging. 646 * 647 * Passing NULL is allowed, but it will only give a meaningful result if 648 * talloc_enable_leak_report() or talloc_enable_leak_report_full() has 649 * been called. 650 * 651 * @param[in] ptr The talloc chunk. 652 * 653 * @return The total size. 654 */ 655 size_t talloc_total_size(const void *ptr); 656 657 /** 658 * @brief Get the number of talloc chunks hanging off a chunk. 659 * 660 * The talloc_total_blocks() function returns the total memory block 661 * count used by this pointer and all child pointers. Mostly useful for 662 * debugging. 663 * 664 * Passing NULL is allowed, but it will only give a meaningful result if 665 * talloc_enable_leak_report() or talloc_enable_leak_report_full() has 666 * been called. 667 * 668 * @param[in] ptr The talloc chunk. 669 * 670 * @return The total size. 671 */ 672 size_t talloc_total_blocks(const void *ptr); 673 674 #ifdef DOXYGEN 675 /** 676 * @brief Duplicate a memory area into a talloc chunk. 677 * 678 * The function is equivalent to: 679 * 680 * @code 681 * ptr = talloc_size(ctx, size); 682 * if (ptr) memcpy(ptr, p, size); 683 * @endcode 684 * 685 * @param[in] t The talloc context to hang the result off. 686 * 687 * @param[in] p The memory chunk you want to duplicate. 688 * 689 * @param[in] size Number of char's that you want copy. 690 * 691 * @return The allocated memory chunk. 692 * 693 * @see talloc_size() 694 */ 695 void *talloc_memdup(const void *t, const void *p, size_t size); 696 #else 108 697 #define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) 109 698 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); 699 #endif 700 701 #ifdef DOXYGEN 702 /** 703 * @brief Assign a type to a talloc chunk. 704 * 705 * This macro allows you to force the name of a pointer to be a particular type. 706 * This can be used in conjunction with talloc_get_type() to do type checking on 707 * void* pointers. 708 * 709 * It is equivalent to this: 710 * 711 * @code 712 * talloc_set_name_const(ptr, #type) 713 * @endcode 714 * 715 * @param[in] ptr The talloc chunk to assign the type to. 716 * 717 * @param[in] type The type to assign. 718 */ 719 void talloc_set_type(const char *ptr, #type); 720 721 /** 722 * @brief Get a typed pointer out of a talloc pointer. 723 * 724 * This macro allows you to do type checking on talloc pointers. It is 725 * particularly useful for void* private pointers. It is equivalent to 726 * this: 727 * 728 * @code 729 * (type *)talloc_check_name(ptr, #type) 730 * @endcode 731 * 732 * @param[in] ptr The talloc pointer to check. 733 * 734 * @param[in] type The type to check against. 735 * 736 * @return The properly casted pointer given by ptr, NULL on error. 737 */ 738 type *talloc_get_type(const void *ptr, #type); 739 #else 110 740 #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) 111 741 #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) 742 #endif 743 744 #ifdef DOXYGEN 745 /** 746 * @brief Safely turn a void pointer into a typed pointer. 747 * 748 * This macro is used together with talloc(mem_ctx, struct foo). If you had to 749 * assing the talloc chunk pointer to some void pointer variable, 750 * talloc_get_type_abort() is the recommended way to get the convert the void 751 * pointer back to a typed pointer. 752 * 753 * @param[in] ptr The void pointer to convert. 754 * 755 * @param[in] type The type that this chunk contains 756 * 757 * @return The same value as ptr, type-checked and properly cast. 758 */ 759 void *talloc_get_type_abort(const void *ptr, #type); 760 #else 112 761 #define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) 113 762 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); 763 #endif 764 765 /** 766 * @brief Find a parent context by name. 767 * 768 * Find a parent memory context of the current context that has the given 769 * name. This can be very useful in complex programs where it may be 770 * difficult to pass all information down to the level you need, but you 771 * know the structure you want is a parent of another context. 772 * 773 * @param[in] ctx The talloc chunk to start from. 774 * 775 * @param[in] name The name of the parent we look for. 776 * 777 * @return The memory context we are looking for, NULL if not 778 * found. 779 */ 780 void *talloc_find_parent_byname(const void *ctx, const char *name); 781 782 #ifdef DOXYGEN 783 /** 784 * @brief Find a parent context by type. 785 * 786 * Find a parent memory context of the current context that has the given 787 * name. This can be very useful in complex programs where it may be 788 * difficult to pass all information down to the level you need, but you 789 * know the structure you want is a parent of another context. 790 * 791 * Like talloc_find_parent_byname() but takes a type, making it typesafe. 792 * 793 * @param[in] ptr The talloc chunk to start from. 794 * 795 * @param[in] type The type of the parent to look for. 796 * 797 * @return The memory context we are looking for, NULL if not 798 * found. 799 */ 800 void *talloc_find_parent_bytype(const void *ptr, #type); 801 #else 114 802 #define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) 115 #define talloc_free(ctx) _talloc_free(ctx, __location__) 116 803 #endif 804 805 /** 806 * @brief Allocate a talloc pool. 807 * 808 * A talloc pool is a pure optimization for specific situations. In the 809 * release process for Samba 3.2 we found out that we had become considerably 810 * slower than Samba 3.0 was. Profiling showed that malloc(3) was a large CPU 811 * consumer in benchmarks. For Samba 3.2 we have internally converted many 812 * static buffers to dynamically allocated ones, so malloc(3) being beaten 813 * more was no surprise. But it made us slower. 814 * 815 * talloc_pool() is an optimization to call malloc(3) a lot less for the use 816 * pattern Samba has: The SMB protocol is mainly a request/response protocol 817 * where we have to allocate a certain amount of memory per request and free 818 * that after the SMB reply is sent to the client. 819 * 820 * talloc_pool() creates a talloc chunk that you can use as a talloc parent 821 * exactly as you would use any other ::TALLOC_CTX. The difference is that 822 * when you talloc a child of this pool, no malloc(3) is done. Instead, talloc 823 * just increments a pointer inside the talloc_pool. This also works 824 * recursively. If you use the child of the talloc pool as a parent for 825 * grand-children, their memory is also taken from the talloc pool. 826 * 827 * If you talloc_free() children of a talloc pool, the memory is not given 828 * back to the system. Instead, free(3) is only called if the talloc_pool() 829 * itself is released with talloc_free(). 830 * 831 * The downside of a talloc pool is that if you talloc_move() a child of a 832 * talloc pool to a talloc parent outside the pool, the whole pool memory is 833 * not free(3)'ed until that moved chunk is also talloc_free()ed. 834 * 835 * @param[in] context The talloc context to hang the result off. 836 * 837 * @param[in] size Size of the talloc pool. 838 * 839 * @return The allocated talloc pool, NULL on error. 840 */ 841 void *talloc_pool(const void *context, size_t size); 842 843 /** 844 * @brief Free a talloc chunk and NULL out the pointer. 845 * 846 * TALLOC_FREE() frees a pointer and sets it to NULL. Use this if you want 847 * immediate feedback (i.e. crash) if you use a pointer after having free'ed 848 * it. 849 * 850 * @param[in] ctx The chunk to be freed. 851 */ 852 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) 853 854 /* @} ******************************************************************/ 855 856 /** 857 * \defgroup talloc_ref The talloc reference function. 858 * @ingroup talloc 859 * 860 * This module contains the definitions around talloc references 861 * 862 * @{ 863 */ 864 865 /** 866 * @brief Increase the reference count of a talloc chunk. 867 * 868 * The talloc_increase_ref_count(ptr) function is exactly equivalent to: 869 * 870 * @code 871 * talloc_reference(NULL, ptr); 872 * @endcode 873 * 874 * You can use either syntax, depending on which you think is clearer in 875 * your code. 876 * 877 * @param[in] ptr The pointer to increase the reference count. 878 * 879 * @return 0 on success, -1 on error. 880 */ 881 int talloc_increase_ref_count(const void *ptr); 882 883 /** 884 * @brief Get the number of references to a talloc chunk. 885 * 886 * @param[in] ptr The pointer to retrieve the reference count from. 887 * 888 * @return The number of references. 889 */ 890 size_t talloc_reference_count(const void *ptr); 891 892 #ifdef DOXYGEN 893 /** 894 * @brief Create an additional talloc parent to a pointer. 895 * 896 * The talloc_reference() function makes "context" an additional parent of 897 * ptr. Each additional reference consumes around 48 bytes of memory on intel 898 * x86 platforms. 899 * 900 * If ptr is NULL, then the function is a no-op, and simply returns NULL. 901 * 902 * After creating a reference you can free it in one of the following ways: 903 * 904 * - you can talloc_free() any parent of the original pointer. That 905 * will reduce the number of parents of this pointer by 1, and will 906 * cause this pointer to be freed if it runs out of parents. 907 * 908 * - you can talloc_free() the pointer itself. That will destroy the 909 * most recently established parent to the pointer and leave the 910 * pointer as a child of its current parent. 911 * 912 * For more control on which parent to remove, see talloc_unlink() 913 * @param[in] ctx The additional parent. 914 * 915 * @param[in] ptr The pointer you want to create an additional parent for. 916 * 917 * @return The original pointer 'ptr', NULL if talloc ran out of 918 * memory in creating the reference. 919 * 920 * Example: 921 * @code 922 * unsigned int *a, *b, *c; 923 * a = talloc(NULL, unsigned int); 924 * b = talloc(NULL, unsigned int); 925 * c = talloc(a, unsigned int); 926 * // b also serves as a parent of c. 927 * talloc_reference(b, c); 928 * @endcode 929 * 930 * @see talloc_unlink() 931 */ 932 void *talloc_reference(const void *ctx, const void *ptr); 933 #else 934 #define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) 935 void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); 936 #endif 937 938 /** 939 * @brief Remove a specific parent from a talloc chunk. 940 * 941 * The function removes a specific parent from ptr. The context passed must 942 * either be a context used in talloc_reference() with this pointer, or must be 943 * a direct parent of ptr. 944 * 945 * Usually you can just use talloc_free() instead of talloc_unlink(), but 946 * sometimes it is useful to have the additional control on which parent is 947 * removed. 948 * 949 * @param[in] context The talloc parent to remove. 950 * 951 * @param[in] ptr The talloc ptr you want to remove the parent from. 952 * 953 * @return 0 on success, -1 on error. 954 * 955 * @note If the parent has already been removed using talloc_free() then 956 * this function will fail and will return -1. Likewise, if ptr is NULL, 957 * then the function will make no modifications and return -1. 958 * 959 * Example: 960 * @code 961 * unsigned int *a, *b, *c; 962 * a = talloc(NULL, unsigned int); 963 * b = talloc(NULL, unsigned int); 964 * c = talloc(a, unsigned int); 965 * // b also serves as a parent of c. 966 * talloc_reference(b, c); 967 * talloc_unlink(b, c); 968 * @endcode 969 */ 970 int talloc_unlink(const void *context, void *ptr); 971 972 /** 973 * @brief Provide a talloc context that is freed at program exit. 974 * 975 * This is a handy utility function that returns a talloc context 976 * which will be automatically freed on program exit. This can be used 977 * to reduce the noise in memory leak reports. 978 * 979 * Never use this in code that might be used in objects loaded with 980 * dlopen and unloaded with dlclose. talloc_autofree_context() 981 * internally uses atexit(3). Some platforms like modern Linux handles 982 * this fine, but for example FreeBSD does not deal well with dlopen() 983 * and atexit() used simultaneously: dlclose() does not clean up the 984 * list of atexit-handlers, so when the program exits the code that 985 * was registered from within talloc_autofree_context() is gone, the 986 * program crashes at exit. 987 * 988 * @return A talloc context, NULL on error. 989 */ 990 void *talloc_autofree_context(void); 991 992 /** 993 * @brief Get the size of a talloc chunk. 994 * 995 * This function lets you know the amount of memory alloced so far by 996 * this context. It does NOT account for subcontext memory. 997 * This can be used to calculate the size of an array. 998 * 999 * @param[in] ctx The talloc chunk. 1000 * 1001 * @return The size of the talloc chunk. 1002 */ 1003 size_t talloc_get_size(const void *ctx); 1004 1005 /** 1006 * @brief Show the parentage of a context. 1007 * 1008 * @param[in] context The talloc context to look at. 1009 * 1010 * @param[in] file The output to use, a file, stdout or stderr. 1011 */ 1012 void talloc_show_parents(const void *context, FILE *file); 1013 1014 /** 1015 * @brief Check if a context is parent of a talloc chunk. 1016 * 1017 * This checks if context is referenced in the talloc hierarchy above ptr. 1018 * 1019 * @param[in] context The assumed talloc context. 1020 * 1021 * @param[in] ptr The talloc chunk to check. 1022 * 1023 * @return Return 1 if this is the case, 0 if not. 1024 */ 1025 int talloc_is_parent(const void *context, const void *ptr); 1026 1027 /** 1028 * @brief Change the parent context of a talloc pointer. 1029 * 1030 * The function changes the parent context of a talloc pointer. It is typically 1031 * used when the context that the pointer is currently a child of is going to be 1032 * freed and you wish to keep the memory for a longer time. 1033 * 1034 * The difference between talloc_reparent() and talloc_steal() is that 1035 * talloc_reparent() can specify which parent you wish to change. This is 1036 * useful when a pointer has multiple parents via references. 1037 * 1038 * @param[in] old_parent 1039 * @param[in] new_parent 1040 * @param[in] ptr 1041 * 1042 * @return Return the pointer you passed. It does not have any 1043 * failure modes. 1044 */ 1045 void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); 1046 1047 /* @} ******************************************************************/ 1048 1049 /** 1050 * @defgroup talloc_array The talloc array functions 1051 * @ingroup talloc 1052 * 1053 * Talloc contains some handy helpers for handling Arrays conveniently 1054 * 1055 * @{ 1056 */ 1057 1058 #ifdef DOXYGEN 1059 /** 1060 * @brief Allocate an array. 1061 * 1062 * The macro is equivalent to: 1063 * 1064 * @code 1065 * (type *)talloc_size(ctx, sizeof(type) * count); 1066 * @endcode 1067 * 1068 * except that it provides integer overflow protection for the multiply, 1069 * returning NULL if the multiply overflows. 1070 * 1071 * @param[in] ctx The talloc context to hang the result off. 1072 * 1073 * @param[in] type The type that we want to allocate. 1074 * 1075 * @param[in] count The number of 'type' elements you want to allocate. 1076 * 1077 * @return The allocated result, properly cast to 'type *', NULL on 1078 * error. 1079 * 1080 * Example: 1081 * @code 1082 * unsigned int *a, *b; 1083 * a = talloc_zero(NULL, unsigned int); 1084 * b = talloc_array(a, unsigned int, 100); 1085 * @endcode 1086 * 1087 * @see talloc() 1088 * @see talloc_zero_array() 1089 */ 1090 void *talloc_array(const void *ctx, #type, unsigned count); 1091 #else 1092 #define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) 1093 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); 1094 #endif 1095 1096 #ifdef DOXYGEN 1097 /** 1098 * @brief Allocate an array. 1099 * 1100 * @param[in] ctx The talloc context to hang the result off. 1101 * 1102 * @param[in] size The size of an array element. 1103 * 1104 * @param[in] count The number of elements you want to allocate. 1105 * 1106 * @return The allocated result, NULL on error. 1107 */ 1108 void *talloc_array_size(const void *ctx, size_t size, unsigned count); 1109 #else 1110 #define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) 1111 #endif 1112 1113 #ifdef DOXYGEN 1114 /** 1115 * @brief Allocate an array into a typed pointer. 1116 * 1117 * The macro should be used when you have a pointer to an array and want to 1118 * allocate memory of an array to point at with this pointer. When compiling 1119 * with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() 1120 * and talloc_get_name() will return the current location in the source file 1121 * and not the type. 1122 * 1123 * @param[in] ctx The talloc context to hang the result off. 1124 * 1125 * @param[in] ptr The pointer you want to assign the result to. 1126 * 1127 * @param[in] count The number of elements you want to allocate. 1128 * 1129 * @return The allocated memory chunk, properly casted. NULL on 1130 * error. 1131 */ 1132 void *talloc_array_ptrtype(const void *ctx, const void *ptr, unsigned count); 1133 #else 1134 #define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) 1135 #endif 1136 1137 #ifdef DOXYGEN 1138 /** 1139 * @brief Get the number of elements in a talloc'ed array. 1140 * 1141 * A talloc chunk carries its own size, so for talloc'ed arrays it is not 1142 * necessary to store the number of elements explicitly. 1143 * 1144 * @param[in] ctx The allocated array. 1145 * 1146 * @return The number of elements in ctx. 1147 */ 1148 size_t talloc_array_length(const void *ctx); 1149 #else 1150 #define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) 1151 #endif 1152 1153 #ifdef DOXYGEN 1154 /** 1155 * @brief Allocate a zero-initialized array 1156 * 1157 * @param[in] ctx The talloc context to hang the result off. 1158 * 1159 * @param[in] type The type that we want to allocate. 1160 * 1161 * @param[in] count The number of "type" elements you want to allocate. 1162 * 1163 * @return The allocated result casted to "type *", NULL on error. 1164 * 1165 * The talloc_zero_array() macro is equivalent to: 1166 * 1167 * @code 1168 * ptr = talloc_array(ctx, type, count); 1169 * if (ptr) memset(ptr, sizeof(type) * count); 1170 * @endcode 1171 */ 1172 void *talloc_zero_array(const void *ctx, #type, unsigned count); 1173 #else 1174 #define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) 1175 void *_talloc_zero_array(const void *ctx, 1176 size_t el_size, 1177 unsigned count, 1178 const char *name); 1179 #endif 1180 1181 #ifdef DOXYGEN 1182 /** 1183 * @brief Change the size of a talloc array. 1184 * 1185 * The macro changes the size of a talloc pointer. The 'count' argument is the 1186 * number of elements of type 'type' that you want the resulting pointer to 1187 * hold. 1188 * 1189 * talloc_realloc() has the following equivalences: 1190 * 1191 * @code 1192 * talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); 1193 * talloc_realloc(ctx, NULL, type, N) ==> talloc_array(ctx, type, N); 1194 * talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); 1195 * @endcode 1196 * 1197 * The "context" argument is only used if "ptr" is NULL, otherwise it is 1198 * ignored. 1199 * 1200 * @param[in] ctx The parent context used if ptr is NULL. 1201 * 1202 * @param[in] ptr The chunk to be resized. 1203 * 1204 * @param[in] type The type of the array element inside ptr. 1205 * 1206 * @param[in] count The intended number of array elements. 1207 * 1208 * @return The new array, NULL on error. The call will fail either 1209 * due to a lack of memory, or because the pointer has more 1210 * than one parent (see talloc_reference()). 1211 */ 1212 void *talloc_realloc(const void *ctx, void *ptr, #type, size_t count); 1213 #else 1214 #define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) 1215 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); 1216 #endif 1217 1218 #ifdef DOXYGEN 1219 /** 1220 * @brief Untyped realloc to change the size of a talloc array. 1221 * 1222 * The macro is useful when the type is not known so the typesafe 1223 * talloc_realloc() cannot be used. 1224 * 1225 * @param[in] ctx The parent context used if 'ptr' is NULL. 1226 * 1227 * @param[in] ptr The chunk to be resized. 1228 * 1229 * @param[in] size The new chunk size. 1230 * 1231 * @return The new array, NULL on error. 1232 */ 1233 void *talloc_realloc_size(const void *ctx, void *ptr, size_t size); 1234 #else 1235 #define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) 1236 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); 1237 #endif 1238 1239 /** 1240 * @brief Provide a function version of talloc_realloc_size. 1241 * 1242 * This is a non-macro version of talloc_realloc(), which is useful as 1243 * libraries sometimes want a ralloc function pointer. A realloc() 1244 * implementation encapsulates the functionality of malloc(), free() and 1245 * realloc() in one call, which is why it is useful to be able to pass around 1246 * a single function pointer. 1247 * 1248 * @param[in] context The parent context used if ptr is NULL. 1249 * 1250 * @param[in] ptr The chunk to be resized. 1251 * 1252 * @param[in] size The new chunk size. 1253 * 1254 * @return The new chunk, NULL on error. 1255 */ 1256 void *talloc_realloc_fn(const void *context, void *ptr, size_t size); 1257 1258 /* @} ******************************************************************/ 1259 1260 /** 1261 * @defgroup talloc_string The talloc string functions. 1262 * @ingroup talloc 1263 * 1264 * talloc string allocation and manipulation functions. 1265 * @{ 1266 */ 1267 1268 /** 1269 * @brief Duplicate a string into a talloc chunk. 1270 * 1271 * This function is equivalent to: 1272 * 1273 * @code 1274 * ptr = talloc_size(ctx, strlen(p)+1); 1275 * if (ptr) memcpy(ptr, p, strlen(p)+1); 1276 * @endcode 1277 * 1278 * This functions sets the name of the new pointer to the passed 1279 * string. This is equivalent to: 1280 * 1281 * @code 1282 * talloc_set_name_const(ptr, ptr) 1283 * @endcode 1284 * 1285 * @param[in] t The talloc context to hang the result off. 1286 * 1287 * @param[in] p The string you want to duplicate. 1288 * 1289 * @return The duplicated string, NULL on error. 1290 */ 1291 char *talloc_strdup(const void *t, const char *p); 1292 1293 /** 1294 * @brief Append a string to given string and duplicate the result. 1295 * 1296 * @param[in] s The destination to append to. 1297 * 1298 * @param[in] a The string you want to append. 1299 * 1300 * @return The duplicated string, NULL on error. 1301 * 1302 * @see talloc_strdup() 1303 */ 1304 char *talloc_strdup_append(char *s, const char *a); 1305 1306 /** 1307 * @brief Append a string to a given buffer and duplicate the result. 1308 * 1309 * @param[in] s The destination buffer to append to. 1310 * 1311 * @param[in] a The string you want to append. 1312 * 1313 * @return The duplicated string, NULL on error. 1314 * 1315 * @see talloc_strdup() 1316 */ 1317 char *talloc_strdup_append_buffer(char *s, const char *a); 1318 1319 /** 1320 * @brief Duplicate a length-limited string into a talloc chunk. 1321 * 1322 * This function is the talloc equivalent of the C library function strndup(3). 1323 * 1324 * This functions sets the name of the new pointer to the passed string. This is 1325 * equivalent to: 1326 * 1327 * @code 1328 * talloc_set_name_const(ptr, ptr) 1329 * @endcode 1330 * 1331 * @param[in] t The talloc context to hang the result off. 1332 * 1333 * @param[in] p The string you want to duplicate. 1334 * 1335 * @param[in] n The maximum string length to duplicate. 1336 * 1337 * @return The duplicated string, NULL on error. 1338 */ 1339 char *talloc_strndup(const void *t, const char *p, size_t n); 1340 1341 /** 1342 * @brief Append at most n characters of a string to given string and duplicate 1343 * the result. 1344 * 1345 * @param[in] s The destination string to append to. 1346 * 1347 * @param[in] a The source string you want to append. 1348 * 1349 * @param[in] n The number of characters you want to append from the 1350 * string. 1351 * 1352 * @return The duplicated string, NULL on error. 1353 * 1354 * @see talloc_strndup() 1355 */ 1356 char *talloc_strndup_append(char *s, const char *a, size_t n); 1357 1358 /** 1359 * @brief Append at most n characters of a string to given buffer and duplicate 1360 * the result. 1361 * 1362 * @param[in] s The destination buffer to append to. 1363 * 1364 * @param[in] a The source string you want to append. 1365 * 1366 * @param[in] n The number of characters you want to append from the 1367 * string. 1368 * 1369 * @return The duplicated string, NULL on error. 1370 * 1371 * @see talloc_strndup() 1372 */ 1373 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); 1374 1375 /** 1376 * @brief Format a string given a va_list. 1377 * 1378 * This function is the talloc equivalent of the C library function 1379 * vasprintf(3). 1380 * 1381 * This functions sets the name of the new pointer to the new string. This is 1382 * equivalent to: 1383 * 1384 * @code 1385 * talloc_set_name_const(ptr, ptr) 1386 * @endcode 1387 * 1388 * @param[in] t The talloc context to hang the result off. 1389 * 1390 * @param[in] fmt The format string. 1391 * 1392 * @param[in] ap The parameters used to fill fmt. 1393 * 1394 * @return The formatted string, NULL on error. 1395 */ 1396 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 1397 1398 /** 1399 * @brief Format a string given a va_list and append it to the given destination 1400 * string. 1401 * 1402 * @param[in] s The destination string to append to. 1403 * 1404 * @param[in] fmt The format string. 1405 * 1406 * @param[in] ap The parameters used to fill fmt. 1407 * 1408 * @return The formatted string, NULL on error. 1409 * 1410 * @see talloc_vasprintf() 1411 */ 1412 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 1413 1414 /** 1415 * @brief Format a string given a va_list and append it to the given destination 1416 * buffer. 1417 * 1418 * @param[in] s The destination buffer to append to. 1419 * 1420 * @param[in] fmt The format string. 1421 * 1422 * @param[in] ap The parameters used to fill fmt. 1423 * 1424 * @return The formatted string, NULL on error. 1425 * 1426 * @see talloc_vasprintf() 1427 */ 1428 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 1429 1430 /** 1431 * @brief Format a string. 1432 * 1433 * This function is the talloc equivalent of the C library function asprintf(3). 1434 * 1435 * This functions sets the name of the new pointer to the new string. This is 1436 * equivalent to: 1437 * 1438 * @code 1439 * talloc_set_name_const(ptr, ptr) 1440 * @endcode 1441 * 1442 * @param[in] t The talloc context to hang the result off. 1443 * 1444 * @param[in] fmt The format string. 1445 * 1446 * @param[in] ... The parameters used to fill fmt. 1447 * 1448 * @return The formatted string, NULL on error. 1449 */ 1450 char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 1451 1452 /** 1453 * @brief Append a formatted string to another string. 1454 * 1455 * This function appends the given formatted string to the given string. Use 1456 * this varient when the string in the current talloc buffer may have been 1457 * truncated in length. 1458 * 1459 * This functions sets the name of the new pointer to the new 1460 * string. This is equivalent to: 1461 * 1462 * @code 1463 * talloc_set_name_const(ptr, ptr) 1464 * @endcode 1465 * 1466 * @param[in] s The string to append to. 1467 * 1468 * @param[in] fmt The format string. 1469 * 1470 * @param[in] ... The parameters used to fill fmt. 1471 * 1472 * @return The formatted string, NULL on error. 1473 */ 1474 char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 1475 1476 /** 1477 * @brief Append a formatted string to another string. 1478 * 1479 * @param[in] s The string to append to 1480 * 1481 * @param[in] fmt The format string. 1482 * 1483 * @param[in] ... The parameters used to fill fmt. 1484 * 1485 * @return The formatted string, NULL on error. 1486 */ 1487 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 1488 1489 /* @} ******************************************************************/ 1490 1491 /** 1492 * @defgroup talloc_debug The talloc debugging support functions 1493 * @ingroup talloc 1494 * 1495 * To aid memory debugging, talloc contains routines to inspect the currently 1496 * allocated memory hierarchy. 1497 * 1498 * @{ 1499 */ 1500 1501 /** 1502 * @brief Walk a complete talloc hierarchy. 1503 * 1504 * This provides a more flexible reports than talloc_report(). It 1505 * will recursively call the callback for the entire tree of memory 1506 * referenced by the pointer. References in the tree are passed with 1507 * is_ref = 1 and the pointer that is referenced. 1508 * 1509 * You can pass NULL for the pointer, in which case a report is 1510 * printed for the top level memory context, but only if 1511 * talloc_enable_leak_report() or talloc_enable_leak_report_full() 1512 * has been called. 1513 * 1514 * The recursion is stopped when depth >= max_depth. 1515 * max_depth = -1 means only stop at leaf nodes. 1516 * 1517 * @param[in] ptr The talloc chunk. 1518 * 1519 * @param[in] depth Internal parameter to control recursion. Call with 0. 1520 * 1521 * @param[in] max_depth Maximum recursion level. 1522 * 1523 * @param[in] callback Function to be called on every chunk. 1524 * 1525 * @param[in] private_data Private pointer passed to callback. 1526 */ 1527 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, 1528 void (*callback)(const void *ptr, 1529 int depth, int max_depth, 1530 int is_ref, 1531 void *private_data), 1532 void *private_data); 1533 1534 /** 1535 * @brief Print a talloc hierarchy. 1536 * 1537 * This provides a more flexible reports than talloc_report(). It 1538 * will let you specify the depth and max_depth. 1539 * 1540 * @param[in] ptr The talloc chunk. 1541 * 1542 * @param[in] depth Internal parameter to control recursion. Call with 0. 1543 * 1544 * @param[in] max_depth Maximum recursion level. 1545 * 1546 * @param[in] f The file handle to print to. 1547 */ 1548 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); 1549 1550 /** 1551 * @brief Print a summary report of all memory used by ptr. 1552 * 1553 * This provides a more detailed report than talloc_report(). It will 1554 * recursively print the ensire tree of memory referenced by the 1555 * pointer. References in the tree are shown by giving the name of the 1556 * pointer that is referenced. 1557 * 1558 * You can pass NULL for the pointer, in which case a report is printed 1559 * for the top level memory context, but only if 1560 * talloc_enable_leak_report() or talloc_enable_leak_report_full() has 1561 * been called. 1562 * 1563 * @param[in] ptr The talloc chunk. 1564 * 1565 * @param[in] f The file handle to print to. 1566 * 1567 * Example: 1568 * @code 1569 * unsigned int *a, *b; 1570 * a = talloc(NULL, unsigned int); 1571 * b = talloc(a, unsigned int); 1572 * fprintf(stderr, "Dumping memory tree for a:\n"); 1573 * talloc_report_full(a, stderr); 1574 * @endcode 1575 * 1576 * @see talloc_report() 1577 */ 1578 void talloc_report_full(const void *ptr, FILE *f); 1579 1580 /** 1581 * @brief Print a summary report of all memory used by ptr. 1582 * 1583 * This function prints a summary report of all memory used by ptr. One line of 1584 * report is printed for each immediate child of ptr, showing the total memory 1585 * and number of blocks used by that child. 1586 * 1587 * You can pass NULL for the pointer, in which case a report is printed 1588 * for the top level memory context, but only if talloc_enable_leak_report() 1589 * or talloc_enable_leak_report_full() has been called. 1590 * 1591 * @param[in] ptr The talloc chunk. 1592 * 1593 * @param[in] f The file handle to print to. 1594 * 1595 * Example: 1596 * @code 1597 * unsigned int *a, *b; 1598 * a = talloc(NULL, unsigned int); 1599 * b = talloc(a, unsigned int); 1600 * fprintf(stderr, "Summary of memory tree for a:\n"); 1601 * talloc_report(a, stderr); 1602 * @endcode 1603 * 1604 * @see talloc_report_full() 1605 */ 1606 void talloc_report(const void *ptr, FILE *f); 1607 1608 /** 1609 * @brief Enable tracking the use of NULL memory contexts. 1610 * 1611 * This enables tracking of the NULL memory context without enabling leak 1612 * reporting on exit. Useful for when you want to do your own leak 1613 * reporting call via talloc_report_null_full(); 1614 */ 1615 void talloc_enable_null_tracking(void); 1616 1617 /** 1618 * @brief Enable tracking the use of NULL memory contexts. 1619 * 1620 * This enables tracking of the NULL memory context without enabling leak 1621 * reporting on exit. Useful for when you want to do your own leak 1622 * reporting call via talloc_report_null_full(); 1623 */ 1624 void talloc_enable_null_tracking_no_autofree(void); 1625 1626 /** 1627 * @brief Disable tracking of the NULL memory context. 1628 * 1629 * This disables tracking of the NULL memory context. 1630 */ 1631 void talloc_disable_null_tracking(void); 1632 1633 /** 1634 * @brief Enable leak report when a program exits. 1635 * 1636 * This enables calling of talloc_report(NULL, stderr) when the program 1637 * exits. In Samba4 this is enabled by using the --leak-report command 1638 * line option. 1639 * 1640 * For it to be useful, this function must be called before any other 1641 * talloc function as it establishes a "null context" that acts as the 1642 * top of the tree. If you don't call this function first then passing 1643 * NULL to talloc_report() or talloc_report_full() won't give you the 1644 * full tree printout. 1645 * 1646 * Here is a typical talloc report: 1647 * 1648 * @code 1649 * talloc report on 'null_context' (total 267 bytes in 15 blocks) 1650 * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks 1651 * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks 1652 * iconv(UTF8,CP850) contains 42 bytes in 2 blocks 1653 * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks 1654 * iconv(CP850,UTF8) contains 42 bytes in 2 blocks 1655 * iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks 1656 * iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks 1657 * @endcode 1658 */ 1659 void talloc_enable_leak_report(void); 1660 1661 /** 1662 * @brief Enable full leak report when a program exits. 1663 * 1664 * This enables calling of talloc_report_full(NULL, stderr) when the 1665 * program exits. In Samba4 this is enabled by using the 1666 * --leak-report-full command line option. 1667 * 1668 * For it to be useful, this function must be called before any other 1669 * talloc function as it establishes a "null context" that acts as the 1670 * top of the tree. If you don't call this function first then passing 1671 * NULL to talloc_report() or talloc_report_full() won't give you the 1672 * full tree printout. 1673 * 1674 * Here is a typical full report: 1675 * 1676 * @code 1677 * full talloc report on 'root' (total 18 bytes in 8 blocks) 1678 * p1 contains 18 bytes in 7 blocks (ref 0) 1679 * r1 contains 13 bytes in 2 blocks (ref 0) 1680 * reference to: p2 1681 * p2 contains 1 bytes in 1 blocks (ref 1) 1682 * x3 contains 1 bytes in 1 blocks (ref 0) 1683 * x2 contains 1 bytes in 1 blocks (ref 0) 1684 * x1 contains 1 bytes in 1 blocks (ref 0) 1685 * @endcode 1686 */ 1687 void talloc_enable_leak_report_full(void); 1688 1689 /* @} ******************************************************************/ 1690 1691 void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); 1692 void talloc_set_log_fn(void (*log_fn)(const char *message)); 1693 void talloc_set_log_stderr(void); 117 1694 118 1695 #if TALLOC_DEPRECATED … … 125 1702 #endif 126 1703 127 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) 128 129 /* The following definitions come from talloc.c */ 130 void *_talloc(const void *context, size_t size); 131 void *talloc_pool(const void *context, size_t size); 132 void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); 133 int talloc_increase_ref_count(const void *ptr); 134 size_t talloc_reference_count(const void *ptr); 135 void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); 136 int talloc_unlink(const void *context, void *ptr); 137 const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 138 void talloc_set_name_const(const void *ptr, const char *name); 139 void *talloc_named(const void *context, size_t size, 140 const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); 141 void *talloc_named_const(const void *context, size_t size, const char *name); 142 const char *talloc_get_name(const void *ptr); 143 void *talloc_check_name(const void *ptr, const char *name); 144 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); 145 void *talloc_parent(const void *ptr); 146 const char *talloc_parent_name(const void *ptr); 147 void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); 148 int _talloc_free(void *ptr, const char *location); 149 void talloc_free_children(void *ptr); 150 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); 151 void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); 152 void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); 153 void *_talloc_move(const void *new_ctx, const void *pptr); 154 size_t talloc_total_size(const void *ptr); 155 size_t talloc_total_blocks(const void *ptr); 156 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, 157 void (*callback)(const void *ptr, 158 int depth, int max_depth, 159 int is_ref, 160 void *private_data), 161 void *private_data); 162 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); 163 void talloc_report_full(const void *ptr, FILE *f); 164 void talloc_report(const void *ptr, FILE *f); 165 void talloc_enable_null_tracking(void); 166 void talloc_enable_null_tracking_no_autofree(void); 167 void talloc_disable_null_tracking(void); 168 void talloc_enable_leak_report(void); 169 void talloc_enable_leak_report_full(void); 170 void *_talloc_zero(const void *ctx, size_t size, const char *name); 171 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); 172 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); 173 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); 174 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); 175 void *talloc_realloc_fn(const void *context, void *ptr, size_t size); 176 void *talloc_autofree_context(void); 177 size_t talloc_get_size(const void *ctx); 178 void *talloc_find_parent_byname(const void *ctx, const char *name); 179 void talloc_show_parents(const void *context, FILE *file); 180 int talloc_is_parent(const void *context, const void *ptr); 181 182 char *talloc_strdup(const void *t, const char *p); 183 char *talloc_strdup_append(char *s, const char *a); 184 char *talloc_strdup_append_buffer(char *s, const char *a); 185 186 char *talloc_strndup(const void *t, const char *p, size_t n); 187 char *talloc_strndup_append(char *s, const char *a, size_t n); 188 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); 189 190 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 191 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 192 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); 193 194 char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 195 char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 196 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); 197 198 void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); 199 void talloc_set_log_fn(void (*log_fn)(const char *message)); 200 void talloc_set_log_stderr(void); 201 202 #endif 1704 #ifndef TALLOC_MAX_DEPTH 1705 #define TALLOC_MAX_DEPTH 10000 1706 #endif 1707 1708 #ifdef __cplusplus 1709 } /* end of extern "C" */ 1710 #endif 1711 1712 #endif -
vendor/current/lib/talloc/talloc.pc.in
r414 r740 7 7 Description: A hierarchical pool based memory system with destructors 8 8 Version: @TALLOC_VERSION@ 9 Libs: -L${libdir} -ltalloc9 Libs: @LIB_RPATH@ -L${libdir} -ltalloc 10 10 Cflags: -I${includedir} 11 11 URL: http://talloc.samba.org/ -
vendor/current/lib/talloc/talloc_guide.txt
r414 r740 75 75 synchronization. 76 76 77 talloc and shared objects 78 ------------------------- 79 80 talloc can be used in shared objects. Special care needs to be taken 81 to never use talloc_autofree_context() in code that might be loaded 82 with dlopen() and unloaded with dlclose(), as talloc_autofree_context() 83 internally uses atexit(3). Some platforms like modern Linux handles 84 this fine, but for example FreeBSD does not deal well with dlopen() 85 and atexit() used simultaneously: dlclose() does not clean up the list 86 of atexit-handlers, so when the program exits the code that was 87 registered from within talloc_autofree_context() is gone, the program 88 crashes at exit. 89 77 90 78 91 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- … … 118 131 119 132 The return value of talloc_free() indicates success or failure, with 0 120 returned for success and -1 for failure. The only possible failure 121 condition is if the pointer had a destructor attached to it and the 122 destructor returned -1. See talloc_set_destructor() for details on 123 destructors. 133 returned for success and -1 for failure. A possible failure condition 134 is if the pointer had a destructor attached to it and the destructor 135 returned -1. See talloc_set_destructor() for details on 136 destructors. Likewise, if "ptr" is NULL, then the function will make 137 no modifications and returns -1. 124 138 125 139 If this pointer has an additional parent when talloc_free() is called … … 653 667 654 668 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 655 ((type *)talloc_array(const void *ctx, type, u int_t count);669 ((type *)talloc_array(const void *ctx, type, unsigned int count); 656 670 657 671 The talloc_array() macro is equivalent to:: … … 664 678 665 679 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 666 void *talloc_array_size(const void *ctx, size_t size, u int_t count);680 void *talloc_array_size(const void *ctx, size_t size, unsigned int count); 667 681 668 682 The talloc_array_size() function is useful when the type is not … … 671 685 672 686 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 673 (typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, u int_t count);687 (typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count); 674 688 675 689 The talloc_ptrtype() macro should be used when you have a pointer to an array -
vendor/current/lib/talloc/testsuite.c
r414 r740 26 26 #include "replace.h" 27 27 #include "system/time.h" 28 #include "talloc.h" 28 #include <talloc.h> 29 30 #include "talloc_testsuite.h" 29 31 30 32 static struct timeval timeval_current(void) … … 102 104 static unsigned int test_abort_count; 103 105 106 #if 0 104 107 static void test_abort_fn(const char *reason) 105 108 { … … 113 116 talloc_set_abort_fn(test_abort_fn); 114 117 } 118 #endif 115 119 116 120 static void test_abort_stop(void) … … 1120 1124 void *pool; 1121 1125 void *p1, *p2, *p3, *p4; 1126 void *p2_2; 1122 1127 1123 1128 pool = talloc_pool(NULL, 1024); 1124 1129 1125 1130 p1 = talloc_size(pool, 80); 1131 memset(p1, 0x11, talloc_get_size(p1)); 1126 1132 p2 = talloc_size(pool, 20); 1133 memset(p2, 0x11, talloc_get_size(p2)); 1127 1134 p3 = talloc_size(p1, 50); 1135 memset(p3, 0x11, talloc_get_size(p3)); 1128 1136 p4 = talloc_size(p3, 1000); 1137 memset(p4, 0x11, talloc_get_size(p4)); 1138 1139 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1140 p2_2 = talloc_realloc_size(pool, p2, 20+1); 1141 torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed"); 1142 memset(p2, 0x11, talloc_get_size(p2)); 1143 p2_2 = talloc_realloc_size(pool, p2, 20-1); 1144 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); 1145 memset(p2, 0x11, talloc_get_size(p2)); 1146 p2_2 = talloc_realloc_size(pool, p2, 20-1); 1147 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); 1148 memset(p2, 0x11, talloc_get_size(p2)); 1149 1150 talloc_free(p3); 1151 1152 /* this should reclaim the memory of p4 and p3 */ 1153 p2_2 = talloc_realloc_size(pool, p2, 400); 1154 torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed"); 1155 memset(p2, 0x11, talloc_get_size(p2)); 1156 1157 talloc_free(p1); 1158 1159 /* this should reclaim the memory of p1 */ 1160 p2_2 = talloc_realloc_size(pool, p2, 800); 1161 torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed"); 1162 p2 = p2_2; 1163 memset(p2, 0x11, talloc_get_size(p2)); 1164 1165 /* this should do a malloc */ 1166 p2_2 = talloc_realloc_size(pool, p2, 1800); 1167 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed"); 1168 p2 = p2_2; 1169 memset(p2, 0x11, talloc_get_size(p2)); 1170 1171 /* this should reclaim the memory from the pool */ 1172 p3 = talloc_size(pool, 80); 1173 torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed"); 1174 memset(p3, 0x11, talloc_get_size(p3)); 1175 1176 talloc_free(p2); 1177 talloc_free(p3); 1178 1179 p1 = talloc_size(pool, 80); 1180 memset(p1, 0x11, talloc_get_size(p1)); 1181 p2 = talloc_size(pool, 20); 1182 memset(p2, 0x11, talloc_get_size(p2)); 1183 1184 talloc_free(p1); 1185 1186 p2_2 = talloc_realloc_size(pool, p2, 20-1); 1187 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); 1188 memset(p2, 0x11, talloc_get_size(p2)); 1189 p2_2 = talloc_realloc_size(pool, p2, 20-1); 1190 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); 1191 memset(p2, 0x11, talloc_get_size(p2)); 1192 1193 /* this should do a malloc */ 1194 p2_2 = talloc_realloc_size(pool, p2, 1800); 1195 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed"); 1196 p2 = p2_2; 1197 memset(p2, 0x11, talloc_get_size(p2)); 1198 1199 /* this should reclaim the memory from the pool */ 1200 p3 = talloc_size(pool, 800); 1201 torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed"); 1202 memset(p3, 0x11, talloc_get_size(p3)); 1203 1204 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1129 1205 1130 1206 talloc_free(pool); … … 1132 1208 return true; 1133 1209 } 1210 1211 static bool test_pool_steal(void) 1212 { 1213 void *root; 1214 void *pool; 1215 void *p1, *p2; 1216 void *p1_2, *p2_2; 1217 size_t hdr; 1218 size_t ofs1, ofs2; 1219 1220 root = talloc_new(NULL); 1221 pool = talloc_pool(root, 1024); 1222 1223 p1 = talloc_size(pool, 4 * 16); 1224 torture_assert("pool allocate 4 * 16", p1 != NULL, "failed "); 1225 memset(p1, 0x11, talloc_get_size(p1)); 1226 p2 = talloc_size(pool, 4 * 16); 1227 torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) "); 1228 memset(p2, 0x11, talloc_get_size(p2)); 1229 1230 ofs1 = PTR_DIFF(p2, p1); 1231 hdr = ofs1 - talloc_get_size(p1); 1232 1233 talloc_steal(root, p1); 1234 talloc_steal(root, p2); 1235 1236 talloc_free(pool); 1237 1238 p1_2 = p1; 1239 1240 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1241 p1_2 = talloc_realloc_size(root, p1, 5 * 16); 1242 torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed"); 1243 memset(p1_2, 0x11, talloc_get_size(p1_2)); 1244 ofs1 = PTR_DIFF(p1_2, p2); 1245 ofs2 = talloc_get_size(p2) + hdr; 1246 1247 torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected"); 1248 1249 p2_2 = talloc_realloc_size(root, p2, 3 * 16); 1250 torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed"); 1251 memset(p2_2, 0x11, talloc_get_size(p2_2)); 1252 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1253 1254 talloc_free(p1_2); 1255 1256 p2_2 = p2; 1257 1258 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1259 /* now we should reclaim the full pool */ 1260 p2_2 = talloc_realloc_size(root, p2, 8 * 16); 1261 torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected"); 1262 p2 = p2_2; 1263 memset(p2_2, 0x11, talloc_get_size(p2_2)); 1264 1265 /* now we malloc and free the full pool space */ 1266 p2_2 = talloc_realloc_size(root, p2, 2 * 1024); 1267 torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected"); 1268 memset(p2_2, 0x11, talloc_get_size(p2_2)); 1269 1270 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ 1271 1272 talloc_free(p2_2); 1273 1274 talloc_free(root); 1275 1276 return true; 1277 } 1278 1279 static bool test_free_ref_null_context(void) 1280 { 1281 void *p1, *p2, *p3; 1282 int ret; 1283 1284 talloc_disable_null_tracking(); 1285 p1 = talloc_new(NULL); 1286 p2 = talloc_new(NULL); 1287 1288 p3 = talloc_reference(p2, p1); 1289 torture_assert("reference", p3 == p1, "failed: reference on null"); 1290 1291 ret = talloc_free(p1); 1292 torture_assert("ref free with null parent", ret == 0, "failed: free with null parent"); 1293 talloc_free(p2); 1294 1295 talloc_enable_null_tracking_no_autofree(); 1296 p1 = talloc_new(NULL); 1297 p2 = talloc_new(NULL); 1298 1299 p3 = talloc_reference(p2, p1); 1300 torture_assert("reference", p3 == p1, "failed: reference on null"); 1301 1302 ret = talloc_free(p1); 1303 torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent"); 1304 talloc_free(p2); 1305 1306 return true; 1307 } 1308 1309 static bool test_rusty(void) 1310 { 1311 void *root; 1312 const char *p1; 1313 1314 talloc_enable_null_tracking(); 1315 root = talloc_new(NULL); 1316 p1 = talloc_strdup(root, "foo"); 1317 talloc_increase_ref_count(p1); 1318 talloc_report_full(root, stdout); 1319 talloc_free(root); 1320 return true; 1321 } 1322 1134 1323 1135 1324 static void test_reset(void) … … 1141 1330 } 1142 1331 1143 struct torture_context;1144 1332 bool torture_local_talloc(struct torture_context *tctx) 1145 1333 { … … 1186 1374 test_reset(); 1187 1375 ret &= test_pool(); 1376 test_reset(); 1377 ret &= test_pool_steal(); 1378 test_reset(); 1379 ret &= test_free_ref_null_context(); 1380 test_reset(); 1381 ret &= test_rusty(); 1188 1382 1189 1383 if (ret) { … … 1195 1389 1196 1390 test_reset(); 1197 1391 talloc_disable_null_tracking(); 1198 1392 return ret; 1199 1393 } -
vendor/current/lib/talloc/testsuite_main.c
r414 r740 26 26 #include "replace.h" 27 27 28 struct torture_context; 29 bool torture_local_talloc(struct torture_context *tctx); 28 #include "talloc_testsuite.h" 30 29 31 30 int main(void) -
vendor/current/lib/tdb/common/check.c
r414 r740 29 29 { 30 30 struct tdb_header hdr; 31 32 if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), DOCONV()) == -1) 31 uint32_t h1, h2; 32 33 if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1) 33 34 return false; 34 35 if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) … … 39 40 goto corrupt; 40 41 41 if (hdr.rwlocks != 0) 42 if (hdr.rwlocks != 0 && hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC) 43 goto corrupt; 44 45 tdb_header_hash(tdb, &h1, &h2); 46 if (hdr.magic1_hash && hdr.magic2_hash && 47 (hdr.magic1_hash != h1 || hdr.magic2_hash != h2)) 42 48 goto corrupt; 43 49 … … 302 308 } 303 309 304 int tdb_check(struct tdb_context *tdb, 310 /* Slow, but should be very rare. */ 311 size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off) 312 { 313 size_t len; 314 315 for (len = 0; off + len < tdb->map_size; len++) { 316 char c; 317 if (tdb->methods->tdb_read(tdb, off, &c, 1, 0)) 318 return 0; 319 if (c != 0 && c != 0x42) 320 break; 321 } 322 return len; 323 } 324 325 _PUBLIC_ int tdb_check(struct tdb_context *tdb, 305 326 int (*check)(TDB_DATA key, TDB_DATA data, void *private_data), 306 327 void *private_data) … … 311 332 struct tdb_record rec; 312 333 bool found_recovery = false; 313 314 if (tdb_lockall(tdb) == -1) 315 return -1; 334 tdb_len_t dead; 335 bool locked; 336 337 /* Read-only databases use no locking at all: it's best-effort. 338 * We may have a write lock already, so skip that case too. */ 339 if (tdb->read_only || tdb->allrecord_lock.count != 0) { 340 locked = false; 341 } else { 342 if (tdb_lockall_read(tdb) == -1) 343 return -1; 344 locked = true; 345 } 316 346 317 347 /* Make sure we know true size of the underlying file. */ … … 370 400 goto free; 371 401 break; 402 /* If we crash after ftruncate, we can get zeroes or fill. */ 403 case TDB_RECOVERY_INVALID_MAGIC: 404 case 0x42424242: 405 if (recovery_start == off) { 406 found_recovery = true; 407 break; 408 } 409 dead = tdb_dead_space(tdb, off); 410 if (dead < sizeof(rec)) 411 goto corrupt; 412 413 TDB_LOG((tdb, TDB_DEBUG_ERROR, 414 "Dead space at %d-%d (of %u)\n", 415 off, off + dead, tdb->map_size)); 416 rec.rec_len = dead - sizeof(rec); 417 break; 372 418 case TDB_RECOVERY_MAGIC: 373 case 0: /* Used for invalid (or in-progress) recovery area. */374 419 if (recovery_start != off) { 375 420 TDB_LOG((tdb, TDB_DEBUG_ERROR, … … 380 425 found_recovery = true; 381 426 break; 382 default: 427 default: ; 428 corrupt: 383 429 tdb->ecode = TDB_ERR_CORRUPT; 384 430 TDB_LOG((tdb, TDB_DEBUG_ERROR, … … 406 452 if (recovery_start != 0 && !found_recovery) { 407 453 TDB_LOG((tdb, TDB_DEBUG_ERROR, 408 "Expected %s recovery area, got %s\n", 409 recovery_start ? "a" : "no", 410 found_recovery ? "one" : "none")); 454 "Expected a recovery area at %u\n", 455 recovery_start)); 411 456 goto free; 412 457 } 413 458 414 459 free(hashes); 415 tdb_unlockall(tdb); 460 if (locked) { 461 tdb_unlockall_read(tdb); 462 } 416 463 return 0; 417 464 … … 419 466 free(hashes); 420 467 unlock: 421 tdb_unlockall(tdb); 468 if (locked) { 469 tdb_unlockall_read(tdb); 470 } 422 471 return -1; 423 472 } -
vendor/current/lib/tdb/common/dump.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 81 81 } 82 82 83 void tdb_dump_all(struct tdb_context *tdb)83 _PUBLIC_ void tdb_dump_all(struct tdb_context *tdb) 84 84 { 85 85 int i; … … 91 91 } 92 92 93 int tdb_printfreelist(struct tdb_context *tdb)93 _PUBLIC_ int tdb_printfreelist(struct tdb_context *tdb) 94 94 { 95 95 int ret; -
vendor/current/lib/tdb/common/error.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 28 28 #include "tdb_private.h" 29 29 30 enum TDB_ERROR tdb_error(struct tdb_context *tdb)30 _PUBLIC_ enum TDB_ERROR tdb_error(struct tdb_context *tdb) 31 31 { 32 32 return tdb->ecode; … … 47 47 48 48 /* Error string for the last tdb error */ 49 const char *tdb_errorstr(struct tdb_context *tdb)49 _PUBLIC_ const char *tdb_errorstr(struct tdb_context *tdb) 50 50 { 51 51 uint32_t i; -
vendor/current/lib/tdb/common/freelist.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 99 99 100 100 /* Add an element into the freelist. Merge adjacent records if 101 nec cessary. */101 necessary. */ 102 102 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) 103 103 { … … 144 144 struct tdb_record l; 145 145 tdb_off_t leftsize; 146 146 147 147 /* Read in tailer and jump back to header */ 148 148 if (tdb_ofs_read(tdb, left, &leftsize) == -1) { … … 335 335 break; 336 336 } 337 337 338 338 /* this multiplier means we only extremely rarely 339 339 search more than 50 or so records. At 50 records we … … 368 368 return the size of the freelist - used to decide if we should repack 369 369 */ 370 int tdb_freelist_size(struct tdb_context *tdb)370 _PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb) 371 371 { 372 372 tdb_off_t ptr; -
vendor/current/lib/tdb/common/freelistcheck.c
r414 r740 44 44 } 45 45 46 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)46 _PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) 47 47 { 48 48 struct tdb_context *mem_tdb = NULL; -
vendor/current/lib/tdb/common/io.c
r597 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 477 477 tdb_oob, 478 478 tdb_expand_file, 479 tdb_brlock480 479 }; 481 480 -
vendor/current/lib/tdb/common/lock.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 28 28 #include "tdb_private.h" 29 29 30 #define TDB_MARK_LOCK 0x80000000 31 32 void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr) 30 _PUBLIC_ void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr) 33 31 { 34 32 tdb->interrupt_sig_ptr = ptr; 33 } 34 35 static int fcntl_lock(struct tdb_context *tdb, 36 int rw, off_t off, off_t len, bool waitflag) 37 { 38 struct flock fl; 39 40 fl.l_type = rw; 41 fl.l_whence = SEEK_SET; 42 fl.l_start = off; 43 fl.l_len = len; 44 fl.l_pid = 0; 45 46 if (waitflag) 47 return fcntl(tdb->fd, F_SETLKW, &fl); 48 else 49 return fcntl(tdb->fd, F_SETLK, &fl); 50 } 51 52 static int fcntl_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len) 53 { 54 struct flock fl; 55 #if 0 /* Check they matched up locks and unlocks correctly. */ 56 char line[80]; 57 FILE *locks; 58 bool found = false; 59 60 locks = fopen("/proc/locks", "r"); 61 62 while (fgets(line, 80, locks)) { 63 char *p; 64 int type, start, l; 65 66 /* eg. 1: FLOCK ADVISORY WRITE 2440 08:01:2180826 0 EOF */ 67 p = strchr(line, ':') + 1; 68 if (strncmp(p, " POSIX ADVISORY ", strlen(" POSIX ADVISORY "))) 69 continue; 70 p += strlen(" FLOCK ADVISORY "); 71 if (strncmp(p, "READ ", strlen("READ ")) == 0) 72 type = F_RDLCK; 73 else if (strncmp(p, "WRITE ", strlen("WRITE ")) == 0) 74 type = F_WRLCK; 75 else 76 abort(); 77 p += 6; 78 if (atoi(p) != getpid()) 79 continue; 80 p = strchr(strchr(p, ' ') + 1, ' ') + 1; 81 start = atoi(p); 82 p = strchr(p, ' ') + 1; 83 if (strncmp(p, "EOF", 3) == 0) 84 l = 0; 85 else 86 l = atoi(p) - start + 1; 87 88 if (off == start) { 89 if (len != l) { 90 fprintf(stderr, "Len %u should be %u: %s", 91 (int)len, l, line); 92 abort(); 93 } 94 if (type != rw) { 95 fprintf(stderr, "Type %s wrong: %s", 96 rw == F_RDLCK ? "READ" : "WRITE", line); 97 abort(); 98 } 99 found = true; 100 break; 101 } 102 } 103 104 if (!found) { 105 fprintf(stderr, "Unlock on %u@%u not found!\n", 106 (int)off, (int)len); 107 abort(); 108 } 109 110 fclose(locks); 111 #endif 112 113 fl.l_type = F_UNLCK; 114 fl.l_whence = SEEK_SET; 115 fl.l_start = off; 116 fl.l_len = len; 117 fl.l_pid = 0; 118 119 return fcntl(tdb->fd, F_SETLKW, &fl); 120 } 121 122 /* list -1 is the alloc list, otherwise a hash chain. */ 123 static tdb_off_t lock_offset(int list) 124 { 125 return FREELIST_TOP + 4*list; 35 126 } 36 127 … … 43 134 note that a len of zero means lock to end of file 44 135 */ 45 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,46 int rw_type, int lck_type, int probe, size_t len)47 { 48 struct flock fl; 136 int tdb_brlock(struct tdb_context *tdb, 137 int rw_type, tdb_off_t offset, size_t len, 138 enum tdb_lock_flags flags) 139 { 49 140 int ret; 50 141 51 142 if (tdb->flags & TDB_NOLOCK) { 143 return 0; 144 } 145 146 if (flags & TDB_LOCK_MARK_ONLY) { 52 147 return 0; 53 148 } … … 58 153 } 59 154 60 fl.l_type = rw_type;61 fl.l_whence = SEEK_SET;62 fl.l_start = offset;63 fl.l_len = len;64 fl.l_pid = 0;65 66 155 do { 67 ret = fcntl (tdb->fd,lck_type,&fl);68 156 ret = fcntl_lock(tdb, rw_type, offset, len, 157 flags & TDB_LOCK_WAIT); 69 158 /* Check for a sigalarm break. */ 70 159 if (ret == -1 && errno == EINTR && … … 80 169 * EAGAIN is an expected return from non-blocking 81 170 * locks. */ 82 if (! probe && lck_type != F_SETLK) {83 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",84 tdb->fd, offset, rw_type, lck_type, (int)len));171 if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) { 172 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n", 173 tdb->fd, offset, rw_type, flags, (int)len)); 85 174 } 86 175 return -1; … … 89 178 } 90 179 180 int tdb_brunlock(struct tdb_context *tdb, 181 int rw_type, tdb_off_t offset, size_t len) 182 { 183 int ret; 184 185 if (tdb->flags & TDB_NOLOCK) { 186 return 0; 187 } 188 189 do { 190 ret = fcntl_unlock(tdb, rw_type, offset, len); 191 } while (ret == -1 && errno == EINTR); 192 193 if (ret == -1) { 194 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n", 195 tdb->fd, offset, rw_type, (int)len)); 196 } 197 return ret; 198 } 91 199 92 200 /* … … 96 204 made. For those OSes we may loop for a while. 97 205 */ 98 int tdb_ brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)206 int tdb_allrecord_upgrade(struct tdb_context *tdb) 99 207 { 100 208 int count = 1000; 209 210 if (tdb->allrecord_lock.count != 1) { 211 TDB_LOG((tdb, TDB_DEBUG_ERROR, 212 "tdb_allrecord_upgrade failed: count %u too high\n", 213 tdb->allrecord_lock.count)); 214 return -1; 215 } 216 217 if (tdb->allrecord_lock.off != 1) { 218 TDB_LOG((tdb, TDB_DEBUG_ERROR, 219 "tdb_allrecord_upgrade failed: already upgraded?\n")); 220 return -1; 221 } 222 101 223 while (count--) { 102 224 struct timeval tv; 103 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { 225 if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, 226 TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) { 227 tdb->allrecord_lock.ltype = F_WRLCK; 228 tdb->allrecord_lock.off = 0; 104 229 return 0; 105 230 } … … 112 237 select(0, NULL, NULL, NULL, &tv); 113 238 } 114 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_ brlock_upgrade failed at offset %d\n", offset));239 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n")); 115 240 return -1; 116 241 } 117 242 118 119 /* lock a list in the database. list -1 is the alloc list */ 120 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) 243 static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb, 244 tdb_off_t offset) 245 { 246 unsigned int i; 247 248 for (i=0; i<tdb->num_lockrecs; i++) { 249 if (tdb->lockrecs[i].off == offset) { 250 return &tdb->lockrecs[i]; 251 } 252 } 253 return NULL; 254 } 255 256 /* lock an offset in the database. */ 257 int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, 258 enum tdb_lock_flags flags) 121 259 { 122 260 struct tdb_lock_type *new_lck; 123 int i; 124 bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); 125 126 ltype &= ~TDB_MARK_LOCK; 127 128 /* a global lock allows us to avoid per chain locks */ 129 if (tdb->global_lock.count && 130 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { 131 return 0; 132 } 133 134 if (tdb->global_lock.count) { 135 tdb->ecode = TDB_ERR_LOCK; 136 return -1; 137 } 138 139 if (list < -1 || list >= (int)tdb->header.hash_size) { 140 tdb->ecode = TDB_ERR_LOCK; 141 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", 142 list, ltype)); 261 262 if (offset >= lock_offset(tdb->header.hash_size)) { 263 tdb->ecode = TDB_ERR_LOCK; 264 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid offset %u for ltype=%d\n", 265 offset, ltype)); 143 266 return -1; 144 267 } … … 146 269 return 0; 147 270 148 for (i=0; i<tdb->num_lockrecs; i++) { 149 if (tdb->lockrecs[i].list == list) { 150 if (tdb->lockrecs[i].count == 0) { 151 /* 152 * Can't happen, see tdb_unlock(). It should 153 * be an assert. 154 */ 155 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " 156 "lck->count == 0 for list %d", list)); 157 } 158 /* 159 * Just increment the in-memory struct, posix locks 160 * don't stack. 161 */ 162 tdb->lockrecs[i].count++; 163 return 0; 164 } 271 new_lck = find_nestlock(tdb, offset); 272 if (new_lck) { 273 /* 274 * Just increment the in-memory struct, posix locks 275 * don't stack. 276 */ 277 new_lck->count++; 278 return 0; 165 279 } 166 280 … … 176 290 /* Since fcntl locks don't nest, we do a lock for the first one, 177 291 and simply bump the count for future ones */ 178 if (!mark_lock && 179 tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, 180 0, 1)) { 181 return -1; 182 } 183 184 tdb->num_locks++; 185 186 tdb->lockrecs[tdb->num_lockrecs].list = list; 292 if (tdb_brlock(tdb, ltype, offset, 1, flags)) { 293 return -1; 294 } 295 296 tdb->lockrecs[tdb->num_lockrecs].off = offset; 187 297 tdb->lockrecs[tdb->num_lockrecs].count = 1; 188 298 tdb->lockrecs[tdb->num_lockrecs].ltype = ltype; 189 tdb->num_lockrecs += 1;299 tdb->num_lockrecs++; 190 300 191 301 return 0; 302 } 303 304 static int tdb_lock_and_recover(struct tdb_context *tdb) 305 { 306 int ret; 307 308 /* We need to match locking order in transaction commit. */ 309 if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, TDB_LOCK_WAIT)) { 310 return -1; 311 } 312 313 if (tdb_brlock(tdb, F_WRLCK, OPEN_LOCK, 1, TDB_LOCK_WAIT)) { 314 tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0); 315 return -1; 316 } 317 318 ret = tdb_transaction_recover(tdb); 319 320 tdb_brunlock(tdb, F_WRLCK, OPEN_LOCK, 1); 321 tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0); 322 323 return ret; 324 } 325 326 static bool have_data_locks(const struct tdb_context *tdb) 327 { 328 unsigned int i; 329 330 for (i = 0; i < tdb->num_lockrecs; i++) { 331 if (tdb->lockrecs[i].off >= lock_offset(-1)) 332 return true; 333 } 334 return false; 335 } 336 337 static int tdb_lock_list(struct tdb_context *tdb, int list, int ltype, 338 enum tdb_lock_flags waitflag) 339 { 340 int ret; 341 bool check = false; 342 343 /* a allrecord lock allows us to avoid per chain locks */ 344 if (tdb->allrecord_lock.count && 345 (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) { 346 return 0; 347 } 348 349 if (tdb->allrecord_lock.count) { 350 tdb->ecode = TDB_ERR_LOCK; 351 ret = -1; 352 } else { 353 /* Only check when we grab first data lock. */ 354 check = !have_data_locks(tdb); 355 ret = tdb_nest_lock(tdb, lock_offset(list), ltype, waitflag); 356 357 if (ret == 0 && check && tdb_needs_recovery(tdb)) { 358 tdb_nest_unlock(tdb, lock_offset(list), ltype, false); 359 360 if (tdb_lock_and_recover(tdb) == -1) { 361 return -1; 362 } 363 return tdb_lock_list(tdb, list, ltype, waitflag); 364 } 365 } 366 return ret; 192 367 } 193 368 … … 196 371 { 197 372 int ret; 198 ret = _tdb_lock(tdb, list, ltype, F_SETLKW); 373 374 ret = tdb_lock_list(tdb, list, ltype, TDB_LOCK_WAIT); 199 375 if (ret) { 200 376 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " … … 207 383 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) 208 384 { 209 return _tdb_lock(tdb, list, ltype, F_SETLK); 210 } 211 212 213 /* unlock the database: returns void because it's too late for errors. */ 214 /* changed to return int it may be interesting to know there 215 has been an error --simo */ 216 int tdb_unlock(struct tdb_context *tdb, int list, int ltype) 385 return tdb_lock_list(tdb, list, ltype, TDB_LOCK_NOWAIT); 386 } 387 388 389 int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, 390 bool mark_lock) 217 391 { 218 392 int ret = -1; 219 int i; 220 struct tdb_lock_type *lck = NULL; 221 bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); 222 223 ltype &= ~TDB_MARK_LOCK; 224 225 /* a global lock allows us to avoid per chain locks */ 226 if (tdb->global_lock.count && 227 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { 228 return 0; 229 } 230 231 if (tdb->global_lock.count) { 232 tdb->ecode = TDB_ERR_LOCK; 233 return -1; 234 } 393 struct tdb_lock_type *lck; 235 394 236 395 if (tdb->flags & TDB_NOLOCK) … … 238 397 239 398 /* Sanity checks */ 240 if ( list < -1 || list >= (int)tdb->header.hash_size) {241 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));399 if (offset >= lock_offset(tdb->header.hash_size)) { 400 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: offset %u invalid (%d)\n", offset, tdb->header.hash_size)); 242 401 return ret; 243 402 } 244 403 245 for (i=0; i<tdb->num_lockrecs; i++) { 246 if (tdb->lockrecs[i].list == list) { 247 lck = &tdb->lockrecs[i]; 248 break; 249 } 250 } 251 404 lck = find_nestlock(tdb, offset); 252 405 if ((lck == NULL) || (lck->count == 0)) { 253 406 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); … … 270 423 ret = 0; 271 424 } else { 272 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, 273 F_SETLKW, 0, 1); 274 } 275 tdb->num_locks--; 425 ret = tdb_brunlock(tdb, ltype, offset, 1); 426 } 276 427 277 428 /* … … 279 430 * last array element. 280 431 */ 281 282 if (tdb->num_lockrecs > 1) { 283 *lck = tdb->lockrecs[tdb->num_lockrecs-1]; 284 } 285 tdb->num_lockrecs -= 1; 432 *lck = tdb->lockrecs[--tdb->num_lockrecs]; 286 433 287 434 /* … … 299 446 } 300 447 448 int tdb_unlock(struct tdb_context *tdb, int list, int ltype) 449 { 450 /* a global lock allows us to avoid per chain locks */ 451 if (tdb->allrecord_lock.count && 452 (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) { 453 return 0; 454 } 455 456 if (tdb->allrecord_lock.count) { 457 tdb->ecode = TDB_ERR_LOCK; 458 return -1; 459 } 460 461 return tdb_nest_unlock(tdb, lock_offset(list), ltype, false); 462 } 463 301 464 /* 302 465 get the transaction lock 303 466 */ 304 int tdb_transaction_lock(struct tdb_context *tdb, int ltype) 305 { 306 if (tdb->global_lock.count) { 307 return 0; 308 } 309 if (tdb->transaction_lock_count > 0) { 310 tdb->transaction_lock_count++; 311 return 0; 312 } 313 314 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, 315 F_SETLKW, 0, 1) == -1) { 316 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); 317 tdb->ecode = TDB_ERR_LOCK; 318 return -1; 319 } 320 tdb->transaction_lock_count++; 321 return 0; 467 int tdb_transaction_lock(struct tdb_context *tdb, int ltype, 468 enum tdb_lock_flags lockflags) 469 { 470 return tdb_nest_lock(tdb, TRANSACTION_LOCK, ltype, lockflags); 322 471 } 323 472 … … 325 474 release the transaction lock 326 475 */ 327 int tdb_transaction_unlock(struct tdb_context *tdb) 328 { 329 int ret; 330 if (tdb->global_lock.count) { 331 return 0; 332 } 333 if (tdb->transaction_lock_count > 1) { 334 tdb->transaction_lock_count--; 335 return 0; 336 } 337 ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); 338 if (ret == 0) { 339 tdb->transaction_lock_count = 0; 340 } 341 return ret; 342 } 343 344 345 346 347 /* lock/unlock entire database */ 348 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) 349 { 350 bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); 351 352 ltype &= ~TDB_MARK_LOCK; 353 476 int tdb_transaction_unlock(struct tdb_context *tdb, int ltype) 477 { 478 return tdb_nest_unlock(tdb, TRANSACTION_LOCK, ltype, false); 479 } 480 481 /* Returns 0 if all done, -1 if error, 1 if ok. */ 482 static int tdb_allrecord_check(struct tdb_context *tdb, int ltype, 483 enum tdb_lock_flags flags, bool upgradable) 484 { 354 485 /* There are no locks on read-only dbs */ 355 486 if (tdb->read_only || tdb->traverse_read) { … … 358 489 } 359 490 360 if (tdb-> global_lock.count && tdb->global_lock.ltype == ltype) {361 tdb-> global_lock.count++;362 return 0; 363 } 364 365 if (tdb-> global_lock.count) {491 if (tdb->allrecord_lock.count && tdb->allrecord_lock.ltype == ltype) { 492 tdb->allrecord_lock.count++; 493 return 0; 494 } 495 496 if (tdb->allrecord_lock.count) { 366 497 /* a global lock of a different type exists */ 367 498 tdb->ecode = TDB_ERR_LOCK; 368 499 return -1; 369 500 } 370 371 if (tdb ->num_locks != 0) {501 502 if (tdb_have_extra_locks(tdb)) { 372 503 /* can't combine global and chain locks */ 373 504 tdb->ecode = TDB_ERR_LOCK; … … 375 506 } 376 507 377 if (!mark_lock && 378 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op, 379 0, 4*tdb->header.hash_size)) { 380 if (op == F_SETLKW) { 381 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno))); 382 } 383 return -1; 384 } 385 386 tdb->global_lock.count = 1; 387 tdb->global_lock.ltype = ltype; 388 508 if (upgradable && ltype != F_RDLCK) { 509 /* tdb error: you can't upgrade a write lock! */ 510 tdb->ecode = TDB_ERR_LOCK; 511 return -1; 512 } 513 return 1; 514 } 515 516 /* We only need to lock individual bytes, but Linux merges consecutive locks 517 * so we lock in contiguous ranges. */ 518 static int tdb_chainlock_gradual(struct tdb_context *tdb, 519 int ltype, enum tdb_lock_flags flags, 520 size_t off, size_t len) 521 { 522 int ret; 523 enum tdb_lock_flags nb_flags = (flags & ~TDB_LOCK_WAIT); 524 525 if (len <= 4) { 526 /* Single record. Just do blocking lock. */ 527 return tdb_brlock(tdb, ltype, off, len, flags); 528 } 529 530 /* First we try non-blocking. */ 531 ret = tdb_brlock(tdb, ltype, off, len, nb_flags); 532 if (ret == 0) { 533 return 0; 534 } 535 536 /* Try locking first half, then second. */ 537 ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2); 538 if (ret == -1) 539 return -1; 540 541 ret = tdb_chainlock_gradual(tdb, ltype, flags, 542 off + len / 2, len - len / 2); 543 if (ret == -1) { 544 tdb_brunlock(tdb, ltype, off, len / 2); 545 return -1; 546 } 389 547 return 0; 390 548 } 391 549 550 /* lock/unlock entire database. It can only be upgradable if you have some 551 * other way of guaranteeing exclusivity (ie. transaction write lock). 552 * We do the locking gradually to avoid being starved by smaller locks. */ 553 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype, 554 enum tdb_lock_flags flags, bool upgradable) 555 { 556 switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) { 557 case -1: 558 return -1; 559 case 0: 560 return 0; 561 } 562 563 /* We cover two kinds of locks: 564 * 1) Normal chain locks. Taken for almost all operations. 565 * 3) Individual records locks. Taken after normal or free 566 * chain locks. 567 * 568 * It is (1) which cause the starvation problem, so we're only 569 * gradual for that. */ 570 if (tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP, 571 tdb->header.hash_size * 4) == -1) { 572 return -1; 573 } 574 575 /* Grab individual record locks. */ 576 if (tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0, 577 flags) == -1) { 578 tdb_brunlock(tdb, ltype, FREELIST_TOP, 579 tdb->header.hash_size * 4); 580 return -1; 581 } 582 583 tdb->allrecord_lock.count = 1; 584 /* If it's upgradable, it's actually exclusive so we can treat 585 * it as a write lock. */ 586 tdb->allrecord_lock.ltype = upgradable ? F_WRLCK : ltype; 587 tdb->allrecord_lock.off = upgradable; 588 589 if (tdb_needs_recovery(tdb)) { 590 bool mark = flags & TDB_LOCK_MARK_ONLY; 591 tdb_allrecord_unlock(tdb, ltype, mark); 592 if (mark) { 593 tdb->ecode = TDB_ERR_LOCK; 594 TDB_LOG((tdb, TDB_DEBUG_ERROR, 595 "tdb_lockall_mark cannot do recovery\n")); 596 return -1; 597 } 598 if (tdb_lock_and_recover(tdb) == -1) { 599 return -1; 600 } 601 return tdb_allrecord_lock(tdb, ltype, flags, upgradable); 602 } 603 604 return 0; 605 } 606 392 607 393 608 394 609 /* unlock entire db */ 395 static int _tdb_unlockall(struct tdb_context *tdb, int ltype) 396 { 397 bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); 398 399 ltype &= ~TDB_MARK_LOCK; 400 610 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock) 611 { 401 612 /* There are no locks on read-only dbs */ 402 613 if (tdb->read_only || tdb->traverse_read) { … … 405 616 } 406 617 407 if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) { 408 tdb->ecode = TDB_ERR_LOCK; 409 return -1; 410 } 411 412 if (tdb->global_lock.count > 1) { 413 tdb->global_lock.count--; 414 return 0; 415 } 416 417 if (!mark_lock && 418 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 419 0, 4*tdb->header.hash_size)) { 618 if (tdb->allrecord_lock.count == 0) { 619 tdb->ecode = TDB_ERR_LOCK; 620 return -1; 621 } 622 623 /* Upgradable locks are marked as write locks. */ 624 if (tdb->allrecord_lock.ltype != ltype 625 && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) { 626 tdb->ecode = TDB_ERR_LOCK; 627 return -1; 628 } 629 630 if (tdb->allrecord_lock.count > 1) { 631 tdb->allrecord_lock.count--; 632 return 0; 633 } 634 635 if (!mark_lock && tdb_brunlock(tdb, ltype, FREELIST_TOP, 0)) { 420 636 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno))); 421 637 return -1; 422 638 } 423 639 424 tdb-> global_lock.count = 0;425 tdb-> global_lock.ltype = 0;640 tdb->allrecord_lock.count = 0; 641 tdb->allrecord_lock.ltype = 0; 426 642 427 643 return 0; … … 429 645 430 646 /* lock entire database with write lock */ 431 int tdb_lockall(struct tdb_context *tdb)647 _PUBLIC_ int tdb_lockall(struct tdb_context *tdb) 432 648 { 433 649 tdb_trace(tdb, "tdb_lockall"); 434 return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);650 return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); 435 651 } 436 652 437 653 /* lock entire database with write lock - mark only */ 438 int tdb_lockall_mark(struct tdb_context *tdb)654 _PUBLIC_ int tdb_lockall_mark(struct tdb_context *tdb) 439 655 { 440 656 tdb_trace(tdb, "tdb_lockall_mark"); 441 return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);657 return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_MARK_ONLY, false); 442 658 } 443 659 444 660 /* unlock entire database with write lock - unmark only */ 445 int tdb_lockall_unmark(struct tdb_context *tdb)661 _PUBLIC_ int tdb_lockall_unmark(struct tdb_context *tdb) 446 662 { 447 663 tdb_trace(tdb, "tdb_lockall_unmark"); 448 return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);664 return tdb_allrecord_unlock(tdb, F_WRLCK, true); 449 665 } 450 666 451 667 /* lock entire database with write lock - nonblocking varient */ 452 int tdb_lockall_nonblock(struct tdb_context *tdb)453 { 454 int ret = _tdb_lockall(tdb, F_WRLCK, F_SETLK);668 _PUBLIC_ int tdb_lockall_nonblock(struct tdb_context *tdb) 669 { 670 int ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_NOWAIT, false); 455 671 tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret); 456 672 return ret; … … 458 674 459 675 /* unlock entire database with write lock */ 460 int tdb_unlockall(struct tdb_context *tdb)676 _PUBLIC_ int tdb_unlockall(struct tdb_context *tdb) 461 677 { 462 678 tdb_trace(tdb, "tdb_unlockall"); 463 return _tdb_unlockall(tdb, F_WRLCK);679 return tdb_allrecord_unlock(tdb, F_WRLCK, false); 464 680 } 465 681 466 682 /* lock entire database with read lock */ 467 int tdb_lockall_read(struct tdb_context *tdb)683 _PUBLIC_ int tdb_lockall_read(struct tdb_context *tdb) 468 684 { 469 685 tdb_trace(tdb, "tdb_lockall_read"); 470 return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);686 return tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); 471 687 } 472 688 473 689 /* lock entire database with read lock - nonblock varient */ 474 int tdb_lockall_read_nonblock(struct tdb_context *tdb)475 { 476 int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK);690 _PUBLIC_ int tdb_lockall_read_nonblock(struct tdb_context *tdb) 691 { 692 int ret = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_NOWAIT, false); 477 693 tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret); 478 694 return ret; … … 480 696 481 697 /* unlock entire database with read lock */ 482 int tdb_unlockall_read(struct tdb_context *tdb)698 _PUBLIC_ int tdb_unlockall_read(struct tdb_context *tdb) 483 699 { 484 700 tdb_trace(tdb, "tdb_unlockall_read"); 485 return _tdb_unlockall(tdb, F_RDLCK);701 return tdb_allrecord_unlock(tdb, F_RDLCK, false); 486 702 } 487 703 488 704 /* lock/unlock one hash chain. This is meant to be used to reduce 489 705 contention - it cannot guarantee how many records will be locked */ 490 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)706 _PUBLIC_ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) 491 707 { 492 708 int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); … … 498 714 to reduce contention - it cannot guarantee how many records will be 499 715 locked */ 500 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)716 _PUBLIC_ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) 501 717 { 502 718 int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); … … 506 722 507 723 /* mark a chain as locked without actually locking it. Warning! use with great caution! */ 508 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) 509 { 510 int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); 724 _PUBLIC_ int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) 725 { 726 int ret = tdb_nest_lock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))), 727 F_WRLCK, TDB_LOCK_MARK_ONLY); 511 728 tdb_trace_1rec(tdb, "tdb_chainlock_mark", key); 512 729 return ret; … … 514 731 515 732 /* unmark a chain as locked without actually locking it. Warning! use with great caution! */ 516 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)733 _PUBLIC_ int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) 517 734 { 518 735 tdb_trace_1rec(tdb, "tdb_chainlock_unmark", key); 519 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); 520 } 521 522 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) 736 return tdb_nest_unlock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))), 737 F_WRLCK, true); 738 } 739 740 _PUBLIC_ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) 523 741 { 524 742 tdb_trace_1rec(tdb, "tdb_chainunlock", key); … … 526 744 } 527 745 528 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)746 _PUBLIC_ int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) 529 747 { 530 748 int ret; … … 534 752 } 535 753 536 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)754 _PUBLIC_ int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) 537 755 { 538 756 tdb_trace_1rec(tdb, "tdb_chainunlock_read", key); … … 540 758 } 541 759 542 543 544 760 /* record lock stops delete underneath */ 545 761 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) 546 762 { 547 if (tdb-> global_lock.count) {548 return 0; 549 } 550 return off ? tdb ->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;763 if (tdb->allrecord_lock.count) { 764 return 0; 765 } 766 return off ? tdb_brlock(tdb, F_RDLCK, off, 1, TDB_LOCK_WAIT) : 0; 551 767 } 552 768 … … 562 778 if (i->off == off) 563 779 return -1; 564 return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1); 565 } 566 567 /* 568 Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not 569 an error to fail to get the lock here. 570 */ 780 if (tdb->allrecord_lock.count) { 781 if (tdb->allrecord_lock.ltype == F_WRLCK) { 782 return 0; 783 } 784 return -1; 785 } 786 return tdb_brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); 787 } 788 571 789 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) 572 790 { 573 return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1); 791 if (tdb->allrecord_lock.count) { 792 return 0; 793 } 794 return tdb_brunlock(tdb, F_WRLCK, off, 1); 574 795 } 575 796 … … 580 801 uint32_t count = 0; 581 802 582 if (tdb-> global_lock.count) {803 if (tdb->allrecord_lock.count) { 583 804 return 0; 584 805 } … … 589 810 if (i->off == off) 590 811 count++; 591 return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0); 592 } 812 return (count == 1 ? tdb_brunlock(tdb, F_RDLCK, off, 1) : 0); 813 } 814 815 bool tdb_have_extra_locks(struct tdb_context *tdb) 816 { 817 unsigned int extra = tdb->num_lockrecs; 818 819 /* A transaction holds the lock for all records. */ 820 if (!tdb->transaction && tdb->allrecord_lock.count) { 821 return true; 822 } 823 824 /* We always hold the active lock if CLEAR_IF_FIRST. */ 825 if (find_nestlock(tdb, ACTIVE_LOCK)) { 826 extra--; 827 } 828 829 /* In a transaction, we expect to hold the transaction lock */ 830 if (tdb->transaction && find_nestlock(tdb, TRANSACTION_LOCK)) { 831 extra--; 832 } 833 834 return extra; 835 } 836 837 /* The transaction code uses this to remove all locks. */ 838 void tdb_release_transaction_locks(struct tdb_context *tdb) 839 { 840 unsigned int i, active = 0; 841 842 if (tdb->allrecord_lock.count != 0) { 843 tdb_brunlock(tdb, tdb->allrecord_lock.ltype, FREELIST_TOP, 0); 844 tdb->allrecord_lock.count = 0; 845 } 846 847 for (i=0;i<tdb->num_lockrecs;i++) { 848 struct tdb_lock_type *lck = &tdb->lockrecs[i]; 849 850 /* Don't release the active lock! Copy it to first entry. */ 851 if (lck->off == ACTIVE_LOCK) { 852 tdb->lockrecs[active++] = *lck; 853 } else { 854 tdb_brunlock(tdb, lck->ltype, lck->off, 1); 855 } 856 } 857 tdb->num_lockrecs = active; 858 if (tdb->num_lockrecs == 0) { 859 SAFE_FREE(tdb->lockrecs); 860 } 861 } -
vendor/current/lib/tdb/common/open.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 31 31 static struct tdb_context *tdbs = NULL; 32 32 33 34 /* This is based on the hash algorithm from gdbm */ 35 static unsigned int default_tdb_hash(TDB_DATA *key) 36 { 37 uint32_t value; /* Used to compute the hash value. */ 38 uint32_t i; /* Used to cycle through random values. */ 39 40 /* Set the initial value from the key size. */ 41 for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) 42 value = (value + (key->dptr[i] << (i*5 % 24))); 43 44 return (1103515243 * value + 12345); 45 } 46 33 /* We use two hashes to double-check they're using the right hash function. */ 34 void tdb_header_hash(struct tdb_context *tdb, 35 uint32_t *magic1_hash, uint32_t *magic2_hash) 36 { 37 TDB_DATA hash_key; 38 uint32_t tdb_magic = TDB_MAGIC; 39 40 hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD); 41 hash_key.dsize = sizeof(TDB_MAGIC_FOOD); 42 *magic1_hash = tdb->hash_fn(&hash_key); 43 44 hash_key.dptr = (unsigned char *)CONVERT(tdb_magic); 45 hash_key.dsize = sizeof(tdb_magic); 46 *magic2_hash = tdb->hash_fn(&hash_key); 47 48 /* Make sure at least one hash is non-zero! */ 49 if (*magic1_hash == 0 && *magic2_hash == 0) 50 *magic1_hash = 1; 51 } 47 52 48 53 /* initialise a new database with a specified hash size */ … … 52 57 size_t size; 53 58 int ret = -1; 54 ssize_t written;55 59 56 60 /* We make it up in memory, then write it out if not internal */ … … 64 68 newdb->version = TDB_VERSION; 65 69 newdb->hash_size = hash_size; 70 71 tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash); 72 73 /* Make sure older tdbs (which don't check the magic hash fields) 74 * will refuse to open this TDB. */ 75 if (tdb->flags & TDB_INCOMPATIBLE_HASH) 76 newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC; 77 66 78 if (tdb->flags & TDB_INTERNAL) { 67 79 tdb->map_size = size; … … 84 96 memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); 85 97 /* we still have "ret == -1" here */ 86 written = write(tdb->fd, newdb, size); 87 if (written == size) { 98 if (tdb_write_all(tdb->fd, newdb, size)) 88 99 ret = 0; 89 } else if (written != -1) {90 /* call write once again, this usually should return -1 and91 * set errno appropriately */92 size -= written;93 written = write(tdb->fd, newdb+written, size);94 if (written == size) {95 ret = 0;96 } else if (written >= 0) {97 /* a second incomplete write - we give up.98 * guessing the errno... */99 errno = ENOSPC;100 }101 }102 100 103 101 fail: … … 112 110 { 113 111 struct tdb_context *i; 114 112 115 113 for (i = tdbs; i; i = i->next) { 116 114 if (i->device == device && i->inode == ino) { … … 132 130 133 131 @param name may be NULL for internal databases. */ 134 struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,132 _PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, 135 133 int open_flags, mode_t mode) 136 134 { … … 144 142 } 145 143 146 147 struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, 144 static bool check_header_hash(struct tdb_context *tdb, 145 bool default_hash, uint32_t *m1, uint32_t *m2) 146 { 147 tdb_header_hash(tdb, m1, m2); 148 if (tdb->header.magic1_hash == *m1 && 149 tdb->header.magic2_hash == *m2) { 150 return true; 151 } 152 153 /* If they explicitly set a hash, always respect it. */ 154 if (!default_hash) 155 return false; 156 157 /* Otherwise, try the other inbuilt hash. */ 158 if (tdb->hash_fn == tdb_old_hash) 159 tdb->hash_fn = tdb_jenkins_hash; 160 else 161 tdb->hash_fn = tdb_old_hash; 162 return check_header_hash(tdb, false, m1, m2); 163 } 164 165 _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, 148 166 int open_flags, mode_t mode, 149 167 const struct tdb_logging_context *log_ctx, … … 156 174 uint32_t vertest; 157 175 unsigned v; 176 const char *hash_alg; 177 uint32_t magic1, magic2; 158 178 159 179 if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { … … 177 197 tdb->log.log_private = NULL; 178 198 } 179 tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; 199 200 if (name == NULL && (tdb_flags & TDB_INTERNAL)) { 201 name = "__TDB_INTERNAL__"; 202 } 203 204 if (name == NULL) { 205 tdb->name = discard_const_p(char, "__NULL__"); 206 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: called with name == NULL\n")); 207 tdb->name = NULL; 208 errno = EINVAL; 209 goto fail; 210 } 211 212 /* now make a copy of the name, as the caller memory might went away */ 213 if (!(tdb->name = (char *)strdup(name))) { 214 /* 215 * set the name as the given string, so that tdb_name() will 216 * work in case of an error. 217 */ 218 tdb->name = discard_const_p(char, name); 219 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't strdup(%s)\n", 220 name)); 221 tdb->name = NULL; 222 errno = ENOMEM; 223 goto fail; 224 } 225 226 if (hash_fn) { 227 tdb->hash_fn = hash_fn; 228 hash_alg = "the user defined"; 229 } else { 230 /* This controls what we use when creating a tdb. */ 231 if (tdb->flags & TDB_INCOMPATIBLE_HASH) { 232 tdb->hash_fn = tdb_jenkins_hash; 233 } else { 234 tdb->hash_fn = tdb_old_hash; 235 } 236 hash_alg = "either default"; 237 } 180 238 181 239 /* cache the page size */ … … 193 251 goto fail; 194 252 } 195 253 196 254 if (hash_size == 0) 197 255 hash_size = DEFAULT_HASH_SIZE; … … 212 270 } 213 271 272 if (getenv("TDB_NO_FSYNC")) { 273 tdb->flags |= TDB_NOSYNC; 274 } 275 214 276 /* 215 277 * TDB_ALLOW_NESTING is the default behavior. … … 242 304 243 305 /* ensure there is only one process initialising at once */ 244 if (tdb ->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {245 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get globallock on %s: %s\n",306 if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) { 307 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get open lock on %s: %s\n", 246 308 name, strerror(errno))); 247 309 goto fail; /* errno set by tdb_brlock */ … … 251 313 if ((tdb_flags & TDB_CLEAR_IF_FIRST) && 252 314 (!tdb->read_only) && 253 (locked = (tdb ->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {315 (locked = (tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE) == 0))) { 254 316 open_flags |= O_CREAT; 255 317 if (ftruncate(tdb->fd, 0) == -1) { … … 290 352 goto fail; 291 353 292 if (tdb->header.rwlocks != 0) { 354 if (tdb->header.rwlocks != 0 && 355 tdb->header.rwlocks != TDB_HASH_RWLOCK_MAGIC) { 293 356 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); 357 goto fail; 358 } 359 360 if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) { 361 /* older TDB without magic hash references */ 362 tdb->hash_fn = tdb_old_hash; 363 } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) { 364 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " 365 "%s was not created with %s hash function we are using\n" 366 "magic1_hash[0x%08X %s 0x%08X] " 367 "magic2_hash[0x%08X %s 0x%08X]\n", 368 name, hash_alg, 369 tdb->header.magic1_hash, 370 (tdb->header.magic1_hash == magic1) ? "==" : "!=", 371 magic1, 372 tdb->header.magic2_hash, 373 (tdb->header.magic2_hash == magic2) ? "==" : "!=", 374 magic2)); 375 errno = EINVAL; 294 376 goto fail; 295 377 } … … 304 386 } 305 387 306 if (!(tdb->name = (char *)strdup(name))) {307 errno = ENOMEM;308 goto fail;309 }310 311 388 tdb->map_size = st.st_size; 312 389 tdb->device = st.st_dev; … … 314 391 tdb_mmap(tdb); 315 392 if (locked) { 316 if (tdb ->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {393 if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) { 317 394 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " 318 "failed to take ACTIVE_LOCK on %s: %s\n",395 "failed to release ACTIVE_LOCK on %s: %s\n", 319 396 name, strerror(errno))); 320 397 goto fail; … … 329 406 if (tdb_flags & TDB_CLEAR_IF_FIRST) { 330 407 /* leave this lock in place to indicate it's in use */ 331 if (tdb ->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)408 if (tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) { 332 409 goto fail; 410 } 333 411 } 334 412 … … 357 435 /* Internal (memory-only) databases skip all the code above to 358 436 * do with disk files, and resume here by releasing their 359 * global lock and hooking into the active list. */ 360 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1) 361 goto fail; 437 * open lock and hooking into the active list. */ 438 if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) { 439 goto fail; 440 } 362 441 tdb->next = tdbs; 363 442 tdbs = tdb; … … 379 458 tdb_munmap(tdb); 380 459 } 381 SAFE_FREE(tdb->name);382 460 if (tdb->fd != -1) 383 461 if (close(tdb->fd) != 0) 384 462 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); 463 SAFE_FREE(tdb->lockrecs); 464 SAFE_FREE(tdb->name); 385 465 SAFE_FREE(tdb); 386 466 errno = save_errno; … … 393 473 */ 394 474 395 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)475 _PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) 396 476 { 397 477 tdb->max_dead_records = max_dead; … … 403 483 * @returns -1 for error; 0 for success. 404 484 **/ 405 int tdb_close(struct tdb_context *tdb)485 _PUBLIC_ int tdb_close(struct tdb_context *tdb) 406 486 { 407 487 struct tdb_context **i; 408 488 int ret = 0; 409 489 490 if (tdb->transaction) { 491 tdb_transaction_cancel(tdb); 492 } 410 493 tdb_trace(tdb, "tdb_close"); 411 if (tdb->transaction) {412 _tdb_transaction_cancel(tdb);413 }414 494 415 495 if (tdb->map_ptr) { … … 444 524 445 525 /* register a loging function */ 446 void tdb_set_logging_function(struct tdb_context *tdb,447 const struct tdb_logging_context *log_ctx)526 _PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb, 527 const struct tdb_logging_context *log_ctx) 448 528 { 449 529 tdb->log = *log_ctx; 450 530 } 451 531 452 void *tdb_get_logging_private(struct tdb_context *tdb)532 _PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb) 453 533 { 454 534 return tdb->log.log_private; … … 466 546 } 467 547 468 if (tdb ->num_locks != 0 || tdb->global_lock.count) {548 if (tdb_have_extra_locks(tdb)) { 469 549 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); 470 550 goto fail; … … 501 581 #endif /* fake pread or pwrite */ 502 582 503 if (active_lock && 504 (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) { 583 /* We may still think we hold the active lock. */ 584 tdb->num_lockrecs = 0; 585 SAFE_FREE(tdb->lockrecs); 586 587 if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) { 505 588 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); 506 589 goto fail; … … 516 599 /* reopen a tdb - this can be used after a fork to ensure that we have an independent 517 600 seek pointer from our parent and to re-establish locks */ 518 int tdb_reopen(struct tdb_context *tdb)601 _PUBLIC_ int tdb_reopen(struct tdb_context *tdb) 519 602 { 520 603 return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST); … … 522 605 523 606 /* reopen all tdb's */ 524 int tdb_reopen_all(int parent_longlived)607 _PUBLIC_ int tdb_reopen_all(int parent_longlived) 525 608 { 526 609 struct tdb_context *tdb; -
vendor/current/lib/tdb/common/tdb.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 28 28 #include "tdb_private.h" 29 29 30 TDB_DATA tdb_null;30 _PUBLIC_ TDB_DATA tdb_null; 31 31 32 32 /* … … 34 34 the TDB_SEQNUM flag 35 35 */ 36 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)36 _PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) 37 37 { 38 38 tdb_off_t seqnum=0; 39 39 40 40 if (!(tdb->flags & TDB_SEQNUM)) { 41 41 return; … … 60 60 } 61 61 62 if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) { 62 if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK, 63 TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) { 63 64 return; 64 65 } … … 66 67 tdb_increment_seqnum_nonblock(tdb); 67 68 68 tdb_ brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);69 tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false); 69 70 } 70 71 … … 80 81 { 81 82 tdb_off_t rec_ptr; 82 83 83 84 /* read in the hash top */ 84 85 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) … … 154 155 } 155 156 } 156 157 157 158 158 /* must be long enough key, data and tailer */ … … 171 171 return tdb_rec_write(tdb, rec_ptr, &rec); 172 172 } 173 173 174 174 return 0; 175 175 } … … 200 200 } 201 201 202 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)202 _PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) 203 203 { 204 204 TDB_DATA ret = _tdb_fetch(tdb, key); … … 213 213 * should be fast and should not block on other syscalls. 214 214 * 215 * DON T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.215 * DON'T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. 216 216 * 217 217 * For mmapped tdb's that do not have a transaction open it points the parsing … … 222 222 * This is interesting for all readers of potentially large data structures in 223 223 * the tdb records, ldb indexes being one example. 224 * 225 * Return -1 if the record was not found. 224 226 */ 225 227 226 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,228 _PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, 227 229 int (*parser)(TDB_DATA key, TDB_DATA data, 228 230 void *private_data), … … 238 240 239 241 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { 242 /* record not found */ 240 243 tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1); 241 244 tdb->ecode = TDB_ERR_NOEXIST; 242 return 0;245 return -1; 243 246 } 244 247 tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0); … … 261 264 { 262 265 struct tdb_record rec; 263 266 264 267 if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) 265 268 return 0; … … 268 271 } 269 272 270 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)273 _PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key) 271 274 { 272 275 uint32_t hash = tdb->hash_fn(&key); … … 319 322 tdb_off_t rec_ptr; 320 323 struct tdb_record rec; 321 324 322 325 /* read in the hash top */ 323 326 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) … … 348 351 return -1; 349 352 } 350 353 351 354 /* read in the hash top */ 352 355 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) … … 427 430 } 428 431 429 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)432 _PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key) 430 433 { 431 434 uint32_t hash = tdb->hash_fn(&key); … … 444 447 { 445 448 tdb_off_t rec_ptr; 446 449 447 450 /* read in the hash top */ 448 451 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) … … 597 600 return 0 on success, -1 on failure 598 601 */ 599 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)602 _PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) 600 603 { 601 604 uint32_t hash; … … 620 623 621 624 /* Append to an entry. Create if not exist. */ 622 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)625 _PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) 623 626 { 624 627 uint32_t hash; … … 659 662 ret = _tdb_store(tdb, key, dbuf, 0, hash); 660 663 tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf); 661 664 662 665 failed: 663 666 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); … … 671 674 useful for external logging functions 672 675 */ 673 const char *tdb_name(struct tdb_context *tdb)676 _PUBLIC_ const char *tdb_name(struct tdb_context *tdb) 674 677 { 675 678 return tdb->name; … … 681 684 of the fd 682 685 */ 683 int tdb_fd(struct tdb_context *tdb)686 _PUBLIC_ int tdb_fd(struct tdb_context *tdb) 684 687 { 685 688 return tdb->fd; … … 690 693 useful for external tdb routines that wish to log tdb errors 691 694 */ 692 tdb_log_func tdb_log_fn(struct tdb_context *tdb)695 _PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb) 693 696 { 694 697 return tdb->log.log_fn; … … 706 709 test of a possible tdb change. 707 710 */ 708 int tdb_get_seqnum(struct tdb_context *tdb)711 _PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb) 709 712 { 710 713 tdb_off_t seqnum=0; … … 714 717 } 715 718 716 int tdb_hash_size(struct tdb_context *tdb)719 _PUBLIC_ int tdb_hash_size(struct tdb_context *tdb) 717 720 { 718 721 return tdb->header.hash_size; 719 722 } 720 723 721 size_t tdb_map_size(struct tdb_context *tdb)724 _PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb) 722 725 { 723 726 return tdb->map_size; 724 727 } 725 728 726 int tdb_get_flags(struct tdb_context *tdb)729 _PUBLIC_ int tdb_get_flags(struct tdb_context *tdb) 727 730 { 728 731 return tdb->flags; 729 732 } 730 733 731 void tdb_add_flags(struct tdb_context *tdb, unsigned flags)734 _PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags) 732 735 { 733 736 if ((flags & TDB_ALLOW_NESTING) && … … 749 752 } 750 753 751 void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)754 _PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags) 752 755 { 753 756 if ((flags & TDB_ALLOW_NESTING) && … … 773 776 enable sequence number handling on an open tdb 774 777 */ 775 void tdb_enable_seqnum(struct tdb_context *tdb)778 _PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb) 776 779 { 777 780 tdb->flags |= TDB_SEQNUM; … … 805 808 /* 806 809 wipe the entire database, deleting all records. This can be done 807 very fast by using a globallock. The entire data portion of the810 very fast by using a allrecord lock. The entire data portion of the 808 811 file becomes a single entry in the freelist. 809 812 810 813 This code carefully steps around the recovery area, leaving it alone 811 814 */ 812 int tdb_wipe_all(struct tdb_context *tdb)815 _PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb) 813 816 { 814 817 int i; … … 917 920 repack a tdb 918 921 */ 919 int tdb_repack(struct tdb_context *tdb)922 _PUBLIC_ int tdb_repack(struct tdb_context *tdb) 920 923 { 921 924 struct tdb_context *tmp_db; … … 987 990 } 988 991 992 /* Even on files, we can get partial writes due to signals. */ 993 bool tdb_write_all(int fd, const void *buf, size_t count) 994 { 995 while (count) { 996 ssize_t ret; 997 ret = write(fd, buf, count); 998 if (ret < 0) 999 return false; 1000 buf = (const char *)buf + ret; 1001 count -= ret; 1002 } 1003 return true; 1004 } 1005 989 1006 #ifdef TDB_TRACE 990 1007 static void tdb_trace_write(struct tdb_context *tdb, const char *str) 991 1008 { 992 if ( write(tdb->tracefd, str, strlen(str)) !=strlen(str)) {1009 if (!tdb_write_alltdb->tracefd, str, strlen(str)) { 993 1010 close(tdb->tracefd); 994 1011 tdb->tracefd = -1; -
vendor/current/lib/tdb/common/tdb_private.h
r414 r740 5 5 6 6 Copyright (C) Andrew Tridgell 2005 7 7 8 8 ** NOTE! The following LGPL license applies to the tdb 9 9 ** library. This does NOT imply that all of Samba is released 10 10 ** under the LGPL 11 11 12 12 This library is free software; you can redistribute it and/or 13 13 modify it under the terms of the GNU Lesser General Public … … 50 50 #define TDB_DEAD_MAGIC (0xFEE1DEAD) 51 51 #define TDB_RECOVERY_MAGIC (0xf53bc0e7U) 52 #define TDB_RECOVERY_INVALID_MAGIC (0x0) 53 #define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U) 52 54 #define TDB_ALIGNMENT 4 53 55 #define DEFAULT_HASH_SIZE 131 … … 102 104 103 105 /* lock offsets */ 104 #define GLOBAL_LOCK0106 #define OPEN_LOCK 0 105 107 #define ACTIVE_LOCK 4 106 108 #define TRANSACTION_LOCK 8 … … 147 149 tdb_off_t recovery_start; /* offset of transaction recovery region */ 148 150 tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ 149 tdb_off_t reserved[29]; 151 uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */ 152 uint32_t magic2_hash; /* hash of TDB_MAGIC. */ 153 tdb_off_t reserved[27]; 150 154 }; 151 155 152 156 struct tdb_lock_type { 153 int list;157 uint32_t off; 154 158 uint32_t count; 155 159 uint32_t ltype; … … 163 167 }; 164 168 169 enum tdb_lock_flags { 170 /* WAIT == F_SETLKW, NOWAIT == F_SETLK */ 171 TDB_LOCK_NOWAIT = 0, 172 TDB_LOCK_WAIT = 1, 173 /* If set, don't log an error on failure. */ 174 TDB_LOCK_PROBE = 2, 175 /* If set, don't actually lock at all. */ 176 TDB_LOCK_MARK_ONLY = 4, 177 }; 165 178 166 179 struct tdb_methods { … … 170 183 int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); 171 184 int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); 172 int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t);173 185 }; 174 186 … … 181 193 int traverse_read; /* read-only traversal */ 182 194 int traverse_write; /* read-write traversal */ 183 struct tdb_lock_type global_lock;195 struct tdb_lock_type allrecord_lock; /* .offset == upgradable */ 184 196 int num_lockrecs; 185 197 struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ … … 194 206 unsigned int (*hash_fn)(TDB_DATA *key); 195 207 int open_flags; /* flags used in the open - needed by reopen */ 196 unsigned int num_locks; /* number of chain locks held */197 208 const struct tdb_methods *methods; 198 209 struct tdb_transaction *transaction; 199 210 int page_size; 200 211 int max_dead_records; 201 int transaction_lock_count;202 212 #ifdef TDB_TRACE 203 213 int tracefd; … … 214 224 int tdb_lock(struct tdb_context *tdb, int list, int ltype); 215 225 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); 226 int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, 227 enum tdb_lock_flags flags); 228 int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, 229 bool mark_lock); 216 230 int tdb_unlock(struct tdb_context *tdb, int list, int ltype); 217 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); 218 int tdb_transaction_lock(struct tdb_context *tdb, int ltype); 219 int tdb_transaction_unlock(struct tdb_context *tdb); 220 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); 231 int tdb_brlock(struct tdb_context *tdb, 232 int rw_type, tdb_off_t offset, size_t len, 233 enum tdb_lock_flags flags); 234 int tdb_brunlock(struct tdb_context *tdb, 235 int rw_type, tdb_off_t offset, size_t len); 236 bool tdb_have_extra_locks(struct tdb_context *tdb); 237 void tdb_release_transaction_locks(struct tdb_context *tdb); 238 int tdb_transaction_lock(struct tdb_context *tdb, int ltype, 239 enum tdb_lock_flags lockflags); 240 int tdb_transaction_unlock(struct tdb_context *tdb, int ltype); 241 int tdb_recovery_area(struct tdb_context *tdb, 242 const struct tdb_methods *methods, 243 tdb_off_t *recovery_offset, 244 struct tdb_record *rec); 245 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype, 246 enum tdb_lock_flags flags, bool upgradable); 247 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock); 248 int tdb_allrecord_upgrade(struct tdb_context *tdb); 221 249 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); 222 250 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); … … 230 258 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); 231 259 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); 232 int _tdb_transaction_cancel(struct tdb_context *tdb);260 bool tdb_needs_recovery(struct tdb_context *tdb); 233 261 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); 234 262 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); … … 246 274 int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, 247 275 struct tdb_record *rec); 248 249 276 bool tdb_write_all(int fd, const void *buf, size_t count); 277 int tdb_transaction_recover(struct tdb_context *tdb); 278 void tdb_header_hash(struct tdb_context *tdb, 279 uint32_t *magic1_hash, uint32_t *magic2_hash); 280 unsigned int tdb_old_hash(TDB_DATA *key); 281 size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off); -
vendor/current/lib/tdb/common/transaction.c
r414 r740 9 9 ** library. This does NOT imply that all of Samba is released 10 10 ** under the LGPL 11 11 12 12 This library is free software; you can redistribute it and/or 13 13 modify it under the terms of the GNU Lesser General Public … … 60 60 existing transaction record. If the inner transaction is cancelled 61 61 then a subsequent commit will fail 62 62 63 63 - keep a mirrored copy of the tdb hash chain heads to allow for the 64 64 fast hash heads scan on traverse, updating the mirrored copy in … … 77 77 78 78 - check for a valid recovery record on open of the tdb, while the 79 globallock is held. Automatically recover from the transaction79 open lock is held. Automatically recover from the transaction 80 80 recovery area if needed, then continue with the open as 81 81 usual. This allows for smooth crash recovery with no administrator … … 136 136 tdb_off_t magic_offset; 137 137 138 /* set when the GLOBAL_LOCK has been taken */139 bool global_lock_taken;140 141 138 /* old file size before transaction */ 142 139 tdb_len_t old_map_size; 143 140 144 /* we should re-pack on commit*/145 bool need_repack;141 /* did we expand in this transaction */ 142 bool expanded; 146 143 }; 147 144 … … 189 186 } 190 187 } 191 188 192 189 /* now copy it out of this block */ 193 190 memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len); … … 296 293 } 297 294 } 298 295 299 296 /* overwrite part of an existing block */ 300 297 if (buf == NULL) { … … 407 404 } 408 405 409 tdb->transaction->need_repack = true; 410 411 return 0; 412 } 413 414 /* 415 brlock during a transaction - ignore them 416 */ 417 static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, 418 int rw_type, int lck_type, int probe, size_t len) 419 { 406 tdb->transaction->expanded = true; 407 420 408 return 0; 421 409 } … … 427 415 transaction_oob, 428 416 transaction_expand_file, 429 transaction_brlock430 417 }; 431 418 … … 435 422 transaction is allowed to be pending per tdb_context 436 423 */ 437 int tdb_transaction_start(struct tdb_context *tdb) 424 static int _tdb_transaction_start(struct tdb_context *tdb, 425 enum tdb_lock_flags lockflags) 438 426 { 439 427 /* some sanity checks */ … … 456 444 } 457 445 458 if (tdb ->num_locks != 0 || tdb->global_lock.count) {446 if (tdb_have_extra_locks(tdb)) { 459 447 /* the caller must not have any locks when starting a 460 448 transaction as otherwise we'll be screwed by lack … … 487 475 discussed with Volker, there are a number of ways we could 488 476 make this async, which we will probably do in the future */ 489 if (tdb_transaction_lock(tdb, F_WRLCK ) == -1) {477 if (tdb_transaction_lock(tdb, F_WRLCK, lockflags) == -1) { 490 478 SAFE_FREE(tdb->transaction->blocks); 491 479 SAFE_FREE(tdb->transaction); 492 return -1; 493 } 494 480 if ((lockflags & TDB_LOCK_WAIT) == 0) { 481 tdb->ecode = TDB_ERR_NOLOCK; 482 } 483 return -1; 484 } 485 495 486 /* get a read lock from the freelist to the end of file. This 496 487 is upgraded to a write lock during the commit */ 497 if (tdb_ brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {488 if (tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, true) == -1) { 498 489 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); 499 tdb->ecode = TDB_ERR_LOCK; 500 goto fail; 490 goto fail_allrecord_lock; 501 491 } 502 492 … … 529 519 tdb_trace(tdb, "tdb_transaction_start"); 530 520 return 0; 531 521 532 522 fail: 533 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); 534 tdb_transaction_unlock(tdb); 523 tdb_allrecord_unlock(tdb, F_RDLCK, false); 524 fail_allrecord_lock: 525 tdb_transaction_unlock(tdb, F_WRLCK); 535 526 SAFE_FREE(tdb->transaction->blocks); 536 527 SAFE_FREE(tdb->transaction->hash_heads); … … 539 530 } 540 531 532 _PUBLIC_ int tdb_transaction_start(struct tdb_context *tdb) 533 { 534 return _tdb_transaction_start(tdb, TDB_LOCK_WAIT); 535 } 536 537 _PUBLIC_ int tdb_transaction_start_nonblock(struct tdb_context *tdb) 538 { 539 return _tdb_transaction_start(tdb, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); 540 } 541 541 542 542 /* … … 549 549 } 550 550 551 #ifdef HAVE_FDATASYNC 552 if (fdatasync(tdb->fd) != 0) { 553 #else 551 554 if (fsync(tdb->fd) != 0) { 555 #endif 552 556 tdb->ecode = TDB_ERR_IO; 553 557 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); … … 570 574 571 575 572 int _tdb_transaction_cancel(struct tdb_context *tdb)576 static int _tdb_transaction_cancel(struct tdb_context *tdb) 573 577 { 574 578 int i, ret = 0; … … 597 601 if (tdb->transaction->magic_offset) { 598 602 const struct tdb_methods *methods = tdb->transaction->io_methods; 599 uint32_t zero = 0;603 const uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC; 600 604 601 605 /* remove the recovery marker */ 602 if (methods->tdb_write(tdb, tdb->transaction->magic_offset, & zero, 4) == -1 ||606 if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 || 603 607 transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) { 604 608 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n")); … … 607 611 } 608 612 609 if (tdb->transaction->global_lock_taken) { 610 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); 611 tdb->transaction->global_lock_taken = false; 612 } 613 614 /* remove any global lock created during the transaction */ 615 if (tdb->global_lock.count != 0) { 616 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); 617 tdb->global_lock.count = 0; 618 } 619 620 /* remove any locks created during the transaction */ 621 if (tdb->num_locks != 0) { 622 for (i=0;i<tdb->num_lockrecs;i++) { 623 tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, 624 F_UNLCK,F_SETLKW, 0, 1); 625 } 626 tdb->num_locks = 0; 627 tdb->num_lockrecs = 0; 628 SAFE_FREE(tdb->lockrecs); 629 } 613 /* This also removes the OPEN_LOCK, if we have it. */ 614 tdb_release_transaction_locks(tdb); 630 615 631 616 /* restore the normal io methods */ 632 617 tdb->methods = tdb->transaction->io_methods; 633 618 634 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);635 tdb_transaction_unlock(tdb);636 619 SAFE_FREE(tdb->transaction->hash_heads); 637 620 SAFE_FREE(tdb->transaction); 638 621 639 622 return ret; 640 623 } … … 643 626 cancel the current transaction 644 627 */ 645 int tdb_transaction_cancel(struct tdb_context *tdb)628 _PUBLIC_ int tdb_transaction_cancel(struct tdb_context *tdb) 646 629 { 647 630 tdb_trace(tdb, "tdb_transaction_cancel"); … … 676 659 } 677 660 661 int tdb_recovery_area(struct tdb_context *tdb, 662 const struct tdb_methods *methods, 663 tdb_off_t *recovery_offset, 664 struct tdb_record *rec) 665 { 666 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, recovery_offset) == -1) { 667 return -1; 668 } 669 670 if (*recovery_offset == 0) { 671 rec->rec_len = 0; 672 return 0; 673 } 674 675 if (methods->tdb_read(tdb, *recovery_offset, rec, sizeof(*rec), 676 DOCONV()) == -1) { 677 return -1; 678 } 679 680 /* ignore invalid recovery regions: can happen in crash */ 681 if (rec->magic != TDB_RECOVERY_MAGIC && 682 rec->magic != TDB_RECOVERY_INVALID_MAGIC) { 683 *recovery_offset = 0; 684 rec->rec_len = 0; 685 } 686 return 0; 687 } 688 678 689 /* 679 690 allocate the recovery area, or use an existing recovery area if it is … … 689 700 tdb_off_t recovery_head; 690 701 691 if (tdb_ ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {702 if (tdb_recovery_area(tdb, methods, &recovery_head, &rec) == -1) { 692 703 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); 693 return -1;694 }695 696 rec.rec_len = 0;697 698 if (recovery_head != 0 &&699 methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {700 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));701 704 return -1; 702 705 } … … 794 797 memset(rec, 0, sizeof(*rec)); 795 798 796 rec->magic = 0;799 rec->magic = TDB_RECOVERY_INVALID_MAGIC; 797 800 rec->data_len = recovery_size; 798 801 rec->rec_len = recovery_max_size; 799 802 rec->key_len = old_map_size; 800 CONVERT( rec);803 CONVERT(*rec); 801 804 802 805 /* build the recovery data into a single blob to allow us to do a single … … 816 819 length = tdb->transaction->last_block_size; 817 820 } 818 821 819 822 if (offset >= old_map_size) { 820 823 continue; … … 845 848 tailer = sizeof(*rec) + recovery_max_size; 846 849 memcpy(p, &tailer, 4); 847 CONVERT(p); 850 if (DOCONV()) { 851 tdb_convert(p, 4); 852 } 848 853 849 854 /* write the recovery data to the recovery area */ … … 929 934 930 935 methods = tdb->transaction->io_methods; 931 936 932 937 /* if there are any locks pending then the caller has not 933 938 nested their locks properly, so fail the transaction */ 934 if (tdb ->num_locks || tdb->global_lock.count) {939 if (tdb_have_extra_locks(tdb)) { 935 940 tdb->ecode = TDB_ERR_LOCK; 936 941 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n")); … … 940 945 941 946 /* upgrade the main transaction lock region to a write lock */ 942 if (tdb_ brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {947 if (tdb_allrecord_upgrade(tdb) == -1) { 943 948 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to upgrade hash locks\n")); 944 tdb->ecode = TDB_ERR_LOCK;945 949 _tdb_transaction_cancel(tdb); 946 950 return -1; 947 951 } 948 952 949 /* get the globallock - this prevents new users attaching to the database953 /* get the open lock - this prevents new users attaching to the database 950 954 during the commit */ 951 if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { 952 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get global lock\n")); 953 tdb->ecode = TDB_ERR_LOCK; 955 if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) { 956 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get open lock\n")); 954 957 _tdb_transaction_cancel(tdb); 955 958 return -1; 956 959 } 957 958 tdb->transaction->global_lock_taken = true;959 960 960 961 if (!(tdb->flags & TDB_NOSYNC)) { … … 983 984 } 984 985 985 /* Keep the globallock until the actual commit */986 /* Keep the open lock until the actual commit */ 986 987 987 988 return 0; … … 991 992 prepare to commit the current transaction 992 993 */ 993 int tdb_transaction_prepare_commit(struct tdb_context *tdb)994 { 994 _PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb) 995 { 995 996 tdb_trace(tdb, "tdb_transaction_prepare_commit"); 996 997 return _tdb_transaction_prepare_commit(tdb); 997 998 } 998 999 1000 /* A repack is worthwhile if the largest is less than half total free. */ 1001 static bool repack_worthwhile(struct tdb_context *tdb) 1002 { 1003 tdb_off_t ptr; 1004 struct tdb_record rec; 1005 tdb_len_t total = 0, largest = 0; 1006 1007 if (tdb_ofs_read(tdb, FREELIST_TOP, &ptr) == -1) { 1008 return false; 1009 } 1010 1011 while (ptr != 0 && tdb_rec_free_read(tdb, ptr, &rec) == 0) { 1012 total += rec.rec_len; 1013 if (rec.rec_len > largest) { 1014 largest = rec.rec_len; 1015 } 1016 ptr = rec.next; 1017 } 1018 1019 return total > largest * 2; 1020 } 1021 999 1022 /* 1000 1023 commit the current transaction 1001 1024 */ 1002 int tdb_transaction_commit(struct tdb_context *tdb)1003 { 1025 _PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb) 1026 { 1004 1027 const struct tdb_methods *methods; 1005 1028 int i; 1006 bool need_repack ;1029 bool need_repack = false; 1007 1030 1008 1031 if (tdb->transaction == NULL) { … … 1057 1080 if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) { 1058 1081 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); 1059 1082 1060 1083 /* we've overwritten part of the data and 1061 1084 possibly expanded the file, so we need to … … 1071 1094 SAFE_FREE(tdb->transaction->blocks[i]); 1072 1095 } 1096 1097 /* Do this before we drop lock or blocks. */ 1098 if (tdb->transaction->expanded) { 1099 need_repack = repack_worthwhile(tdb); 1100 } 1073 1101 1074 1102 SAFE_FREE(tdb->transaction->blocks); … … 1095 1123 #endif 1096 1124 1097 need_repack = tdb->transaction->need_repack;1098 1099 1125 /* use a transaction cancel to free memory and remove the 1100 1126 transaction locks */ … … 1111 1137 /* 1112 1138 recover from an aborted transaction. Must be called with exclusive 1113 database write access already established (including the global1139 database write access already established (including the open 1114 1140 lock to prevent new processes attaching) 1115 1141 */ … … 1212 1238 return -1; 1213 1239 } 1214 1215 /* reduce the file size to the old size */1216 tdb_munmap(tdb);1217 if (ftruncate(tdb->fd, recovery_eof) != 0) {1218 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));1219 tdb->ecode = TDB_ERR_IO;1220 return -1;1221 }1222 tdb->map_size = recovery_eof;1223 tdb_mmap(tdb);1224 1240 1225 1241 if (transaction_sync(tdb, 0, recovery_eof) == -1) { … … 1235 1251 return 0; 1236 1252 } 1253 1254 /* Any I/O failures we say "needs recovery". */ 1255 bool tdb_needs_recovery(struct tdb_context *tdb) 1256 { 1257 tdb_off_t recovery_head; 1258 struct tdb_record rec; 1259 1260 /* find the recovery area */ 1261 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { 1262 return true; 1263 } 1264 1265 if (recovery_head == 0) { 1266 /* we have never allocated a recovery record */ 1267 return false; 1268 } 1269 1270 /* read the recovery record */ 1271 if (tdb->methods->tdb_read(tdb, recovery_head, &rec, 1272 sizeof(rec), DOCONV()) == -1) { 1273 return true; 1274 } 1275 1276 return (rec.magic == TDB_RECOVERY_MAGIC); 1277 } -
vendor/current/lib/tdb/common/traverse.c
r414 r740 7 7 Copyright (C) Paul `Rusty' Russell 2000 8 8 Copyright (C) Jeremy Allison 2000-2003 9 9 10 10 ** NOTE! The following LGPL license applies to the tdb 11 11 ** library. This does NOT imply that all of Samba is released 12 12 ** under the LGPL 13 13 14 14 This library is free software; you can redistribute it and/or 15 15 modify it under the terms of the GNU Lesser General Public … … 45 45 hashes are used. In that case we spend most of our 46 46 time in tdb_brlock(), locking empty hash chains. 47 47 48 48 To avoid this, we do an unlocked pre-check to see 49 49 if the hash chain is empty before starting to look … … 53 53 lock, so instead we get the lock and re-fetch the 54 54 value below. 55 55 56 56 Notice that not doing this optimisation on the 57 57 first hash chain is critical. We must guarantee … … 63 63 could miss them anyway without this trick, so the 64 64 semantics don't change. 65 65 66 66 With a non-indexed ldb search this trick gains us a 67 67 factor of around 80 in speed on a linux 2.6.x … … 213 213 a write style traverse - temporarily marks the db read only 214 214 */ 215 int tdb_traverse_read(struct tdb_context *tdb,215 _PUBLIC_ int tdb_traverse_read(struct tdb_context *tdb, 216 216 tdb_traverse_func fn, void *private_data) 217 217 { … … 221 221 /* we need to get a read lock on the transaction lock here to 222 222 cope with the lock ordering semantics of solaris10 */ 223 if (tdb_transaction_lock(tdb, F_RDLCK )) {223 if (tdb_transaction_lock(tdb, F_RDLCK, TDB_LOCK_WAIT)) { 224 224 return -1; 225 225 } … … 230 230 tdb->traverse_read--; 231 231 232 tdb_transaction_unlock(tdb );232 tdb_transaction_unlock(tdb, F_RDLCK); 233 233 234 234 return ret; … … 242 242 alignment restrictions malloc gives you. 243 243 */ 244 int tdb_traverse(struct tdb_context *tdb,244 _PUBLIC_ int tdb_traverse(struct tdb_context *tdb, 245 245 tdb_traverse_func fn, void *private_data) 246 246 { … … 252 252 } 253 253 254 if (tdb_transaction_lock(tdb, F_WRLCK )) {254 if (tdb_transaction_lock(tdb, F_WRLCK, TDB_LOCK_WAIT)) { 255 255 return -1; 256 256 } … … 261 261 tdb->traverse_write--; 262 262 263 tdb_transaction_unlock(tdb );263 tdb_transaction_unlock(tdb, F_WRLCK); 264 264 265 265 return ret; … … 268 268 269 269 /* find the first entry in the database and return its key */ 270 TDB_DATA tdb_firstkey(struct tdb_context *tdb)270 _PUBLIC_ TDB_DATA tdb_firstkey(struct tdb_context *tdb) 271 271 { 272 272 TDB_DATA key; … … 299 299 300 300 /* find the next entry in the database, returning its key */ 301 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)301 _PUBLIC_ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) 302 302 { 303 303 uint32_t oldhash; -
vendor/current/lib/tdb/docs/README
r414 r740 106 106 107 107 ---------------------------------------------------------------------- 108 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, 109 int (*parser)(TDB_DATA key, TDB_DATA data, 110 void *private_data), 111 void *private_data); 112 113 Hand a record to a parser function without allocating it. 114 115 This function is meant as a fast tdb_fetch alternative for large records 116 that are frequently read. The "key" and "data" arguments point directly 117 into the tdb shared memory, they are not aligned at any boundary. 118 119 WARNING: The parser is called while tdb holds a lock on the record. DO NOT 120 call other tdb routines from within the parser. Also, for good performance 121 you should make the parser fast to allow parallel operations. 122 123 tdb_parse_record returns -1 if the record was not found. If the record was 124 found, the return value of "parser" is passed up to the caller. 125 126 ---------------------------------------------------------------------- 108 127 int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); 109 128 -
vendor/current/lib/tdb/include/tdb.h
r414 r740 31 31 #endif 32 32 33 #include "signal.h" 34 35 /* flags to tdb_store() */ 36 #define TDB_REPLACE 1 /* Unused */ 37 #define TDB_INSERT 2 /* Don't overwrite an existing entry */ 38 #define TDB_MODIFY 3 /* Don't create an existing entry */ 39 40 /* flags for tdb_open() */ 41 #define TDB_DEFAULT 0 /* just a readability place holder */ 42 #define TDB_CLEAR_IF_FIRST 1 43 #define TDB_INTERNAL 2 /* don't store on disk */ 44 #define TDB_NOLOCK 4 /* don't do any locking */ 45 #define TDB_NOMMAP 8 /* don't use mmap */ 46 #define TDB_CONVERT 16 /* convert endian (internal use) */ 47 #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ 48 #define TDB_NOSYNC 64 /* don't use synchronous transactions */ 49 #define TDB_SEQNUM 128 /* maintain a sequence number */ 50 #define TDB_VOLATILE 256 /* Activate the per-hashchain freelist, default 5 */ 51 #define TDB_ALLOW_NESTING 512 /* Allow transactions to nest */ 52 #define TDB_DISALLOW_NESTING 1024 /* Disallow transactions to nest */ 53 54 /* error codes */ 33 #include <signal.h> 34 35 /** 36 * @defgroup tdb The tdb API 37 * 38 * tdb is a Trivial database. In concept, it is very much like GDBM, and BSD's 39 * DB except that it allows multiple simultaneous writers and uses locking 40 * internally to keep writers from trampling on each other. tdb is also 41 * extremely small. 42 * 43 * @section tdb_interface Interface 44 * 45 * The interface is very similar to gdbm except for the following: 46 * 47 * <ul> 48 * <li>different open interface. The tdb_open call is more similar to a 49 * traditional open()</li> 50 * <li>no tdbm_reorganise() function</li> 51 * <li>no tdbm_sync() function. No operations are cached in the library 52 * anyway</li> 53 * <li>added a tdb_traverse() function for traversing the whole database</li> 54 * <li>added transactions support</li> 55 * </ul> 56 * 57 * A general rule for using tdb is that the caller frees any returned TDB_DATA 58 * structures. Just call free(p.dptr) to free a TDB_DATA return value called p. 59 * This is the same as gdbm. 60 * 61 * @{ 62 */ 63 64 /** Flags to tdb_store() */ 65 #define TDB_REPLACE 1 /** Unused */ 66 #define TDB_INSERT 2 /** Don't overwrite an existing entry */ 67 #define TDB_MODIFY 3 /** Don't create an existing entry */ 68 69 /** Flags for tdb_open() */ 70 #define TDB_DEFAULT 0 /** just a readability place holder */ 71 #define TDB_CLEAR_IF_FIRST 1 /** If this is the first open, wipe the db */ 72 #define TDB_INTERNAL 2 /** Don't store on disk */ 73 #define TDB_NOLOCK 4 /** Don't do any locking */ 74 #define TDB_NOMMAP 8 /** Don't use mmap */ 75 #define TDB_CONVERT 16 /** Convert endian (internal use) */ 76 #define TDB_BIGENDIAN 32 /** Header is big-endian (internal use) */ 77 #define TDB_NOSYNC 64 /** Don't use synchronous transactions */ 78 #define TDB_SEQNUM 128 /** Maintain a sequence number */ 79 #define TDB_VOLATILE 256 /** Activate the per-hashchain freelist, default 5 */ 80 #define TDB_ALLOW_NESTING 512 /** Allow transactions to nest */ 81 #define TDB_DISALLOW_NESTING 1024 /** Disallow transactions to nest */ 82 #define TDB_INCOMPATIBLE_HASH 2048 /** Better hashing: can't be opened by tdb < 1.2.6. */ 83 84 /** The tdb error codes */ 55 85 enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, 56 86 TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, … … 58 88 TDB_ERR_NESTING}; 59 89 60 /* debugging uses one of the following levels */90 /** Debugging uses one of the following levels */ 61 91 enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, 62 92 TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; 63 93 94 /** The tdb data structure */ 64 95 typedef struct TDB_DATA { 65 96 unsigned char *dptr; … … 79 110 #endif 80 111 81 /* this is the context structure that is returned from a db open*/112 /** This is the context structure that is returned from a db open. */ 82 113 typedef struct tdb_context TDB_CONTEXT; 83 114 … … 91 122 }; 92 123 124 /** 125 * @brief Open the database and creating it if necessary. 126 * 127 * @param[in] name The name of the db to open. 128 * 129 * @param[in] hash_size The hash size is advisory, use zero for a default 130 * value. 131 * 132 * @param[in] tdb_flags The flags to use to open the db:\n\n 133 * TDB_CLEAR_IF_FIRST - Clear database if we are the 134 * only one with it open\n 135 * TDB_INTERNAL - Don't use a file, instaed store the 136 * data in memory. The filename is 137 * ignored in this case.\n 138 * TDB_NOLOCK - Don't do any locking\n 139 * TDB_NOMMAP - Don't use mmap\n 140 * TDB_NOSYNC - Don't synchronise transactions to disk\n 141 * TDB_SEQNUM - Maintain a sequence number\n 142 * TDB_VOLATILE - activate the per-hashchain freelist, 143 * default 5.\n 144 * TDB_ALLOW_NESTING - Allow transactions to nest.\n 145 * TDB_DISALLOW_NESTING - Disallow transactions to nest.\n 146 * 147 * @param[in] open_flags Flags for the open(2) function. 148 * 149 * @param[in] mode The mode for the open(2) function. 150 * 151 * @return A tdb context structure, NULL on error. 152 */ 93 153 struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, 94 154 int open_flags, mode_t mode); 155 156 /** 157 * @brief Open the database and creating it if necessary. 158 * 159 * This is like tdb_open(), but allows you to pass an initial logging and 160 * hash function. Be careful when passing a hash function - all users of the 161 * database must use the same hash function or you will get data corruption. 162 * 163 * @param[in] name The name of the db to open. 164 * 165 * @param[in] hash_size The hash size is advisory, use zero for a default 166 * value. 167 * 168 * @param[in] tdb_flags The flags to use to open the db:\n\n 169 * TDB_CLEAR_IF_FIRST - Clear database if we are the 170 * only one with it open\n 171 * TDB_INTERNAL - Don't use a file, instaed store the 172 * data in memory. The filename is 173 * ignored in this case.\n 174 * TDB_NOLOCK - Don't do any locking\n 175 * TDB_NOMMAP - Don't use mmap\n 176 * TDB_NOSYNC - Don't synchronise transactions to disk\n 177 * TDB_SEQNUM - Maintain a sequence number\n 178 * TDB_VOLATILE - activate the per-hashchain freelist, 179 * default 5.\n 180 * TDB_ALLOW_NESTING - Allow transactions to nest.\n 181 * TDB_DISALLOW_NESTING - Disallow transactions to nest.\n 182 * 183 * @param[in] open_flags Flags for the open(2) function. 184 * 185 * @param[in] mode The mode for the open(2) function. 186 * 187 * @param[in] log_ctx The logging function to use. 188 * 189 * @param[in] hash_fn The hash function you want to use. 190 * 191 * @return A tdb context structure, NULL on error. 192 * 193 * @see tdb_open() 194 */ 95 195 struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, 96 196 int open_flags, mode_t mode, 97 197 const struct tdb_logging_context *log_ctx, 98 198 tdb_hash_func hash_fn); 199 200 /** 201 * @brief Set the maximum number of dead records per hash chain. 202 * 203 * @param[in] tdb The database handle to set the maximum. 204 * 205 * @param[in] max_dead The maximum number of dead records per hash chain. 206 */ 99 207 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead); 100 208 209 /** 210 * @brief Reopen a tdb. 211 * 212 * This can be used after a fork to ensure that we have an independent seek 213 * pointer from our parent and to re-establish locks. 214 * 215 * @param[in] tdb The database to reopen. 216 * 217 * @return 0 on success, -1 on error. 218 */ 101 219 int tdb_reopen(struct tdb_context *tdb); 220 221 /** 222 * @brief Reopen all tdb's 223 * 224 * If the parent is longlived (ie. a parent daemon architecture), we know it 225 * will keep it's active lock on a tdb opened with CLEAR_IF_FIRST. Thus for 226 * child processes we don't have to add an active lock. This is essential to 227 * improve performance on systems that keep POSIX locks as a non-scalable data 228 * structure in the kernel. 229 * 230 * @param[in] parent_longlived Wether the parent is longlived or not. 231 * 232 * @return 0 on success, -1 on error. 233 */ 102 234 int tdb_reopen_all(int parent_longlived); 235 236 /** 237 * @brief Set a different tdb logging function. 238 * 239 * @param[in] tdb The tdb to set the logging function. 240 * 241 * @param[in] log_ctx The logging function to set. 242 */ 103 243 void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx); 244 245 /** 246 * @brief Get the tdb last error code. 247 * 248 * @param[in] tdb The tdb to get the error code from. 249 * 250 * @return A TDB_ERROR code. 251 * 252 * @see TDB_ERROR 253 */ 104 254 enum TDB_ERROR tdb_error(struct tdb_context *tdb); 255 256 /** 257 * @brief Get a error string for the last tdb error 258 * 259 * @param[in] tdb The tdb to get the error code from. 260 * 261 * @return An error string. 262 */ 105 263 const char *tdb_errorstr(struct tdb_context *tdb); 264 265 /** 266 * @brief Fetch an entry in the database given a key. 267 * 268 * The caller must free the resulting data. 269 * 270 * @param[in] tdb The tdb to fetch the key. 271 * 272 * @param[in] key The key to fetch. 273 * 274 * @return The key entry found in the database, NULL on error with 275 * TDB_ERROR set. 276 * 277 * @see tdb_error() 278 * @see tdb_errorstr() 279 */ 106 280 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); 281 282 /** 283 * @brief Hand a record to a parser function without allocating it. 284 * 285 * This function is meant as a fast tdb_fetch alternative for large records 286 * that are frequently read. The "key" and "data" arguments point directly 287 * into the tdb shared memory, they are not aligned at any boundary. 288 * 289 * @warning The parser is called while tdb holds a lock on the record. DO NOT 290 * call other tdb routines from within the parser. Also, for good performance 291 * you should make the parser fast to allow parallel operations. 292 * 293 * @param[in] tdb The tdb to parse the record. 294 * 295 * @param[in] key The key to parse. 296 * 297 * @param[in] parser The parser to use to parse the data. 298 * 299 * @param[in] private_data A private data pointer which is passed to the parser 300 * function. 301 * 302 * @return -1 if the record was not found. If the record was found, 303 * the return value of "parser" is passed up to the caller. 304 */ 107 305 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, 108 int (*parser)(TDB_DATA key, TDB_DATA data, 109 void *private_data), 110 void *private_data); 306 int (*parser)(TDB_DATA key, TDB_DATA data, 307 void *private_data), 308 void *private_data); 309 310 /** 311 * @brief Delete an entry in the database given a key. 312 * 313 * @param[in] tdb The tdb to delete the key. 314 * 315 * @param[in] key The key to delete. 316 * 317 * @return 0 on success, -1 if the key doesn't exist. 318 */ 111 319 int tdb_delete(struct tdb_context *tdb, TDB_DATA key); 320 321 /** 322 * @brief Store an element in the database. 323 * 324 * This replaces any existing element with the same key. 325 * 326 * @param[in] tdb The tdb to store the entry. 327 * 328 * @param[in] key The key to use to store the entry. 329 * 330 * @param[in] dbuf The data to store under the key. 331 * 332 * @param[in] flag The flags to store the key:\n\n 333 * TDB_INSERT: Don't overwrite an existing entry.\n 334 * TDB_MODIFY: Don't create a new entry\n 335 * 336 * @return 0 on success, -1 on error with error code set. 337 * 338 * @see tdb_error() 339 * @see tdb_errorstr() 340 */ 112 341 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); 342 343 /** 344 * @brief Append data to an entry. 345 * 346 * If the entry doesn't exist, it will create a new one. 347 * 348 * @param[in] tdb The database to use. 349 * 350 * @param[in] key The key to append the data. 351 * 352 * @param[in] new_dbuf The data to append to the key. 353 * 354 * @return 0 on success, -1 on error with error code set. 355 * 356 * @see tdb_error() 357 * @see tdb_errorstr() 358 */ 113 359 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); 360 361 /** 362 * @brief Close a database. 363 * 364 * @param[in] tdb The database to close. 365 * 366 * @return 0 for success, -1 on error. 367 */ 114 368 int tdb_close(struct tdb_context *tdb); 369 370 /** 371 * @brief Find the first entry in the database and return its key. 372 * 373 * The caller must free the returned data. 374 * 375 * @param[in] tdb The database to use. 376 * 377 * @return The first entry of the database, an empty TDB_DATA entry 378 * if the database is empty. 379 */ 115 380 TDB_DATA tdb_firstkey(struct tdb_context *tdb); 381 382 /** 383 * @brief Find the next entry in the database, returning its key. 384 * 385 * The caller must free the returned data. 386 * 387 * @param[in] tdb The database to use. 388 * 389 * @param[in] key The key from which you want the next key. 390 * 391 * @return The next entry of the current key, an empty TDB_DATA 392 * entry if there is no entry. 393 */ 116 394 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); 117 int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); 118 int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); 395 396 /** 397 * @brief Traverse the entire database. 398 * 399 * While travering the function fn(tdb, key, data, state) is called on each 400 * element. If fn is NULL then it is not called. A non-zero return value from 401 * fn() indicates that the traversal should stop. Traversal callbacks may not 402 * start transactions. 403 * 404 * @warning The data buffer given to the callback fn does NOT meet the alignment 405 * restrictions malloc gives you. 406 * 407 * @param[in] tdb The database to traverse. 408 * 409 * @param[in] fn The function to call on each entry. 410 * 411 * @param[in] private_data The private data which should be passed to the 412 * traversing function. 413 * 414 * @return The record count traversed, -1 on error. 415 */ 416 int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data); 417 418 /** 419 * @brief Traverse the entire database. 420 * 421 * While traversing the database the function fn(tdb, key, data, state) is 422 * called on each element, but marking the database read only during the 423 * traversal, so any write operations will fail. This allows tdb to use read 424 * locks, which increases the parallelism possible during the traversal. 425 * 426 * @param[in] tdb The database to traverse. 427 * 428 * @param[in] fn The function to call on each entry. 429 * 430 * @param[in] private_data The private data which should be passed to the 431 * traversing function. 432 * 433 * @return The record count traversed, -1 on error. 434 */ 435 int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data); 436 437 /** 438 * @brief Check if an entry in the database exists. 439 * 440 * @note 1 is returned if the key is found and 0 is returned if not found this 441 * doesn't match the conventions in the rest of this module, but is compatible 442 * with gdbm. 443 * 444 * @param[in] tdb The database to check if the entry exists. 445 * 446 * @param[in] key The key to check if the entry exists. 447 * 448 * @return 1 if the key is found, 0 if not. 449 */ 119 450 int tdb_exists(struct tdb_context *tdb, TDB_DATA key); 451 452 /** 453 * @brief Lock entire database with a write lock. 454 * 455 * @param[in] tdb The database to lock. 456 * 457 * @return 0 on success, -1 on error with error code set. 458 * 459 * @see tdb_error() 460 * @see tdb_errorstr() 461 */ 120 462 int tdb_lockall(struct tdb_context *tdb); 463 464 /** 465 * @brief Lock entire database with a write lock. 466 * 467 * This is the non-blocking call. 468 * 469 * @param[in] tdb The database to lock. 470 * 471 * @return 0 on success, -1 on error with error code set. 472 * 473 * @see tdb_lockall() 474 * @see tdb_error() 475 * @see tdb_errorstr() 476 */ 121 477 int tdb_lockall_nonblock(struct tdb_context *tdb); 478 479 /** 480 * @brief Unlock entire database with write lock. 481 * 482 * @param[in] tdb The database to unlock. 483 * 484 * @return 0 on success, -1 on error with error code set. 485 * 486 * @see tdb_lockall() 487 * @see tdb_error() 488 * @see tdb_errorstr() 489 */ 122 490 int tdb_unlockall(struct tdb_context *tdb); 491 492 /** 493 * @brief Lock entire database with a read lock. 494 * 495 * @param[in] tdb The database to lock. 496 * 497 * @return 0 on success, -1 on error with error code set. 498 * 499 * @see tdb_error() 500 * @see tdb_errorstr() 501 */ 123 502 int tdb_lockall_read(struct tdb_context *tdb); 503 504 /** 505 * @brief Lock entire database with a read lock. 506 * 507 * This is the non-blocking call. 508 * 509 * @param[in] tdb The database to lock. 510 * 511 * @return 0 on success, -1 on error with error code set. 512 * 513 * @see tdb_lockall_read() 514 * @see tdb_error() 515 * @see tdb_errorstr() 516 */ 124 517 int tdb_lockall_read_nonblock(struct tdb_context *tdb); 518 519 /** 520 * @brief Unlock entire database with read lock. 521 * 522 * @param[in] tdb The database to unlock. 523 * 524 * @return 0 on success, -1 on error with error code set. 525 * 526 * @see tdb_lockall_read() 527 * @see tdb_error() 528 * @see tdb_errorstr() 529 */ 125 530 int tdb_unlockall_read(struct tdb_context *tdb); 531 532 /** 533 * @brief Lock entire database with write lock - mark only. 534 * 535 * @todo Add more details. 536 * 537 * @param[in] tdb The database to mark. 538 * 539 * @return 0 on success, -1 on error with error code set. 540 * 541 * @see tdb_error() 542 * @see tdb_errorstr() 543 */ 126 544 int tdb_lockall_mark(struct tdb_context *tdb); 545 546 /** 547 * @brief Lock entire database with write lock - unmark only. 548 * 549 * @todo Add more details. 550 * 551 * @param[in] tdb The database to mark. 552 * 553 * @return 0 on success, -1 on error with error code set. 554 * 555 * @see tdb_error() 556 * @see tdb_errorstr() 557 */ 127 558 int tdb_lockall_unmark(struct tdb_context *tdb); 559 560 /** 561 * @brief Get the name of the current tdb file. 562 * 563 * This is useful for external logging functions. 564 * 565 * @param[in] tdb The database to get the name from. 566 * 567 * @return The name of the database. 568 */ 128 569 const char *tdb_name(struct tdb_context *tdb); 570 571 /** 572 * @brief Get the underlying file descriptor being used by tdb. 573 * 574 * This is useful for external routines that want to check the device/inode 575 * of the fd. 576 * 577 * @param[in] tdb The database to get the fd from. 578 * 579 * @return The file descriptor or -1. 580 */ 129 581 int tdb_fd(struct tdb_context *tdb); 582 583 /** 584 * @brief Get the current logging function. 585 * 586 * This is useful for external tdb routines that wish to log tdb errors. 587 * 588 * @param[in] tdb The database to get the logging function from. 589 * 590 * @return The logging function of the database. 591 * 592 * @see tdb_get_logging_private() 593 */ 130 594 tdb_log_func tdb_log_fn(struct tdb_context *tdb); 595 596 /** 597 * @brief Get the private data of the logging function. 598 * 599 * @param[in] tdb The database to get the data from. 600 * 601 * @return The private data pointer of the logging function. 602 * 603 * @see tdb_log_fn() 604 */ 131 605 void *tdb_get_logging_private(struct tdb_context *tdb); 606 607 /** 608 * @brief Start a transaction. 609 * 610 * All operations after the transaction start can either be committed with 611 * tdb_transaction_commit() or cancelled with tdb_transaction_cancel(). 612 * 613 * If you call tdb_transaction_start() again on the same tdb context while a 614 * transaction is in progress, then the same transaction buffer is re-used. The 615 * number of tdb_transaction_{commit,cancel} operations must match the number 616 * of successful tdb_transaction_start() calls. 617 * 618 * Note that transactions are by default disk synchronous, and use a recover 619 * area in the database to automatically recover the database on the next open 620 * if the system crashes during a transaction. You can disable the synchronous 621 * transaction recovery setup using the TDB_NOSYNC flag, which will greatly 622 * speed up operations at the risk of corrupting your database if the system 623 * crashes. 624 * 625 * Operations made within a transaction are not visible to other users of the 626 * database until a successful commit. 627 * 628 * @param[in] tdb The database to start the transaction. 629 * 630 * @return 0 on success, -1 on error with error code set. 631 * 632 * @see tdb_error() 633 * @see tdb_errorstr() 634 */ 132 635 int tdb_transaction_start(struct tdb_context *tdb); 636 637 /** 638 * @brief Start a transaction, non-blocking. 639 * 640 * @param[in] tdb The database to start the transaction. 641 * 642 * @return 0 on success, -1 on error with error code set. 643 * 644 * @see tdb_error() 645 * @see tdb_errorstr() 646 * @see tdb_transaction_start() 647 */ 648 int tdb_transaction_start_nonblock(struct tdb_context *tdb); 649 650 /** 651 * @brief Prepare to commit a current transaction, for two-phase commits. 652 * 653 * Once prepared for commit, the only allowed calls are tdb_transaction_commit() 654 * or tdb_transaction_cancel(). Preparing allocates disk space for the pending 655 * updates, so a subsequent commit should succeed (barring any hardware 656 * failures). 657 * 658 * @param[in] tdb The database to prepare the commit. 659 * 660 * @return 0 on success, -1 on error with error code set. 661 * 662 * @see tdb_error() 663 * @see tdb_errorstr() 664 */ 133 665 int tdb_transaction_prepare_commit(struct tdb_context *tdb); 666 667 /** 668 * @brief Commit a current transaction. 669 * 670 * This updates the database and releases the current transaction locks. 671 * 672 * @param[in] tdb The database to commit the transaction. 673 * 674 * @return 0 on success, -1 on error with error code set. 675 * 676 * @see tdb_error() 677 * @see tdb_errorstr() 678 */ 134 679 int tdb_transaction_commit(struct tdb_context *tdb); 680 681 /** 682 * @brief Cancel a current transaction. 683 * 684 * This discards all write and lock operations that have been made since the 685 * transaction started. 686 * 687 * @param[in] tdb The tdb to cancel the transaction on. 688 * 689 * @return 0 on success, -1 on error with error code set. 690 * 691 * @see tdb_error() 692 * @see tdb_errorstr() 693 */ 135 694 int tdb_transaction_cancel(struct tdb_context *tdb); 136 int tdb_transaction_recover(struct tdb_context *tdb); 695 696 /** 697 * @brief Get the tdb sequence number. 698 * 699 * Only makes sense if the writers opened with TDB_SEQNUM set. Note that this 700 * sequence number will wrap quite quickly, so it should only be used for a 701 * 'has something changed' test, not for code that relies on the count of the 702 * number of changes made. If you want a counter then use a tdb record. 703 * 704 * The aim of this sequence number is to allow for a very lightweight test of a 705 * possible tdb change. 706 * 707 * @param[in] tdb The database to get the sequence number from. 708 * 709 * @return The sequence number or 0. 710 * 711 * @see tdb_open() 712 * @see tdb_enable_seqnum() 713 */ 137 714 int tdb_get_seqnum(struct tdb_context *tdb); 715 716 /** 717 * @brief Get the hash size. 718 * 719 * @param[in] tdb The database to get the hash size from. 720 * 721 * @return The hash size. 722 */ 138 723 int tdb_hash_size(struct tdb_context *tdb); 724 725 /** 726 * @brief Get the map size. 727 * 728 * @param[in] tdb The database to get the map size from. 729 * 730 * @return The map size. 731 */ 139 732 size_t tdb_map_size(struct tdb_context *tdb); 733 734 /** 735 * @brief Get the tdb flags set during open. 736 * 737 * @param[in] tdb The database to get the flags form. 738 * 739 * @return The flags set to on the database. 740 */ 140 741 int tdb_get_flags(struct tdb_context *tdb); 742 743 /** 744 * @brief Add flags to the database. 745 * 746 * @param[in] tdb The database to add the flags. 747 * 748 * @param[in] flag The tdb flags to add. 749 */ 141 750 void tdb_add_flags(struct tdb_context *tdb, unsigned flag); 751 752 /** 753 * @brief Remove flags from the database. 754 * 755 * @param[in] tdb The database to remove the flags. 756 * 757 * @param[in] flag The tdb flags to remove. 758 */ 142 759 void tdb_remove_flags(struct tdb_context *tdb, unsigned flag); 760 761 /** 762 * @brief Enable sequence number handling on an open tdb. 763 * 764 * @param[in] tdb The database to enable sequence number handling. 765 * 766 * @see tdb_get_seqnum() 767 */ 143 768 void tdb_enable_seqnum(struct tdb_context *tdb); 769 770 /** 771 * @brief Increment the tdb sequence number. 772 * 773 * This only works if the tdb has been opened using the TDB_SEQNUM flag or 774 * enabled useing tdb_enable_seqnum(). 775 * 776 * @param[in] tdb The database to increment the sequence number. 777 * 778 * @see tdb_enable_seqnum() 779 * @see tdb_get_seqnum() 780 */ 144 781 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb); 782 783 /** 784 * @brief Create a hash of the key. 785 * 786 * @param[in] key The key to hash 787 * 788 * @return The hash. 789 */ 790 unsigned int tdb_jenkins_hash(TDB_DATA *key); 791 792 /** 793 * @brief Check the consistency of the database. 794 * 795 * This check the consistency of the database calling back the check function 796 * (if non-NULL) on each record. If some consistency check fails, or the 797 * supplied check function returns -1, tdb_check returns -1, otherwise 0. 798 * 799 * @note The logging function (if set) will be called with additional 800 * information on the corruption found. 801 * 802 * @param[in] tdb The database to check. 803 * 804 * @param[in] check The check function to use. 805 * 806 * @param[in] private_data the private data to pass to the check function. 807 * 808 * @return 0 on success, -1 on error with error code set. 809 * 810 * @see tdb_error() 811 * @see tdb_errorstr() 812 */ 145 813 int tdb_check(struct tdb_context *tdb, 146 814 int (*check) (TDB_DATA key, TDB_DATA data, void *private_data), 147 815 void *private_data); 816 817 /* @} ******************************************************************/ 148 818 149 819 /* Low level locking functions: use with care */ … … 167 837 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries); 168 838 int tdb_freelist_size(struct tdb_context *tdb); 839 char *tdb_summary(struct tdb_context *tdb); 169 840 170 841 extern TDB_DATA tdb_null; -
vendor/current/lib/tdb/libtdb.m4
r414 r740 14 14 fi 15 15 TDB_OBJ="common/tdb.o common/dump.o common/transaction.o common/error.o common/traverse.o" 16 TDB_OBJ="$TDB_OBJ common/freelist.o common/freelistcheck.o common/io.o common/lock.o common/open.o common/check.o "16 TDB_OBJ="$TDB_OBJ common/freelist.o common/freelistcheck.o common/io.o common/lock.o common/open.o common/check.o common/hash.o common/summary.o" 17 17 AC_SUBST(TDB_OBJ) 18 18 AC_SUBST(LIBREPLACEOBJ) … … 20 20 TDB_LIBS="" 21 21 AC_SUBST(TDB_LIBS) 22 23 TDB_DEPS="" 24 if test x$libreplace_cv_HAVE_FDATASYNC_IN_LIBRT = xyes ; then 25 TDB_DEPS="$TDB_DEPS -lrt" 26 fi 27 AC_SUBST(TDB_DEPS) 22 28 23 29 TDB_CFLAGS="-I$tdbdir/include" -
vendor/current/lib/tdb/manpages/tdbbackup.8.xml
r414 r740 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="tdbbackup.8"> 4 4 … … 8 8 <refmiscinfo class="source">Samba</refmiscinfo> 9 9 <refmiscinfo class="manual">System Administration tools</refmiscinfo> 10 <refmiscinfo class="version">3. 5</refmiscinfo>10 <refmiscinfo class="version">3.6</refmiscinfo> 11 11 </refmeta> 12 12 -
vendor/current/lib/tdb/manpages/tdbdump.8.xml
r414 r740 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="tdbdump.8"> 4 4 … … 8 8 <refmiscinfo class="source">Samba</refmiscinfo> 9 9 <refmiscinfo class="manual">System Administration tools</refmiscinfo> 10 <refmiscinfo class="version">3. 5</refmiscinfo>10 <refmiscinfo class="version">3.6</refmiscinfo> 11 11 </refmeta> 12 12 -
vendor/current/lib/tdb/manpages/tdbtool.8.xml
r414 r740 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="tdbtool.8"> 4 4 … … 8 8 <refmiscinfo class="source">Samba</refmiscinfo> 9 9 <refmiscinfo class="manual">System Administration tools</refmiscinfo> 10 <refmiscinfo class="version">3. 5</refmiscinfo>10 <refmiscinfo class="version">3.6</refmiscinfo> 11 11 </refmeta> 12 12 -
vendor/current/lib/tdb/pytdb.c
r414 r740 10 10 ** library. This does NOT imply that all of Samba is released 11 11 ** under the LGPL 12 12 13 13 This library is free software; you can redistribute it and/or 14 14 modify it under the terms of the GNU Lesser General Public … … 25 25 */ 26 26 27 #include <Python.h> 27 28 #include "replace.h" 28 29 #include "system/filesys.h" 29 30 30 #include <Python.h>31 31 #ifndef Py_RETURN_NONE 32 32 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None … … 42 42 } PyTdbObject; 43 43 44 PyAPI_DATA(PyTypeObject)PyTdb;44 staticforward PyTypeObject PyTdb; 45 45 46 46 static void PyErr_SetTDBError(TDB_CONTEXT *tdb) … … 78 78 static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs) 79 79 { 80 char *name ;80 char *name = NULL; 81 81 int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600; 82 82 TDB_CONTEXT *ctx; … … 84 84 const char *kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL }; 85 85 86 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode)) 87 return NULL; 86 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode)) 87 return NULL; 88 89 if (name == NULL) { 90 tdb_flags |= TDB_INTERNAL; 91 } 88 92 89 93 ctx = tdb_open(name, hash_size, tdb_flags, flags, mode); … … 94 98 95 99 ret = PyObject_New(PyTdbObject, &PyTdb); 100 if (!ret) { 101 tdb_close(ctx); 102 return NULL; 103 } 104 96 105 ret->ctx = ctx; 97 106 ret->closed = false; … … 113 122 } 114 123 115 static PyObject *obj_transaction_ recover(PyTdbObject *self)116 { 117 int ret = tdb_transaction_ recover(self->ctx);124 static PyObject *obj_transaction_prepare_commit(PyTdbObject *self) 125 { 126 int ret = tdb_transaction_prepare_commit(self->ctx); 118 127 PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); 119 128 Py_RETURN_NONE; … … 267 276 } 268 277 278 static PyObject *obj_add_flags(PyTdbObject *self, PyObject *args) 279 { 280 unsigned flags; 281 282 if (!PyArg_ParseTuple(args, "I", &flags)) 283 return NULL; 284 285 tdb_add_flags(self->ctx, flags); 286 Py_RETURN_NONE; 287 } 288 289 static PyObject *obj_remove_flags(PyTdbObject *self, PyObject *args) 290 { 291 unsigned flags; 292 293 if (!PyArg_ParseTuple(args, "I", &flags)) 294 return NULL; 295 296 tdb_remove_flags(self->ctx, flags); 297 Py_RETURN_NONE; 298 } 269 299 270 300 typedef struct { … … 306 336 307 337 ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator); 338 if (!ret) 339 return NULL; 308 340 ret->current = tdb_firstkey(self->ctx); 309 341 ret->iteratee = self; … … 316 348 int ret = tdb_wipe_all(self->ctx); 317 349 PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); 350 Py_RETURN_NONE; 351 } 352 353 static PyObject *obj_repack(PyTdbObject *self) 354 { 355 int ret = tdb_repack(self->ctx); 356 PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); 357 Py_RETURN_NONE; 358 } 359 360 static PyObject *obj_enable_seqnum(PyTdbObject *self) 361 { 362 tdb_enable_seqnum(self->ctx); 363 Py_RETURN_NONE; 364 } 365 366 static PyObject *obj_increment_seqnum_nonblock(PyTdbObject *self) 367 { 368 tdb_increment_seqnum_nonblock(self->ctx); 318 369 Py_RETURN_NONE; 319 370 } … … 326 377 "S.transaction_commit() -> None\n" 327 378 "Commit the currently active transaction." }, 328 { "transaction_ recover", (PyCFunction)obj_transaction_recover, METH_NOARGS,329 "S.transaction_ recover() -> None\n"330 " Recover the currently active transaction." },379 { "transaction_prepare_commit", (PyCFunction)obj_transaction_prepare_commit, METH_NOARGS, 380 "S.transaction_prepare_commit() -> None\n" 381 "Prepare to commit the currently active transaction" }, 331 382 { "transaction_start", (PyCFunction)obj_transaction_start, METH_NOARGS, 332 383 "S.transaction_start() -> None\n" … … 352 403 { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None" 353 404 "Store data." }, 405 { "add_flags", (PyCFunction)obj_add_flags, METH_VARARGS, "S.add_flags(flags) -> None" }, 406 { "remove_flags", (PyCFunction)obj_remove_flags, METH_VARARGS, "S.remove_flags(flags) -> None" }, 354 407 { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, 355 408 { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n" 356 409 "Wipe the entire database." }, 410 { "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n" 411 "Repack the entire database." }, 412 { "enable_seqnum", (PyCFunction)obj_enable_seqnum, METH_NOARGS, 413 "S.enable_seqnum() -> None" }, 414 { "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS, 415 "S.increment_seqnum_nonblock() -> None" }, 357 416 { NULL } 358 417 }; … … 376 435 } 377 436 437 static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure) 438 { 439 return PyInt_FromLong(tdb_freelist_size(self->ctx)); 440 } 441 378 442 static PyObject *obj_get_flags(PyTdbObject *self, void *closure) 379 443 { … … 385 449 return PyString_FromString(tdb_name(self->ctx)); 386 450 } 451 452 static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure) 453 { 454 return PyInt_FromLong(tdb_get_seqnum(self->ctx)); 455 } 456 387 457 388 458 static PyGetSetDef tdb_object_getsetters[] = { 389 459 { (char *)"hash_size", (getter)obj_get_hash_size, NULL, NULL }, 390 460 { (char *)"map_size", (getter)obj_get_map_size, NULL, NULL }, 461 { (char *)"freelist_size", (getter)obj_get_freelist_size, NULL, NULL }, 391 462 { (char *)"flags", (getter)obj_get_flags, NULL, NULL }, 392 463 { (char *)"max_dead", NULL, (setter)obj_set_max_dead, NULL }, 393 464 { (char *)"filename", (getter)obj_get_filename, NULL, (char *)"The filename of this TDB file."}, 465 { (char *)"seqnum", (getter)obj_get_seqnum, NULL, NULL }, 394 466 { NULL } 395 467 }; … … 397 469 static PyObject *tdb_object_repr(PyTdbObject *self) 398 470 { 399 return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx)); 471 if (tdb_get_flags(self->ctx) & TDB_INTERNAL) { 472 return PyString_FromString("Tdb(<internal>)"); 473 } else { 474 return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx)); 475 } 400 476 } 401 477 … … 404 480 if (!self->closed) 405 481 tdb_close(self->ctx); 406 PyObject_Del(self);482 self->ob_type->tp_free(self); 407 483 } 408 484 … … 463 539 .mp_ass_subscript = (objobjargproc)obj_setitem, 464 540 }; 465 PyTypeObject PyTdb = {541 static PyTypeObject PyTdb = { 466 542 .tp_name = "Tdb", 467 543 .tp_basicsize = sizeof(PyTdbObject), … … 483 559 }; 484 560 561 void inittdb(void); 485 562 void inittdb(void) 486 563 { … … 508 585 PyModule_AddObject(m, "CONVERT", PyInt_FromLong(TDB_CONVERT)); 509 586 PyModule_AddObject(m, "BIGENDIAN", PyInt_FromLong(TDB_BIGENDIAN)); 587 PyModule_AddObject(m, "NOSYNC", PyInt_FromLong(TDB_NOSYNC)); 588 PyModule_AddObject(m, "SEQNUM", PyInt_FromLong(TDB_SEQNUM)); 589 PyModule_AddObject(m, "VOLATILE", PyInt_FromLong(TDB_VOLATILE)); 590 PyModule_AddObject(m, "ALLOW_NESTING", PyInt_FromLong(TDB_ALLOW_NESTING)); 591 PyModule_AddObject(m, "DISALLOW_NESTING", PyInt_FromLong(TDB_DISALLOW_NESTING)); 592 PyModule_AddObject(m, "INCOMPATIBLE_HASH", PyInt_FromLong(TDB_INCOMPATIBLE_HASH)); 593 510 594 PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText")); 595 596 PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION)); 511 597 512 598 Py_INCREF(&PyTdb); -
vendor/current/lib/tdb/python/tdbdump.py
r414 r740 1 #!/usr/bin/ python1 #!/usr/bin/env python 2 2 # Trivial reimplementation of tdbdump in Python 3 3 -
vendor/current/lib/tdb/python/tests/simple.py
r414 r740 1 #!/usr/bin/ python1 #!/usr/bin/env python 2 2 # Some simple tests for the Python bindings for TDB 3 3 # Note that this tests the interface of the Python bindings … … 13 13 14 14 class OpenTdbTests(TestCase): 15 15 16 def test_nonexistant_read(self): 16 self.assertRaises(IOError, tdb.Tdb, "/some/nonexistant/file", 0, tdb.DEFAULT, os.O_RDWR) 17 self.assertRaises(IOError, tdb.Tdb, "/some/nonexistant/file", 0, 18 tdb.DEFAULT, os.O_RDWR) 17 19 18 20 class CloseTdbTests(TestCase): 21 19 22 def test_double_close(self): 20 self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR) 23 self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, 24 os.O_CREAT|os.O_RDWR) 21 25 self.assertNotEqual(None, self.tdb) 22 26 … … 26 30 27 31 32 class InternalTdbTests(TestCase): 33 34 def test_repr(self): 35 self.tdb = tdb.Tdb() 36 37 # repr used to crash on internal db 38 self.assertEquals(repr(self.tdb), "Tdb(<internal>)") 39 40 28 41 class SimpleTdbTests(TestCase): 42 29 43 def setUp(self): 30 44 super(SimpleTdbTests, self).setUp() 31 self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR) 45 self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, 46 os.O_CREAT|os.O_RDWR) 32 47 self.assertNotEqual(None, self.tdb) 33 48 … … 82 97 self.tdb.map_size 83 98 99 def test_freelist_size(self): 100 self.tdb.freelist_size 101 84 102 def test_name(self): 85 103 self.tdb.filename … … 104 122 self.assertEquals("1", self.tdb["bloe"]) 105 123 106 def test_ iterator(self):124 def test_transaction_prepare_commit(self): 107 125 self.tdb["bloe"] = "2" 108 self.tdb["bla"] = "hoi" 109 i = iter(self.tdb) 110 self.assertEquals(set(["bloe", "bla"]), set([i.next(), i.next()])) 126 self.tdb.transaction_start() 127 self.tdb["bloe"] = "1" 128 self.tdb.transaction_prepare_commit() 129 self.tdb.transaction_commit() 130 self.assertEquals("1", self.tdb["bloe"]) 111 131 112 132 def test_iterkeys(self): … … 123 143 self.assertEquals(0, len(list(self.tdb))) 124 144 145 def test_repack(self): 146 self.tdb["foo"] = "abc" 147 self.tdb["bar"] = "def" 148 del self.tdb["foo"] 149 self.tdb.repack() 150 151 def test_seqnum(self): 152 self.tdb.enable_seqnum() 153 seq1 = self.tdb.seqnum 154 self.tdb.increment_seqnum_nonblock() 155 seq2 = self.tdb.seqnum 156 self.assertEquals(seq2-seq1, 1) 157 125 158 def test_len(self): 126 159 self.assertEquals(0, len(list(self.tdb))) … … 128 161 self.assertEquals(1, len(list(self.tdb))) 129 162 163 def test_add_flags(self): 164 self.tdb.add_flags(tdb.NOMMAP) 165 self.tdb.remove_flags(tdb.NOMMAP) 166 167 168 class VersionTests(TestCase): 169 170 def test_present(self): 171 self.assertTrue(isinstance(tdb.__version__, str)) 172 130 173 131 174 if __name__ == '__main__': -
vendor/current/lib/tdb/tdb.pc.in
r414 r740 7 7 Description: A trivial database 8 8 Version: @PACKAGE_VERSION@ 9 Libs: -L${libdir} -ltdb9 Libs: @LIB_RPATH@ -L${libdir} -ltdb 10 10 Cflags: -I${includedir} 11 11 URL: http://tdb.samba.org/ -
vendor/current/lib/tdb/tools/tdbbackup.c
r414 r740 153 153 } 154 154 155 if (tdb_transaction_start(tdb_new) != 0) { 156 printf("Failed to start transaction on new tdb\n"); 155 /* lock the backup tdb so that nobody else can change it */ 156 if (tdb_lockall(tdb_new) != 0) { 157 printf("Failed to lock backup tdb\n"); 157 158 tdb_close(tdb); 158 159 tdb_close(tdb_new); … … 178 179 tdb_close(tdb); 179 180 180 if (tdb_transaction_commit(tdb_new) != 0) { 181 fprintf(stderr, "Failed to commit new tdb\n"); 182 tdb_close(tdb_new); 183 unlink(tmp_name); 184 free(tmp_name); 185 return 1; 181 /* copy done, unlock the backup tdb */ 182 tdb_unlockall(tdb_new); 183 184 #ifdef HAVE_FDATASYNC 185 if (fdatasync(tdb_fd(tdb_new)) != 0) { 186 #else 187 if (fsync(tdb_fd(tdb_new)) != 0) { 188 #endif 189 /* not fatal */ 190 fprintf(stderr, "failed to fsync backup file\n"); 186 191 } 187 192 -
vendor/current/lib/tdb/tools/tdbtest.c
r414 r740 216 216 } 217 217 218 static char *test_path(const char *filename) 219 { 220 const char *prefix = getenv("TEST_DATA_PREFIX"); 221 222 if (prefix) { 223 char *path = NULL; 224 int ret; 225 226 ret = asprintf(&path, "%s/%s", prefix, filename); 227 if (ret == -1) { 228 return NULL; 229 } 230 return path; 231 } 232 233 return strdup(filename); 234 } 235 218 236 int main(int argc, const char *argv[]) 219 237 { … … 221 239 int loops = 10000; 222 240 int num_entries; 223 char test_gdbm[] = "test.gdbm"; 224 225 unlink("test.gdbm"); 226 227 db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST, 241 char test_gdbm[1] = "test.gdbm"; 242 char *test_tdb; 243 244 test_gdbm[0] = test_path("test.gdbm"); 245 test_tdb = test_path("test.tdb"); 246 247 unlink(test_gdbm[0]); 248 249 db = tdb_open(test_tdb, 0, TDB_CLEAR_IF_FIRST, 228 250 O_RDWR | O_CREAT | O_TRUNC, 0600); 229 251 gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST, … … 262 284 gdbm_close(gdbm); 263 285 286 free(test_gdbm[0]); 287 free(test_tdb); 288 264 289 return 0; 265 290 } -
vendor/current/lib/tdb/tools/tdbtool.c
r414 r740 410 410 static void info_tdb(void) 411 411 { 412 int count;413 total_bytes = 0; 414 if ( (count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)412 char *summary = tdb_summary(tdb); 413 414 if (!summary) { 415 415 printf("Error = %s\n", tdb_errorstr(tdb)); 416 else 417 printf("%d records totalling %d bytes\n", count, total_bytes); 416 } else { 417 printf("%s", summary); 418 free(summary); 419 } 418 420 } 419 421 -
vendor/current/lib/tdb/tools/tdbtorture.c
r414 r740 31 31 static int error_count; 32 32 static int always_transaction = 0; 33 static int hash_size = 2; 34 static int loopnum; 35 static int count_pipe; 36 static struct tdb_logging_context log_ctx; 33 37 34 38 #ifdef PRINTF_ATTRIBUTE … … 49 53 fflush(stdout); 50 54 #if 0 51 {55 if (level != TDB_DEBUG_TRACE) { 52 56 char *ptr; 57 signal(SIGUSR1, SIG_IGN); 53 58 asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid()); 54 59 system(ptr); … … 212 217 static void usage(void) 213 218 { 214 printf("Usage: tdbtorture [-t] [- n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");219 printf("Usage: tdbtorture [-t] [-k] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n"); 215 220 exit(0); 216 221 } 217 222 218 int main(int argc, char * const *argv) 219 { 220 int i, seed = -1; 221 int num_procs = 3; 222 int num_loops = 5000; 223 int hash_size = 2; 224 int c; 225 extern char *optarg; 226 pid_t *pids; 227 228 struct tdb_logging_context log_ctx; 229 log_ctx.log_fn = tdb_log; 230 231 while ((c = getopt(argc, argv, "n:l:s:H:th")) != -1) { 232 switch (c) { 233 case 'n': 234 num_procs = strtol(optarg, NULL, 0); 235 break; 236 case 'l': 237 num_loops = strtol(optarg, NULL, 0); 238 break; 239 case 'H': 240 hash_size = strtol(optarg, NULL, 0); 241 break; 242 case 's': 243 seed = strtol(optarg, NULL, 0); 244 break; 245 case 't': 246 always_transaction = 1; 247 break; 248 default: 249 usage(); 250 } 251 } 252 253 unlink("torture.tdb"); 254 255 pids = (pid_t *)calloc(sizeof(pid_t), num_procs); 256 pids[0] = getpid(); 257 258 for (i=0;i<num_procs-1;i++) { 259 if ((pids[i+1]=fork()) == 0) break; 260 } 261 262 db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST, 223 static void send_count_and_suicide(int sig) 224 { 225 /* This ensures our successor can continue where we left off. */ 226 write(count_pipe, &loopnum, sizeof(loopnum)); 227 /* This gives a unique signature. */ 228 kill(getpid(), SIGUSR2); 229 } 230 231 static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start) 232 { 233 db = tdb_open_ex(filename, hash_size, TDB_DEFAULT, 263 234 O_RDWR | O_CREAT, 0600, &log_ctx, NULL); 264 235 if (!db) { … … 266 237 } 267 238 268 if (seed == -1) {269 seed = (getpid() + time(NULL)) & 0x7FFFFFFF;270 }271 272 if (i == 0) {273 printf("testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",274 num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");275 }276 277 239 srand(seed + i); 278 240 srandom(seed + i); 279 241 280 for (i=0;i<num_loops && error_count == 0;i++) { 242 /* Set global, then we're ready to handle being killed. */ 243 loopnum = start; 244 signal(SIGUSR1, send_count_and_suicide); 245 246 for (;loopnum<num_loops && error_count == 0;loopnum++) { 281 247 addrec_db(); 282 248 } … … 302 268 tdb_close(db); 303 269 304 if (getpid() != pids[0]) { 305 return error_count; 306 } 307 308 for (i=1;i<num_procs;i++) { 270 return (error_count < 100 ? error_count : 100); 271 } 272 273 static char *test_path(const char *filename) 274 { 275 const char *prefix = getenv("TEST_DATA_PREFIX"); 276 277 if (prefix) { 278 char *path = NULL; 279 int ret; 280 281 ret = asprintf(&path, "%s/%s", prefix, filename); 282 if (ret == -1) { 283 return NULL; 284 } 285 return path; 286 } 287 288 return strdup(filename); 289 } 290 291 int main(int argc, char * const *argv) 292 { 293 int i, seed = -1; 294 int num_loops = 5000; 295 int num_procs = 3; 296 int c, pfds[2]; 297 extern char *optarg; 298 pid_t *pids; 299 int kill_random = 0; 300 int *done; 301 char *test_tdb; 302 303 log_ctx.log_fn = tdb_log; 304 305 while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) { 306 switch (c) { 307 case 'n': 308 num_procs = strtol(optarg, NULL, 0); 309 break; 310 case 'l': 311 num_loops = strtol(optarg, NULL, 0); 312 break; 313 case 'H': 314 hash_size = strtol(optarg, NULL, 0); 315 break; 316 case 's': 317 seed = strtol(optarg, NULL, 0); 318 break; 319 case 't': 320 always_transaction = 1; 321 break; 322 case 'k': 323 kill_random = 1; 324 break; 325 default: 326 usage(); 327 } 328 } 329 330 test_tdb = test_path("torture.tdb"); 331 332 unlink(test_tdb); 333 334 if (seed == -1) { 335 seed = (getpid() + time(NULL)) & 0x7FFFFFFF; 336 } 337 338 if (num_procs == 1 && !kill_random) { 339 /* Don't fork for this case, makes debugging easier. */ 340 error_count = run_child(test_tdb, 0, seed, num_loops, 0); 341 goto done; 342 } 343 344 pids = (pid_t *)calloc(sizeof(pid_t), num_procs); 345 done = (int *)calloc(sizeof(int), num_procs); 346 347 if (pipe(pfds) != 0) { 348 perror("Creating pipe"); 349 exit(1); 350 } 351 count_pipe = pfds[1]; 352 353 for (i=0;i<num_procs;i++) { 354 if ((pids[i]=fork()) == 0) { 355 close(pfds[0]); 356 if (i == 0) { 357 printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n", 358 num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : ""); 359 } 360 exit(run_child(test_tdb, i, seed, num_loops, 0)); 361 } 362 } 363 364 while (num_procs) { 309 365 int status, j; 310 366 pid_t pid; 367 311 368 if (error_count != 0) { 312 369 /* try and stop the test on any failure */ 313 for (j= 1;j<num_procs;j++) {370 for (j=0;j<num_procs;j++) { 314 371 if (pids[j] != 0) { 315 372 kill(pids[j], SIGTERM); … … 317 374 } 318 375 } 319 pid = waitpid(-1, &status, 0); 376 377 pid = waitpid(-1, &status, kill_random ? WNOHANG : 0); 378 if (pid == 0) { 379 struct timeval tv; 380 381 /* Sleep for 1/10 second. */ 382 tv.tv_sec = 0; 383 tv.tv_usec = 100000; 384 select(0, NULL, NULL, NULL, &tv); 385 386 /* Kill someone. */ 387 kill(pids[random() % num_procs], SIGUSR1); 388 continue; 389 } 390 320 391 if (pid == -1) { 321 392 perror("failed to wait for child\n"); 322 393 exit(1); 323 394 } 324 for (j=1;j<num_procs;j++) { 395 396 for (j=0;j<num_procs;j++) { 325 397 if (pids[j] == pid) break; 326 398 } … … 329 401 exit(1); 330 402 } 331 if (WEXITSTATUS(status) != 0) { 332 printf("child %d exited with status %d\n", 333 (int)pid, WEXITSTATUS(status)); 403 if (WIFSIGNALED(status)) { 404 if (WTERMSIG(status) == SIGUSR2 405 || WTERMSIG(status) == SIGUSR1) { 406 /* SIGUSR2 means they wrote to pipe. */ 407 if (WTERMSIG(status) == SIGUSR2) { 408 read(pfds[0], &done[j], 409 sizeof(done[j])); 410 } 411 pids[j] = fork(); 412 if (pids[j] == 0) 413 exit(run_child(test_tdb, j, seed, 414 num_loops, done[j])); 415 printf("Restarting child %i for %u-%u\n", 416 j, done[j], num_loops); 417 continue; 418 } 419 printf("child %d exited with signal %d\n", 420 (int)pid, WTERMSIG(status)); 334 421 error_count++; 335 } 336 pids[j] = 0; 422 } else { 423 if (WEXITSTATUS(status) != 0) { 424 printf("child %d exited with status %d\n", 425 (int)pid, WEXITSTATUS(status)); 426 error_count++; 427 } 428 } 429 memmove(&pids[j], &pids[j+1], 430 (num_procs - j - 1)*sizeof(pids[0])); 431 num_procs--; 337 432 } 338 433 339 434 free(pids); 340 435 436 done: 341 437 if (error_count == 0) { 438 db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT, 439 O_RDWR, 0, &log_ctx, NULL); 440 if (!db) { 441 fatal("db open failed"); 442 } 443 if (tdb_check(db, NULL, NULL) == -1) { 444 printf("db check failed"); 445 exit(1); 446 } 447 tdb_close(db); 342 448 printf("OK\n"); 343 449 } 344 450 451 free(test_tdb); 345 452 return error_count; 346 453 } -
vendor/current/lib/tdr/tdr.c
r414 r740 164 164 TDR_PULL_NEED_BYTES(tdr, el_size*length); 165 165 166 if (!convert_string_talloc _convenience(ctx, tdr->iconv_convenience, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v), &ret, false)) {166 if (!convert_string_talloc(ctx, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v), &ret, false)) { 167 167 return NT_STATUS_INVALID_PARAMETER; 168 168 } … … 184 184 TDR_PUSH_NEED_BYTES(tdr, required); 185 185 186 if (!convert_string_convenience(tdr->iconv_convenience, CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->data.length, required, &ret, false)) { 186 ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->data.length, required, false); 187 if (ret == -1) { 187 188 return NT_STATUS_INVALID_PARAMETER; 188 189 } … … 344 345 } 345 346 346 struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx , struct smb_iconv_convenience *ic)347 struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx) 347 348 { 348 349 struct tdr_push *push = talloc_zero(mem_ctx, struct tdr_push); … … 351 352 return NULL; 352 353 353 push->iconv_convenience = talloc_reference(push, ic);354 355 354 return push; 356 355 } 357 356 358 struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx , struct smb_iconv_convenience *ic)357 struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx) 359 358 { 360 359 struct tdr_pull *pull = talloc_zero(mem_ctx, struct tdr_pull); … … 363 362 return NULL; 364 363 365 pull->iconv_convenience = talloc_reference(pull, ic);366 367 364 return pull; 368 365 } 369 366 370 NTSTATUS tdr_push_to_fd(int fd, struct smb_iconv_convenience *iconv_convenience,tdr_push_fn_t push_fn, const void *p)371 { 372 struct tdr_push *push = tdr_push_init(NULL , iconv_convenience);367 NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p) 368 { 369 struct tdr_push *push = tdr_push_init(NULL); 373 370 374 371 if (push == NULL) … … 391 388 } 392 389 393 void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)390 void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) 394 391 { 395 392 va_list ap; -
vendor/current/lib/tdr/tdr.h
r414 r740 3 3 TDR definitions 4 4 Copyright (C) Jelmer Vernooij 2005 5 5 6 6 This program is free software; you can redistribute it and/or modify 7 7 it under the terms of the GNU General Public License as published by 8 8 the Free Software Foundation; either version 3 of the License, or 9 9 (at your option) any later version. 10 10 11 11 This program is distributed in the hope that it will be useful, 12 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 14 GNU General Public License for more details. 15 15 16 16 You should have received a copy of the GNU General Public License 17 17 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 34 34 uint32_t offset; 35 35 int flags; 36 struct smb_iconv_convenience *iconv_convenience;37 36 }; 38 37 … … 40 39 DATA_BLOB data; 41 40 int flags; 42 struct smb_iconv_convenience *iconv_convenience;43 41 }; 44 42 … … 63 61 typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, TALLOC_CTX *, void *); 64 62 65 #include "../lib/tdr/tdr_proto.h" 63 NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size); 64 NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v); 65 NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v); 66 NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v); 67 NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v); 68 NTSTATUS tdr_pull_uint1632(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v); 69 NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v); 70 NTSTATUS tdr_push_uint1632(struct tdr_push *tdr, const uint16_t *v); 71 NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v); 72 NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v); 73 NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v); 74 NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v); 75 NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, charset_t chset); 76 NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, charset_t chset); 77 NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, charset_t chset); 78 79 NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v); 80 NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v); 81 82 NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t); 83 NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t); 84 NTSTATUS tdr_print_NTTIME(struct tdr_print *tdr, const char *name, NTTIME *t); 85 86 NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t); 87 NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t); 88 NTSTATUS tdr_print_time_t(struct tdr_print *tdr, const char *name, time_t *t); 89 90 NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB *r); 91 NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob); 92 NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob); 93 94 struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx); 95 struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx); 96 97 NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p); 98 void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) PRINTF_ATTRIBUTE(2,3); 66 99 67 100 #endif /* __TDR_H__ */ -
vendor/current/lib/tdr/testsuite.c
r414 r740 26 26 { 27 27 uint8_t v = 4; 28 struct tdr_push *tdr = tdr_push_init(tctx , global_iconv_convenience);28 struct tdr_push *tdr = tdr_push_init(tctx); 29 29 30 30 torture_assert_ntstatus_ok(tctx, tdr_push_uint8(tdr, &v), "push failed"); … … 38 38 uint8_t d = 2; 39 39 uint8_t l; 40 struct tdr_pull *tdr = tdr_pull_init(tctx , global_iconv_convenience);40 struct tdr_pull *tdr = tdr_pull_init(tctx); 41 41 tdr->data.data = &d; 42 42 tdr->data.length = 1; … … 53 53 { 54 54 uint16_t v = 0xF32; 55 struct tdr_push *tdr = tdr_push_init(tctx , global_iconv_convenience);55 struct tdr_push *tdr = tdr_push_init(tctx); 56 56 57 57 torture_assert_ntstatus_ok(tctx, tdr_push_uint16(tdr, &v), "push failed"); … … 66 66 uint8_t d[2] = { 782 & 0xFF, (782 & 0xFF00) / 0x100 }; 67 67 uint16_t l; 68 struct tdr_pull *tdr = tdr_pull_init(tctx , global_iconv_convenience);68 struct tdr_pull *tdr = tdr_pull_init(tctx); 69 69 tdr->data.data = d; 70 70 tdr->data.length = 2; … … 81 81 { 82 82 uint32_t v = 0x100F32; 83 struct tdr_push *tdr = tdr_push_init(tctx , global_iconv_convenience);83 struct tdr_push *tdr = tdr_push_init(tctx); 84 84 85 85 torture_assert_ntstatus_ok(tctx, tdr_push_uint32(tdr, &v), "push failed"); … … 96 96 uint8_t d[4] = { 782 & 0xFF, (782 & 0xFF00) / 0x100, 0, 0 }; 97 97 uint32_t l; 98 struct tdr_pull *tdr = tdr_pull_init(tctx , global_iconv_convenience);98 struct tdr_pull *tdr = tdr_pull_init(tctx); 99 99 tdr->data.data = d; 100 100 tdr->data.length = 4; … … 110 110 static bool test_pull_charset(struct torture_context *tctx) 111 111 { 112 struct tdr_pull *tdr = tdr_pull_init(tctx , global_iconv_convenience);112 struct tdr_pull *tdr = tdr_pull_init(tctx); 113 113 const char *l = NULL; 114 114 tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla"); … … 132 132 static bool test_pull_charset_empty(struct torture_context *tctx) 133 133 { 134 struct tdr_pull *tdr = tdr_pull_init(tctx , global_iconv_convenience);134 struct tdr_pull *tdr = tdr_pull_init(tctx); 135 135 const char *l = NULL; 136 136 tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla"); … … 151 151 { 152 152 const char *l = "bloe"; 153 struct tdr_push *tdr = tdr_push_init(tctx , global_iconv_convenience);153 struct tdr_push *tdr = tdr_push_init(tctx); 154 154 torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, 4, 1, CH_UTF8), 155 155 "push failed"); 156 156 torture_assert_int_equal(tctx, 4, tdr->data.length, "offset invalid"); 157 torture_assert(tctx, str cmp("bloe", (const char *)tdr->data.data) == 0, "right string push");157 torture_assert(tctx, strncmp("bloe", (const char *)tdr->data.data, 4) == 0, "right string push"); 158 158 159 159 torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, -1, 1, CH_UTF8), … … 167 167 struct torture_suite *torture_local_tdr(TALLOC_CTX *mem_ctx) 168 168 { 169 struct torture_suite *suite = torture_suite_create(mem_ctx, " TDR");169 struct torture_suite *suite = torture_suite_create(mem_ctx, "tdr"); 170 170 171 171 torture_suite_add_simple_test(suite, "pull_uint8", test_pull_uint8); -
vendor/current/lib/tevent/libtevent.m4
r414 r740 31 31 TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o" 32 32 TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" 33 TEVENT_OBJ="$TEVENT_OBJ tevent_poll.o" 33 34 34 35 AC_CHECK_HEADERS(sys/epoll.h) -
vendor/current/lib/tevent/testsuite.c
r618 r740 149 149 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) 150 150 { 151 struct torture_suite *suite = torture_suite_create(mem_ctx, " EVENT");151 struct torture_suite *suite = torture_suite_create(mem_ctx, "event"); 152 152 const char **list = event_backend_list(suite); 153 153 int i; -
vendor/current/lib/tevent/tevent.c
r427 r740 89 89 } 90 90 91 e = talloc( talloc_autofree_context(), struct tevent_ops_list);91 e = talloc(NULL, struct tevent_ops_list); 92 92 if (e == NULL) return false; 93 93 … … 105 105 { 106 106 talloc_free(tevent_default_backend); 107 tevent_default_backend = talloc_strdup(talloc_autofree_context(), 108 backend); 107 tevent_default_backend = talloc_strdup(NULL, backend); 109 108 } 110 109 … … 115 114 { 116 115 tevent_select_init(); 116 tevent_poll_init(); 117 117 tevent_standard_init(); 118 118 #ifdef HAVE_EPOLL … … 263 263 add a fd based event 264 264 return NULL on failure (memory allocation error) 265 266 if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when267 the returned fd_event context is freed268 265 */ 269 266 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, … … 617 614 return ev->ops->loop_wait(ev, location); 618 615 } 616 617 618 /* 619 re-initialise a tevent context. This leaves you with the same 620 event context, but all events are wiped and the structure is 621 re-initialised. This is most useful after a fork() 622 623 zero is returned on success, non-zero on failure 624 */ 625 int tevent_re_initialise(struct tevent_context *ev) 626 { 627 tevent_common_context_destructor(ev); 628 629 return ev->ops->context_init(ev); 630 } -
vendor/current/lib/tevent/tevent.h
r414 r740 41 41 struct tevent_signal; 42 42 43 /** 44 * @defgroup tevent The tevent API 45 * 46 * The tevent low-level API 47 * 48 * This API provides the public interface to manage events in the tevent 49 * mainloop. Functions are provided for managing low-level events such 50 * as timer events, fd events and signal handling. 51 * 52 * @{ 53 */ 54 43 55 /* event handler types */ 56 /** 57 * Called when a file descriptor monitored by tevent has 58 * data to be read or written on it. 59 */ 44 60 typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, 45 61 struct tevent_fd *fde, 46 62 uint16_t flags, 47 63 void *private_data); 64 65 /** 66 * Called when tevent is ceasing the monitoring of a file descriptor. 67 */ 48 68 typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev, 49 69 struct tevent_fd *fde, 50 70 int fd, 51 71 void *private_data); 72 73 /** 74 * Called when a tevent timer has fired. 75 */ 52 76 typedef void (*tevent_timer_handler_t)(struct tevent_context *ev, 53 77 struct tevent_timer *te, 54 78 struct timeval current_time, 55 79 void *private_data); 80 81 /** 82 * Called when a tevent immediate event is invoked. 83 */ 56 84 typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx, 57 85 struct tevent_immediate *im, 58 86 void *private_data); 87 88 /** 89 * Called after tevent detects the specified signal. 90 */ 59 91 typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, 60 92 struct tevent_signal *se, … … 64 96 void *private_data); 65 97 98 /** 99 * @brief Create a event_context structure. 100 * 101 * This must be the first events call, and all subsequent calls pass this 102 * event_context as the first element. Event handlers also receive this as 103 * their first argument. 104 * 105 * @param[in] mem_ctx The memory context to use. 106 * 107 * @return An allocated tevent context, NULL on error. 108 * 109 * @see tevent_context_init() 110 */ 66 111 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); 112 113 /** 114 * @brief Create a event_context structure and name it. 115 * 116 * This must be the first events call, and all subsequent calls pass this 117 * event_context as the first element. Event handlers also receive this as 118 * their first argument. 119 * 120 * @param[in] mem_ctx The memory context to use. 121 * 122 * @param[in] name The name for the tevent context. 123 * 124 * @return An allocated tevent context, NULL on error. 125 */ 67 126 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); 127 128 /** 129 * @brief List available backends. 130 * 131 * @param[in] mem_ctx The memory context to use. 132 * 133 * @return A string vector with a terminating NULL element, NULL 134 * on error. 135 */ 68 136 const char **tevent_backend_list(TALLOC_CTX *mem_ctx); 137 138 /** 139 * @brief Set the default tevent backent. 140 * 141 * @param[in] backend The name of the backend to set. 142 */ 69 143 void tevent_set_default_backend(const char *backend); 70 144 145 #ifdef DOXYGEN 146 /** 147 * @brief Add a file descriptor based event. 148 * 149 * @param[in] ev The event context to work on. 150 * 151 * @param[in] mem_ctx The talloc memory context to use. 152 * 153 * @param[in] fd The file descriptor to base the event on. 154 * 155 * @param[in] flags #TEVENT_FD_READ or #TEVENT_FD_WRITE 156 * 157 * @param[in] handler The callback handler for the event. 158 * 159 * @param[in] private_data The private data passed to the callback handler. 160 * 161 * @return The file descriptor based event, NULL on error. 162 * 163 * @note To cancel the monitoring of a file descriptor, call talloc_free() 164 * on the object returned by this function. 165 */ 166 struct tevent_fd *tevent_add_fd(struct tevent_context *ev, 167 TALLOC_CTX *mem_ctx, 168 int fd, 169 uint16_t flags, 170 tevent_fd_handler_t handler, 171 void *private_data); 172 #else 71 173 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, 72 174 TALLOC_CTX *mem_ctx, … … 80 182 _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ 81 183 #handler, __location__) 82 184 #endif 185 186 #ifdef DOXYGEN 187 /** 188 * @brief Add a timed event 189 * 190 * @param[in] ev The event context to work on. 191 * 192 * @param[in] mem_ctx The talloc memory context to use. 193 * 194 * @param[in] next_event Timeval specifying the absolute time to fire this 195 * event. This is not an offset. 196 * 197 * @param[in] handler The callback handler for the event. 198 * 199 * @param[in] private_data The private data passed to the callback handler. 200 * 201 * @return The newly-created timer event, or NULL on error. 202 * 203 * @note To cancel a timer event before it fires, call talloc_free() on the 204 * event returned from this function. This event is automatically 205 * talloc_free()-ed after its event handler files, if it hasn't been freed yet. 206 * 207 * @note Unlike some mainloops, tevent timers are one-time events. To set up 208 * a recurring event, it is necessary to call tevent_add_timer() again during 209 * the handler processing. 210 * 211 * @note Due to the internal mainloop processing, a timer set to run 212 * immediately will do so after any other pending timers fire, but before 213 * any further file descriptor or signal handling events fire. Callers should 214 * not rely on this behavior! 215 */ 216 struct tevent_timer *tevent_add_timer(struct tevent_context *ev, 217 TALLOC_CTX *mem_ctx, 218 struct timeval next_event, 219 tevent_timer_handler_t handler, 220 void *private_data); 221 #else 83 222 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, 84 223 TALLOC_CTX *mem_ctx, … … 91 230 _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ 92 231 #handler, __location__) 93 232 #endif 233 234 #ifdef DOXYGEN 235 /** 236 * Initialize an immediate event object 237 * 238 * This object can be used to trigger an event to occur immediately after 239 * returning from the current event (before any other event occurs) 240 * 241 * @param[in] mem_ctx The talloc memory context to use as the parent 242 * 243 * @return An empty tevent_immediate object. Use tevent_schedule_immediate 244 * to populate and use it. 245 * 246 * @note Available as of tevent 0.9.8 247 */ 248 struct tevent_immediate *tevent_create_immediate(TALLOC_CTX *mem_ctx); 249 #else 94 250 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, 95 251 const char *location); 96 252 #define tevent_create_immediate(mem_ctx) \ 97 253 _tevent_create_immediate(mem_ctx, __location__) 98 254 #endif 255 256 #ifdef DOXYGEN 257 258 /** 259 * Schedule an event for immediate execution. This event will occur 260 * immediately after returning from the current event (before any other 261 * event occurs) 262 * 263 * @param[in] im The tevent_immediate object to populate and use 264 * @param[in] ctx The tevent_context to run this event 265 * @param[in] handler The event handler to run when this event fires 266 * @param[in] private_data Data to pass to the event handler 267 */ 268 void tevent_schedule_immediate(struct tevent_immediate *im, 269 struct tevent_context *ctx, 270 tevent_immediate_handler_t handler, 271 void *private_data); 272 #else 99 273 void _tevent_schedule_immediate(struct tevent_immediate *im, 100 274 struct tevent_context *ctx, … … 106 280 _tevent_schedule_immediate(im, ctx, handler, private_data, \ 107 281 #handler, __location__); 108 282 #endif 283 284 #ifdef DOXYGEN 285 /** 286 * @brief Add a tevent signal handler 287 * 288 * tevent_add_signal() creates a new event for handling a signal the next 289 * time through the mainloop. It implements a very simple traditional signal 290 * handler whose only purpose is to add the handler event into the mainloop. 291 * 292 * @param[in] ev The event context to work on. 293 * 294 * @param[in] mem_ctx The talloc memory context to use. 295 * 296 * @param[in] signum The signal to trap 297 * 298 * @param[in] handler The callback handler for the signal. 299 * 300 * @param[in] sa_flags sigaction flags for this signal handler. 301 * 302 * @param[in] private_data The private data passed to the callback handler. 303 * 304 * @return The newly-created signal handler event, or NULL on error. 305 * 306 * @note To cancel a signal handler, call talloc_free() on the event returned 307 * from this function. 308 */ 309 struct tevent_signal *tevent_add_signal(struct tevent_context *ev, 310 TALLOC_CTX *mem_ctx, 311 int signum, 312 int sa_flags, 313 tevent_signal_handler_t handler, 314 void *private_data); 315 #else 109 316 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, 110 317 TALLOC_CTX *mem_ctx, … … 118 325 _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ 119 326 #handler, __location__) 120 327 #endif 328 329 #ifdef DOXYGEN 330 /** 331 * @brief Pass a single time through the mainloop 332 * 333 * This will process any appropriate signal, immediate, fd and timer events 334 * 335 * @param[in] ev The event context to process 336 * 337 * @return Zero on success, nonzero if an internal error occurred 338 */ 339 int tevent_loop_once(struct tevent_context *ev); 340 #else 121 341 int _tevent_loop_once(struct tevent_context *ev, const char *location); 122 342 #define tevent_loop_once(ev) \ 123 _tevent_loop_once(ev, __location__) \ 124 343 _tevent_loop_once(ev, __location__) 344 #endif 345 346 #ifdef DOXYGEN 347 /** 348 * @brief Run the mainloop 349 * 350 * The mainloop will run until there are no events remaining to be processed 351 * 352 * @param[in] ev The event context to process 353 * 354 * @return Zero if all events have been processed. Nonzero if an internal 355 * error occurred. 356 */ 357 int tevent_loop_wait(struct tevent_context *ev); 358 #else 125 359 int _tevent_loop_wait(struct tevent_context *ev, const char *location); 126 360 #define tevent_loop_wait(ev) \ 127 _tevent_loop_wait(ev, __location__) \ 128 361 _tevent_loop_wait(ev, __location__) 362 #endif 363 364 365 /** 366 * Assign a function to run when a tevent_fd is freed 367 * 368 * This function is a destructor for the tevent_fd. It does not automatically 369 * close the file descriptor. If this is the desired behavior, then it must be 370 * performed by the close_fn. 371 * 372 * @param[in] fde File descriptor event on which to set the destructor 373 * @param[in] close_fn Destructor to execute when fde is freed 374 */ 129 375 void tevent_fd_set_close_fn(struct tevent_fd *fde, 130 376 tevent_fd_close_fn_t close_fn); 377 378 /** 379 * Automatically close the file descriptor when the tevent_fd is freed 380 * 381 * This function calls close(fd) internally. 382 * 383 * @param[in] fde File descriptor event to auto-close 384 */ 131 385 void tevent_fd_set_auto_close(struct tevent_fd *fde); 386 387 /** 388 * Return the flags set on this file descriptor event 389 * 390 * @param[in] fde File descriptor event to query 391 * 392 * @return The flags set on the event. See #TEVENT_FD_READ and 393 * #TEVENT_FD_WRITE 394 */ 132 395 uint16_t tevent_fd_get_flags(struct tevent_fd *fde); 396 397 /** 398 * Set flags on a file descriptor event 399 * 400 * @param[in] fde File descriptor event to set 401 * @param[in] flags Flags to set on the event. See #TEVENT_FD_READ and 402 * #TEVENT_FD_WRITE 403 */ 133 404 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); 134 405 406 /** 407 * Query whether tevent supports signal handling 408 * 409 * @param[in] ev An initialized tevent context 410 * 411 * @return True if this platform and tevent context support signal handling 412 */ 135 413 bool tevent_signal_support(struct tevent_context *ev); 136 414 … … 138 416 139 417 /* bits for file descriptor event flags */ 418 419 /** 420 * Monitor a file descriptor for write availability 421 */ 140 422 #define TEVENT_FD_READ 1 423 /** 424 * Monitor a file descriptor for data to be read 425 */ 141 426 #define TEVENT_FD_WRITE 2 142 427 428 /** 429 * Convenience function for declaring a tevent_fd writable 430 */ 143 431 #define TEVENT_FD_WRITEABLE(fde) \ 144 432 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_WRITE) 433 434 /** 435 * Convenience function for declaring a tevent_fd readable 436 */ 145 437 #define TEVENT_FD_READABLE(fde) \ 146 438 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_READ) 147 439 440 /** 441 * Convenience function for declaring a tevent_fd non-writable 442 */ 148 443 #define TEVENT_FD_NOT_WRITEABLE(fde) \ 149 444 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_WRITE) 445 446 /** 447 * Convenience function for declaring a tevent_fd non-readable 448 */ 150 449 #define TEVENT_FD_NOT_READABLE(fde) \ 151 450 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) 152 451 153 /* DEBUG */ 452 /** 453 * Debug level of tevent 454 */ 154 455 enum tevent_debug_level { 155 456 TEVENT_DEBUG_FATAL, … … 159 460 }; 160 461 462 /** 463 * @brief The tevent debug callbac. 464 * 465 * @param[in] context The memory context to use. 466 * 467 * @param[in] level The debug level. 468 * 469 * @param[in] fmt The format string. 470 * 471 * @param[in] ap The arguments for the format string. 472 */ 473 typedef void (*tevent_debug_fn)(void *context, 474 enum tevent_debug_level level, 475 const char *fmt, 476 va_list ap) PRINTF_ATTRIBUTE(3,0); 477 478 /** 479 * Set destination for tevent debug messages 480 * 481 * @param[in] ev Event context to debug 482 * @param[in] debug Function to handle output printing 483 * @param[in] context The context to pass to the debug function. 484 * 485 * @return Always returns 0 as of version 0.9.8 486 * 487 * @note Default is to emit no debug messages 488 */ 161 489 int tevent_set_debug(struct tevent_context *ev, 162 void (*debug)(void *context, 163 enum tevent_debug_level level, 164 const char *fmt, 165 va_list ap) PRINTF_ATTRIBUTE(3,0), 490 tevent_debug_fn debug, 166 491 void *context); 492 493 /** 494 * Designate stderr for debug message output 495 * 496 * @param[in] ev Event context to debug 497 * 498 * @note This function will only output TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR 499 * and TEVENT_DEBUG_WARNING messages. For TEVENT_DEBUG_TRACE, please define a 500 * function for tevent_set_debug() 501 */ 167 502 int tevent_set_debug_stderr(struct tevent_context *ev); 168 503 169 504 /** 170 * An async request moves between the following 4 states: 505 * @} 506 */ 507 508 /** 509 * @defgroup tevent_request The tevent request functions. 510 * @ingroup tevent 511 * 512 * A tevent_req represents an asynchronous computation. 513 * 514 * The tevent_req group of API calls is the recommended way of 515 * programming async computations within tevent. In particular the 516 * file descriptor (tevent_add_fd) and timer (tevent_add_timed) events 517 * are considered too low-level to be used in larger computations. To 518 * read and write from and to sockets, Samba provides two calls on top 519 * of tevent_add_fd: read_packet_send/recv and writev_send/recv. These 520 * requests are much easier to compose than the low-level event 521 * handlers called from tevent_add_fd. 522 * 523 * A lot of the simplicity tevent_req has brought to the notoriously 524 * hairy async programming came via a set of conventions that every 525 * async computation programmed should follow. One central piece of 526 * these conventions is the naming of routines and variables. 527 * 528 * Every async computation needs a name (sensibly called "computation" 529 * down from here). From this name quite a few naming conventions are 530 * derived. 531 * 532 * Every computation that requires local state needs a 533 * @code 534 * struct computation_state { 535 * int local_var; 536 * }; 537 * @endcode 538 * Even if no local variables are required, such a state struct should 539 * be created containing a dummy variable. Quite a few helper 540 * functions and macros (for example tevent_req_create()) assume such 541 * a state struct. 542 * 543 * An async computation is started by a computation_send 544 * function. When it is finished, its result can be received by a 545 * computation_recv function. For an example how to set up an async 546 * computation, see the code example in the documentation for 547 * tevent_req_create() and tevent_req_post(). The prototypes for _send 548 * and _recv functions should follow some conventions: 549 * 550 * @code 551 * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, 552 * struct tevent_req *ev, 553 * ... further args); 554 * int computation_recv(struct tevent_req *req, ... further output args); 555 * @endcode 556 * 557 * The "int" result of computation_recv() depends on the result the 558 * sync version of the function would have, "int" is just an example 559 * here. 560 * 561 * Another important piece of the conventions is that the program flow 562 * is interrupted as little as possible. Because a blocking 563 * sub-computation requires that the flow needs to continue in a 564 * separate function that is the logical sequel of some computation, 565 * it should lexically follow sending off the blocking 566 * sub-computation. Setting the callback function via 567 * tevent_req_set_callback() requires referencing a function lexically 568 * below the call to tevent_req_set_callback(), forward declarations 569 * are required. A lot of the async computations thus begin with a 570 * sequence of declarations such as 571 * 572 * @code 573 * static void computation_step1_done(struct tevent_req *subreq); 574 * static void computation_step2_done(struct tevent_req *subreq); 575 * static void computation_step3_done(struct tevent_req *subreq); 576 * @endcode 577 * 578 * It really helps readability a lot to do these forward declarations, 579 * because the lexically sequential program flow makes the async 580 * computations almost as clear to read as a normal, sync program 581 * flow. 582 * 583 * It is up to the user of the async computation to talloc_free it 584 * after it has finished. If an async computation should be aborted, 585 * the tevent_req structure can be talloc_free'ed. After it has 586 * finished, it should talloc_free'ed by the API user. 587 * 588 * @{ 589 */ 590 591 /** 592 * An async request moves from TEVENT_REQ_INIT to 593 * TEVENT_REQ_IN_PROGRESS. All other states are valid after a request 594 * has finished. 171 595 */ 172 596 enum tevent_req_state { 173 597 /** 174 * we are creating the request598 * We are creating the request 175 599 */ 176 600 TEVENT_REQ_INIT, 177 601 /** 178 * we are waiting the request to complete602 * We are waiting the request to complete 179 603 */ 180 604 TEVENT_REQ_IN_PROGRESS, 181 605 /** 182 * the request is finished606 * The request is finished successfully 183 607 */ 184 608 TEVENT_REQ_DONE, 185 609 /** 186 * A user error has occured 610 * A user error has occurred. The user error has been 611 * indicated by tevent_req_error(), it can be retrieved via 612 * tevent_req_is_error(). 187 613 */ 188 614 TEVENT_REQ_USER_ERROR, 189 615 /** 190 * Request timed out 616 * Request timed out after the timeout set by tevent_req_set_endtime. 191 617 */ 192 618 TEVENT_REQ_TIMED_OUT, 193 619 /** 194 * No memory in between 620 * An internal allocation has failed, or tevent_req_nomem has 621 * been given a NULL pointer as the first argument. 195 622 */ 196 623 TEVENT_REQ_NO_MEMORY, 197 624 /** 198 * the request is already received by the caller 625 * The request has been received by the caller. No further 626 * action is valid. 199 627 */ 200 628 TEVENT_REQ_RECEIVED … … 203 631 /** 204 632 * @brief An async request 205 * 206 * This represents an async request being processed by callbacks via an event 207 * context. A user can issue for example a write request to a socket, giving 208 * an implementation function the fd, the buffer and the number of bytes to 209 * transfer. The function issuing the request will immediately return without 210 * blocking most likely without having sent anything. The API user then fills 211 * in req->async.fn and req->async.private_data, functions that are called 212 * when the request is finished. 213 * 214 * It is up to the user of the async request to talloc_free it after it has 215 * finished. This can happen while the completion function is called. 216 */ 217 633 */ 218 634 struct tevent_req; 219 635 220 typedef void (*tevent_req_fn)(struct tevent_req *); 221 636 /** 637 * @brief A tevent request callback function. 638 * 639 * @param[in] req The tevent async request which executed this callback. 640 */ 641 typedef void (*tevent_req_fn)(struct tevent_req *req); 642 643 /** 644 * @brief Set an async request callback. 645 * 646 * See the documentation of tevent_req_post() for an example how this 647 * is supposed to be used. 648 * 649 * @param[in] req The async request to set the callback. 650 * 651 * @param[in] fn The callback function to set. 652 * 653 * @param[in] pvt A pointer to private data to pass to the async request 654 * callback. 655 */ 222 656 void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); 657 658 #ifdef DOXYGEN 659 /** 660 * @brief Get the private data cast to the given type for a callback from 661 * a tevent request structure. 662 * 663 * @code 664 * static void computation_done(struct tevent_req *subreq) { 665 * struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); 666 * struct computation_state *state = tevent_req_data(req, struct computation_state); 667 * .... more things, eventually maybe call tevent_req_done(req); 668 * } 669 * @endcode 670 * 671 * @param[in] req The structure to get the callback data from. 672 * 673 * @param[in] type The type of the private callback data to get. 674 * 675 * @return The type casted private data set NULL if not set. 676 */ 677 void *tevent_req_callback_data(struct tevent_req *req, #type); 678 #else 223 679 void *_tevent_req_callback_data(struct tevent_req *req); 224 void *_tevent_req_data(struct tevent_req *req);225 226 680 #define tevent_req_callback_data(_req, _type) \ 227 681 talloc_get_type_abort(_tevent_req_callback_data(_req), _type) 682 #endif 683 684 #ifdef DOXYGEN 685 /** 686 * @brief Get the private data for a callback from a tevent request structure. 687 * 688 * @param[in] req The structure to get the callback data from. 689 * 690 * @param[in] req The structure to get the data from. 691 * 692 * @return The private data or NULL if not set. 693 */ 694 void *tevent_req_callback_data_void(struct tevent_req *req); 695 #else 228 696 #define tevent_req_callback_data_void(_req) \ 229 697 _tevent_req_callback_data(_req) 698 #endif 699 700 #ifdef DOXYGEN 701 /** 702 * @brief Get the private data from a tevent request structure. 703 * 704 * When the tevent_req has been created by tevent_req_create, the 705 * result of tevent_req_data() is the state variable created by 706 * tevent_req_create() as a child of the req. 707 * 708 * @param[in] req The structure to get the private data from. 709 * 710 * @param[in] type The type of the private data 711 * 712 * @return The private data or NULL if not set. 713 */ 714 void *tevent_req_data(struct tevent_req *req, #type); 715 #else 716 void *_tevent_req_data(struct tevent_req *req); 230 717 #define tevent_req_data(_req, _type) \ 231 718 talloc_get_type_abort(_tevent_req_data(_req), _type) 232 233 typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); 234 719 #endif 720 721 /** 722 * @brief The print function which can be set for a tevent async request. 723 * 724 * @param[in] req The tevent async request. 725 * 726 * @param[in] ctx A talloc memory context which can be uses to allocate 727 * memory. 728 * 729 * @return An allocated string buffer to print. 730 * 731 * Example: 732 * @code 733 * static char *my_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) 734 * { 735 * struct my_data *data = tevent_req_data(req, struct my_data); 736 * char *result; 737 * 738 * result = tevent_req_default_print(mem_ctx, req); 739 * if (result == NULL) { 740 * return NULL; 741 * } 742 * 743 * return talloc_asprintf_append_buffer(result, "foo=%d, bar=%d", 744 * data->foo, data->bar); 745 * } 746 * @endcode 747 */ 748 typedef char *(*tevent_req_print_fn)(struct tevent_req *req, TALLOC_CTX *ctx); 749 750 /** 751 * @brief This function sets a print function for the given request. 752 * 753 * This function can be used to setup a print function for the given request. 754 * This will be triggered if the tevent_req_print() function was 755 * called on the given request. 756 * 757 * @param[in] req The request to use. 758 * 759 * @param[in] fn A pointer to the print function 760 * 761 * @note This function should only be used for debugging. 762 */ 235 763 void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); 236 764 765 /** 766 * @brief The default print function for creating debug messages. 767 * 768 * The function should not be used by users of the async API, 769 * but custom print function can use it and append custom text 770 * to the string. 771 * 772 * @param[in] req The request to be printed. 773 * 774 * @param[in] mem_ctx The memory context for the result. 775 * 776 * @return Text representation of request. 777 * 778 */ 237 779 char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); 238 780 781 /** 782 * @brief Print an tevent_req structure in debug messages. 783 * 784 * This function should be used by callers of the async API. 785 * 786 * @param[in] mem_ctx The memory context for the result. 787 * 788 * @param[in] req The request to be printed. 789 * 790 * @return Text representation of request. 791 */ 239 792 char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); 240 793 241 typedef bool (*tevent_req_cancel_fn)(struct tevent_req *); 242 794 /** 795 * @brief A typedef for a cancel function for a tevent request. 796 * 797 * @param[in] req The tevent request calling this function. 798 * 799 * @return True if the request could be canceled, false if not. 800 */ 801 typedef bool (*tevent_req_cancel_fn)(struct tevent_req *req); 802 803 /** 804 * @brief This function sets a cancel function for the given tevent request. 805 * 806 * This function can be used to setup a cancel function for the given request. 807 * This will be triggered if the tevent_req_cancel() function was 808 * called on the given request. 809 * 810 * @param[in] req The request to use. 811 * 812 * @param[in] fn A pointer to the cancel function. 813 */ 243 814 void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); 244 815 816 #ifdef DOXYGEN 817 /** 818 * @brief Try to cancel the given tevent request. 819 * 820 * This function can be used to cancel the given request. 821 * 822 * It is only possible to cancel a request when the implementation 823 * has registered a cancel function via the tevent_req_set_cancel_fn(). 824 * 825 * @param[in] req The request to use. 826 * 827 * @return This function returns true is the request is cancelable, 828 * othererwise false is returned. 829 * 830 * @note Even if the function returns true, the caller need to wait 831 * for the function to complete normally. 832 * Only the _recv() function of the given request indicates 833 * if the request was really canceled. 834 */ 835 bool tevent_req_cancel(struct tevent_req *req); 836 #else 245 837 bool _tevent_req_cancel(struct tevent_req *req, const char *location); 246 838 #define tevent_req_cancel(req) \ 247 839 _tevent_req_cancel(req, __location__) 248 840 #endif 841 842 #ifdef DOXYGEN 843 /** 844 * @brief Create an async tevent request. 845 * 846 * The new async request will be initialized in state TEVENT_REQ_IN_PROGRESS. 847 * 848 * @code 849 * struct tevent_req *req; 850 * struct computation_state *state; 851 * req = tevent_req_create(mem_ctx, &state, struct computation_state); 852 * @endcode 853 * 854 * Tevent_req_create() creates the state variable as a talloc child of 855 * its result. The state variable should be used as the talloc parent 856 * for all temporary variables that are allocated during the async 857 * computation. This way, when the user of the async computation frees 858 * the request, the state as a talloc child will be free'd along with 859 * all the temporary variables hanging off the state. 860 * 861 * @param[in] mem_ctx The memory context for the result. 862 * @param[in] pstate Pointer to the private request state. 863 * @param[in] type The name of the request. 864 * 865 * @return A new async request. NULL on error. 866 */ 867 struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, 868 void **pstate, #type); 869 #else 249 870 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, 250 871 void *pstate, … … 256 877 _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ 257 878 #_type, __location__) 258 879 #endif 880 881 /** 882 * @brief Set a timeout for an async request. 883 * 884 * @param[in] req The request to set the timeout for. 885 * 886 * @param[in] ev The event context to use for the timer. 887 * 888 * @param[in] endtime The endtime of the request. 889 * 890 * @return True if succeeded, false if not. 891 */ 259 892 bool tevent_req_set_endtime(struct tevent_req *req, 260 893 struct tevent_context *ev, 261 894 struct timeval endtime); 262 895 896 #ifdef DOXYGEN 897 /** 898 * @brief Call the notify callback of the given tevent request manually. 899 * 900 * @param[in] req The tevent request to call the notify function from. 901 * 902 * @see tevent_req_set_callback() 903 */ 904 void tevent_req_notify_callback(struct tevent_req *req); 905 #else 263 906 void _tevent_req_notify_callback(struct tevent_req *req, const char *location); 264 907 #define tevent_req_notify_callback(req) \ 265 908 _tevent_req_notify_callback(req, __location__) 266 909 #endif 910 911 #ifdef DOXYGEN 912 /** 913 * @brief An async request has successfully finished. 914 * 915 * This function is to be used by implementors of async requests. When a 916 * request is successfully finished, this function calls the user's completion 917 * function. 918 * 919 * @param[in] req The finished request. 920 */ 921 void tevent_req_done(struct tevent_req *req); 922 #else 267 923 void _tevent_req_done(struct tevent_req *req, 268 924 const char *location); 269 925 #define tevent_req_done(req) \ 270 926 _tevent_req_done(req, __location__) 271 927 #endif 928 929 #ifdef DOXYGEN 930 /** 931 * @brief An async request has seen an error. 932 * 933 * This function is to be used by implementors of async requests. When a 934 * request can not successfully completed, the implementation should call this 935 * function with the appropriate status code. 936 * 937 * If error is 0 the function returns false and does nothing more. 938 * 939 * @param[in] req The request with an error. 940 * 941 * @param[in] error The error code. 942 * 943 * @return On success true is returned, false if error is 0. 944 * 945 * @code 946 * int error = first_function(); 947 * if (tevent_req_error(req, error)) { 948 * return; 949 * } 950 * 951 * error = second_function(); 952 * if (tevent_req_error(req, error)) { 953 * return; 954 * } 955 * 956 * tevent_req_done(req); 957 * return; 958 * @endcode 959 */ 960 bool tevent_req_error(struct tevent_req *req, 961 uint64_t error); 962 #else 272 963 bool _tevent_req_error(struct tevent_req *req, 273 964 uint64_t error, … … 275 966 #define tevent_req_error(req, error) \ 276 967 _tevent_req_error(req, error, __location__) 277 968 #endif 969 970 #ifdef DOXYGEN 971 /** 972 * @brief Helper function for nomem check. 973 * 974 * Convenience helper to easily check alloc failure within a callback 975 * implementing the next step of an async request. 976 * 977 * @param[in] p The pointer to be checked. 978 * 979 * @param[in] req The request being processed. 980 * 981 * @code 982 * p = talloc(mem_ctx, bla); 983 * if (tevent_req_nomem(p, req)) { 984 * return; 985 * } 986 * @endcode 987 */ 988 bool tevent_req_nomem(const void *p, 989 struct tevent_req *req); 990 #else 278 991 bool _tevent_req_nomem(const void *p, 279 992 struct tevent_req *req, … … 281 994 #define tevent_req_nomem(p, req) \ 282 995 _tevent_req_nomem(p, req, __location__) 283 996 #endif 997 998 /** 999 * @brief Finish a request before the caller had the change to set the callback. 1000 * 1001 * An implementation of an async request might find that it can either finish 1002 * the request without waiting for an external event, or it can not even start 1003 * the engine. To present the illusion of a callback to the user of the API, 1004 * the implementation can call this helper function which triggers an 1005 * immediate timed event. This way the caller can use the same calling 1006 * conventions, independent of whether the request was actually deferred. 1007 * 1008 * @code 1009 * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, 1010 * struct tevent_context *ev) 1011 * { 1012 * struct tevent_req *req, *subreq; 1013 * struct computation_state *state; 1014 * req = tevent_req_create(mem_ctx, &state, struct computation_state); 1015 * if (req == NULL) { 1016 * return NULL; 1017 * } 1018 * subreq = subcomputation_send(state, ev); 1019 * if (tevent_req_nomem(subreq, req)) { 1020 * return tevent_req_post(req, ev); 1021 * } 1022 * tevent_req_set_callback(subreq, computation_done, req); 1023 * return req; 1024 * } 1025 * @endcode 1026 * 1027 * @param[in] req The finished request. 1028 * 1029 * @param[in] ev The tevent_context for the timed event. 1030 * 1031 * @return The given request will be returned. 1032 */ 284 1033 struct tevent_req *tevent_req_post(struct tevent_req *req, 285 1034 struct tevent_context *ev); 286 1035 1036 /** 1037 * @brief Check if the given request is still in progress. 1038 * 1039 * It is typically used by sync wrapper functions. 1040 * 1041 * @param[in] req The request to poll. 1042 * 1043 * @return The boolean form of "is in progress". 1044 */ 287 1045 bool tevent_req_is_in_progress(struct tevent_req *req); 288 1046 1047 /** 1048 * @brief Actively poll for the given request to finish. 1049 * 1050 * This function is typically used by sync wrapper functions. 1051 * 1052 * @param[in] req The request to poll. 1053 * 1054 * @param[in] ev The tevent_context to be used. 1055 * 1056 * @return On success true is returned. If a critical error has 1057 * happened in the tevent loop layer false is returned. 1058 * This is not the return value of the given request! 1059 * 1060 * @note This should only be used if the given tevent context was created by the 1061 * caller, to avoid event loop nesting. 1062 * 1063 * @code 1064 * req = tstream_writev_queue_send(mem_ctx, 1065 * ev_ctx, 1066 * tstream, 1067 * send_queue, 1068 * iov, 2); 1069 * ok = tevent_req_poll(req, tctx->ev); 1070 * rc = tstream_writev_queue_recv(req, &sys_errno); 1071 * TALLOC_FREE(req); 1072 * @endcode 1073 */ 289 1074 bool tevent_req_poll(struct tevent_req *req, 290 1075 struct tevent_context *ev); 291 1076 1077 /** 1078 * @brief Get the tevent request state and the actual error set by 1079 * tevent_req_error. 1080 * 1081 * @code 1082 * int computation_recv(struct tevent_req *req, uint64_t *perr) 1083 * { 1084 * enum tevent_req_state state; 1085 * uint64_t err; 1086 * if (tevent_req_is_error(req, &state, &err)) { 1087 * *perr = err; 1088 * return -1; 1089 * } 1090 * return 0; 1091 * } 1092 * @endcode 1093 * 1094 * @param[in] req The tevent request to get the error from. 1095 * 1096 * @param[out] state A pointer to store the tevent request error state. 1097 * 1098 * @param[out] error A pointer to store the error set by tevent_req_error(). 1099 * 1100 * @return True if the function could set error and state, false 1101 * otherwise. 1102 * 1103 * @see tevent_req_error() 1104 */ 292 1105 bool tevent_req_is_error(struct tevent_req *req, 293 1106 enum tevent_req_state *state, 294 1107 uint64_t *error); 295 1108 1109 /** 1110 * @brief Use as the last action of a _recv() function. 1111 * 1112 * This function destroys the attached private data. 1113 * 1114 * @param[in] req The finished request. 1115 */ 296 1116 void tevent_req_received(struct tevent_req *req); 297 1117 1118 /** 1119 * @brief Create a tevent subrequest at a given time. 1120 * 1121 * The idea is that always the same syntax for tevent requests. 1122 * 1123 * @param[in] mem_ctx The talloc memory context to use. 1124 * 1125 * @param[in] ev The event handle to setup the request. 1126 * 1127 * @param[in] wakeup_time The time to wakeup and execute the request. 1128 * 1129 * @return The new subrequest, NULL on error. 1130 * 1131 * Example: 1132 * @code 1133 * static void my_callback_wakeup_done(tevent_req *subreq) 1134 * { 1135 * struct tevent_req *req = tevent_req_callback_data(subreq, 1136 * struct tevent_req); 1137 * bool ok; 1138 * 1139 * ok = tevent_wakeup_recv(subreq); 1140 * TALLOC_FREE(subreq); 1141 * if (!ok) { 1142 * tevent_req_error(req, -1); 1143 * return; 1144 * } 1145 * ... 1146 * } 1147 * @endcode 1148 * 1149 * @code 1150 * subreq = tevent_wakeup_send(mem_ctx, ev, wakeup_time); 1151 * if (tevent_req_nomem(subreq, req)) { 1152 * return false; 1153 * } 1154 * tevent_set_callback(subreq, my_callback_wakeup_done, req); 1155 * @endcode 1156 * 1157 * @see tevent_wakeup_recv() 1158 */ 298 1159 struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, 299 1160 struct tevent_context *ev, 300 1161 struct timeval wakeup_time); 1162 1163 /** 1164 * @brief Check if the wakeup has been correctly executed. 1165 * 1166 * This function needs to be called in the callback function set after calling 1167 * tevent_wakeup_send(). 1168 * 1169 * @param[in] req The tevent request to check. 1170 * 1171 * @return True on success, false otherwise. 1172 * 1173 * @see tevent_wakeup_recv() 1174 */ 301 1175 bool tevent_wakeup_recv(struct tevent_req *req); 302 1176 1177 /* @} */ 1178 1179 /** 1180 * @defgroup tevent_helpers The tevent helper functiions 1181 * @ingroup tevent 1182 * 1183 * @todo description 1184 * 1185 * @{ 1186 */ 1187 1188 /** 1189 * @brief Compare two timeval values. 1190 * 1191 * @param[in] tv1 The first timeval value to compare. 1192 * 1193 * @param[in] tv2 The second timeval value to compare. 1194 * 1195 * @return 0 if they are equal. 1196 * 1 if the first time is greater than the second. 1197 * -1 if the first time is smaller than the second. 1198 */ 303 1199 int tevent_timeval_compare(const struct timeval *tv1, 304 1200 const struct timeval *tv2); 305 1201 1202 /** 1203 * @brief Get a zero timval value. 1204 * 1205 * @return A zero timval value. 1206 */ 306 1207 struct timeval tevent_timeval_zero(void); 307 1208 1209 /** 1210 * @brief Get a timeval value for the current time. 1211 * 1212 * @return A timval value with the current time. 1213 */ 308 1214 struct timeval tevent_timeval_current(void); 309 1215 1216 /** 1217 * @brief Get a timeval structure with the given values. 1218 * 1219 * @param[in] secs The seconds to set. 1220 * 1221 * @param[in] usecs The milliseconds to set. 1222 * 1223 * @return A timeval structure with the given values. 1224 */ 310 1225 struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs); 311 1226 1227 /** 1228 * @brief Get the difference between two timeval values. 1229 * 1230 * @param[in] tv1 The first timeval. 1231 * 1232 * @param[in] tv2 The second timeval. 1233 * 1234 * @return A timeval structure with the difference between the 1235 * first and the second value. 1236 */ 312 1237 struct timeval tevent_timeval_until(const struct timeval *tv1, 313 1238 const struct timeval *tv2); 314 1239 1240 /** 1241 * @brief Check if a given timeval structure is zero. 1242 * 1243 * @param[in] tv The timeval to check if it is zero. 1244 * 1245 * @return True if it is zero, false otherwise. 1246 */ 315 1247 bool tevent_timeval_is_zero(const struct timeval *tv); 316 1248 1249 /** 1250 * @brief Add the given amount of time to a timeval structure. 1251 * 1252 * @param[in] tv The timeval structure to add the time. 1253 * 1254 * @param[in] secs The seconds to add to the timeval. 1255 * 1256 * @param[in] usecs The milliseconds to add to the timeval. 1257 * 1258 * @return The timeval structure with the new time. 1259 */ 317 1260 struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, 318 1261 uint32_t usecs); 319 1262 1263 /** 1264 * @brief Get a timeval in the future with a specified offset from now. 1265 * 1266 * @param[in] secs The seconds of the offset from now. 1267 * 1268 * @param[in] usecs The milliseconds of the offset from now. 1269 * 1270 * @return A timval with the given offset in the future. 1271 */ 320 1272 struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); 321 1273 1274 /* @} */ 1275 1276 1277 /** 1278 * @defgroup tevent_queue The tevent queue functions 1279 * @ingroup tevent 1280 * 1281 * A tevent_queue is used to queue up async requests that must be 1282 * serialized. For example writing buffers into a socket must be 1283 * serialized. Writing a large lump of data into a socket can require 1284 * multiple write(2) or send(2) system calls. If more than one async 1285 * request is outstanding to write large buffers into a socket, every 1286 * request must individually be completed before the next one begins, 1287 * even if multiple syscalls are required. 1288 * 1289 * Take a look at @ref tevent_queue_tutorial for more details. 1290 * @{ 1291 */ 1292 322 1293 struct tevent_queue; 323 1294 1295 #ifdef DOXYGEN 1296 /** 1297 * @brief Create and start a tevent queue. 1298 * 1299 * @param[in] mem_ctx The talloc memory context to allocate the queue. 1300 * 1301 * @param[in] name The name to use to identify the queue. 1302 * 1303 * @return An allocated tevent queue on success, NULL on error. 1304 * 1305 * @see tevent_start() 1306 * @see tevent_stop() 1307 */ 1308 struct tevent_queue *tevent_queue_create(TALLOC_CTX *mem_ctx, 1309 const char *name); 1310 #else 324 1311 struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, 325 1312 const char *name, … … 328 1315 #define tevent_queue_create(_mem_ctx, _name) \ 329 1316 _tevent_queue_create((_mem_ctx), (_name), __location__) 330 1317 #endif 1318 1319 /** 1320 * @brief A callback trigger function run by the queue. 1321 * 1322 * @param[in] req The tevent request the trigger function is executed on. 1323 * 1324 * @param[in] private_data The private data pointer specified by 1325 * tevent_queue_add(). 1326 * 1327 * @see tevent_queue_add() 1328 */ 331 1329 typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, 332 1330 void *private_data); 1331 1332 /** 1333 * @brief Add a tevent request to the queue. 1334 * 1335 * @param[in] queue The queue to add the request. 1336 * 1337 * @param[in] ev The event handle to use for the request. 1338 * 1339 * @param[in] req The tevent request to add to the queue. 1340 * 1341 * @param[in] trigger The function triggered by the queue when the request 1342 * is called. 1343 * 1344 * @param[in] private_data The private data passed to the trigger function. 1345 * 1346 * @return True if the request has been successfully added, false 1347 * otherwise. 1348 */ 333 1349 bool tevent_queue_add(struct tevent_queue *queue, 334 1350 struct tevent_context *ev, … … 336 1352 tevent_queue_trigger_fn_t trigger, 337 1353 void *private_data); 1354 1355 /** 1356 * @brief Start a tevent queue. 1357 * 1358 * The queue is started by default. 1359 * 1360 * @param[in] queue The queue to start. 1361 */ 338 1362 void tevent_queue_start(struct tevent_queue *queue); 1363 1364 /** 1365 * @brief Stop a tevent queue. 1366 * 1367 * The queue is started by default. 1368 * 1369 * @param[in] queue The queue to stop. 1370 */ 339 1371 void tevent_queue_stop(struct tevent_queue *queue); 340 1372 1373 /** 1374 * @brief Get the length of the queue. 1375 * 1376 * @param[in] queue The queue to get the length from. 1377 * 1378 * @return The number of elements. 1379 */ 341 1380 size_t tevent_queue_length(struct tevent_queue *queue); 342 1381 … … 367 1406 #endif 368 1407 369 370 /** 1408 int tevent_re_initialise(struct tevent_context *ev); 1409 1410 /* @} */ 1411 1412 /** 1413 * @defgroup tevent_ops The tevent operation functions 1414 * @ingroup tevent 1415 * 371 1416 * The following structure and registration functions are exclusively 372 1417 * needed for people writing and pluggin a different event engine. 373 1418 * There is nothing useful for normal tevent user in here. 1419 * @{ 374 1420 */ 375 1421 … … 424 1470 bool tevent_register_backend(const char *name, const struct tevent_ops *ops); 425 1471 426 427 /** 1472 /* @} */ 1473 1474 /** 1475 * @defgroup tevent_compat The tevent compatibility functions 1476 * @ingroup tevent 1477 * 428 1478 * The following definitions are usueful only for compatibility with the 429 1479 * implementation originally developed within the samba4 code and will be 430 1480 * soon removed. Please NEVER use in new code. 1481 * 1482 * @todo Ignore it? 1483 * 1484 * @{ 431 1485 */ 432 1486 … … 505 1559 #endif /* TEVENT_COMPAT_DEFINES */ 506 1560 1561 /* @} */ 1562 507 1563 #endif /* __TEVENT_H__ */ -
vendor/current/lib/tevent/tevent.pc.in
r414 r740 9 9 Requires: talloc 10 10 Libs: -L${libdir} -ltevent 11 Cflags: -I${includedir}11 Cflags: @LIB_RPATH@ -I${includedir} 12 12 URL: http://samba.org/ -
vendor/current/lib/tevent/tevent_epoll.c
r414 r740 43 43 44 44 /* 45 called when a epoll call fails, and we should fallback 46 to using select 45 called when a epoll call fails 47 46 */ 48 47 static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason) … … 438 437 }; 439 438 440 bool tevent_epoll_init(void)439 _PRIVATE_ bool tevent_epoll_init(void) 441 440 { 442 441 return tevent_register_backend("epoll", &epoll_event_ops); -
vendor/current/lib/tevent/tevent_fd.c
r414 r740 52 52 struct tevent_fd *fde; 53 53 54 /* tevent will crash later on select() if we save 55 * a negative file descriptor. Better to fail here 56 * so that consumers will be able to debug it 57 */ 58 if (fd < 0) return NULL; 59 54 60 fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); 55 61 if (!fde) return NULL; -
vendor/current/lib/tevent/tevent_internal.h
r427 r740 163 163 const char *location; 164 164 /* this is private for the events_ops implementation */ 165 uint 16_t additional_flags;165 uint64_t additional_flags; 166 166 void *additional_data; 167 167 }; … … 304 304 bool tevent_standard_init(void); 305 305 bool tevent_select_init(void); 306 bool tevent_poll_init(void); 306 307 #ifdef HAVE_EPOLL 307 308 bool tevent_epoll_init(void); -
vendor/current/lib/tevent/tevent_liboop.c
r414 r740 32 32 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 33 33 34 NOTE: this code compiles fine, but is complet ly *UNTESTED*35 and is only commit ed asexample34 NOTE: this code compiles fine, but is completely *UNTESTED* 35 and is only committed as an example 36 36 37 37 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -
vendor/current/lib/tevent/tevent_req.c
r414 r740 27 27 #include "tevent_internal.h" 28 28 #include "tevent_util.h" 29 30 /**31 * @brief The default print function for creating debug messages32 * @param[in] req The request to be printed33 * @param[in] mem_ctx The memory context for the result34 * @retval Text representation of req35 *36 * The function should not be used by users of the asynx API,37 * but custom print function can use it and append custom text38 * to the string.39 */40 29 41 30 char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) … … 54 43 } 55 44 56 /**57 * @brief Print an tevent_req structure in debug messages58 * @param[in] mem_ctx The memory context for the result59 * @param[in] req The request to be printed60 * @retval Text representation of req61 *62 * This function should be used by callers of the async API63 */64 65 45 char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) 66 46 { … … 71 51 return req->private_print(req, mem_ctx); 72 52 } 73 74 /**75 * @brief Create an async request76 * @param[in] mem_ctx The memory context for the result77 * @param[in] ev The event context this async request will be driven by78 * @retval A new async request79 *80 * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS81 */82 53 83 54 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, … … 134 105 } 135 106 136 /**137 * @brief An async request has successfully finished138 * @param[in] req The finished request139 *140 * tevent_req_done is to be used by implementors of async requests. When a141 * request is successfully finished, this function calls the user's completion142 * function.143 */144 145 107 void _tevent_req_done(struct tevent_req *req, 146 108 const char *location) … … 148 110 tevent_req_finish(req, TEVENT_REQ_DONE, location); 149 111 } 150 151 /**152 * @brief An async request has seen an error153 * @param[in] req The request with an error154 * @param[in] error The error code155 *156 * tevent_req_done is to be used by implementors of async requests. When a157 * request can not successfully completed, the implementation should call this158 * function with the appropriate status code.159 *160 * If error is 0 the function returns false and does nothing more.161 *162 * Call pattern would be163 * \code164 * int error = first_function();165 * if (tevent_req_error(req, error)) {166 * return;167 * }168 *169 * error = second_function();170 * if (tevent_req_error(req, error)) {171 * return;172 * }173 *174 * tevent_req_done(req);175 * return;176 * \endcode177 */178 112 179 113 bool _tevent_req_error(struct tevent_req *req, … … 190 124 } 191 125 192 /**193 * @brief Helper function for nomem check194 * @param[in] p The pointer to be checked195 * @param[in] req The request being processed196 *197 * Convenience helper to easily check alloc failure within a callback198 * implementing the next step of an async request.199 *200 * Call pattern would be201 * \code202 * p = talloc(mem_ctx, bla);203 * if (tevent_req_nomem(p, req)) {204 * return;205 * }206 * \endcode207 */208 209 126 bool _tevent_req_nomem(const void *p, 210 127 struct tevent_req *req, … … 219 136 220 137 /** 221 * @brief Immediate event callback 222 * @param[in] ev Event context 223 * @param[in] im The immediate event 224 * @param[in] priv The async request to be finished 138 * @internal 139 * 140 * @brief Immediate event callback. 141 * 142 * @param[in] ev The event context to use. 143 * 144 * @param[in] im The immediate event. 145 * 146 * @param[in] priv The async request to be finished. 225 147 */ 226 148 static void tevent_req_trigger(struct tevent_context *ev, … … 235 157 } 236 158 237 /**238 * @brief Finish a request before the caller had the change to set the callback239 * @param[in] req The finished request240 * @param[in] ev The tevent_context for the timed event241 * @retval req will be returned242 *243 * An implementation of an async request might find that it can either finish244 * the request without waiting for an external event, or it can't even start245 * the engine. To present the illusion of a callback to the user of the API,246 * the implementation can call this helper function which triggers an247 * immediate timed event. This way the caller can use the same calling248 * conventions, independent of whether the request was actually deferred.249 */250 251 159 struct tevent_req *tevent_req_post(struct tevent_req *req, 252 160 struct tevent_context *ev) … … 257 165 } 258 166 259 /**260 * @brief This function destroys the attached private data261 * @param[in] req The request to poll262 * @retval The boolean form of "is in progress".263 *264 * This function can be used to ask if the given request265 * is still in progress.266 *267 * This function is typically used by sync wrapper functions.268 */269 167 bool tevent_req_is_in_progress(struct tevent_req *req) 270 168 { … … 276 174 } 277 175 278 /**279 * @brief This function destroys the attached private data280 * @param[in] req The finished request281 *282 * This function can be called as last action of a _recv()283 * function, it destroys the data attached to the tevent_req.284 */285 176 void tevent_req_received(struct tevent_req *req) 286 177 { … … 294 185 } 295 186 296 /**297 * @brief This function destroys the attached private data298 * @param[in] req The request to poll299 * @param[in] ev The tevent_context to be used300 * @retval If a critical error has happened in the301 * tevent loop layer false is returned.302 * Otherwise true is returned.303 * This is not the return value of the given request!304 *305 * This function can be used to actively poll for the306 * given request to finish.307 *308 * Note: this should only be used if the given tevent context309 * was created by the caller, to avoid event loop nesting.310 *311 * This function is typically used by sync wrapper functions.312 */313 187 bool tevent_req_poll(struct tevent_req *req, 314 188 struct tevent_context *ev) … … 384 258 } 385 259 386 /**387 * @brief This function sets a print function for the given request388 * @param[in] req The given request389 * @param[in] fn A pointer to the print function390 *391 * This function can be used to setup a print function for the given request.392 * This will be triggered if the tevent_req_print() function was393 * called on the given request.394 *395 * Note: this function should only be used for debugging.396 */397 260 void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) 398 261 { … … 400 263 } 401 264 402 /**403 * @brief This function sets a cancel function for the given request404 * @param[in] req The given request405 * @param[in] fn A pointer to the cancel function406 *407 * This function can be used to setup a cancel function for the given request.408 * This will be triggered if the tevent_req_cancel() function was409 * called on the given request.410 *411 */412 265 void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn) 413 266 { … … 415 268 } 416 269 417 /**418 * @brief This function tries to cancel the given request419 * @param[in] req The given request420 * @param[in] location Automaticly filled with the __location__ macro421 * via the tevent_req_cancel() macro. This is for debugging422 * only!423 * @retval This function returns true is the request is cancelable.424 * Otherwise false is returned.425 *426 * This function can be used to cancel the given request.427 *428 * It is only possible to cancel a request when the implementation429 * has registered a cancel function via the tevent_req_set_cancel_fn().430 *431 * Note: Even if the function returns true, the caller need to wait432 * for the function to complete normally.433 * Only the _recv() function of the given request indicates434 * if the request was really canceled.435 */436 270 bool _tevent_req_cancel(struct tevent_req *req, const char *location) 437 271 { -
vendor/current/lib/tevent/tevent_select.c
r591 r740 122 122 if (!fde) return NULL; 123 123 124 if (fde->fd > select_ev->maxfd) { 124 if ((select_ev->maxfd != EVENT_INVALID_MAXFD) 125 && (fde->fd > select_ev->maxfd)) { 125 126 select_ev->maxfd = fde->fd; 126 127 } … … 252 253 }; 253 254 254 bool tevent_select_init(void)255 _PRIVATE_ bool tevent_select_init(void) 255 256 { 256 257 return tevent_register_backend("select", &select_event_ops); -
vendor/current/lib/tevent/tevent_signal.c
r618 r740 211 211 multiple event contexts */ 212 212 if (sig_state == NULL) { 213 sig_state = talloc_zero( talloc_autofree_context(), struct tevent_sig_state);213 sig_state = talloc_zero(NULL, struct tevent_sig_state); 214 214 if (sig_state == NULL) { 215 215 return NULL; -
vendor/current/lib/tevent/tevent_standard.c
r591 r740 462 462 return -1; 463 463 } 464 465 464 if (fde->flags & TEVENT_FD_READ) { 466 465 FD_SET(fde->fd, &r_fds); … … 511 510 if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ; 512 511 if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE; 513 if (flags ) {512 if (flags & fde->flags) { 514 513 fde->handler(std_ev->ev, fde, flags, fde->private_data); 515 514 break; … … 568 567 569 568 570 bool tevent_standard_init(void)569 _PRIVATE_ bool tevent_standard_init(void) 571 570 { 572 571 return tevent_register_backend("standard", &std_event_ops); -
vendor/current/lib/tevent/tevent_timed.c
r414 r740 198 198 do a single event loop using the events defined in ev 199 199 200 return the delay until lthe next timed event,200 return the delay until the next timed event, 201 201 or zero if a timed event was triggered 202 202 */ … … 209 209 /* have a default tick time of 30 seconds. This guarantees 210 210 that code that uses its own timeout checking will be 211 able to procee ed eventually */211 able to proceed eventually */ 212 212 return tevent_timeval_set(30, 0); 213 213 } -
vendor/current/lib/tevent/tevent_util.h
r414 r740 2 2 Unix SMB/CIFS implementation. 3 3 4 Copyright (C) Andrew Tridgell 1998-20 054 Copyright (C) Andrew Tridgell 1998-2010 5 5 Copyright (C) Jelmer Vernooij 2005 6 6 … … 25 25 #define _DLINKLIST_H 26 26 27 /* 28 February 2010 - changed list format to have a prev pointer from the 29 list head. This makes DLIST_ADD_END() O(1) even though we only have 30 one list pointer. 27 31 28 /* hook into the front of the list */ 32 The scheme is as follows: 33 34 1) with no entries in the list: 35 list_head == NULL 36 37 2) with 1 entry in the list: 38 list_head->next == NULL 39 list_head->prev == list_head 40 41 3) with 2 entries in the list: 42 list_head->next == element2 43 list_head->prev == element2 44 element2->prev == list_head 45 element2->next == NULL 46 47 4) with N entries in the list: 48 list_head->next == element2 49 list_head->prev == elementN 50 elementN->prev == element{N-1} 51 elementN->next == NULL 52 53 This allows us to find the tail of the list by using 54 list_head->prev, which means we can add to the end of the list in 55 O(1) time 56 57 58 Note that the 'type' arguments below are no longer needed, but 59 are kept for now to prevent an incompatible argument change 60 */ 61 62 63 /* 64 add an element at the front of a list 65 */ 29 66 #define DLIST_ADD(list, p) \ 30 67 do { \ 31 68 if (!(list)) { \ 32 ( list) = (p);\33 (p)->next = (p)->prev =NULL; \69 (p)->prev = (list) = (p); \ 70 (p)->next = NULL; \ 34 71 } else { \ 72 (p)->prev = (list)->prev; \ 35 73 (list)->prev = (p); \ 36 74 (p)->next = (list); \ 37 (p)->prev = NULL; \38 75 (list) = (p); \ 39 } \76 } \ 40 77 } while (0) 41 78 42 /* remove an element from a list - element doesn't have to be in list. */ 79 /* 80 remove an element from a list 81 Note that the element doesn't have to be in the list. If it 82 isn't then this is a no-op 83 */ 43 84 #define DLIST_REMOVE(list, p) \ 44 85 do { \ 45 86 if ((p) == (list)) { \ 87 if ((p)->next) (p)->next->prev = (p)->prev; \ 46 88 (list) = (p)->next; \ 47 if (list) (list)->prev = NULL; \ 89 } else if ((list) && (p) == (list)->prev) { \ 90 (p)->prev->next = NULL; \ 91 (list)->prev = (p)->prev; \ 48 92 } else { \ 49 93 if ((p)->prev) (p)->prev->next = (p)->next; \ 50 94 if ((p)->next) (p)->next->prev = (p)->prev; \ 51 95 } \ 52 if ((p) != (list)) (p)->next = (p)->prev = NULL; 96 if ((p) != (list)) (p)->next = (p)->prev = NULL; \ 53 97 } while (0) 54 98 55 /* promote an element to the top of the list */ 56 #define DLIST_PROMOTE(list, p) \ 99 /* 100 find the head of the list given any element in it. 101 Note that this costs O(N), so you should avoid this macro 102 if at all possible! 103 */ 104 #define DLIST_HEAD(p, result_head) \ 57 105 do { \ 58 DLIST_REMOVE(list,p); \59 DLIST_ADD(list, p); \60 } while 106 (result_head) = (p); \ 107 while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ 108 } while(0) 61 109 62 /* hook into the end of the list - needs a tmp pointer */ 63 #define DLIST_ADD_END(list, p, type) \ 64 do { \ 65 if (!(list)) { \ 66 (list) = (p); \ 67 (p)->next = (p)->prev = NULL; \ 68 } else { \ 69 type tmp; \ 70 for (tmp = (list); tmp->next; tmp = tmp->next) ; \ 71 tmp->next = (p); \ 72 (p)->next = NULL; \ 73 (p)->prev = tmp; \ 74 } \ 75 } while (0) 110 /* return the last element in the list */ 111 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL) 112 113 /* return the previous element in the list. */ 114 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) 76 115 77 116 /* insert 'p' after the given element 'el' in a list. If el is NULL then … … 82 121 DLIST_ADD(list, p); \ 83 122 } else { \ 84 p->prev = el; \ 85 p->next = el->next; \ 86 el->next = p; \ 87 if (p->next) p->next->prev = p; \ 123 (p)->prev = (el); \ 124 (p)->next = (el)->next; \ 125 (el)->next = (p); \ 126 if ((p)->next) (p)->next->prev = (p); \ 127 if ((list)->prev == (el)) (list)->prev = (p); \ 88 128 }\ 89 129 } while (0) 90 130 91 /* demote an element to the end of the list, needs a tmp pointer */ 92 #define DLIST_DEMOTE(list, p, tmp) \ 131 132 /* 133 add to the end of a list. 134 Note that 'type' is ignored 135 */ 136 #define DLIST_ADD_END(list, p, type) \ 93 137 do { \ 94 DLIST_REMOVE(list, p); \ 95 DLIST_ADD_END(list, p, tmp); \ 138 if (!(list)) { \ 139 DLIST_ADD(list, p); \ 140 } else { \ 141 DLIST_ADD_AFTER(list, p, (list)->prev); \ 142 } \ 96 143 } while (0) 97 144 98 /* concatenate two lists - putting all elements of the 2nd list at the 99 end of the first list */ 100 #define DLIST_CONCATENATE(list1, list2, type) \ 145 /* promote an element to the from of a list */ 146 #define DLIST_PROMOTE(list, p) \ 101 147 do { \ 102 if (!(list1)) { \ 103 (list1) = (list2); \ 104 } else { \ 105 type tmp; \ 106 for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ 107 tmp->next = (list2); \ 108 if (list2) { \ 109 (list2)->prev = tmp; \ 110 } \ 148 DLIST_REMOVE(list, p); \ 149 DLIST_ADD(list, p); \ 150 } while (0) 151 152 /* 153 demote an element to the end of a list. 154 Note that 'type' is ignored 155 */ 156 #define DLIST_DEMOTE(list, p, type) \ 157 do { \ 158 DLIST_REMOVE(list, p); \ 159 DLIST_ADD_END(list, p, NULL); \ 160 } while (0) 161 162 /* 163 concatenate two lists - putting all elements of the 2nd list at the 164 end of the first list. 165 Note that 'type' is ignored 166 */ 167 #define DLIST_CONCATENATE(list1, list2, type) \ 168 do { \ 169 if (!(list1)) { \ 170 (list1) = (list2); \ 171 } else { \ 172 (list1)->prev->next = (list2); \ 173 if (list2) { \ 174 void *_tmplist = (void *)(list1)->prev; \ 175 (list1)->prev = (list2)->prev; \ 176 (list2)->prev = _tmplist; \ 111 177 } \ 178 } \ 112 179 } while (0) 113 180 -
vendor/current/lib/torture/subunit.c
r414 r740 20 20 #include "includes.h" 21 21 #include "lib/torture/torture.h" 22 #include <subunit/child.h> 22 23 23 static void subunit_suite_start(struct torture_context *ctx,24 static void torture_subunit_suite_start(struct torture_context *ctx, 24 25 struct torture_suite *suite) 25 26 { 26 27 } 27 28 28 static void subunit_print_testname(struct torture_context *ctx,29 static char *torture_subunit_test_name(struct torture_context *ctx, 29 30 struct torture_tcase *tcase, 30 31 struct torture_test *test) 31 32 { 32 33 if (!strcmp(tcase->name, test->name)) { 33 printf("%s", test->name);34 return talloc_strdup(ctx, test->name); 34 35 } else { 35 printf("%s.%s", tcase->name, test->name);36 return talloc_asprintf(ctx, "%s.%s", tcase->name, test->name); 36 37 } 37 38 } 38 39 39 static void subunit_test_start(struct torture_context *ctx, 40 static void torture_subunit_report_time(struct torture_context *tctx) 41 { 42 struct timespec tp; 43 struct tm *tmp; 44 char timestr[200]; 45 if (clock_gettime(CLOCK_REALTIME, &tp) != 0) { 46 perror("clock_gettime"); 47 return; 48 } 49 50 tmp = localtime(&tp.tv_sec); 51 if (!tmp) { 52 perror("localtime"); 53 return; 54 } 55 56 if (strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tmp) <= 0) { 57 perror("strftime"); 58 return; 59 } 60 61 printf("time: %s.%06ld\n", timestr, tp.tv_nsec / 1000); 62 } 63 64 static void torture_subunit_test_start(struct torture_context *context, 40 65 struct torture_tcase *tcase, 41 66 struct torture_test *test) 42 67 { 43 printf("test: "); 44 subunit_print_testname(ctx, tcase, test); 45 printf("\n"); 68 char *fullname = torture_subunit_test_name(context, context->active_tcase, context->active_test); 69 subunit_test_start(fullname); 70 torture_subunit_report_time(context); 71 talloc_free(fullname); 46 72 } 47 73 48 static void subunit_test_result(struct torture_context *context,74 static void torture_subunit_test_result(struct torture_context *context, 49 75 enum torture_result res, const char *reason) 50 76 { 77 char *fullname = torture_subunit_test_name(context, context->active_tcase, context->active_test); 78 torture_subunit_report_time(context); 51 79 switch (res) { 52 80 case TORTURE_OK: 53 printf("success: ");81 subunit_test_pass(fullname); 54 82 break; 55 83 case TORTURE_FAIL: 56 printf("failure: ");84 subunit_test_fail(fullname, reason); 57 85 break; 58 86 case TORTURE_ERROR: 59 printf("error: ");87 subunit_test_error(fullname, reason); 60 88 break; 61 89 case TORTURE_SKIP: 62 printf("skip: ");90 subunit_test_skip(fullname, reason); 63 91 break; 64 92 } 65 subunit_print_testname(context, context->active_tcase, context->active_test); 66 67 if (reason) 68 printf(" [\n%s\n]", reason); 69 printf("\n"); 93 talloc_free(fullname); 70 94 } 71 95 72 static void subunit_comment(struct torture_context *test,96 static void torture_subunit_comment(struct torture_context *test, 73 97 const char *comment) 74 98 { … … 76 100 } 77 101 78 static void subunit_warning(struct torture_context *test,102 static void torture_subunit_warning(struct torture_context *test, 79 103 const char *comment) 80 104 { … … 82 106 } 83 107 108 static void torture_subunit_progress(struct torture_context *tctx, int offset, enum torture_progress_whence whence) 109 { 110 switch (whence) { 111 case TORTURE_PROGRESS_SET: 112 printf("progress: %d\n", offset); 113 break; 114 case TORTURE_PROGRESS_CUR: 115 printf("progress: %+-d\n", offset); 116 break; 117 case TORTURE_PROGRESS_POP: 118 printf("progress: pop\n"); 119 break; 120 case TORTURE_PROGRESS_PUSH: 121 printf("progress: push\n"); 122 break; 123 default: 124 fprintf(stderr, "Invalid call to progress()\n"); 125 break; 126 } 127 } 128 84 129 const struct torture_ui_ops torture_subunit_ui_ops = { 85 .comment = subunit_comment, 86 .warning = subunit_warning, 87 .test_start = subunit_test_start, 88 .test_result = subunit_test_result, 89 .suite_start = subunit_suite_start 130 .comment = torture_subunit_comment, 131 .warning = torture_subunit_warning, 132 .test_start = torture_subunit_test_start, 133 .test_result = torture_subunit_test_result, 134 .suite_start = torture_subunit_suite_start, 135 .progress = torture_subunit_progress, 136 .report_time = torture_subunit_report_time, 90 137 }; -
vendor/current/lib/torture/torture.c
r414 r740 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 SMB torture UI functions 4 4 5 5 Copyright (C) Jelmer Vernooij 2006-2008 6 6 7 7 This program is free software; you can redistribute it and/or modify 8 8 it under the terms of the GNU General Public License as published by 9 9 the Free Software Foundation; either version 3 of the License, or 10 10 (at your option) any later version. 11 11 12 12 This program is distributed in the hope that it will be useful, 13 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 GNU General Public License for more details. 16 16 17 17 You should have received a copy of the GNU General Public License 18 18 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 24 24 #include "param/param.h" 25 25 #include "system/filesys.h" 26 #include "system/dir.h" 27 26 28 27 29 struct torture_results *torture_results_init(TALLOC_CTX *mem_ctx, const struct torture_ui_ops *ui_ops) … … 72 74 73 75 return subtorture; 74 } 75 76 /** 77 create a temporary directory .76 } 77 78 /** 79 create a temporary directory under the output dir 78 80 */ 79 _PUBLIC_ NTSTATUS torture_temp_dir(struct torture_context *tctx, 80 const char *prefix, 81 char **tempdir) 81 _PUBLIC_ NTSTATUS torture_temp_dir(struct torture_context *tctx, 82 const char *prefix, char **tempdir) 82 83 { 83 84 SMB_ASSERT(tctx->outputdir != NULL); 84 85 85 *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir, 86 *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir, 86 87 prefix); 87 88 NT_STATUS_HAVE_NO_MEMORY(*tempdir); … … 91 92 } 92 93 94 return NT_STATUS_OK; 95 } 96 97 static int local_deltree(const char *path) 98 { 99 int ret = 0; 100 struct dirent *dirent; 101 DIR *dir = opendir(path); 102 if (!dir) { 103 char *error = talloc_asprintf(NULL, "Could not open directory %s", path); 104 perror(error); 105 talloc_free(error); 106 return -1; 107 } 108 while ((dirent = readdir(dir))) { 109 char *name; 110 if ((strcmp(dirent->d_name, ".") == 0) || (strcmp(dirent->d_name, "..") == 0)) { 111 continue; 112 } 113 name = talloc_asprintf(NULL, "%s/%s", path, 114 dirent->d_name); 115 if (name == NULL) { 116 closedir(dir); 117 return -1; 118 } 119 DEBUG(0, ("About to remove %s\n", name)); 120 ret = remove(name); 121 if (ret == 0) { 122 talloc_free(name); 123 continue; 124 } 125 126 if (errno == ENOTEMPTY) { 127 ret = local_deltree(name); 128 if (ret == 0) { 129 ret = remove(name); 130 } 131 } 132 talloc_free(name); 133 if (ret != 0) { 134 char *error = talloc_asprintf(NULL, "Could not remove %s", path); 135 perror(error); 136 talloc_free(error); 137 break; 138 } 139 } 140 closedir(dir); 141 rmdir(path); 142 return ret; 143 } 144 145 _PUBLIC_ NTSTATUS torture_deltree_outputdir(struct torture_context *tctx) 146 { 147 if (tctx->outputdir == NULL) { 148 return NT_STATUS_OK; 149 } 150 if ((strcmp(tctx->outputdir, "/") == 0) 151 || (strcmp(tctx->outputdir, "") == 0)) { 152 return NT_STATUS_INVALID_PARAMETER; 153 } 154 155 if (local_deltree(tctx->outputdir) == -1) { 156 if (errno != 0) { 157 return map_nt_error_from_unix(errno); 158 } 159 return NT_STATUS_UNSUCCESSFUL; 160 } 93 161 return NT_STATUS_OK; 94 162 } … … 108 176 tmp = talloc_vasprintf(context, comment, ap); 109 177 va_end(ap); 110 178 111 179 context->results->ui_ops->comment(context, tmp); 112 180 113 181 talloc_free(tmp); 114 182 } … … 246 314 } 247 315 316 int torture_suite_children_count(const struct torture_suite *suite) 317 { 318 int ret = 0; 319 struct torture_tcase *tcase; 320 struct torture_test *test; 321 struct torture_suite *tsuite; 322 for (tcase = suite->testcases; tcase; tcase = tcase->next) { 323 for (test = tcase->tests; test; test = test->next) { 324 ret++; 325 } 326 } 327 for (tsuite = suite->children; tsuite; tsuite = tsuite->next) { 328 ret ++; 329 } 330 return ret; 331 } 332 248 333 /** 249 334 * Run a torture test suite. … … 251 336 bool torture_run_suite(struct torture_context *context, 252 337 struct torture_suite *suite) 338 { 339 return torture_run_suite_restricted(context, suite, NULL); 340 } 341 342 bool torture_run_suite_restricted(struct torture_context *context, 343 struct torture_suite *suite, const char **restricted) 253 344 { 254 345 bool ret = true; 255 346 struct torture_tcase *tcase; 256 347 struct torture_suite *tsuite; 257 char *old_testname;258 348 259 349 if (context->results->ui_ops->suite_start) 260 350 context->results->ui_ops->suite_start(context, suite); 261 351 262 old_testname = context->active_testname; 263 if (old_testname != NULL) 264 context->active_testname = talloc_asprintf(context, "%s-%s", 265 old_testname, suite->name); 266 else 267 context->active_testname = talloc_strdup(context, suite->name); 352 /* FIXME: Adjust torture_suite_children_count if restricted != NULL */ 353 context->results->ui_ops->progress(context, 354 torture_suite_children_count(suite), TORTURE_PROGRESS_SET); 268 355 269 356 for (tcase = suite->testcases; tcase; tcase = tcase->next) { 270 ret &= torture_run_tcase (context, tcase);357 ret &= torture_run_tcase_restricted(context, tcase, restricted); 271 358 } 272 359 273 360 for (tsuite = suite->children; tsuite; tsuite = tsuite->next) { 274 ret &= torture_run_suite(context, tsuite); 275 } 276 277 talloc_free(context->active_testname); 278 context->active_testname = old_testname; 361 context->results->ui_ops->progress(context, 0, TORTURE_PROGRESS_PUSH); 362 ret &= torture_run_suite_restricted(context, tsuite, restricted); 363 context->results->ui_ops->progress(context, 0, TORTURE_PROGRESS_POP); 364 } 279 365 280 366 if (context->results->ui_ops->suite_finish) … … 303 389 } 304 390 391 static bool test_needs_running(const char *name, const char **restricted) 392 { 393 int i; 394 if (restricted == NULL) 395 return true; 396 for (i = 0; restricted[i]; i++) { 397 if (!strcmp(name, restricted[i])) 398 return true; 399 } 400 return false; 401 } 402 305 403 static bool internal_torture_run_test(struct torture_context *context, 306 404 struct torture_tcase *tcase, 307 405 struct torture_test *test, 308 bool already_setup) 406 bool already_setup, 407 const char **restricted) 309 408 { 310 409 bool success; 311 char * old_testname = NULL;410 char *subunit_testname = NULL; 312 411 313 412 if (tcase == NULL || strcmp(test->name, tcase->name) != 0) { 314 old_testname = context->active_testname; 315 context->active_testname = talloc_asprintf(context, "%s-%s", old_testname, test->name); 316 } 413 subunit_testname = talloc_asprintf(context, "%s.%s", tcase->name, test->name); 414 } else { 415 subunit_testname = talloc_strdup(context, test->name); 416 } 417 418 if (!test_needs_running(subunit_testname, restricted)) 419 return true; 317 420 318 421 context->active_tcase = tcase; … … 358 461 talloc_free(context->last_reason); 359 462 360 if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {361 talloc_free(context->active_testname);362 context->active_testname = old_testname;363 }364 463 context->active_test = NULL; 365 464 context->active_tcase = NULL; … … 368 467 } 369 468 370 bool torture_run_tcase(struct torture_context *context, 469 bool torture_run_tcase(struct torture_context *context, 371 470 struct torture_tcase *tcase) 372 471 { 472 return torture_run_tcase_restricted(context, tcase, NULL); 473 } 474 475 bool torture_run_tcase_restricted(struct torture_context *context, 476 struct torture_tcase *tcase, const char **restricted) 477 { 373 478 bool ret = true; 374 char *old_testname;375 479 struct torture_test *test; 480 bool setup_succeeded = true; 481 const char * setup_reason = "Setup failed"; 376 482 377 483 context->active_tcase = tcase; … … 379 485 context->results->ui_ops->tcase_start(context, tcase); 380 486 381 if (tcase->fixture_persistent && tcase->setup 382 && !tcase->setup(context, &tcase->data)) { 383 /* FIXME: Use torture ui ops for reporting this error */ 384 fprintf(stderr, "Setup failed: "); 385 if (context->last_reason != NULL) 386 fprintf(stderr, "%s", context->last_reason); 387 fprintf(stderr, "\n"); 487 if (tcase->fixture_persistent && tcase->setup) { 488 setup_succeeded = tcase->setup(context, &tcase->data); 489 } 490 491 if (!setup_succeeded) { 492 /* Uh-oh. The setup failed, so we can't run any of the tests 493 * in this testcase. The subunit format doesn't specify what 494 * to do here, so we keep the failure reason, and manually 495 * use it to fail every test. 496 */ 497 if (context->last_reason != NULL) { 498 setup_reason = talloc_asprintf(context, 499 "Setup failed: %s", context->last_reason); 500 } 501 } 502 503 for (test = tcase->tests; test; test = test->next) { 504 if (setup_succeeded) { 505 ret &= internal_torture_run_test(context, tcase, test, 506 tcase->fixture_persistent, restricted); 507 } else { 508 context->active_tcase = tcase; 509 context->active_test = test; 510 torture_ui_test_start(context, tcase, test); 511 torture_ui_test_result(context, TORTURE_FAIL, setup_reason); 512 } 513 } 514 515 if (setup_succeeded && tcase->fixture_persistent && tcase->teardown && 516 !tcase->teardown(context, tcase->data)) { 388 517 ret = false; 389 goto done; 390 } 391 392 old_testname = context->active_testname; 393 context->active_testname = talloc_asprintf(context, "%s-%s", 394 old_testname, tcase->name); 395 for (test = tcase->tests; test; test = test->next) { 396 ret &= internal_torture_run_test(context, tcase, test, 397 tcase->fixture_persistent); 398 } 399 talloc_free(context->active_testname); 400 context->active_testname = old_testname; 401 402 if (tcase->fixture_persistent && tcase->teardown && 403 !tcase->teardown(context, tcase->data)) 404 ret = false; 405 406 done: 518 } 519 407 520 context->active_tcase = NULL; 521 context->active_test = NULL; 408 522 409 523 if (context->results->ui_ops->tcase_finish) 410 524 context->results->ui_ops->tcase_finish(context, tcase); 411 525 412 return ret;526 return (!setup_succeeded) ? false : ret; 413 527 } 414 528 … … 417 531 struct torture_test *test) 418 532 { 419 return internal_torture_run_test(context, tcase, test, false); 533 return internal_torture_run_test(context, tcase, test, false, NULL); 534 } 535 536 bool torture_run_test_restricted(struct torture_context *context, 537 struct torture_tcase *tcase, 538 struct torture_test *test, 539 const char **restricted) 540 { 541 return internal_torture_run_test(context, tcase, test, false, restricted); 420 542 } 421 543 … … 423 545 int default_value) 424 546 { 425 return lp_parm_int(test->lp_ctx, NULL, "torture", name, default_value); 547 return lpcfg_parm_int(test->lp_ctx, NULL, "torture", name, default_value); 548 } 549 550 unsigned long torture_setting_ulong(struct torture_context *test, 551 const char *name, 552 unsigned long default_value) 553 { 554 return lpcfg_parm_ulong(test->lp_ctx, NULL, "torture", name, 555 default_value); 426 556 } 427 557 … … 429 559 double default_value) 430 560 { 431 return lp _parm_double(test->lp_ctx, NULL, "torture", name, default_value);561 return lpcfg_parm_double(test->lp_ctx, NULL, "torture", name, default_value); 432 562 } 433 563 … … 435 565 bool default_value) 436 566 { 437 return lp _parm_bool(test->lp_ctx, NULL, "torture", name, default_value);567 return lpcfg_parm_bool(test->lp_ctx, NULL, "torture", name, default_value); 438 568 } 439 569 … … 447 577 SMB_ASSERT(test->lp_ctx != NULL); 448 578 449 ret = lp _parm_string(test->lp_ctx, NULL, "torture", name);579 ret = lpcfg_parm_string(test->lp_ctx, NULL, "torture", name); 450 580 451 581 if (ret == NULL) … … 620 750 return test; 621 751 } 752 753 void torture_ui_report_time(struct torture_context *context) 754 { 755 if (context->results->ui_ops->report_time) 756 context->results->ui_ops->report_time(context); 757 } -
vendor/current/lib/torture/torture.h
r414 r740 33 33 TORTURE_ERROR=2, 34 34 TORTURE_SKIP=3 35 }; 36 37 enum torture_progress_whence { 38 TORTURE_PROGRESS_SET, 39 TORTURE_PROGRESS_CUR, 40 TORTURE_PROGRESS_POP, 41 TORTURE_PROGRESS_PUSH, 35 42 }; 36 43 … … 53 60 void (*test_result) (struct torture_context *, 54 61 enum torture_result, const char *reason); 62 void (*progress) (struct torture_context *, int offset, enum torture_progress_whence whence); 63 void (*report_time) (struct torture_context *); 55 64 }; 56 65 … … 62 71 enum torture_result result, 63 72 const char *comment); 73 74 void torture_ui_report_time(struct torture_context *context); 64 75 65 76 /* … … 77 88 struct torture_results *results; 78 89 79 char *active_testname;80 90 struct torture_test *active_test; 81 91 struct torture_tcase *active_tcase; … … 86 96 /** Directory used for temporary test data */ 87 97 const char *outputdir; 88 98 89 99 /** Event context */ 90 100 struct tevent_context *ev; … … 211 221 struct torture_suite *suite); 212 222 223 /* Run the specified testsuite recursively, but only the specified 224 * tests */ 225 bool torture_run_suite_restricted(struct torture_context *context, 226 struct torture_suite *suite, const char **restricted); 227 213 228 /* Run the specified testcase */ 214 229 bool torture_run_tcase(struct torture_context *context, 215 230 struct torture_tcase *tcase); 231 232 bool torture_run_tcase_restricted(struct torture_context *context, 233 struct torture_tcase *tcase, const char **restricted); 216 234 217 235 /* Run the specified test */ … … 220 238 struct torture_test *test); 221 239 240 bool torture_run_test_restricted(struct torture_context *context, 241 struct torture_tcase *tcase, 242 struct torture_test *test, 243 const char **restricted); 244 222 245 void torture_comment(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3); 223 246 void torture_warning(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3); … … 229 252 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \ 230 253 return false; \ 254 } 255 256 #define torture_assert_goto(torture_ctx,expr,ret,label,cmt) \ 257 if (!(expr)) { \ 258 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \ 259 ret = false; \ 260 goto label; \ 231 261 } 232 262 … … 278 308 __location__": "#got" was %s, expected %s: %s", \ 279 309 __got, __expected, cmt); \ 310 return false; \ 311 } \ 312 } while(0) 313 314 #define torture_assert_strn_equal(torture_ctx,got,expected,len,cmt)\ 315 do { const char *__got = (got), *__expected = (expected); \ 316 if (strncmp(__got, __expected, len) != 0) { \ 317 torture_result(torture_ctx, TORTURE_FAIL, \ 318 __location__": "#got" %s of len %d did not match "#expected" %s: %s", \ 319 __got, (int)len, __expected, cmt); \ 280 320 return false; \ 281 321 } \ … … 358 398 if (__got != __expected) { \ 359 399 torture_result(torture_ctx, TORTURE_FAIL, \ 360 __location__": "#got" was %d , expected %d: %s", \361 __got, __ expected, cmt); \400 __location__": "#got" was %d (0x%X), expected %d (0x%X): %s", \ 401 __got, __got, __expected, __expected, cmt); \ 362 402 return false; \ 363 403 } \ … … 368 408 if (__got != __expected) { \ 369 409 torture_result(torture_ctx, TORTURE_FAIL, \ 370 __location__": "#got" was %d , expected %d: %s", \371 __got, __ expected, cmt); \410 __location__": "#got" was %d (0x%X), expected %d (0x%X): %s", \ 411 __got, __got, __expected, __expected, cmt); \ 372 412 ret = false; \ 373 413 goto label; \ … … 379 419 if (__got != __expected) { \ 380 420 torture_result(torture_ctx, TORTURE_FAIL, \ 381 __location__": "#got" was %llu, expected %llu: %s", \ 382 (unsigned long long)__got, (unsigned long long)__expected, cmt); \ 383 return false; \ 421 __location__": "#got" was %llu (0x%llX), expected %llu (0x%llX): %s", \ 422 (unsigned long long)__got, (unsigned long long)__got, \ 423 (unsigned long long)__expected, (unsigned long long)__expected, \ 424 cmt); \ 425 return false; \ 426 } \ 427 } while(0) 428 429 #define torture_assert_u64_equal_goto(torture_ctx,got,expected,ret,label,cmt)\ 430 do { uint64_t __got = (got), __expected = (expected); \ 431 if (__got != __expected) { \ 432 torture_result(torture_ctx, TORTURE_FAIL, \ 433 __location__": "#got" was %llu (0x%llX), expected %llu (0x%llX): %s", \ 434 (unsigned long long)__got, (unsigned long long)__got, \ 435 (unsigned long long)__expected, (unsigned long long)__expected, \ 436 cmt); \ 437 ret = false; \ 438 goto label; \ 384 439 } \ 385 440 } while(0) … … 396 451 } while(0) 397 452 398 453 #define torture_assert_nttime_equal(torture_ctx,got,expected,cmt) \ 454 do { NTTIME __got = got, __expected = expected; \ 455 if (!nt_time_equal(&__got, &__expected)) { \ 456 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", nt_time_string(tctx, __got), nt_time_string(tctx, __expected), cmt); \ 457 return false; \ 458 }\ 459 } while(0) 399 460 400 461 #define torture_skip(torture_ctx,cmt) do {\ … … 450 511 const char *name); 451 512 513 unsigned long torture_setting_ulong(struct torture_context *test, 514 const char *name, 515 unsigned long default_value); 516 452 517 NTSTATUS torture_temp_dir(struct torture_context *tctx, 453 518 const char *prefix, 454 519 char **tempdir); 520 NTSTATUS torture_deltree_outputdir(struct torture_context *tctx); 455 521 456 522 struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase, … … 462 528 struct torture_tcase *tcase, 463 529 const char *name); 530 int torture_suite_children_count(const struct torture_suite *suite); 464 531 465 532 struct torture_context *torture_context_init(struct tevent_context *event_ctx, struct torture_results *results); -
vendor/current/lib/torture/torture.pc.in
r414 r740 9 9 Requires: talloc 10 10 Version: 0.0.1 11 Libs: -L${libdir} -ltorture11 Libs: @LIB_RPATH@ -L${libdir} -ltorture 12 12 Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -
vendor/current/lib/tsocket/tsocket.c
r414 r740 47 47 return -1; 48 48 default: 49 *perrno = EIO; 50 return -1; 49 break; 51 50 } 52 51 -
vendor/current/lib/tsocket/tsocket.h
r478 r740 84 84 85 85 /** 86 * @brief Get a string representa ion of the endpoint.86 * @brief Get a string representation of the endpoint. 87 87 * 88 88 * This function creates a string representation of the endpoint for debugging. … … 102 102 * @return The address as a string representation, NULL on error. 103 103 * 104 * @see tsocket_address_is_inet() 104 105 * @see tsocket_address_inet_addr_string() 105 106 * @see tsocket_address_inet_port() … … 486 487 * @{ 487 488 */ 489 490 /** 491 * @brief Find out if the tsocket_address represents an ipv4 or ipv6 endpoint. 492 * 493 * @param[in] addr The tsocket_address pointer 494 * 495 * @param[in] fam The family can be can be "ipv4", "ipv6" or "ip". With 496 * "ip" is autodetects "ipv4" or "ipv6" based on the 497 * addr. 498 * 499 * @return true if addr represents an address of the given family, 500 * otherwise false. 501 */ 502 bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam); 488 503 489 504 #if DOXYGEN … … 534 549 * @return A newly allocated string of the address, NULL on error 535 550 * with errno set. 551 * 552 * @see tsocket_address_is_inet() 536 553 */ 537 554 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr, … … 559 576 uint16_t port); 560 577 578 /** 579 * @brief Find out if the tsocket_address represents an unix domain endpoint. 580 * 581 * @param[in] addr The tsocket_address pointer 582 * 583 * @return true if addr represents an unix domain endpoint, 584 * otherwise false. 585 */ 586 bool tsocket_address_is_unix(const struct tsocket_address *addr); 587 561 588 #ifdef DOXYGEN 562 589 /** … … 570 597 * 571 598 * @return 0 on success, -1 on error with errno set. 599 * 600 * @see tsocket_address_is_unix() 572 601 */ 573 602 int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx, … … 696 725 * @param[in] mem_ctx The talloc memory context to use. 697 726 * 698 * @param[ in]stream A tstream_context pointer to setup the tcp communication727 * @param[out] stream A tstream_context pointer to setup the tcp communication 699 728 * on. This function will allocate the memory. 729 * 730 * @param[out] local The real 'inet' tsocket_address of the local endpoint. 731 * This parameter is optional and can be NULL. 700 732 * 701 733 * @return 0 on success, -1 on error with perrno set. … … 704 736 int *perrno, 705 737 TALLOC_CTX *mem_ctx, 706 struct tstream_context **stream); 738 struct tstream_context **stream, 739 struct tsocket_address **local) 707 740 #else 708 741 int _tstream_inet_tcp_connect_recv(struct tevent_req *req, … … 710 743 TALLOC_CTX *mem_ctx, 711 744 struct tstream_context **stream, 745 struct tsocket_address **local, 712 746 const char *location); 713 #define tstream_inet_tcp_connect_recv(req, perrno, mem_ctx, stream ) \714 _tstream_inet_tcp_connect_recv(req, perrno, mem_ctx, stream, \747 #define tstream_inet_tcp_connect_recv(req, perrno, mem_ctx, stream, local) \ 748 _tstream_inet_tcp_connect_recv(req, perrno, mem_ctx, stream, local, \ 715 749 __location__) 716 750 #endif … … 874 908 * freed. If you still want to use the fd you have have to create a duplicate. 875 909 * 876 * @param[in] mem_ctx The talloc memory context to use. 877 * 878 * @param[in] fd The non blocking fd to use! 879 * 880 * @param[in] stream The filed tstream_context you allocated before. 881 * 882 * @return 0 on success, -1 on error with errno set. 883 * 884 * @warning You should read the tsocket_bsd.c code and unterstand it in order 885 * use this function. 910 * @param[in] mem_ctx The talloc memory context to use. 911 * 912 * @param[in] fd The non blocking fd to use! 913 * 914 * @param[out] stream A pointer to store an allocated tstream_context. 915 * 916 * @return 0 on success, -1 on error. 917 * 918 * Example: 919 * @code 920 * fd2 = dup(fd); 921 * rc = tstream_bsd_existing_socket(mem_ctx, fd2, &tstream); 922 * if (rc < 0) { 923 * stream_terminate_connection(conn, "named_pipe_accept: out of memory"); 924 * return; 925 * } 926 * @endcode 927 * 928 * @warning This is an internal function. You should read the code to fully 929 * understand it if you plan to use it. 886 930 */ 887 931 int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx, -
vendor/current/lib/tsocket/tsocket_bsd.c
r478 r740 264 264 265 265 bsda->sa_socklen = sa_socklen; 266 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 267 bsda->u.sa.sa_len = bsda->sa_socklen; 268 #endif 266 269 267 270 *_addr = addr; … … 292 295 293 296 memcpy(sa, &bsda->u.ss, sa_socklen); 297 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 298 sa->sa_len = sa_socklen; 299 #endif 294 300 return sa_socklen; 301 } 302 303 bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam) 304 { 305 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data, 306 struct tsocket_address_bsd); 307 308 if (!bsda) { 309 return false; 310 } 311 312 switch (bsda->u.sa.sa_family) { 313 case AF_INET: 314 if (strcasecmp(fam, "ip") == 0) { 315 return true; 316 } 317 318 if (strcasecmp(fam, "ipv4") == 0) { 319 return true; 320 } 321 322 return false; 323 #ifdef HAVE_IPV6 324 case AF_INET6: 325 if (strcasecmp(fam, "ip") == 0) { 326 return true; 327 } 328 329 if (strcasecmp(fam, "ipv6") == 0) { 330 return true; 331 } 332 333 return false; 334 #endif 335 } 336 337 return false; 295 338 } 296 339 … … 465 508 466 509 return 0; 510 } 511 512 bool tsocket_address_is_unix(const struct tsocket_address *addr) 513 { 514 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data, 515 struct tsocket_address_bsd); 516 517 if (!bsda) { 518 return false; 519 } 520 521 switch (bsda->u.sa.sa_family) { 522 case AF_UNIX: 523 return true; 524 } 525 526 return false; 467 527 } 468 528 … … 847 907 ZERO_STRUCTP(bsda); 848 908 bsda->sa_socklen = sizeof(bsda->u.ss); 909 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 910 bsda->u.sa.sa_len = bsda->sa_socklen; 911 #endif 849 912 850 913 ret = recvfrom(bsds->fd, state->buf, state->len, 0, … … 1054 1117 } 1055 1118 1119 TALLOC_FREE(bsds->fde); 1056 1120 ret = close(bsds->fd); 1057 1121 bsds->fd = -1; … … 1184 1248 fd = socket(sa_fam, SOCK_DGRAM, 0); 1185 1249 if (fd < 0) { 1186 return fd;1250 return -1; 1187 1251 } 1188 1252 1189 1253 fd = tsocket_bsd_common_prepare_fd(fd, true); 1190 1254 if (fd < 0) { 1191 return fd;1255 return -1; 1192 1256 } 1193 1257 … … 1217 1281 talloc_free(dgram); 1218 1282 errno = saved_errno; 1219 return ret;1283 return -1; 1220 1284 } 1221 1285 } … … 1231 1295 talloc_free(dgram); 1232 1296 errno = saved_errno; 1233 return ret;1297 return -1; 1234 1298 } 1235 1299 } … … 1244 1308 talloc_free(dgram); 1245 1309 errno = saved_errno; 1246 return ret;1310 return -1; 1247 1311 } 1248 1312 } … … 1254 1318 talloc_free(dgram); 1255 1319 errno = saved_errno; 1256 return ret;1320 return -1; 1257 1321 } 1258 1322 } … … 1270 1334 talloc_free(dgram); 1271 1335 errno = saved_errno; 1272 return ret;1336 return -1; 1273 1337 } 1274 1338 } … … 1610 1674 base = (uint8_t *)state->vector[0].iov_base; 1611 1675 base += ret; 1612 state->vector[0].iov_base = base;1676 state->vector[0].iov_base = (void *)base; 1613 1677 state->vector[0].iov_len -= ret; 1614 1678 break; … … 1770 1834 base = (uint8_t *)state->vector[0].iov_base; 1771 1835 base += ret; 1772 state->vector[0].iov_base = base;1836 state->vector[0].iov_base = (void *)base; 1773 1837 state->vector[0].iov_len -= ret; 1774 1838 break; … … 1841 1905 } 1842 1906 1907 TALLOC_FREE(bsds->fde); 1843 1908 ret = close(bsds->fd); 1844 1909 bsds->fd = -1; … … 1918 1983 struct tevent_fd *fde; 1919 1984 struct tstream_conext *stream; 1985 struct tsocket_address *local; 1920 1986 }; 1921 1987 … … 1936 2002 void *private_data); 1937 2003 1938 static struct tevent_req * 2004 static struct tevent_req *tstream_bsd_connect_send(TALLOC_CTX *mem_ctx, 1939 2005 struct tevent_context *ev, 1940 2006 int sys_errno, … … 1947 2013 talloc_get_type_abort(local->private_data, 1948 2014 struct tsocket_address_bsd); 2015 struct tsocket_address_bsd *lrbsda = NULL; 1949 2016 struct tsocket_address_bsd *rbsda = 1950 2017 talloc_get_type_abort(remote->private_data, … … 2026 2093 } 2027 2094 2095 if (is_inet) { 2096 state->local = tsocket_address_create(state, 2097 &tsocket_address_bsd_ops, 2098 &lrbsda, 2099 struct tsocket_address_bsd, 2100 __location__ "bsd_connect"); 2101 if (tevent_req_nomem(state->local, req)) { 2102 goto post; 2103 } 2104 2105 ZERO_STRUCTP(lrbsda); 2106 lrbsda->sa_socklen = sizeof(lrbsda->u.ss); 2107 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 2108 lrbsda->u.sa.sa_len = lrbsda->sa_socklen; 2109 #endif 2110 } 2111 2028 2112 state->fd = socket(sa_fam, SOCK_STREAM, 0); 2029 2113 if (state->fd == -1) { … … 2082 2166 } 2083 2167 if (tevent_req_error(req, err)) { 2168 goto post; 2169 } 2170 2171 if (!state->local) { 2172 tevent_req_done(req); 2173 goto post; 2174 } 2175 2176 ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen); 2177 if (ret == -1) { 2178 tevent_req_error(req, errno); 2084 2179 goto post; 2085 2180 } … … 2114 2209 struct tstream_bsd_connect_state *state = tevent_req_data(req, 2115 2210 struct tstream_bsd_connect_state); 2211 struct tsocket_address_bsd *lrbsda = NULL; 2116 2212 int ret; 2117 2213 int error=0; … … 2136 2232 } 2137 2233 2234 if (!state->local) { 2235 tevent_req_done(req); 2236 return; 2237 } 2238 2239 lrbsda = talloc_get_type_abort(state->local->private_data, 2240 struct tsocket_address_bsd); 2241 2242 ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen); 2243 if (ret == -1) { 2244 tevent_req_error(req, errno); 2245 return; 2246 } 2247 2138 2248 tevent_req_done(req); 2139 2249 } … … 2143 2253 TALLOC_CTX *mem_ctx, 2144 2254 struct tstream_context **stream, 2255 struct tsocket_address **local, 2145 2256 const char *location) 2146 2257 { … … 2161 2272 TALLOC_FREE(state->fde); 2162 2273 state->fd = -1; 2274 2275 if (local) { 2276 *local = talloc_move(mem_ctx, &state->local); 2277 } 2163 2278 } 2164 2279 … … 2200 2315 TALLOC_CTX *mem_ctx, 2201 2316 struct tstream_context **stream, 2317 struct tsocket_address **local, 2202 2318 const char *location) 2203 2319 { 2204 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location); 2320 return tstream_bsd_connect_recv(req, perrno, 2321 mem_ctx, stream, local, 2322 location); 2205 2323 } 2206 2324 … … 2235 2353 const char *location) 2236 2354 { 2237 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location); 2355 return tstream_bsd_connect_recv(req, perrno, 2356 mem_ctx, stream, NULL, 2357 location); 2238 2358 } 2239 2359 -
vendor/current/lib/tsocket/tsocket_guide.txt
r414 r740 24 24 =============================== 25 25 26 The tsocket_address represents an socket endpoint genericly.27 As it's like an abstract class it has no specificconstructor.28 The specific constructors are descripted later sections.29 30 There's a function get the string representation of the 31 endpoint for debugging. Callers should not try to parse32 the string! The should use additional methods of the specific 33 tsocket_address implemention to get more details.26 A tsocket_address represents a generic socket endpoint. 27 It behaves like an abstract class, therefore it has no direct constructor. 28 Constructors are described in later sections of this document. 29 30 A function get the string representation of an endpoint for debugging is 31 available but callers SHOULD NOT try to parse this string. To get more 32 details callers should use getter methods of the specific tsocket_address 33 implemention. 34 34 35 35 char *tsocket_address_string(const struct tsocket_address *addr, 36 36 TALLOC_CTX *mem_ctx); 37 37 38 There's a function to create a copy of the tsocket_address.39 This is useful whenbefore doing modifications to a socket38 A function to create a copy of the tsocket_address is also avilable. 39 This is useful before doing modifications to a socket 40 40 via additional methods of the specific tsocket_address implementation. 41 41 … … 48 48 The tdgram_context is like an abstract class for datagram 49 49 based sockets. The interface provides async 'tevent_req' based 50 functions on top functionality is similar to the 51 recvfrom(2)/sendto(2)/close(2) syscalls. 50 functions similar to recvfrom(2)/sendto(2)/close(2) syscalls. 52 51 53 52 The tdgram_recvfrom_send() method can be called to ask for the 54 next available datagram onthe abstracted tdgram_context.53 next available datagram from the abstracted tdgram_context. 55 54 It returns a 'tevent_req' handle, where the caller can register 56 55 a callback with tevent_req_set_callback(). The callback is triggered 57 when a datagram is available or an error happened.56 when a datagram is available or an error occurs. 58 57 59 58 The callback is then supposed to get the result by calling … … 123 122 =============================== 124 123 125 Thetstream_context is like an abstract class for stream124 A tstream_context is like an abstract class for stream 126 125 based sockets. The interface provides async 'tevent_req' based 127 functions on top functionality is similar to the 128 readv(2)/writev(2)/close(2) syscalls. 129 130 The tstream_pending_bytes() function is able to report 131 how much bytes of the incoming stream have arrived 132 but not consumed yet. It returns -1 and sets 'errno' on failure. 133 Otherwise it returns the number of uncomsumed bytes 134 (it can return 0!). 126 functions similar to the readv(2)/writev(2)/close(2) syscalls. 127 128 The tstream_pending_bytes() function is able to report how many bytes of 129 the incoming stream have been received but have not been consumed yet. 130 It returns -1 and sets 'errno' on failure. 131 Otherwise it returns the number of uncomsumed bytes (it can return 0!). 135 132 136 133 ssize_t tstream_pending_bytes(struct tstream_context *stream); 137 134 138 The tstream_readv_send() method can be called to read fora135 The tstream_readv_send() method can be called to read a 139 136 specific amount of bytes from the stream into the buffers 140 137 of the given iovec vector. The caller has to preallocate the buffers … … 144 141 where the caller can register a callback with tevent_req_set_callback(). 145 142 The callback is triggered when all iovec buffers are completely 146 filled with bytes from the socket or an error happened.143 filled with bytes from the socket or an error occurs. 147 144 148 145 The callback is then supposed to get the result by calling 149 146 tstream_readv_recv() on the 'tevent_req'. It returns -1 150 147 and sets '*perrno' to the actual 'errno' on failure. 151 Otherwise it returns the length of the datagram 152 (0 is never returned!). 148 Otherwise it returns the length of the datagram (0 is never returned!). 153 149 154 150 The caller can only have one outstanding tstream_readv_send() … … 166 162 The tstream_writev_send() method can be called to write 167 163 buffers in the given iovec vector into the stream socket. 168 It 's invalid to pass an empty vector.164 It is invalid to pass an empty vector. 169 165 tstream_writev_send() returns a 'tevent_req' handle, 170 166 where the caller can register a callback with tevent_req_set_callback(). … … 190 186 int *perrno); 191 187 192 The tstream_disconnect_send() method should be used to normally188 The tstream_disconnect_send() method should normally be used to 193 189 shutdown/close the abstracted socket. 194 190 … … 209 205 ============================ 210 206 211 In order to make the live easier for callers whichwant to implement207 In order to simplify the job, for callers that want to implement 212 208 a function to receive a full PDU with a single async function pair, 213 there're some helper functions.209 some helper functions are provided. 214 210 215 211 The caller can use the tstream_readv_pdu_send() function … … 217 213 The caller needs to provide a "next_vector" function and a private 218 214 state for this function. The tstream_readv_pdu engine will ask 219 the next_vector function for the next iovec ve tor to be filled.215 the next_vector function for the next iovec vector to be used. 220 216 There's a tstream_readv_send/recv pair for each vector returned 221 217 by the next_vector function. If the next_vector function detects … … 223 219 of the tevent_req (returned by tstream_readv_pdu_send()) is triggered. 224 220 Note: the buffer allocation is completely up to the next_vector function 225 and it 's private state.221 and its private state. 226 222 227 223 See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an … … 245 241 =========================================== 246 242 247 There're some cases where the caller wants doesn't care aboutthe248 order of doing IO on the abstracted sockets.243 In some cases the caller doesn't care about the IO ordering on the 244 abstracted socket. 249 245 (Remember at the low level there's always only one IO in a specific 250 246 direction allowed, only one tdgram_sendto_send() at a time). 251 247 252 There're some helpers using 'tevent_queue' to make it easier 253 for callers. The functions just get a 'queue' argument 254 and serialize theoperations.248 Some helpers that use 'tevent_queue' are avilable to simplify handling 249 multiple IO requests. The functions just get a 'queue' argument and 250 internally serialize all operations. 255 251 256 252 struct tevent_req *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx, … … 296 292 (dns names are not allowed!). But it's valid to pass NULL, 297 293 which gets mapped to "0.0.0.0" or "::". 298 It return -1 and seterrno on error. Otherwise it returns 0.294 It returns -1 and sets errno on error. Otherwise it returns 0. 299 295 300 296 int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx, … … 343 339 you can use the tsocket_address_unix_path() function. 344 340 It will return NULL and set errno to EINVAL if the tsocket_address 345 doesn't represent a nunix domain endpoint path.341 doesn't represent a unix domain endpoint path. 346 342 347 343 char *tsocket_address_unix_path(const struct tsocket_address *addr, … … 372 368 struct tdgram_context **dgram); 373 369 374 You can use tstream_inet_tcp_connect_send to async 370 You can use tstream_inet_tcp_connect_send to asynchronously 375 371 connect to a remote ipv4 or ipv6 TCP endpoint and create a 376 372 tstream_context for the stream based communication. "local_address" has to be … … 398 394 struct tstream_context **stream); 399 395 400 You can use tstream_unix_connect_send to async 396 You can use tstream_unix_connect_send to asynchronously 401 397 connect to a unix domain endpoint and create a 402 398 tstream_context for the stream based communication. … … 439 435 for that. This should only be used if really needed, because of 440 436 already existing fixed APIs. Only AF_INET, AF_INET6 and AF_UNIX 441 sockets are allowed. The function returns -1 and set errno on error.437 sockets are allowed. The function returns -1 and sets errno on error. 442 438 Otherwise it returns 0. 443 439 -
vendor/current/lib/uid_wrapper/uid_wrapper.c
r414 r740 16 16 */ 17 17 18 #ifdef _SAMBA_BUILD_ 19 18 20 #define UID_WRAPPER_NOT_REPLACE 19 #include "includes.h" 21 #include "../replace/replace.h" 22 #include <talloc.h> 20 23 #include "system/passwd.h" 21 #include "system/filesys.h" 24 25 #else /* _SAMBA_BUILD_ */ 26 27 #error uid_wrapper_only_supported_in_samba_yet 28 29 #endif 22 30 23 31 #ifndef _PUBLIC_ … … 45 53 /* put us in one group */ 46 54 uwrap.ngroups = 1; 47 uwrap.groups = talloc_array( talloc_autofree_context(), gid_t, 1);55 uwrap.groups = talloc_array(NULL, gid_t, 1); 48 56 uwrap.groups[0] = 0; 49 57 } … … 109 117 110 118 if (size != 0) { 111 uwrap.groups = talloc_array( talloc_autofree_context(), gid_t, size);119 uwrap.groups = talloc_array(NULL, gid_t, size); 112 120 if (uwrap.groups == NULL) { 113 121 errno = ENOMEM; -
vendor/current/lib/uid_wrapper/uid_wrapper.h
r414 r740 18 18 #ifndef __UID_WRAPPER_H__ 19 19 #define __UID_WRAPPER_H__ 20 #ifndef uwrap_enabled 21 22 int uwrap_enabled(void); 23 int uwrap_seteuid(uid_t euid); 24 uid_t uwrap_geteuid(void); 25 int uwrap_setegid(gid_t egid); 26 uid_t uwrap_getegid(void); 27 int uwrap_setgroups(size_t size, const gid_t *list); 28 int uwrap_getgroups(int size, gid_t *list); 29 uid_t uwrap_getuid(void); 30 gid_t uwrap_getgid(void); 20 31 21 32 #ifdef seteuid … … 59 70 #define getgid uwrap_getgid 60 71 61 int uwrap_enabled(void); 62 72 #endif 63 73 #endif /* __UID_WRAPPER_H__ */ -
vendor/current/lib/util/asn1.c
r597 r740 215 215 } 216 216 217 bool ber_write_OID_String( DATA_BLOB *blob, const char *OID)218 { 219 u int_t v, v2;217 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID) 218 { 219 unsigned int v, v2; 220 220 const char *p = (const char *)OID; 221 221 char *newp; 222 222 int i; 223 223 224 if (!isdigit(*p)) return false; 224 225 v = strtoul(p, &newp, 10); 225 226 if (newp[0] != '.') return false; 226 227 p = newp + 1; 227 228 229 if (!isdigit(*p)) return false; 228 230 v2 = strtoul(p, &newp, 10); 229 231 if (newp[0] != '.') return false; … … 231 233 232 234 /*the ber representation can't use more space then the string one */ 233 *blob = data_blob (NULL, strlen(OID));235 *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID)); 234 236 if (!blob->data) return false; 235 237 … … 238 240 i = 1; 239 241 while (*p) { 242 if (!isdigit(*p)) return false; 240 243 v = strtoul(p, &newp, 10); 241 244 if (newp[0] == '.') { 242 245 p = newp + 1; 246 /* check for empty last component */ 247 if (!*p) return false; 243 248 } else if (newp[0] == '\0') { 244 249 p = newp; … … 259 264 } 260 265 266 /** 267 * Serialize partial OID string. 268 * Partial OIDs are in the form: 269 * 1:2.5.6:0x81 270 * 1:2.5.6:0x8182 271 */ 272 bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid) 273 { 274 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 275 char *oid = talloc_strdup(tmp_ctx, partial_oid); 276 char *p; 277 278 /* truncate partial part so ber_write_OID_String() works */ 279 p = strchr(oid, ':'); 280 if (p) { 281 *p = '\0'; 282 p++; 283 } 284 285 if (!ber_write_OID_String(mem_ctx, blob, oid)) { 286 talloc_free(tmp_ctx); 287 return false; 288 } 289 290 /* Add partially encoded sub-identifier */ 291 if (p) { 292 DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p); 293 if (!data_blob_append(mem_ctx, blob, tmp_blob.data, 294 tmp_blob.length)) { 295 talloc_free(tmp_ctx); 296 return false; 297 } 298 } 299 300 talloc_free(tmp_ctx); 301 302 return true; 303 } 304 261 305 /* write an object ID to a ASN1 buffer */ 262 306 bool asn1_write_OID(struct asn1_data *data, const char *OID) … … 266 310 if (!asn1_push_tag(data, ASN1_OID)) return false; 267 311 268 if (!ber_write_OID_String( &blob, OID)) {312 if (!ber_write_OID_String(NULL, &blob, OID)) { 269 313 data->has_error = true; 270 314 return false; … … 453 497 454 498 return (b == tag); 499 } 500 501 /* 502 * just get the needed size the tag would consume 503 */ 504 bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size) 505 { 506 off_t start_ofs = data->ofs; 507 uint8_t b; 508 size_t taglen = 0; 509 510 if (data->has_error) { 511 return false; 512 } 513 514 if (!asn1_read_uint8(data, &b)) { 515 data->ofs = start_ofs; 516 data->has_error = false; 517 return false; 518 } 519 520 if (b != tag) { 521 data->ofs = start_ofs; 522 data->has_error = false; 523 return false; 524 } 525 526 if (!asn1_read_uint8(data, &b)) { 527 data->ofs = start_ofs; 528 data->has_error = false; 529 return false; 530 } 531 532 if (b & 0x80) { 533 int n = b & 0x7f; 534 if (!asn1_read_uint8(data, &b)) { 535 data->ofs = start_ofs; 536 data->has_error = false; 537 return false; 538 } 539 if (n > 4) { 540 /* 541 * We should not allow more than 4 bytes 542 * for the encoding of the tag length. 543 * 544 * Otherwise we'd overflow the taglen 545 * variable on 32 bit systems. 546 */ 547 data->ofs = start_ofs; 548 data->has_error = false; 549 return false; 550 } 551 taglen = b; 552 while (n > 1) { 553 if (!asn1_read_uint8(data, &b)) { 554 data->ofs = start_ofs; 555 data->has_error = false; 556 return false; 557 } 558 taglen = (taglen << 8) | b; 559 n--; 560 } 561 } else { 562 taglen = b; 563 } 564 565 *size = (data->ofs - start_ofs) + taglen; 566 567 data->ofs = start_ofs; 568 data->has_error = false; 569 return true; 455 570 } 456 571 … … 544 659 } 545 660 546 /* read an object ID from a data blob */ 547 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) 661 /** 662 * Internal implementation for reading binary OIDs 663 * Reading is done as far in the buffer as valid OID 664 * till buffer ends or not valid sub-identifier is found. 665 */ 666 static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob, 667 char **OID, size_t *bytes_eaten) 548 668 { 549 669 int i; 550 670 uint8_t *b; 551 u int_t v;671 unsigned int v; 552 672 char *tmp_oid = NULL; 553 673 … … 560 680 tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", b[0]%40); 561 681 if (!tmp_oid) goto nomem; 682 683 if (bytes_eaten != NULL) { 684 *bytes_eaten = 0; 685 } 562 686 563 687 for(i = 1, v = 0; i < blob.length; i++) { … … 566 690 tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); 567 691 v = 0; 692 if (bytes_eaten) 693 *bytes_eaten = i+1; 568 694 } 569 695 if (!tmp_oid) goto nomem; 570 696 } 571 697 572 if (v != 0) {573 talloc_free(tmp_oid);574 return false;575 }576 577 698 *OID = tmp_oid; 578 699 return true; 579 700 580 nomem: 701 nomem: 581 702 return false; 582 703 } 583 704 705 /* read an object ID from a data blob */ 706 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID) 707 { 708 size_t bytes_eaten; 709 710 if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten)) 711 return false; 712 713 return (bytes_eaten == blob.length); 714 } 715 716 /** 717 * Deserialize partial OID string. 718 * Partial OIDs are in the form: 719 * 1:2.5.6:0x81 720 * 1:2.5.6:0x8182 721 */ 722 bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, 723 char **partial_oid) 724 { 725 size_t bytes_left; 726 size_t bytes_eaten; 727 char *identifier = NULL; 728 char *tmp_oid = NULL; 729 730 if (!_ber_read_OID_String_impl(mem_ctx, blob, &tmp_oid, &bytes_eaten)) 731 return false; 732 733 if (bytes_eaten < blob.length) { 734 bytes_left = blob.length - bytes_eaten; 735 identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left); 736 if (!identifier) goto nomem; 737 738 *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier); 739 if (!*partial_oid) goto nomem; 740 TALLOC_FREE(identifier); 741 } else { 742 *partial_oid = tmp_oid; 743 } 744 745 return true; 746 747 nomem: 748 TALLOC_FREE(identifier); 749 TALLOC_FREE(tmp_oid); 750 return false; 751 } 752 584 753 /* read an object ID from a ASN1 buffer */ 585 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, c onst char **OID)754 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID) 586 755 { 587 756 DATA_BLOB blob; … … 622 791 bool asn1_check_OID(struct asn1_data *data, const char *OID) 623 792 { 624 c onst char *id;793 char *id; 625 794 626 795 if (!asn1_read_OID(data, data, &id)) return false; 627 796 628 797 if (strcmp(id, OID) != 0) { 629 talloc_free( discard_const(id));630 data->has_error = true; 631 return false; 632 } 633 talloc_free( discard_const(id));798 talloc_free(id); 799 data->has_error = true; 800 return false; 801 } 802 talloc_free(id); 634 803 return true; 635 804 } … … 865 1034 if (size > blob.length) { 866 1035 return STATUS_MORE_ENTRIES; 867 } 1036 } 868 1037 869 1038 *packet_size = size; 870 1039 return NT_STATUS_OK; 871 1040 } 1041 1042 NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) 1043 { 1044 struct asn1_data asn1; 1045 size_t size; 1046 bool ok; 1047 1048 ZERO_STRUCT(asn1); 1049 asn1.data = blob.data; 1050 asn1.length = blob.length; 1051 1052 ok = asn1_peek_tag_needed_size(&asn1, tag, &size); 1053 if (!ok) { 1054 return NT_STATUS_INVALID_BUFFER_SIZE; 1055 } 1056 1057 if (size > blob.length) { 1058 *packet_size = size; 1059 return STATUS_MORE_ENTRIES; 1060 } 1061 1062 *packet_size = size; 1063 return NT_STATUS_OK; 1064 } -
vendor/current/lib/util/asn1.h
r414 r740 62 62 bool asn1_write_Integer(struct asn1_data *data, int i); 63 63 bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding); 64 bool ber_write_OID_String(DATA_BLOB *blob, const char *OID); 64 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID); 65 bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid); 65 66 bool asn1_write_OID(struct asn1_data *data, const char *OID); 66 67 bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length); … … 79 80 bool asn1_read_uint8(struct asn1_data *data, uint8_t *v); 80 81 bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v); 82 bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size); 81 83 bool asn1_peek_tag(struct asn1_data *data, uint8_t tag); 82 84 bool asn1_start_tag(struct asn1_data *data, uint8_t tag); 83 85 bool asn1_end_tag(struct asn1_data *data); 84 86 int asn1_tag_remaining(struct asn1_data *data); 85 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID); 86 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID); 87 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID); 88 bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **partial_oid); 89 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID); 87 90 bool asn1_check_OID(struct asn1_data *data, const char *OID); 88 91 bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s); … … 99 102 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len); 100 103 NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size); 104 NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size); 101 105 102 106 #endif /* _ASN_1_H */ -
vendor/current/lib/util/attr.h
r414 r740 28 28 # define UNUSED(param) param 29 29 /** Feel free to add definitions for other compilers here. */ 30 #endif31 32 #ifdef HAVE_VISIBILITY_ATTR33 # define _PUBLIC_ __attribute__((visibility("default")))34 #else35 # define _PUBLIC_36 30 #endif 37 31 … … 88 82 #endif 89 83 84 #ifndef FORMAT_ATTRIBUTE 85 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) 86 /** Use gcc attribute to check printf fns. a1 is argument to format() 87 * in the above macro. This is needed to support Heimdal's printf 88 * decorations. Note that some gcc 2.x versions don't handle this 89 * properly, and as such I've used the same minimum from heimdal: GCC 3.1 **/ 90 #define FORMAT_ATTRIBUTE(a) __attribute__ ((format a)) 91 #else 92 #define FORMAT_ATTRIBUTE(a) 93 #endif 94 #endif 95 90 96 #endif /* __UTIL_ATTR_H__ */ -
vendor/current/lib/util/become_daemon.c
r414 r740 67 67 ****************************************************************************/ 68 68 69 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group )69 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout) 70 70 { 71 71 if (do_fork) { … … 88 88 #endif /* HAVE_SETSID */ 89 89 90 /* Close fd's 0,1,2. Needed if started by rsh */ 91 close_low_fds(false); /* Don't close stderr, let the debug system 92 attach it to the logfile */ 90 if (!log_stdout) { 91 /* Close fd's 0,1,2. Needed if started by rsh */ 92 close_low_fds(false); /* Don't close stderr, let the debug system 93 attach it to the logfile */ 94 } 93 95 } -
vendor/current/lib/util/binsearch.h
r414 r740 66 66 }} } while (0) 67 67 68 /* 69 like BINARY_ARRAY_SEARCH_P, but assumes that the array is an array 70 of elements, rather than pointers to structures 71 72 result points to the found structure, or NULL 73 */ 74 #define BINARY_ARRAY_SEARCH_V(array, array_size, target, comparison_fn, result) do { \ 75 int32_t _b, _e; \ 76 (result) = NULL; \ 77 if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ 78 int32_t _i = (_b+_e)/2; \ 79 int _r = comparison_fn(target, array[_i]); \ 80 if (_r == 0) { (result) = &array[_i]; break; } \ 81 if (_r < 0) _e = _i - 1; else _b = _i + 1; \ 82 }} } while (0) 83 68 84 #endif -
vendor/current/lib/util/byteorder.h
r414 r740 55 55 56 56 #define CVAL(buf,pos) (((uint8_t *)(buf))[pos]) 57 #define PVAL(buf,pos) ((u int_t)CVAL(buf,pos))57 #define PVAL(buf,pos) ((unsigned int)CVAL(buf,pos)) 58 58 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) 59 59 … … 145 145 #endif 146 146 147 #define CVAL(buf,pos) ((u int_t)(((const uint8_t *)(buf))[pos]))147 #define CVAL(buf,pos) ((unsigned int)(((const uint8_t *)(buf))[pos])) 148 148 #define CVAL_NC(buf,pos) (((uint8_t *)(buf))[pos]) /* Non-const version of CVAL */ 149 149 #define PVAL(buf,pos) (CVAL(buf,pos)) … … 186 186 /* get single value from an SMB buffer */ 187 187 #define SVAL(buf,pos) (*(const uint16_t *)((const char *)(buf) + (pos))) 188 #define SVAL_NC(buf,pos) (*(uint16_t *)(( char *)(buf) + (pos))) /* Non const version of above. */188 #define SVAL_NC(buf,pos) (*(uint16_t *)((void *)((char *)(buf) + (pos)))) /* Non const version of above. */ 189 189 #define IVAL(buf,pos) (*(const uint32_t *)((const char *)(buf) + (pos))) 190 #define IVAL_NC(buf,pos) (*(uint32_t *)(( char *)(buf) + (pos))) /* Non const version of above. */190 #define IVAL_NC(buf,pos) (*(uint32_t *)((void *)((char *)(buf) + (pos)))) /* Non const version of above. */ 191 191 #define SVALS(buf,pos) (*(const int16_t *)((const char *)(buf) + (pos))) 192 #define SVALS_NC(buf,pos) (*(int16_t *)(( char *)(buf) + (pos))) /* Non const version of above. */192 #define SVALS_NC(buf,pos) (*(int16_t *)((void *)((char *)(buf) + (pos)))) /* Non const version of above. */ 193 193 #define IVALS(buf,pos) (*(const int32_t *)((const char *)(buf) + (pos))) 194 #define IVALS_NC(buf,pos) (*(int32_t *)(( char *)(buf) + (pos))) /* Non const version of above. */194 #define IVALS_NC(buf,pos) (*(int32_t *)((void *)((char *)(buf) + (pos)))) /* Non const version of above. */ 195 195 196 196 /* store single value in an SMB buffer */ … … 202 202 #endif /* not CAREFUL_ALIGNMENT */ 203 203 204 /* now the reverse routines - these are used in nmb packets (mostly) */205 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))206 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))207 208 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))209 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))210 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))211 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))212 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))213 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))214 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))215 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))216 217 /* Alignment macros. */218 #define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3))219 #define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1))220 221 222 /* macros for accessing SMB protocol elements */223 #define VWV(vwv) ((vwv)*2)224 225 204 /* 64 bit macros */ 226 205 #define BVAL(p, ofs) (IVAL(p,ofs) | (((uint64_t)IVAL(p,(ofs)+4)) << 32)) … … 229 208 #define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)v)) 230 209 210 /* now the reverse routines - these are used in nmb packets (mostly) */ 211 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) 212 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) 213 #define BREV(x) ((IREV(x)<<32) | (IREV((x)>>32))) 214 215 #define RSVAL(buf,pos) SREV(SVAL(buf,pos)) 216 #define RSVALS(buf,pos) SREV(SVALS(buf,pos)) 217 #define RIVAL(buf,pos) IREV(IVAL(buf,pos)) 218 #define RIVALS(buf,pos) IREV(IVALS(buf,pos)) 219 #define RBVAL(buf,pos) BREV(BVAL(buf,pos)) 220 #define RBVALS(buf,pos) BREV(BVALS(buf,pos)) 221 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) 222 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) 223 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) 224 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) 225 #define RSBVAL(buf,pos,val) SBVAL(buf,pos,BREV(val)) 226 #define RSBVALS(buf,pos,val) SBVALS(buf,pos,BREV(val)) 227 228 /* Alignment macros. */ 229 #define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3)) 230 #define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1)) 231 232 233 /* macros for accessing SMB protocol elements */ 234 #define VWV(vwv) ((vwv)*2) 235 231 236 #endif /* _BYTEORDER_H */ -
vendor/current/lib/util/charset/charcnv.c
r414 r740 39 39 */ 40 40 41 struct smb_iconv_convenience {42 const char *unix_charset;43 const char *dos_charset;44 bool native_iconv;45 smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];46 };47 48 49 /**50 * Return the name of a charset to give to iconv().51 **/52 static const char *charset_name(struct smb_iconv_convenience *ic, charset_t ch)53 {54 switch (ch) {55 case CH_UTF16: return "UTF-16LE";56 case CH_UNIX: return ic->unix_charset;57 case CH_DOS: return ic->dos_charset;58 case CH_UTF8: return "UTF8";59 case CH_UTF16BE: return "UTF-16BE";60 case CH_UTF16MUNGED: return "UTF16_MUNGED";61 default:62 return "ASCII";63 }64 }65 66 /**67 re-initialize iconv conversion descriptors68 **/69 static int close_iconv_convenience(struct smb_iconv_convenience *data)70 {71 unsigned c1, c2;72 for (c1=0;c1<NUM_CHARSETS;c1++) {73 for (c2=0;c2<NUM_CHARSETS;c2++) {74 if (data->conv_handles[c1][c2] != NULL) {75 if (data->conv_handles[c1][c2] != (smb_iconv_t)-1) {76 smb_iconv_close(data->conv_handles[c1][c2]);77 }78 data->conv_handles[c1][c2] = NULL;79 }80 }81 }82 83 return 0;84 }85 86 _PUBLIC_ struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx,87 const char *dos_charset,88 const char *unix_charset,89 bool native_iconv)90 {91 struct smb_iconv_convenience *ret = talloc_zero(mem_ctx,92 struct smb_iconv_convenience);93 94 if (ret == NULL) {95 return NULL;96 }97 98 talloc_set_destructor(ret, close_iconv_convenience);99 100 ret->dos_charset = talloc_strdup(ret, dos_charset);101 ret->unix_charset = talloc_strdup(ret, unix_charset);102 ret->native_iconv = native_iconv;103 104 return ret;105 }106 107 /*108 on-demand initialisation of conversion handles109 */110 static smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic,111 charset_t from, charset_t to)112 {113 const char *n1, *n2;114 static bool initialised;115 116 if (initialised == false) {117 initialised = true;118 119 #ifdef LC_ALL120 /* we set back the locale to C to get ASCII-compatible121 toupper/lower functions. For now we do not need122 any other POSIX localisations anyway. When we123 should really need localized string functions one124 day we need to write our own ascii_tolower etc.125 */126 setlocale(LC_ALL, "C");127 #endif128 }129 130 if (ic->conv_handles[from][to]) {131 return ic->conv_handles[from][to];132 }133 134 n1 = charset_name(ic, from);135 n2 = charset_name(ic, to);136 137 ic->conv_handles[from][to] = smb_iconv_open_ex(ic, n2, n1,138 ic->native_iconv);139 140 if (ic->conv_handles[from][to] == (smb_iconv_t)-1) {141 if ((from == CH_DOS || to == CH_DOS) &&142 strcasecmp(charset_name(ic, CH_DOS), "ASCII") != 0) {143 DEBUG(0,("dos charset '%s' unavailable - using ASCII\n",144 charset_name(ic, CH_DOS)));145 ic->dos_charset = "ASCII";146 147 n1 = charset_name(ic, from);148 n2 = charset_name(ic, to);149 150 ic->conv_handles[from][to] =151 smb_iconv_open_ex(ic, n2, n1, ic->native_iconv);152 }153 }154 155 return ic->conv_handles[from][to];156 }157 158 41 /** 159 42 * Convert string from one encoding to another, making error checking etc … … 214 97 break; 215 98 } 216 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); 99 DEBUG(0,("Conversion error: %s - ",reason)); 100 dump_data(0, (const uint8_t *) inbuf, i_len); 217 101 talloc_free(ob); 218 102 return (size_t)-1; … … 349 233 } 350 234 351 /*352 return the unicode codepoint for the next multi-byte CH_UNIX character353 in the string354 355 also return the number of bytes consumed (which tells the caller356 how many bytes to skip to get to the next CH_UNIX character)357 358 return INVALID_CODEPOINT if the next character cannot be converted359 */360 _PUBLIC_ codepoint_t next_codepoint_convenience(struct smb_iconv_convenience *ic,361 const char *str, size_t *size)362 {363 /* it cannot occupy more than 4 bytes in UTF16 format */364 uint8_t buf[4];365 smb_iconv_t descriptor;366 size_t ilen_orig;367 size_t ilen;368 size_t olen;369 char *outbuf;370 371 if ((str[0] & 0x80) == 0) {372 *size = 1;373 return (codepoint_t)str[0];374 }375 376 /* we assume that no multi-byte character can take377 more than 5 bytes. This is OK as we only378 support codepoints up to 1M */379 ilen_orig = strnlen(str, 5);380 ilen = ilen_orig;381 382 descriptor = get_conv_handle(ic, CH_UNIX, CH_UTF16);383 if (descriptor == (smb_iconv_t)-1) {384 *size = 1;385 return INVALID_CODEPOINT;386 }387 388 /* this looks a little strange, but it is needed to cope389 with codepoints above 64k */390 olen = 2;391 outbuf = (char *)buf;392 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);393 if (olen == 2) {394 olen = 4;395 outbuf = (char *)buf;396 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);397 if (olen == 4) {398 /* we didn't convert any bytes */399 *size = 1;400 return INVALID_CODEPOINT;401 }402 olen = 4 - olen;403 } else {404 olen = 2 - olen;405 }406 407 *size = ilen_orig - ilen;408 409 if (olen == 2) {410 return (codepoint_t)SVAL(buf, 0);411 }412 if (olen == 4) {413 /* decode a 4 byte UTF16 character manually */414 return (codepoint_t)0x10000 +415 (buf[2] | ((buf[3] & 0x3)<<8) |416 (buf[0]<<10) | ((buf[1] & 0x3)<<18));417 }418 419 /* no other length is valid */420 return INVALID_CODEPOINT;421 }422 423 /*424 push a single codepoint into a CH_UNIX string the target string must425 be able to hold the full character, which is guaranteed if it is at426 least 5 bytes in size. The caller may pass less than 5 bytes if they427 are sure the character will fit (for example, you can assume that428 uppercase/lowercase of a character will not add more than 1 byte)429 430 return the number of bytes occupied by the CH_UNIX character, or431 -1 on failure432 */433 _PUBLIC_ ssize_t push_codepoint_convenience(struct smb_iconv_convenience *ic,434 char *str, codepoint_t c)435 {436 smb_iconv_t descriptor;437 uint8_t buf[4];438 size_t ilen, olen;439 const char *inbuf;440 441 if (c < 128) {442 *str = c;443 return 1;444 }445 446 descriptor = get_conv_handle(ic,447 CH_UTF16, CH_UNIX);448 if (descriptor == (smb_iconv_t)-1) {449 return -1;450 }451 452 if (c < 0x10000) {453 ilen = 2;454 olen = 5;455 inbuf = (char *)buf;456 SSVAL(buf, 0, c);457 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);458 if (ilen != 0) {459 return -1;460 }461 return 5 - olen;462 }463 464 c -= 0x10000;465 466 buf[0] = (c>>10) & 0xFF;467 buf[1] = (c>>18) | 0xd8;468 buf[2] = c & 0xFF;469 buf[3] = ((c>>8) & 0x3) | 0xdc;470 471 ilen = 4;472 olen = 5;473 inbuf = (char *)buf;474 475 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);476 if (ilen != 0) {477 return -1;478 }479 return 5 - olen;480 }481 482 -
vendor/current/lib/util/charset/charset.h
r587 r740 40 40 typedef uint16_t smb_ucs2_t; 41 41 42 #ifdef WORDS_BIGENDIAN 43 #define UCS2_SHIFT 8 44 #else 45 #define UCS2_SHIFT 0 46 #endif 47 48 /* turn a 7 bit character into a ucs2 character */ 49 #define UCS2_CHAR(c) ((c) << UCS2_SHIFT) 50 51 /* return an ascii version of a ucs2 character */ 52 #define UCS2_TO_CHAR(c) (((c) >> UCS2_SHIFT) & 0xff) 53 54 /* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */ 55 #define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((unsigned char *)(src))[0],\ 56 ((unsigned char *)(dest))[1] = ((unsigned char *)(src))[1], (dest)) 57 58 59 42 60 /* 43 61 * for each charset we have a function that pulls from that charset to … … 103 121 104 122 char *strchr_m(const char *s, char c); 123 size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset); 124 size_t strlen_m_ext_term(const char *s, charset_t src_charset, 125 charset_t dst_charset); 105 126 size_t strlen_m_term(const char *s); 106 127 size_t strlen_m_term_null(const char *s); … … 150 171 151 172 extern struct smb_iconv_convenience *global_iconv_convenience; 152 173 struct smb_iconv_convenience *get_iconv_convenience(void); 174 smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic, 175 charset_t from, charset_t to); 176 const char *charset_name(struct smb_iconv_convenience *ic, charset_t ch); 177 178 codepoint_t next_codepoint_ext(const char *str, charset_t src_charset, 179 size_t *size); 153 180 codepoint_t next_codepoint(const char *str, size_t *size); 154 181 ssize_t push_codepoint(char *str, codepoint_t c); 155 182 156 183 /* codepoints */ 184 codepoint_t next_codepoint_convenience_ext(struct smb_iconv_convenience *ic, 185 const char *str, charset_t src_charset, 186 size_t *size); 157 187 codepoint_t next_codepoint_convenience(struct smb_iconv_convenience *ic, 158 188 const char *str, size_t *size); 159 189 ssize_t push_codepoint_convenience(struct smb_iconv_convenience *ic, 160 190 char *str, codepoint_t c); 191 161 192 codepoint_t toupper_m(codepoint_t val); 162 193 codepoint_t tolower_m(codepoint_t val); 194 bool islower_m(codepoint_t val); 195 bool isupper_m(codepoint_t val); 163 196 int codepoint_cmpi(codepoint_t c1, codepoint_t c2); 164 197 165 198 /* Iconv convenience functions */ 166 struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx, 167 const char *dos_charset, 168 const char *unix_charset, 169 bool native_iconv); 199 struct smb_iconv_convenience *smb_iconv_convenience_reinit(TALLOC_CTX *mem_ctx, 200 const char *dos_charset, 201 const char *unix_charset, 202 const char *display_charset, 203 bool native_iconv, 204 struct smb_iconv_convenience *old_ic); 170 205 171 206 bool convert_string_convenience(struct smb_iconv_convenience *ic, … … 189 224 190 225 void load_case_tables(void); 191 bool charset_register_backend(const void *_funcs); 226 void load_case_tables_library(void); 227 bool smb_register_charset(const struct charset_functions *funcs_in); 192 228 193 229 /* … … 264 300 NTSTATUS charset_ ## CHARSETNAME ## _init(void) \ 265 301 { \ 266 return smb_register_charset(& CHARSETNAME ## _functions); \ 267 } \ 302 if (!smb_register_charset(& CHARSETNAME ## _functions)) { \ 303 return NT_STATUS_INTERNAL_ERROR; \ 304 } \ 305 return NT_STATUS_OK; \ 306 } \ 268 307 269 308 -
vendor/current/lib/util/charset/codepoints.c
r414 r740 1 1 /* 2 2 Unix SMB/CIFS implementation. 3 Samba utility functions 4 Copyright (C) Andrew Tridgell 1992-2001 3 Character set conversion Extensions 4 Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001 5 Copyright (C) Andrew Tridgell 2001 5 6 Copyright (C) Simo Sorce 2001 7 Copyright (C) Jelmer Vernooij 2007 6 8 7 9 This program is free software; you can redistribute it and/or modify … … 17 19 You should have received a copy of the GNU General Public License 18 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 19 22 */ 20 21 23 #include "includes.h" 24 #include "lib/util/charset/charset.h" 22 25 #include "system/locale.h" 23 #include "dynconfig/dynconfig.h" 26 #include "dynconfig.h" 27 28 #ifdef strcasecmp 29 #undef strcasecmp 30 #endif 24 31 25 32 /** … … 36 43 /******************************************************************* 37 44 load the case handling tables 45 46 This is the function that should be called from library code. 38 47 ********************************************************************/ 39 void load_case_tables (void)48 void load_case_tables_library(void) 40 49 { 41 50 TALLOC_CTX *mem_ctx; … … 45 54 smb_panic("No memory for case_tables"); 46 55 } 47 upcase_table = map_file(talloc_asprintf(mem_ctx, "%s/upcase.dat", dyn_DATADIR), 0x20000);48 lowcase_table = map_file(talloc_asprintf(mem_ctx, "%s/lowcase.dat", dyn_DATADIR), 0x20000);56 upcase_table = map_file(talloc_asprintf(mem_ctx, "%s/upcase.dat", get_dyn_CODEPAGEDIR()), 0x20000); 57 lowcase_table = map_file(talloc_asprintf(mem_ctx, "%s/lowcase.dat", get_dyn_CODEPAGEDIR()), 0x20000); 49 58 talloc_free(mem_ctx); 50 59 if (upcase_table == NULL) { 51 /* try also under codepages for testing purposes */ 52 upcase_table = map_file("codepages/upcase.dat", 0x20000); 53 if (upcase_table == NULL) { 54 upcase_table = (void *)-1; 55 } 60 DEBUG(1, ("Failed to load upcase.dat, will use lame ASCII-only case sensitivity rules\n")); 61 upcase_table = (void *)-1; 56 62 } 57 63 if (lowcase_table == NULL) { 58 /* try also under codepages for testing purposes */ 59 lowcase_table = map_file("codepages/lowcase.dat", 0x20000); 60 if (lowcase_table == NULL) { 61 lowcase_table = (void *)-1; 62 } 63 } 64 DEBUG(1, ("Failed to load lowcase.dat, will use lame ASCII-only case sensitivity rules\n")); 65 lowcase_table = (void *)-1; 66 } 67 } 68 69 /******************************************************************* 70 load the case handling tables 71 72 This MUST only be called from main() in application code, never from a 73 library. We don't know if the calling program has already done 74 setlocale() to another value, and can't tell if they have. 75 ********************************************************************/ 76 void load_case_tables(void) 77 { 78 /* This is a useful global hook where we can ensure that the 79 * locale is set from the environment. This is needed so that 80 * we can use LOCALE as a codepage */ 81 #ifdef HAVE_SETLOCALE 82 setlocale(LC_ALL, ""); 83 #endif 84 load_case_tables_library(); 64 85 } 65 86 … … 73 94 } 74 95 if (upcase_table == NULL) { 75 load_case_tables ();96 load_case_tables_library(); 76 97 } 77 98 if (upcase_table == (void *)-1) { … … 93 114 } 94 115 if (lowcase_table == NULL) { 95 load_case_tables ();116 load_case_tables_library(); 96 117 } 97 118 if (lowcase_table == (void *)-1) { … … 102 123 } 103 124 return SVAL(lowcase_table, val*2); 125 } 126 127 /** 128 If we upper cased this character, would we get the same character? 129 **/ 130 _PUBLIC_ bool islower_m(codepoint_t val) 131 { 132 return (toupper_m(val) != val); 133 } 134 135 /** 136 If we lower cased this character, would we get the same character? 137 **/ 138 _PUBLIC_ bool isupper_m(codepoint_t val) 139 { 140 return (tolower_m(val) != val); 104 141 } 105 142 … … 117 154 118 155 156 struct smb_iconv_convenience { 157 TALLOC_CTX *child_ctx; 158 const char *unix_charset; 159 const char *dos_charset; 160 const char *display_charset; 161 bool native_iconv; 162 smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; 163 }; 164 165 struct smb_iconv_convenience *global_iconv_convenience = NULL; 166 167 struct smb_iconv_convenience *get_iconv_convenience(void) 168 { 169 if (global_iconv_convenience == NULL) 170 global_iconv_convenience = smb_iconv_convenience_reinit(talloc_autofree_context(), 171 "ASCII", "UTF-8", "ASCII", true, NULL); 172 return global_iconv_convenience; 173 } 174 175 /** 176 * Return the name of a charset to give to iconv(). 177 **/ 178 const char *charset_name(struct smb_iconv_convenience *ic, charset_t ch) 179 { 180 switch (ch) { 181 case CH_UTF16: return "UTF-16LE"; 182 case CH_UNIX: return ic->unix_charset; 183 case CH_DOS: return ic->dos_charset; 184 case CH_DISPLAY: return ic->display_charset; 185 case CH_UTF8: return "UTF8"; 186 case CH_UTF16BE: return "UTF-16BE"; 187 case CH_UTF16MUNGED: return "UTF16_MUNGED"; 188 default: 189 return "ASCII"; 190 } 191 } 192 193 /** 194 re-initialize iconv conversion descriptors 195 **/ 196 static int close_iconv_convenience(struct smb_iconv_convenience *data) 197 { 198 unsigned c1, c2; 199 for (c1=0;c1<NUM_CHARSETS;c1++) { 200 for (c2=0;c2<NUM_CHARSETS;c2++) { 201 if (data->conv_handles[c1][c2] != NULL) { 202 if (data->conv_handles[c1][c2] != (smb_iconv_t)-1) { 203 smb_iconv_close(data->conv_handles[c1][c2]); 204 } 205 data->conv_handles[c1][c2] = NULL; 206 } 207 } 208 } 209 210 return 0; 211 } 212 213 static const char *map_locale(const char *charset) 214 { 215 if (strcmp(charset, "LOCALE") != 0) { 216 return charset; 217 } 218 #if defined(HAVE_NL_LANGINFO) && defined(CODESET) 219 { 220 const char *ln; 221 smb_iconv_t handle; 222 223 ln = nl_langinfo(CODESET); 224 if (ln == NULL) { 225 DEBUG(1,("Unable to determine charset for LOCALE - using ASCII\n")); 226 return "ASCII"; 227 } 228 /* Check whether the charset name is supported 229 by iconv */ 230 handle = smb_iconv_open(ln, "UCS-2LE"); 231 if (handle == (smb_iconv_t) -1) { 232 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln)); 233 return "ASCII"; 234 } else { 235 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln)); 236 smb_iconv_close(handle); 237 } 238 return ln; 239 } 240 #endif 241 return "ASCII"; 242 } 243 244 /* 245 the old_ic is passed in here as the smb_iconv_convenience structure 246 is used as a global pointer in some places (eg. python modules). We 247 don't want to invalidate those global pointers, but we do want to 248 update them with the right charset information when loadparm 249 runs. To do that we need to re-use the structure pointer, but 250 re-fill the elements in the structure with the updated values 251 */ 252 _PUBLIC_ struct smb_iconv_convenience *smb_iconv_convenience_reinit(TALLOC_CTX *mem_ctx, 253 const char *dos_charset, 254 const char *unix_charset, 255 const char *display_charset, 256 bool native_iconv, 257 struct smb_iconv_convenience *old_ic) 258 { 259 struct smb_iconv_convenience *ret; 260 261 display_charset = map_locale(display_charset); 262 263 if (old_ic != NULL) { 264 ret = old_ic; 265 close_iconv_convenience(ret); 266 talloc_free(ret->child_ctx); 267 ZERO_STRUCTP(ret); 268 } else { 269 ret = talloc_zero(mem_ctx, struct smb_iconv_convenience); 270 } 271 if (ret == NULL) { 272 return NULL; 273 } 274 275 /* we use a child context to allow us to free all ptrs without 276 freeing the structure itself */ 277 ret->child_ctx = talloc_new(ret); 278 if (ret->child_ctx == NULL) { 279 return NULL; 280 } 281 282 talloc_set_destructor(ret, close_iconv_convenience); 283 284 ret->dos_charset = talloc_strdup(ret->child_ctx, dos_charset); 285 ret->unix_charset = talloc_strdup(ret->child_ctx, unix_charset); 286 ret->display_charset = talloc_strdup(ret->child_ctx, display_charset); 287 ret->native_iconv = native_iconv; 288 289 return ret; 290 } 291 292 /* 293 on-demand initialisation of conversion handles 294 */ 295 smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic, 296 charset_t from, charset_t to) 297 { 298 const char *n1, *n2; 299 static bool initialised; 300 301 if (initialised == false) { 302 initialised = true; 303 } 304 305 if (ic->conv_handles[from][to]) { 306 return ic->conv_handles[from][to]; 307 } 308 309 n1 = charset_name(ic, from); 310 n2 = charset_name(ic, to); 311 312 ic->conv_handles[from][to] = smb_iconv_open_ex(ic, n2, n1, 313 ic->native_iconv); 314 315 if (ic->conv_handles[from][to] == (smb_iconv_t)-1) { 316 if ((from == CH_DOS || to == CH_DOS) && 317 strcasecmp(charset_name(ic, CH_DOS), "ASCII") != 0) { 318 DEBUG(0,("dos charset '%s' unavailable - using ASCII\n", 319 charset_name(ic, CH_DOS))); 320 ic->dos_charset = "ASCII"; 321 322 n1 = charset_name(ic, from); 323 n2 = charset_name(ic, to); 324 325 ic->conv_handles[from][to] = 326 smb_iconv_open_ex(ic, n2, n1, ic->native_iconv); 327 } 328 } 329 330 return ic->conv_handles[from][to]; 331 } 332 333 /** 334 * Return the unicode codepoint for the next character in the input 335 * string in the given src_charset. 336 * The unicode codepoint (codepoint_t) is an unsinged 32 bit value. 337 * 338 * Also return the number of bytes consumed (which tells the caller 339 * how many bytes to skip to get to the next src_charset-character). 340 * 341 * This is implemented (in the non-ascii-case) by first converting the 342 * next character in the input string to UTF16_LE and then calculating 343 * the unicode codepoint from that. 344 * 345 * Return INVALID_CODEPOINT if the next character cannot be converted. 346 */ 347 _PUBLIC_ codepoint_t next_codepoint_convenience_ext( 348 struct smb_iconv_convenience *ic, 349 const char *str, charset_t src_charset, 350 size_t *bytes_consumed) 351 { 352 /* it cannot occupy more than 4 bytes in UTF16 format */ 353 uint8_t buf[4]; 354 smb_iconv_t descriptor; 355 size_t ilen_orig; 356 size_t ilen; 357 size_t olen; 358 char *outbuf; 359 360 if ((str[0] & 0x80) == 0) { 361 *bytes_consumed = 1; 362 return (codepoint_t)str[0]; 363 } 364 365 /* 366 * we assume that no multi-byte character can take more than 5 bytes. 367 * This is OK as we only support codepoints up to 1M (U+100000) 368 */ 369 ilen_orig = strnlen(str, 5); 370 ilen = ilen_orig; 371 372 descriptor = get_conv_handle(ic, src_charset, CH_UTF16); 373 if (descriptor == (smb_iconv_t)-1) { 374 *bytes_consumed = 1; 375 return INVALID_CODEPOINT; 376 } 377 378 /* 379 * this looks a little strange, but it is needed to cope with 380 * codepoints above 64k (U+1000) which are encoded as per RFC2781. 381 */ 382 olen = 2; 383 outbuf = (char *)buf; 384 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); 385 if (olen == 2) { 386 olen = 4; 387 outbuf = (char *)buf; 388 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); 389 if (olen == 4) { 390 /* we didn't convert any bytes */ 391 *bytes_consumed = 1; 392 return INVALID_CODEPOINT; 393 } 394 olen = 4 - olen; 395 } else { 396 olen = 2 - olen; 397 } 398 399 *bytes_consumed = ilen_orig - ilen; 400 401 if (olen == 2) { 402 return (codepoint_t)SVAL(buf, 0); 403 } 404 if (olen == 4) { 405 /* decode a 4 byte UTF16 character manually */ 406 return (codepoint_t)0x10000 + 407 (buf[2] | ((buf[3] & 0x3)<<8) | 408 (buf[0]<<10) | ((buf[1] & 0x3)<<18)); 409 } 410 411 /* no other length is valid */ 412 return INVALID_CODEPOINT; 413 } 414 415 /* 416 return the unicode codepoint for the next multi-byte CH_UNIX character 417 in the string 418 419 also return the number of bytes consumed (which tells the caller 420 how many bytes to skip to get to the next CH_UNIX character) 421 422 return INVALID_CODEPOINT if the next character cannot be converted 423 */ 424 _PUBLIC_ codepoint_t next_codepoint_convenience(struct smb_iconv_convenience *ic, 425 const char *str, size_t *size) 426 { 427 return next_codepoint_convenience_ext(ic, str, CH_UNIX, size); 428 } 429 430 /* 431 push a single codepoint into a CH_UNIX string the target string must 432 be able to hold the full character, which is guaranteed if it is at 433 least 5 bytes in size. The caller may pass less than 5 bytes if they 434 are sure the character will fit (for example, you can assume that 435 uppercase/lowercase of a character will not add more than 1 byte) 436 437 return the number of bytes occupied by the CH_UNIX character, or 438 -1 on failure 439 */ 440 _PUBLIC_ ssize_t push_codepoint_convenience(struct smb_iconv_convenience *ic, 441 char *str, codepoint_t c) 442 { 443 smb_iconv_t descriptor; 444 uint8_t buf[4]; 445 size_t ilen, olen; 446 const char *inbuf; 447 448 if (c < 128) { 449 *str = c; 450 return 1; 451 } 452 453 descriptor = get_conv_handle(ic, 454 CH_UTF16, CH_UNIX); 455 if (descriptor == (smb_iconv_t)-1) { 456 return -1; 457 } 458 459 if (c < 0x10000) { 460 ilen = 2; 461 olen = 5; 462 inbuf = (char *)buf; 463 SSVAL(buf, 0, c); 464 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); 465 if (ilen != 0) { 466 return -1; 467 } 468 return 5 - olen; 469 } 470 471 c -= 0x10000; 472 473 buf[0] = (c>>10) & 0xFF; 474 buf[1] = (c>>18) | 0xd8; 475 buf[2] = c & 0xFF; 476 buf[3] = ((c>>8) & 0x3) | 0xdc; 477 478 ilen = 4; 479 olen = 5; 480 inbuf = (char *)buf; 481 482 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); 483 if (ilen != 0) { 484 return -1; 485 } 486 return 5 - olen; 487 } 488 489 _PUBLIC_ codepoint_t next_codepoint_ext(const char *str, charset_t src_charset, 490 size_t *size) 491 { 492 return next_codepoint_convenience_ext(get_iconv_convenience(), str, 493 src_charset, size); 494 } 495 496 _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size) 497 { 498 return next_codepoint_convenience(get_iconv_convenience(), str, size); 499 } 500 501 _PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c) 502 { 503 return push_codepoint_convenience(get_iconv_convenience(), str, c); 504 } -
vendor/current/lib/util/charset/iconv.c
r414 r740 24 24 #include "system/filesys.h" 25 25 26 #ifdef strcasecmp 27 #undef strcasecmp 28 #endif 29 30 #ifdef static_decl_charset 31 static_decl_charset; 32 #endif 26 33 27 34 /** … … 50 57 static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); 51 58 static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); 59 static size_t latin1_push(void *,const char **, size_t *, char **, size_t *); 52 60 static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); 53 61 static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); … … 73 81 74 82 {"ASCII", ascii_pull, ascii_push}, 83 {"646", ascii_pull, ascii_push}, 84 {"ISO-8859-1", ascii_pull, latin1_push}, 75 85 {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} 76 86 }; … … 78 88 static struct charset_functions *charsets = NULL; 79 89 80 bool charset_register_backend(const void *_funcs) 81 { 82 struct charset_functions *funcs = (struct charset_functions *)memdup(_funcs,sizeof(struct charset_functions)); 90 static struct charset_functions *find_charset_functions(const char *name) 91 { 83 92 struct charset_functions *c; 84 93 85 94 /* Check whether we already have this charset... */ 86 95 for (c = charsets; c != NULL; c = c->next) { 87 if(!strcasecmp(c->name, funcs->name)) { 88 DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); 89 return false; 90 } 91 } 96 if(strcasecmp(c->name, name) == 0) { 97 return c; 98 } 99 c = c->next; 100 } 101 102 return NULL; 103 } 104 105 bool smb_register_charset(const struct charset_functions *funcs_in) 106 { 107 struct charset_functions *funcs; 108 109 DEBUG(5, ("Attempting to register new charset %s\n", funcs_in->name)); 110 /* Check whether we already have this charset... */ 111 if (find_charset_functions(funcs_in->name)) { 112 DEBUG(0, ("Duplicate charset %s, not registering\n", funcs_in->name)); 113 return false; 114 } 115 116 funcs = talloc(NULL, struct charset_functions); 117 if (!funcs) { 118 DEBUG(0, ("Out of memory duplicating charset %s\n", funcs_in->name)); 119 return false; 120 } 121 *funcs = *funcs_in; 92 122 93 123 funcs->next = funcs->prev = NULL; 124 DEBUG(5, ("Registered charset %s\n", funcs->name)); 94 125 DLIST_ADD(charsets, funcs); 95 126 return true; 127 } 128 129 static void lazy_initialize_iconv(void) 130 { 131 static bool initialized; 132 133 #ifdef static_init_charset 134 if (!initialized) { 135 static_init_charset; 136 initialized = true; 137 } 138 #endif 96 139 } 97 140 … … 159 202 } 160 203 161 int smb_iconv_t_destructor(smb_iconv_t hwd)162 { 204 static int smb_iconv_t_destructor(smb_iconv_t hwd) 205 { 163 206 #ifdef HAVE_NATIVE_ICONV 164 207 if (hwd->cd_pull != NULL && hwd->cd_pull != (iconv_t)-1) … … 180 223 int i; 181 224 225 lazy_initialize_iconv(); 226 182 227 ret = (smb_iconv_t)talloc_named(mem_ctx, 183 228 sizeof(*ret), … … 261 306 if (is_utf16(tocode)) { 262 307 ret->direct = sys_iconv; 263 /* could be set just above - so we need to close iconv */264 if (ret->cd_direct != NULL && ret->cd_direct != (iconv_t)-1)265 iconv_close(ret->cd_direct);266 308 ret->cd_direct = ret->cd_pull; 267 309 ret->cd_pull = NULL; … … 286 328 _PUBLIC_ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) 287 329 { 288 return smb_iconv_open_ex( talloc_autofree_context(), tocode, fromcode, true);330 return smb_iconv_open_ex(NULL, tocode, fromcode, true); 289 331 } 290 332 … … 351 393 } 352 394 395 static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, 396 char **outbuf, size_t *outbytesleft) 397 { 398 int ir_count=0; 399 400 while (*inbytesleft >= 2 && *outbytesleft >= 1) { 401 (*outbuf)[0] = (*inbuf)[0]; 402 if ((*inbuf)[1]) ir_count++; 403 (*inbytesleft) -= 2; 404 (*outbytesleft) -= 1; 405 (*inbuf) += 2; 406 (*outbuf) += 1; 407 } 408 409 if (*inbytesleft == 1) { 410 errno = EINVAL; 411 return -1; 412 } 413 414 if (*inbytesleft > 1) { 415 errno = E2BIG; 416 return -1; 417 } 418 419 return ir_count; 420 } 353 421 354 422 static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, … … 356 424 { 357 425 while (*inbytesleft >= 1 && *outbytesleft >= 2) { 358 u int_t v;426 unsigned int v; 359 427 360 428 if ((*inbuf)[0] != '@') { -
vendor/current/lib/util/charset/tests/charset.c
r414 r740 247 247 struct torture_suite *torture_local_charset(TALLOC_CTX *mem_ctx) 248 248 { 249 struct torture_suite *suite = torture_suite_create(mem_ctx, " CHARSET");249 struct torture_suite *suite = torture_suite_create(mem_ctx, "charset"); 250 250 251 251 torture_suite_add_simple_test(suite, "toupper_m", test_toupper_m); -
vendor/current/lib/util/charset/tests/iconv.c
r414 r740 36 36 iconv_t cd; 37 37 38 if (!lp _parm_bool(tctx->lp_ctx, NULL, "iconv", "native", true))38 if (!lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "native", true)) 39 39 torture_skip(tctx, "system iconv disabled - skipping test"); 40 40 … … 135 135 uint8_t buf1[1000], buf2[1000], buf3[1000]; 136 136 size_t outsize1, outsize2, outsize3; 137 c onst char *ptr_in;137 char *ptr_in; 138 138 char *ptr_out; 139 139 size_t size_in1, size_in2, size_in3; … … 159 159 charset)); 160 160 } 161 cd2 = smb_iconv_open_ex(test, charset, "UTF-16LE", lp _parm_bool(test->lp_ctx, NULL, "iconv", "native", true));162 cd3 = smb_iconv_open_ex(test, "UTF-16LE", charset, lp _parm_bool(test->lp_ctx, NULL, "iconv", "native", true));161 cd2 = smb_iconv_open_ex(test, charset, "UTF-16LE", lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "native", true)); 162 cd3 = smb_iconv_open_ex(test, "UTF-16LE", charset, lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "native", true)); 163 163 last_charset = charset; 164 164 } 165 165 166 166 /* internal convert to charset - placing result in buf1 */ 167 ptr_in = (c onst char *)inbuf;167 ptr_in = (char *)inbuf; 168 168 ptr_out = (char *)buf1; 169 169 size_in1 = size; … … 172 172 memset(ptr_out, 0, outsize1); 173 173 errno = 0; 174 ret1 = smb_iconv(cd2, &ptr_in, &size_in1, &ptr_out, &outsize1);174 ret1 = smb_iconv(cd2, (const char **) &ptr_in, &size_in1, &ptr_out, &outsize1); 175 175 errno1 = errno; 176 176 177 177 /* system convert to charset - placing result in buf2 */ 178 ptr_in = (c onst char *)inbuf;178 ptr_in = (char *)inbuf; 179 179 ptr_out = (char *)buf2; 180 180 size_in2 = size; … … 183 183 memset(ptr_out, 0, outsize2); 184 184 errno = 0; 185 ret2 = iconv(cd, discard_const_p(char *, &ptr_in), &size_in2, &ptr_out, &outsize2);185 ret2 = iconv(cd, &ptr_in, &size_in2, &ptr_out, &outsize2); 186 186 errno2 = errno; 187 187 … … 237 237 /* convert back to UTF-16, putting result in buf3 */ 238 238 size = size - size_in1; 239 ptr_in = (c onst char *)buf1;239 ptr_in = (char *)buf1; 240 240 ptr_out = (char *)buf3; 241 241 size_in3 = len1; … … 243 243 244 244 memset(ptr_out, 0, outsize3); 245 ret3 = smb_iconv(cd3, &ptr_in, &size_in3, &ptr_out, &outsize3);245 ret3 = smb_iconv(cd3, (const char **) &ptr_in, &size_in3, &ptr_out, &outsize3); 246 246 247 247 /* we only internally support the first 1M codepoints */ … … 290 290 codepoint_t c; 291 291 292 size = push_codepoint_convenience(lp _iconv_convenience(tctx->lp_ctx), (char *)buf, codepoint);292 size = push_codepoint_convenience(lpcfg_iconv_convenience(tctx->lp_ctx), (char *)buf, codepoint); 293 293 torture_assert(tctx, size != -1 || (codepoint >= 0xd800 && codepoint <= 0x10000), 294 294 "Invalid Codepoint range"); … … 301 301 buf[size+3] = random(); 302 302 303 c = next_codepoint_convenience(lp _iconv_convenience(tctx->lp_ctx), (char *)buf, &size2);303 c = next_codepoint_convenience(lpcfg_iconv_convenience(tctx->lp_ctx), (char *)buf, &size2); 304 304 305 305 torture_assert(tctx, c == codepoint, … … 452 452 struct torture_suite *torture_local_iconv(TALLOC_CTX *mem_ctx) 453 453 { 454 struct torture_suite *suite = torture_suite_create(mem_ctx, " ICONV");454 struct torture_suite *suite = torture_suite_create(mem_ctx, "iconv"); 455 455 456 456 torture_suite_add_simple_test(suite, "string2key", -
vendor/current/lib/util/charset/util_unistr.c
r414 r740 22 22 #include "system/locale.h" 23 23 24 struct smb_iconv_convenience *global_iconv_convenience = NULL;25 26 static inline struct smb_iconv_convenience *get_iconv_convenience(void)27 {28 if (global_iconv_convenience == NULL)29 global_iconv_convenience = smb_iconv_convenience_init(talloc_autofree_context(), "ASCII", "UTF-8", true);30 return global_iconv_convenience;31 }32 33 24 /** 34 25 Case insensitive string compararison … … 68 59 69 60 return *s1 - *s2; 70 }71 72 /**73 * Get the next token from a string, return False if none found.74 * Handles double-quotes.75 *76 * Based on a routine by GJC@VILLAGE.COM.77 * Extensively modified by Andrew.Tridgell@anu.edu.au78 **/79 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)80 {81 const char *s;82 bool quoted;83 size_t len=1;84 85 if (!ptr)86 return false;87 88 s = *ptr;89 90 /* default to simple separators */91 if (!sep)92 sep = " \t\n\r";93 94 /* find the first non sep char */95 while (*s && strchr_m(sep,*s))96 s++;97 98 /* nothing left? */99 if (!*s)100 return false;101 102 /* copy over the token */103 for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {104 if (*s == '\"') {105 quoted = !quoted;106 } else {107 len++;108 *buff++ = *s;109 }110 }111 112 *ptr = (*s) ? s+1 : s;113 *buff = 0;114 115 return true;116 61 } 117 62 … … 249 194 250 195 /** 251 Count the number of UCS2 characters in a string. Normally this will 252 be the same as the number of bytes in a string for single byte strings, 253 but will be different for multibyte. 254 **/ 255 _PUBLIC_ size_t strlen_m(const char *s) 196 * Calculate the number of units (8 or 16-bit, depending on the 197 * destination charset), that would be needed to convert the input 198 * string which is expected to be in in src_charset encoding to the 199 * destination charset (which should be a unicode charset). 200 */ 201 _PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset) 256 202 { 257 203 size_t count = 0; … … 273 219 while (*s) { 274 220 size_t c_size; 275 codepoint_t c = next_codepoint_convenience(ic, s, &c_size); 276 if (c < 0x10000) { 221 codepoint_t c = next_codepoint_convenience_ext(ic, s, src_charset, &c_size); 222 s += c_size; 223 224 switch (dst_charset) { 225 case CH_UTF16LE: 226 case CH_UTF16BE: 227 case CH_UTF16MUNGED: 228 if (c < 0x10000) { 229 count += 1; 230 } else { 231 count += 2; 232 } 233 break; 234 case CH_UTF8: 235 /* 236 * this only checks ranges, and does not 237 * check for invalid codepoints 238 */ 239 if (c < 0x80) { 240 count += 1; 241 } else if (c < 0x800) { 242 count += 2; 243 } else if (c < 0x1000) { 244 count += 3; 245 } else { 246 count += 4; 247 } 248 break; 249 default: 250 /* 251 * non-unicode encoding: 252 * assume that each codepoint fits into 253 * one unit in the destination encoding. 254 */ 277 255 count += 1; 278 } else { 279 count += 2; 280 } 281 s += c_size; 256 } 282 257 } 283 258 284 259 return count; 260 } 261 262 _PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset, 263 const charset_t dst_charset) 264 { 265 if (!s) { 266 return 0; 267 } 268 return strlen_m_ext(s, src_charset, dst_charset) + 1; 269 } 270 271 /** 272 * Calculate the number of 16-bit units that would be needed to convert 273 * the input string which is expected to be in CH_UNIX encoding to UTF16. 274 * 275 * This will be the same as the number of bytes in a string for single 276 * byte strings, but will be different for multibyte. 277 */ 278 _PUBLIC_ size_t strlen_m(const char *s) 279 { 280 return strlen_m_ext(s, CH_UNIX, CH_UTF16LE); 285 281 } 286 282 … … 430 426 char *dest; 431 427 struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience(); 428 429 if(src == NULL) { 430 return NULL; 431 } 432 432 433 433 /* this takes advantage of the fact that upper/lower can't … … 988 988 } 989 989 990 991 _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size)992 {993 return next_codepoint_convenience(get_iconv_convenience(), str, size);994 }995 996 _PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c)997 {998 return push_codepoint_convenience(get_iconv_convenience(), str, c);999 } -
vendor/current/lib/util/data_blob.c
r414 r740 34 34 _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) 35 35 { 36 return data_blob_talloc_named(NULL, p, length, name); 37 } 38 39 /** 40 construct a data blob, using supplied TALLOC_CTX 41 **/ 42 _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name) 43 { 36 44 DATA_BLOB ret; 37 45 … … 42 50 43 51 if (p) { 44 ret.data = (uint8_t *)talloc_memdup( NULL, p, length);52 ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length); 45 53 } else { 46 ret.data = talloc_array( NULL, uint8_t, length);54 ret.data = talloc_array(mem_ctx, uint8_t, length); 47 55 } 48 56 if (ret.data == NULL) { … … 52 60 talloc_set_name_const(ret.data, name); 53 61 ret.length = length; 54 return ret;55 }56 57 /**58 construct a data blob, using supplied TALLOC_CTX59 **/60 _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)61 {62 DATA_BLOB ret = data_blob_named(p, length, name);63 64 if (ret.data) {65 talloc_steal(mem_ctx, ret.data);66 }67 return ret;68 }69 70 71 /**72 reference a data blob, to the supplied TALLOC_CTX.73 Returns a NULL DATA_BLOB on failure74 **/75 _PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob)76 {77 DATA_BLOB ret = *blob;78 79 ret.data = talloc_reference(mem_ctx, blob->data);80 81 if (!ret.data) {82 return data_blob(NULL, 0);83 }84 62 return ret; 85 63 } … … 154 132 print the data_blob as hex string 155 133 **/ 156 _PUBLIC_ char *data_blob_hex_string (TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)134 _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) 157 135 { 158 136 int i; … … 174 152 } 175 153 154 _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) 155 { 156 int i; 157 char *hex_string; 158 159 hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); 160 if (!hex_string) { 161 return NULL; 162 } 163 164 for (i = 0; i < blob->length; i++) 165 slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]); 166 167 hex_string[(blob->length*2)] = '\0'; 168 return hex_string; 169 } 170 176 171 /** 177 172 useful for constructing data blobs in test suites, while -
vendor/current/lib/util/data_blob.h
r414 r740 2 2 Unix SMB/CIFS implementation. 3 3 DATA BLOB 4 4 5 Copyright (C) Andrew Tridgell 2001 6 Copyright (C) Andrew Bartlett 2001 7 5 8 This program is free software; you can redistribute it and/or modify 6 9 it under the terms of the GNU General Public License as published by … … 62 65 63 66 /** 64 reference a data blob, to the supplied TALLOC_CTX.65 Returns a NULL DATA_BLOB on failure66 **/67 _PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob);68 69 /**70 67 construct a zero data blob, using supplied TALLOC_CTX. 71 68 use this sparingly as it initialises data - better to initialise … … 97 94 print the data_blob as hex string 98 95 **/ 99 _PUBLIC_ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); 96 _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); 97 98 /** 99 print the data_blob as hex string 100 **/ 101 _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); 100 102 101 103 /** -
vendor/current/lib/util/debug.c
r414 r740 1 1 /* 2 2 Unix SMB/CIFS implementation. 3 Samba debug functions 4 Copyright (C) Andrew Tridgell 2003 5 Copyright (C) James J Myers 2003 3 Samba utility functions 4 Copyright (C) Andrew Tridgell 1992-1998 5 Copyright (C) Elrond 2002 6 Copyright (C) Simo Sorce 2002 6 7 7 8 This program is free software; you can redistribute it and/or modify … … 21 22 #include "includes.h" 22 23 #include "system/filesys.h" 23 #include "system/time.h" 24 #include "dynconfig/dynconfig.h" 24 #include "system/syslog.h" 25 #include "lib/util/time.h" 26 27 /* define what facility to use for syslog */ 28 #ifndef SYSLOG_FACILITY 29 #define SYSLOG_FACILITY LOG_DAEMON 30 #endif 31 32 /* -------------------------------------------------------------------------- ** 33 * Defines... 34 * 35 * FORMAT_BUFR_MAX - Index of the last byte of the format buffer; 36 * format_bufr[FORMAT_BUFR_MAX] should always be reserved 37 * for a terminating null byte. 38 */ 39 40 #define FORMAT_BUFR_SIZE 1024 41 #define FORMAT_BUFR_MAX (FORMAT_BUFR_SIZE - 1) 42 43 /* -------------------------------------------------------------------------- ** 44 * This module implements Samba's debugging utility. 45 * 46 * The syntax of a debugging log file is represented as: 47 * 48 * <debugfile> :== { <debugmsg> } 49 * 50 * <debugmsg> :== <debughdr> '\n' <debugtext> 51 * 52 * <debughdr> :== '[' TIME ',' LEVEL ']' [ [FILENAME ':'] [FUNCTION '()'] ] 53 * 54 * <debugtext> :== { <debugline> } 55 * 56 * <debugline> :== TEXT '\n' 57 * 58 * TEXT is a string of characters excluding the newline character. 59 * LEVEL is the DEBUG level of the message (an integer in the range 0..10). 60 * TIME is a timestamp. 61 * FILENAME is the name of the file from which the debug message was generated. 62 * FUNCTION is the function from which the debug message was generated. 63 * 64 * Basically, what that all means is: 65 * 66 * - A debugging log file is made up of debug messages. 67 * 68 * - Each debug message is made up of a header and text. The header is 69 * separated from the text by a newline. 70 * 71 * - The header begins with the timestamp and debug level of the message 72 * enclosed in brackets. The filename and function from which the 73 * message was generated may follow. The filename is terminated by a 74 * colon, and the function name is terminated by parenthesis. 75 * 76 * - The message text is made up of zero or more lines, each terminated by 77 * a newline. 78 */ 79 80 /* state variables for the debug system */ 81 static struct { 82 bool initialized; 83 int fd; /* The log file handle */ 84 enum debug_logtype logtype; /* The type of logging we are doing: eg stdout, file, stderr */ 85 const char *prog_name; 86 bool reopening_logs; 87 bool schedule_reopen_logs; 88 89 struct debug_settings settings; 90 char *debugf; 91 } state = { 92 .settings = { 93 .timestamp_logs = true 94 } 95 }; 96 97 /* -------------------------------------------------------------------------- ** 98 * External variables. 99 * 100 * debugf - Debug file name. 101 * DEBUGLEVEL - System-wide debug message limit. Messages with message- 102 * levels higher than DEBUGLEVEL will not be processed. 103 */ 104 105 /* 106 used to check if the user specified a 107 logfile on the command line 108 */ 109 bool override_logfile; 110 111 /* 112 * This is to allow reading of DEBUGLEVEL_CLASS before the debug 113 * system has been initialized. 114 */ 115 static const int debug_class_list_initial[DBGC_MAX_FIXED + 1]; 116 117 static int debug_num_classes = 0; 118 int *DEBUGLEVEL_CLASS = discard_const_p(int, debug_class_list_initial); 119 120 121 /* -------------------------------------------------------------------------- ** 122 * Internal variables. 123 * 124 * debug_count - Number of debug messages that have been output. 125 * Used to check log size. 126 * 127 * syslog_level - Internal copy of the message debug level. Written by 128 * dbghdr() and read by Debug1(). 129 * 130 * format_bufr - Used to format debug messages. The dbgtext() function 131 * prints debug messages to a string, and then passes the 132 * string to format_debug_text(), which uses format_bufr 133 * to build the formatted output. 134 * 135 * format_pos - Marks the first free byte of the format_bufr. 136 * 137 * 138 * log_overflow - When this variable is true, never attempt to check the 139 * size of the log. This is a hack, so that we can write 140 * a message using DEBUG, from open_logs() when we 141 * are unable to open a new log file for some reason. 142 */ 143 144 static int debug_count = 0; 145 #ifdef WITH_SYSLOG 146 static int syslog_level = 0; 147 #endif 148 static char *format_bufr = NULL; 149 static size_t format_pos = 0; 150 static bool log_overflow = false; 151 152 /* 153 * Define all the debug class selection names here. Names *MUST NOT* contain 154 * white space. There must be one name for each DBGC_<class name>, and they 155 * must be in the table in the order of DBGC_<class name>.. 156 */ 157 static const char *default_classname_table[] = { 158 "all", /* DBGC_ALL; index refs traditional DEBUGLEVEL */ 159 "tdb", /* DBGC_TDB */ 160 "printdrivers", /* DBGC_PRINTDRIVERS */ 161 "lanman", /* DBGC_LANMAN */ 162 "smb", /* DBGC_SMB */ 163 "rpc_parse", /* DBGC_RPC_PARSE */ 164 "rpc_srv", /* DBGC_RPC_SRV */ 165 "rpc_cli", /* DBGC_RPC_CLI */ 166 "passdb", /* DBGC_PASSDB */ 167 "sam", /* DBGC_SAM */ 168 "auth", /* DBGC_AUTH */ 169 "winbind", /* DBGC_WINBIND */ 170 "vfs", /* DBGC_VFS */ 171 "idmap", /* DBGC_IDMAP */ 172 "quota", /* DBGC_QUOTA */ 173 "acls", /* DBGC_ACLS */ 174 "locking", /* DBGC_LOCKING */ 175 "msdfs", /* DBGC_MSDFS */ 176 "dmapi", /* DBGC_DMAPI */ 177 "registry", /* DBGC_REGISTRY */ 178 NULL 179 }; 180 181 static char **classname_table = NULL; 182 183 184 /* -------------------------------------------------------------------------- ** 185 * Functions... 186 */ 187 188 static void debug_init(void); 189 190 /*************************************************************************** 191 Free memory pointed to by global pointers. 192 ****************************************************************************/ 193 194 void gfree_debugsyms(void) 195 { 196 TALLOC_FREE(classname_table); 197 198 if ( DEBUGLEVEL_CLASS != debug_class_list_initial ) { 199 TALLOC_FREE( DEBUGLEVEL_CLASS ); 200 DEBUGLEVEL_CLASS = discard_const_p(int, debug_class_list_initial); 201 } 202 203 TALLOC_FREE(format_bufr); 204 205 debug_num_classes = DBGC_MAX_FIXED; 206 207 state.initialized = false; 208 } 209 210 /**************************************************************************** 211 utility lists registered debug class names's 212 ****************************************************************************/ 213 214 char *debug_list_class_names_and_levels(void) 215 { 216 char *buf = NULL; 217 unsigned int i; 218 /* prepare strings */ 219 for (i = 0; i < debug_num_classes; i++) { 220 buf = talloc_asprintf_append(buf, 221 "%s:%d%s", 222 classname_table[i], 223 DEBUGLEVEL_CLASS[i], 224 i == (debug_num_classes - 1) ? "\n" : " "); 225 if (buf == NULL) { 226 return NULL; 227 } 228 } 229 return buf; 230 } 231 232 /**************************************************************************** 233 Utility to translate names to debug class index's (internal version). 234 ****************************************************************************/ 235 236 static int debug_lookup_classname_int(const char* classname) 237 { 238 int i; 239 240 if (!classname) return -1; 241 242 for (i=0; i < debug_num_classes; i++) { 243 if (strcmp(classname, classname_table[i])==0) 244 return i; 245 } 246 return -1; 247 } 248 249 /**************************************************************************** 250 Add a new debug class to the system. 251 ****************************************************************************/ 252 253 int debug_add_class(const char *classname) 254 { 255 int ndx; 256 int *new_class_list; 257 char **new_name_list; 258 int default_level; 259 260 if (!classname) 261 return -1; 262 263 /* check the init has yet been called */ 264 debug_init(); 265 266 ndx = debug_lookup_classname_int(classname); 267 if (ndx >= 0) 268 return ndx; 269 ndx = debug_num_classes; 270 271 if (DEBUGLEVEL_CLASS == debug_class_list_initial) { 272 /* Initial loading... */ 273 new_class_list = NULL; 274 } else { 275 new_class_list = DEBUGLEVEL_CLASS; 276 } 277 278 default_level = DEBUGLEVEL_CLASS[DBGC_ALL]; 279 280 new_class_list = talloc_realloc(NULL, new_class_list, int, ndx + 1); 281 if (!new_class_list) 282 return -1; 283 DEBUGLEVEL_CLASS = new_class_list; 284 285 DEBUGLEVEL_CLASS[ndx] = default_level; 286 287 new_name_list = talloc_realloc(NULL, classname_table, char *, ndx + 1); 288 if (!new_name_list) 289 return -1; 290 classname_table = new_name_list; 291 292 classname_table[ndx] = talloc_strdup(classname_table, classname); 293 if (! classname_table[ndx]) 294 return -1; 295 296 debug_num_classes = ndx + 1; 297 298 return ndx; 299 } 300 301 /**************************************************************************** 302 Utility to translate names to debug class index's (public version). 303 ****************************************************************************/ 304 305 int debug_lookup_classname(const char *classname) 306 { 307 int ndx; 308 309 if (!classname || !*classname) 310 return -1; 311 312 ndx = debug_lookup_classname_int(classname); 313 314 if (ndx != -1) 315 return ndx; 316 317 DEBUG(0, ("debug_lookup_classname(%s): Unknown class\n", 318 classname)); 319 return debug_add_class(classname); 320 } 321 322 /**************************************************************************** 323 Dump the current registered debug levels. 324 ****************************************************************************/ 325 326 static void debug_dump_status(int level) 327 { 328 int q; 329 330 DEBUG(level, ("INFO: Current debug levels:\n")); 331 for (q = 0; q < debug_num_classes; q++) { 332 const char *classname = classname_table[q]; 333 DEBUGADD(level, (" %s: %d\n", 334 classname, 335 DEBUGLEVEL_CLASS[q])); 336 } 337 } 338 339 /**************************************************************************** 340 parse the debug levels from smbcontrol. Example debug level parameter: 341 printdrivers:7 342 ****************************************************************************/ 343 344 static bool debug_parse_params(char **params) 345 { 346 int i, ndx; 347 char *class_name; 348 char *class_level; 349 350 if (!params) 351 return false; 352 353 /* Allow DBGC_ALL to be specified w/o requiring its class name e.g."10" 354 * v.s. "all:10", this is the traditional way to set DEBUGLEVEL 355 */ 356 if (isdigit((int)params[0][0])) { 357 DEBUGLEVEL_CLASS[DBGC_ALL] = atoi(params[0]); 358 i = 1; /* start processing at the next params */ 359 } else { 360 DEBUGLEVEL_CLASS[DBGC_ALL] = 0; 361 i = 0; /* DBGC_ALL not specified OR class name was included */ 362 } 363 364 /* Array is debug_num_classes long */ 365 for (ndx = DBGC_ALL; ndx < debug_num_classes; ndx++) { 366 DEBUGLEVEL_CLASS[ndx] = DEBUGLEVEL_CLASS[DBGC_ALL]; 367 } 368 369 /* Fill in new debug class levels */ 370 for (; i < debug_num_classes && params[i]; i++) { 371 char *saveptr; 372 if ((class_name = strtok_r(params[i],":", &saveptr)) && 373 (class_level = strtok_r(NULL, "\0", &saveptr)) && 374 ((ndx = debug_lookup_classname(class_name)) != -1)) { 375 DEBUGLEVEL_CLASS[ndx] = atoi(class_level); 376 } else { 377 DEBUG(0,("debug_parse_params: unrecognized debug class name or format [%s]\n", params[i])); 378 return false; 379 } 380 } 381 382 return true; 383 } 384 385 /**************************************************************************** 386 Parse the debug levels from smb.conf. Example debug level string: 387 3 tdb:5 printdrivers:7 388 Note: the 1st param has no "name:" preceeding it. 389 ****************************************************************************/ 390 391 bool debug_parse_levels(const char *params_str) 392 { 393 char **params; 394 395 /* Just in case */ 396 debug_init(); 397 398 params = str_list_make(NULL, params_str, NULL); 399 400 if (debug_parse_params(params)) { 401 debug_dump_status(5); 402 TALLOC_FREE(params); 403 return true; 404 } else { 405 TALLOC_FREE(params); 406 return false; 407 } 408 } 409 410 /* setup for logging of talloc warnings */ 411 static void talloc_log_fn(const char *msg) 412 { 413 DEBUG(0,("%s", msg)); 414 } 415 416 void debug_setup_talloc_log(void) 417 { 418 talloc_set_log_fn(talloc_log_fn); 419 } 420 421 422 /**************************************************************************** 423 Init debugging (one time stuff) 424 ****************************************************************************/ 425 426 static void debug_init(void) 427 { 428 const char **p; 429 430 if (state.initialized) 431 return; 432 433 state.initialized = true; 434 435 debug_setup_talloc_log(); 436 437 for(p = default_classname_table; *p; p++) { 438 debug_add_class(*p); 439 } 440 format_bufr = talloc_array(NULL, char, FORMAT_BUFR_SIZE); 441 if (!format_bufr) { 442 smb_panic("debug_init: unable to create buffer"); 443 } 444 } 445 446 /* This forces in some smb.conf derived values into the debug system. 447 * There are no pointers in this structure, so we can just 448 * structure-assign it in */ 449 void debug_set_settings(struct debug_settings *settings) 450 { 451 state.settings = *settings; 452 } 25 453 26 454 /** 27 * @file 28 * @brief Debug logging 29 **/ 30 31 /** 32 * this global variable determines what messages are printed 33 */ 34 int _debug_level = 0; 35 _PUBLIC_ int *debug_level = &_debug_level; 36 static int debug_all_class_hack = 1; 37 int *DEBUGLEVEL_CLASS = &debug_all_class_hack; /* For samba 3 */ 38 static bool debug_all_class_isset_hack = true; 39 bool *DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack; /* For samba 3 */ 40 XFILE *dbf = NULL; /* For Samba 3*/ 455 control the name of the logfile and whether logging will be to stdout, stderr 456 or a file, and set up syslog 457 458 new_log indicates the destination for the debug log (an enum in 459 order of precedence - once set to DEBUG_FILE, it is not possible to 460 reset to DEBUG_STDOUT for example. This makes it easy to override 461 for debug to stderr on the command line, as the smb.conf cannot 462 reset it back to file-based logging 463 */ 464 void setup_logging(const char *prog_name, enum debug_logtype new_logtype) 465 { 466 debug_init(); 467 if (state.logtype < new_logtype) { 468 state.logtype = new_logtype; 469 } 470 if (prog_name) { 471 state.prog_name = prog_name; 472 } 473 reopen_logs_internal(); 474 475 if (state.logtype == DEBUG_FILE) { 476 #ifdef WITH_SYSLOG 477 const char *p = strrchr_m( prog_name,'/' ); 478 if (p) 479 prog_name = p + 1; 480 #ifdef LOG_DAEMON 481 openlog( prog_name, LOG_PID, SYSLOG_FACILITY ); 482 #else 483 /* for old systems that have no facility codes. */ 484 openlog( prog_name, LOG_PID ); 485 #endif 486 #endif 487 } 488 } 489 490 /*************************************************************************** 491 Set the logfile name. 492 **************************************************************************/ 493 494 void debug_set_logfile(const char *name) 495 { 496 if (name == NULL || *name == 0) { 497 /* this copes with calls when smb.conf is not loaded yet */ 498 return; 499 } 500 TALLOC_FREE(state.debugf); 501 state.debugf = talloc_strdup(NULL, name); 502 } 503 504 static void debug_close_fd(int fd) 505 { 506 if (fd > 2) { 507 close(fd); 508 } 509 } 510 511 bool debug_get_output_is_stderr(void) 512 { 513 return (state.logtype == DEBUG_DEFAULT_STDERR) || (state.logtype == DEBUG_STDERR); 514 } 515 516 /************************************************************************** 517 reopen the log files 518 note that we now do this unconditionally 519 We attempt to open the new debug fp before closing the old. This means 520 if we run out of fd's we just keep using the old fd rather than aborting. 521 Fix from dgibson@linuxcare.com. 522 **************************************************************************/ 523 524 /** 525 reopen the log file (usually called because the log file name might have changed) 526 */ 527 bool reopen_logs_internal(void) 528 { 529 mode_t oldumask; 530 int new_fd = 0; 531 int old_fd = 0; 532 bool ret = true; 533 534 char *fname = NULL; 535 if (state.reopening_logs) { 536 return true; 537 } 538 539 /* Now clear the SIGHUP induced flag */ 540 state.schedule_reopen_logs = false; 541 542 switch (state.logtype) { 543 case DEBUG_STDOUT: 544 debug_close_fd(state.fd); 545 state.fd = 1; 546 return true; 547 548 case DEBUG_DEFAULT_STDERR: 549 case DEBUG_STDERR: 550 debug_close_fd(state.fd); 551 state.fd = 2; 552 return true; 553 554 case DEBUG_FILE: 555 break; 556 } 557 558 oldumask = umask( 022 ); 559 560 fname = state.debugf; 561 if (!fname) { 562 return false; 563 } 564 565 state.reopening_logs = true; 566 567 new_fd = open( state.debugf, O_WRONLY|O_APPEND|O_CREAT, 0644); 568 569 if (new_fd == -1) { 570 log_overflow = true; 571 DEBUG(0, ("Unable to open new log file '%s': %s\n", state.debugf, strerror(errno))); 572 log_overflow = false; 573 ret = false; 574 } else { 575 old_fd = state.fd; 576 state.fd = new_fd; 577 debug_close_fd(old_fd); 578 } 579 580 /* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De 581 * to fix problem where smbd's that generate less 582 * than 100 messages keep growing the log. 583 */ 584 force_check_log_size(); 585 (void)umask(oldumask); 586 587 /* Take over stderr to catch output into logs */ 588 if (state.fd > 0 && dup2(state.fd, 2) == -1) { 589 close_low_fds(true); /* Close stderr too, if dup2 can't point it 590 at the logfile */ 591 } 592 593 state.reopening_logs = false; 594 595 return ret; 596 } 597 598 /************************************************************************** 599 Force a check of the log size. 600 ***************************************************************************/ 601 602 void force_check_log_size( void ) 603 { 604 debug_count = 100; 605 } 606 607 _PUBLIC_ void debug_schedule_reopen_logs(void) 608 { 609 state.schedule_reopen_logs = true; 610 } 611 612 613 /*************************************************************************** 614 Check to see if there is any need to check if the logfile has grown too big. 615 **************************************************************************/ 616 617 bool need_to_check_log_size( void ) 618 { 619 int maxlog; 620 621 if( debug_count < 100) 622 return( false ); 623 624 maxlog = state.settings.max_log_size * 1024; 625 if ( state.fd <=2 || maxlog <= 0 ) { 626 debug_count = 0; 627 return(false); 628 } 629 return( true ); 630 } 631 632 /************************************************************************** 633 Check to see if the log has grown to be too big. 634 **************************************************************************/ 635 636 void check_log_size( void ) 637 { 638 int maxlog; 639 struct stat st; 640 641 /* 642 * We need to be root to check/change log-file, skip this and let the main 643 * loop check do a new check as root. 644 */ 645 646 if( geteuid() != 0) { 647 /* We don't check sec_initial_uid() here as it isn't 648 * available in common code and we don't generally 649 * want to rotate and the possibly lose logs in 650 * make test or the build farm */ 651 return; 652 } 653 654 if(log_overflow || (!state.schedule_reopen_logs && !need_to_check_log_size())) { 655 return; 656 } 657 658 maxlog = state.settings.max_log_size * 1024; 659 660 if (state.schedule_reopen_logs || 661 (fstat(state.fd, &st) == 0 662 && st.st_size > maxlog )) { 663 (void)reopen_logs_internal(); 664 if (state.fd > 0 && fstat(state.fd, &st) == 0) { 665 if (st.st_size > maxlog) { 666 char *name = NULL; 667 668 if (asprintf(&name, "%s.old", state.debugf ) < 0) { 669 return; 670 } 671 (void)rename(state.debugf, name); 672 673 if (!reopen_logs_internal()) { 674 /* We failed to reopen a log - continue using the old name. */ 675 (void)rename(name, state.debugf); 676 } 677 SAFE_FREE(name); 678 } 679 } 680 } 681 682 /* 683 * Here's where we need to panic if state.fd == 0 or -1 (invalid values) 684 */ 685 686 if (state.fd <= 0) { 687 /* This code should only be reached in very strange 688 * circumstances. If we merely fail to open the new log we 689 * should stick with the old one. ergo this should only be 690 * reached when opening the logs for the first time: at 691 * startup or when the log level is increased from zero. 692 * -dwg 6 June 2000 693 */ 694 int fd = open( "/dev/console", O_WRONLY, 0); 695 if (fd != -1) { 696 state.fd = fd; 697 DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n", 698 state.debugf )); 699 } else { 700 /* 701 * We cannot continue without a debug file handle. 702 */ 703 abort(); 704 } 705 } 706 debug_count = 0; 707 } 708 709 /************************************************************************* 710 Write an debug message on the debugfile. 711 This is called by dbghdr() and format_debug_text(). 712 ************************************************************************/ 713 714 int Debug1( const char *format_str, ... ) 715 { 716 va_list ap; 717 int old_errno = errno; 718 719 debug_count++; 720 721 if ( state.logtype != DEBUG_FILE ) { 722 va_start( ap, format_str ); 723 if (state.fd > 0) 724 (void)vdprintf( state.fd, format_str, ap ); 725 va_end( ap ); 726 errno = old_errno; 727 goto done; 728 } 729 730 #ifdef WITH_SYSLOG 731 if( !state.settings.syslog_only) 732 #endif 733 { 734 if( state.fd <= 0 ) { 735 mode_t oldumask = umask( 022 ); 736 int fd = open( state.debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 ); 737 (void)umask( oldumask ); 738 if(fd == -1) { 739 errno = old_errno; 740 goto done; 741 } 742 state.fd = fd; 743 } 744 } 745 746 #ifdef WITH_SYSLOG 747 if( syslog_level < state.settings.syslog ) { 748 /* map debug levels to syslog() priorities 749 * note that not all DEBUG(0, ...) calls are 750 * necessarily errors */ 751 static const int priority_map[4] = { 752 LOG_ERR, /* 0 */ 753 LOG_WARNING, /* 1 */ 754 LOG_NOTICE, /* 2 */ 755 LOG_INFO, /* 3 */ 756 }; 757 int priority; 758 char *msgbuf = NULL; 759 int ret; 760 761 if( syslog_level >= ARRAY_SIZE(priority_map) || syslog_level < 0) 762 priority = LOG_DEBUG; 763 else 764 priority = priority_map[syslog_level]; 765 766 /* 767 * Specify the facility to interoperate with other syslog 768 * callers (vfs_full_audit for example). 769 */ 770 priority |= SYSLOG_FACILITY; 771 772 va_start(ap, format_str); 773 ret = vasprintf(&msgbuf, format_str, ap); 774 va_end(ap); 775 776 if (ret != -1) { 777 syslog(priority, "%s", msgbuf); 778 } 779 SAFE_FREE(msgbuf); 780 } 781 #endif 782 783 check_log_size(); 784 785 #ifdef WITH_SYSLOG 786 if( !state.settings.syslog_only) 787 #endif 788 { 789 va_start( ap, format_str ); 790 if (state.fd > 0) 791 (void)vdprintf( state.fd, format_str, ap ); 792 va_end( ap ); 793 } 794 795 done: 796 errno = old_errno; 797 798 return( 0 ); 799 } 800 801 802 /************************************************************************** 803 Print the buffer content via Debug1(), then reset the buffer. 804 Input: none 805 Output: none 806 ****************************************************************************/ 807 808 static void bufr_print( void ) 809 { 810 format_bufr[format_pos] = '\0'; 811 (void)Debug1( "%s", format_bufr ); 812 format_pos = 0; 813 } 814 815 /*************************************************************************** 816 Format the debug message text. 817 818 Input: msg - Text to be added to the "current" debug message text. 819 820 Output: none. 821 822 Notes: The purpose of this is two-fold. First, each call to syslog() 823 (used by Debug1(), see above) generates a new line of syslog 824 output. This is fixed by storing the partial lines until the 825 newline character is encountered. Second, printing the debug 826 message lines when a newline is encountered allows us to add 827 spaces, thus indenting the body of the message and making it 828 more readable. 829 **************************************************************************/ 830 831 static void format_debug_text( const char *msg ) 832 { 833 size_t i; 834 bool timestamp = (state.logtype == DEBUG_FILE && (state.settings.timestamp_logs)); 835 836 if (!format_bufr) { 837 debug_init(); 838 } 839 840 for( i = 0; msg[i]; i++ ) { 841 /* Indent two spaces at each new line. */ 842 if(timestamp && 0 == format_pos) { 843 format_bufr[0] = format_bufr[1] = ' '; 844 format_pos = 2; 845 } 846 847 /* If there's room, copy the character to the format buffer. */ 848 if( format_pos < FORMAT_BUFR_MAX ) 849 format_bufr[format_pos++] = msg[i]; 850 851 /* If a newline is encountered, print & restart. */ 852 if( '\n' == msg[i] ) 853 bufr_print(); 854 855 /* If the buffer is full dump it out, reset it, and put out a line 856 * continuation indicator. 857 */ 858 if( format_pos >= FORMAT_BUFR_MAX ) { 859 bufr_print(); 860 (void)Debug1( " +>\n" ); 861 } 862 } 863 864 /* Just to be safe... */ 865 format_bufr[format_pos] = '\0'; 866 } 867 868 /*************************************************************************** 869 Flush debug output, including the format buffer content. 870 871 Input: none 872 Output: none 873 ***************************************************************************/ 874 875 void dbgflush( void ) 876 { 877 bufr_print(); 878 } 879 880 /*************************************************************************** 881 Print a Debug Header. 882 883 Input: level - Debug level of the message (not the system-wide debug 884 level. ) 885 cls - Debuglevel class of the calling module. 886 file - Pointer to a string containing the name of the file 887 from which this function was called, or an empty string 888 if the __FILE__ macro is not implemented. 889 func - Pointer to a string containing the name of the function 890 from which this function was called, or an empty string 891 if the __FUNCTION__ macro is not implemented. 892 line - line number of the call to dbghdr, assuming __LINE__ 893 works. 894 895 Output: Always true. This makes it easy to fudge a call to dbghdr() 896 in a macro, since the function can be called as part of a test. 897 Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) ) 898 899 Notes: This function takes care of setting syslog_level. 900 901 ****************************************************************************/ 902 903 bool dbghdrclass(int level, int cls, const char *location, const char *func) 904 { 905 /* Ensure we don't lose any real errno value. */ 906 int old_errno = errno; 907 908 if( format_pos ) { 909 /* This is a fudge. If there is stuff sitting in the format_bufr, then 910 * the *right* thing to do is to call 911 * format_debug_text( "\n" ); 912 * to write the remainder, and then proceed with the new header. 913 * Unfortunately, there are several places in the code at which 914 * the DEBUG() macro is used to build partial lines. That in mind, 915 * we'll work under the assumption that an incomplete line indicates 916 * that a new header is *not* desired. 917 */ 918 return( true ); 919 } 920 921 #ifdef WITH_SYSLOG 922 /* Set syslog_level. */ 923 syslog_level = level; 924 #endif 925 926 /* Don't print a header if we're logging to stdout. */ 927 if ( state.logtype != DEBUG_FILE ) { 928 return( true ); 929 } 930 931 /* Print the header if timestamps are turned on. If parameters are 932 * not yet loaded, then default to timestamps on. 933 */ 934 if( state.settings.timestamp_logs || state.settings.debug_prefix_timestamp) { 935 char header_str[200]; 936 937 header_str[0] = '\0'; 938 939 if( state.settings.debug_pid) 940 slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)getpid()); 941 942 if( state.settings.debug_uid) { 943 size_t hs_len = strlen(header_str); 944 slprintf(header_str + hs_len, 945 sizeof(header_str) - 1 - hs_len, 946 ", effective(%u, %u), real(%u, %u)", 947 (unsigned int)geteuid(), (unsigned int)getegid(), 948 (unsigned int)getuid(), (unsigned int)getgid()); 949 } 950 951 if (state.settings.debug_class && (cls != DBGC_ALL)) { 952 size_t hs_len = strlen(header_str); 953 slprintf(header_str + hs_len, 954 sizeof(header_str) -1 - hs_len, 955 ", class=%s", 956 default_classname_table[cls]); 957 } 958 959 /* Print it all out at once to prevent split syslog output. */ 960 if( state.settings.debug_prefix_timestamp ) { 961 char *time_str = current_timestring(NULL, 962 state.settings.debug_hires_timestamp); 963 (void)Debug1( "[%s, %2d%s] ", 964 time_str, 965 level, header_str); 966 talloc_free(time_str); 967 } else { 968 char *time_str = current_timestring(NULL, 969 state.settings.debug_hires_timestamp); 970 (void)Debug1( "[%s, %2d%s] %s(%s)\n", 971 time_str, 972 level, header_str, location, func ); 973 talloc_free(time_str); 974 } 975 } 976 977 errno = old_errno; 978 return( true ); 979 } 980 981 /*************************************************************************** 982 Add text to the body of the "current" debug message via the format buffer. 983 984 Input: format_str - Format string, as used in printf(), et. al. 985 ... - Variable argument list. 986 987 ..or.. va_alist - Old style variable parameter list starting point. 988 989 Output: Always true. See dbghdr() for more info, though this is not 990 likely to be used in the same way. 991 992 ***************************************************************************/ 993 994 bool dbgtext( const char *format_str, ... ) 995 { 996 va_list ap; 997 char *msgbuf = NULL; 998 bool ret = true; 999 int res; 1000 1001 va_start(ap, format_str); 1002 res = vasprintf(&msgbuf, format_str, ap); 1003 va_end(ap); 1004 1005 if (res != -1) { 1006 format_debug_text(msgbuf); 1007 } else { 1008 ret = false; 1009 } 1010 SAFE_FREE(msgbuf); 1011 return ret; 1012 } 1013 41 1014 42 1015 /* the registered mutex handlers */ … … 46 1019 } debug_handlers; 47 1020 48 /* state variables for the debug system */49 static struct {50 int fd;51 enum debug_logtype logtype;52 const char *prog_name;53 bool reopening_logs;54 } state;55 56 static bool reopen_logs_scheduled;57 static bool check_reopen_logs(void)58 {59 if (state.fd == 0 || reopen_logs_scheduled) {60 reopen_logs_scheduled = false;61 reopen_logs();62 }63 64 if (state.fd <= 0)65 return false;66 67 return true;68 }69 70 _PUBLIC_ void debug_schedule_reopen_logs(void)71 {72 reopen_logs_scheduled = true;73 }74 75 static void log_timestring(int level, const char *location, const char *func)76 {77 char *t = NULL;78 char *s = NULL;79 80 if (!check_reopen_logs()) return;81 82 if (state.logtype != DEBUG_FILE) return;83 84 t = timestring(NULL, time(NULL));85 if (!t) return;86 87 asprintf(&s, "[%s, %d %s:%s()]\n", t, level, location, func);88 talloc_free(t);89 if (!s) return;90 91 write(state.fd, s, strlen(s));92 free(s);93 }94 95 /**96 the backend for debug messages. Note that the DEBUG() macro has already97 ensured that the log level has been met before this is called98 */99 _PUBLIC_ void dbghdr(int level, const char *location, const char *func)100 {101 log_timestring(level, location, func);102 log_task_id();103 }104 105 106 _PUBLIC_ void dbghdrclass(int level, int dclass, const char *location, const char *func)107 {108 /* Simple wrapper, Samba 4 doesn't do debug classes */109 dbghdr(level, location, func);110 }111 112 /**113 the backend for debug messages. Note that the DEBUG() macro has already114 ensured that the log level has been met before this is called115 116 @note You should never have to call this function directly. Call the DEBUG()117 macro instead.118 */119 _PUBLIC_ void dbgtext(const char *format, ...)120 {121 va_list ap;122 char *s = NULL;123 124 if (!check_reopen_logs()) return;125 126 va_start(ap, format);127 vasprintf(&s, format, ap);128 va_end(ap);129 130 write(state.fd, s, strlen(s));131 free(s);132 }133 134 _PUBLIC_ const char *logfile = NULL;135 136 /**137 reopen the log file (usually called because the log file name might have changed)138 */139 _PUBLIC_ void reopen_logs(void)140 {141 char *fname = NULL;142 int old_fd = state.fd;143 if (state.reopening_logs) {144 return;145 }146 147 switch (state.logtype) {148 case DEBUG_STDOUT:149 state.fd = 1;150 break;151 152 case DEBUG_STDERR:153 state.fd = 2;154 break;155 156 case DEBUG_FILE:157 state.reopening_logs = true;158 if (logfile && (*logfile) == '/') {159 fname = strdup(logfile);160 } else {161 asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, state.prog_name);162 }163 if (fname) {164 int newfd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0600);165 if (newfd == -1) {166 DEBUG(1, ("Failed to open new logfile: %s\n", fname));167 old_fd = -1;168 } else {169 state.fd = newfd;170 }171 free(fname);172 } else {173 DEBUG(1, ("Failed to find name for file-based logfile!\n"));174 }175 state.reopening_logs = false;176 177 break;178 }179 180 if (old_fd > 2) {181 close(old_fd);182 }183 }184 185 /**186 control the name of the logfile and whether logging will be to stdout, stderr187 or a file188 */189 _PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype)190 {191 if (state.logtype < new_logtype) {192 state.logtype = new_logtype;193 }194 if (prog_name) {195 state.prog_name = prog_name;196 }197 reopen_logs();198 }199 200 /**201 Just run logging to stdout for this program202 */203 _PUBLIC_ void setup_logging_stdout(void)204 {205 setup_logging(NULL, DEBUG_STDOUT);206 }207 208 /**209 return a string constant containing n tabs210 no more than 10 tabs are returned211 */212 _PUBLIC_ const char *do_debug_tab(int n)213 {214 const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t",215 "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t",216 "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"};217 return tabs[MIN(n, 10)];218 }219 220 221 1021 /** 222 1022 log suspicious usage - print comments and backtrace … … 252 1052 if (!debug_handlers.ops.log_task_id) return; 253 1053 254 if (! check_reopen_logs()) return;1054 if (!reopen_logs_internal()) return; 255 1055 256 1056 debug_handlers.ops.log_task_id(state.fd); -
vendor/current/lib/util/debug.h
r414 r740 1 1 /* 2 2 Unix SMB/CIFS implementation. 3 Samba debug defines 4 Copyright (C) Andrew Tridgell 2003 3 SMB debug stuff 4 Copyright (C) Andrew Tridgell 1992-1998 5 Copyright (C) John H Terpstra 1996-1998 6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998 7 Copyright (C) Paul Ashton 1998 5 8 6 9 This program is free software; you can redistribute it and/or modify … … 8 11 the Free Software Foundation; either version 3 of the License, or 9 12 (at your option) any later version. 10 13 11 14 This program is distributed in the hope that it will be useful, 12 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 17 GNU General Public License for more details. 15 18 16 19 You should have received a copy of the GNU General Public License 17 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 21 */ 19 22 20 #ifndef _SAMBA_DEBUG_H_ 21 #define _SAMBA_DEBUG_H_ 22 23 /** 24 * @file 25 * @brief Debugging macros 26 */ 27 28 /* the debug operations structure - contains function pointers to 29 various debug implementations of each operation */ 30 struct debug_ops { 31 /* function to log (using DEBUG) suspicious usage of data structure */ 32 void (*log_suspicious_usage)(const char* from, const char* info); 33 34 /* function to log (using printf) suspicious usage of data structure. 35 * To be used in circumstances when using DEBUG would cause loop. */ 36 void (*print_suspicious_usage)(const char* from, const char* info); 37 38 /* function to return process/thread id */ 39 uint32_t (*get_task_id)(void); 40 41 /* function to log process/thread id */ 42 void (*log_task_id)(int fd); 43 }; 44 45 #define DEBUGLEVEL *debug_level 46 extern int DEBUGLEVEL; 47 48 #define debug_ctx() (_debug_ctx?_debug_ctx:(_debug_ctx=talloc_new(NULL))) 49 50 #define DEBUGLVL(level) ((level) <= DEBUGLEVEL) 51 #define _DEBUG(level, body, header) do { \ 52 if (DEBUGLVL(level)) { \ 53 void* _debug_ctx=NULL; \ 54 if (header) { \ 55 dbghdr(level, __location__, __FUNCTION__); \ 56 } \ 57 dbgtext body; \ 58 talloc_free(_debug_ctx); \ 59 } \ 60 } while (0) 61 /** 62 * Write to the debug log. 63 */ 64 #define DEBUG(level, body) _DEBUG(level, body, true) 65 /** 66 * Add data to an existing debug log entry. 67 */ 68 #define DEBUGADD(level, body) _DEBUG(level, body, false) 69 70 /** 71 * Obtain indentation string for the debug log. 72 * 73 * Level specified by n. 74 */ 75 #define DEBUGTAB(n) do_debug_tab(n) 23 #ifndef _DEBUG_H 24 #define _DEBUG_H 25 26 /* -------------------------------------------------------------------------- ** 27 * Debugging code. See also debug.c 28 */ 29 30 /* the maximum debug level to compile into the code. This assumes a good 31 optimising compiler that can remove unused code 32 for embedded or low-memory systems set this to a value like 2 to get 33 only important messages. This gives *much* smaller binaries 34 */ 35 #ifndef MAX_DEBUG_LEVEL 36 #define MAX_DEBUG_LEVEL 1000 37 #endif 38 39 int Debug1( const char *, ... ) PRINTF_ATTRIBUTE(1,2); 40 bool dbgtext( const char *, ... ) PRINTF_ATTRIBUTE(1,2); 41 bool dbghdrclass( int level, int cls, const char *location, const char *func); 42 bool dbghdr( int level, const char *location, const char *func); 43 44 /* 45 * Redefine DEBUGLEVEL because so we don't have to change every source file 46 * that *unnecessarily* references it. 47 */ 48 #define DEBUGLEVEL DEBUGLEVEL_CLASS[DBGC_ALL] 49 50 /* 51 * Define all new debug classes here. A class is represented by an entry in 52 * the DEBUGLEVEL_CLASS array. Index zero of this arrray is equivalent to the 53 * old DEBUGLEVEL. Any source file that does NOT add the following lines: 54 * 55 * #undef DBGC_CLASS 56 * #define DBGC_CLASS DBGC_<your class name here> 57 * 58 * at the start of the file (after #include "includes.h") will default to 59 * using index zero, so it will behaive just like it always has. 60 */ 61 #define DBGC_ALL 0 /* index equivalent to DEBUGLEVEL */ 62 63 #define DBGC_TDB 1 64 #define DBGC_PRINTDRIVERS 2 65 #define DBGC_LANMAN 3 66 #define DBGC_SMB 4 67 #define DBGC_RPC_PARSE 5 68 #define DBGC_RPC_SRV 6 69 #define DBGC_RPC_CLI 7 70 #define DBGC_PASSDB 8 71 #define DBGC_SAM 9 72 #define DBGC_AUTH 10 73 #define DBGC_WINBIND 11 74 #define DBGC_VFS 12 75 #define DBGC_IDMAP 13 76 #define DBGC_QUOTA 14 77 #define DBGC_ACLS 15 78 #define DBGC_LOCKING 16 79 #define DBGC_MSDFS 17 80 #define DBGC_DMAPI 18 81 #define DBGC_REGISTRY 19 82 83 /* Always ensure this is updated when new fixed classes area added, to ensure the array in debug.c is the right size */ 84 #define DBGC_MAX_FIXED 19 85 86 /* So you can define DBGC_CLASS before including debug.h */ 87 #ifndef DBGC_CLASS 88 #define DBGC_CLASS 0 /* override as shown above */ 89 #endif 90 91 extern int *DEBUGLEVEL_CLASS; 92 93 /* Debugging macros 94 * 95 * DEBUGLVL() 96 * If the 'file specific' debug class level >= level OR the system-wide 97 * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then 98 * generate a header using the default macros for file, line, and 99 * function name. Returns True if the debug level was <= DEBUGLEVEL. 100 * 101 * Example: if( DEBUGLVL( 2 ) ) dbgtext( "Some text.\n" ); 102 * 103 * DEBUG() 104 * If the 'file specific' debug class level >= level OR the system-wide 105 * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then 106 * generate a header using the default macros for file, line, and 107 * function name. Each call to DEBUG() generates a new header *unless* the 108 * previous debug output was unterminated (i.e. no '\n'). 109 * See debug.c:dbghdr() for more info. 110 * 111 * Example: DEBUG( 2, ("Some text and a value %d.\n", value) ); 112 * 113 * DEBUGC() 114 * If the 'macro specified' debug class level >= level OR the system-wide 115 * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then 116 * generate a header using the default macros for file, line, and 117 * function name. Each call to DEBUG() generates a new header *unless* the 118 * previous debug output was unterminated (i.e. no '\n'). 119 * See debug.c:dbghdr() for more info. 120 * 121 * Example: DEBUGC( DBGC_TDB, 2, ("Some text and a value %d.\n", value) ); 122 * 123 * DEBUGADD(), DEBUGADDC() 124 * Same as DEBUG() and DEBUGC() except the text is appended to the previous 125 * DEBUG(), DEBUGC(), DEBUGADD(), DEBUGADDC() with out another interviening 126 * header. 127 * 128 * Example: DEBUGADD( 2, ("Some text and a value %d.\n", value) ); 129 * DEBUGADDC( DBGC_TDB, 2, ("Some text and a value %d.\n", value) ); 130 * 131 * Note: If the debug class has not be redeined (see above) then the optimizer 132 * will remove the extra conditional test. 133 */ 134 135 /* 136 * From talloc.c: 137 */ 138 139 /* these macros gain us a few percent of speed on gcc */ 140 #if (__GNUC__ >= 3) 141 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 142 as its first argument */ 143 #ifndef likely 144 #define likely(x) __builtin_expect(!!(x), 1) 145 #endif 146 #ifndef unlikely 147 #define unlikely(x) __builtin_expect(!!(x), 0) 148 #endif 149 #else 150 #ifndef likely 151 #define likely(x) (x) 152 #endif 153 #ifndef unlikely 154 #define unlikely(x) (x) 155 #endif 156 #endif 157 158 #define CHECK_DEBUGLVL( level ) \ 159 ( ((level) <= MAX_DEBUG_LEVEL) && \ 160 unlikely(DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))) 161 162 #define DEBUGLVL( level ) \ 163 ( CHECK_DEBUGLVL(level) \ 164 && dbghdrclass( level, DBGC_CLASS, __location__, __FUNCTION__ ) ) 165 166 167 #define DEBUG( level, body ) \ 168 (void)( ((level) <= MAX_DEBUG_LEVEL) && \ 169 unlikely(DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level)) \ 170 && (dbghdrclass( level, DBGC_CLASS, __location__, __FUNCTION__ )) \ 171 && (dbgtext body) ) 172 173 #define DEBUGC( dbgc_class, level, body ) \ 174 (void)( ((level) <= MAX_DEBUG_LEVEL) && \ 175 unlikely(DEBUGLEVEL_CLASS[ dbgc_class ] >= (level)) \ 176 && (dbghdrclass( level, DBGC_CLASS, __location__, __FUNCTION__ )) \ 177 && (dbgtext body) ) 178 179 #define DEBUGADD( level, body ) \ 180 (void)( ((level) <= MAX_DEBUG_LEVEL) && \ 181 unlikely(DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level)) \ 182 && (dbgtext body) ) 183 184 #define DEBUGADDC( dbgc_class, level, body ) \ 185 (void)( ((level) <= MAX_DEBUG_LEVEL) && \ 186 unlikely((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))) \ 187 && (dbgtext body) ) 188 189 /* Print a separator to the debug log. */ 190 #define DEBUGSEP(level)\ 191 DEBUG((level),("===============================================================\n")) 192 193 /* The following definitions come from lib/debug.c */ 76 194 77 195 /** Possible destinations for the debug log (in order of precedence - … … 80 198 * the command line, as the smb.conf cannot reset it back to 81 199 * file-based logging */ 82 enum debug_logtype {DEBUG_STDOUT = 0, DEBUG_FILE = 1, DEBUG_STDERR = 2}; 83 84 /** 85 the backend for debug messages. Note that the DEBUG() macro has already 86 ensured that the log level has been met before this is called 87 */ 88 _PUBLIC_ void dbghdr(int level, const char *location, const char *func); 89 90 _PUBLIC_ void dbghdrclass(int level, int cls, const char *location, const char *func); 91 92 /** 93 reopen the log file (usually called because the log file name might have changed) 94 */ 95 _PUBLIC_ void reopen_logs(void); 96 97 /** 98 * this global variable determines what messages are printed 99 */ 100 _PUBLIC_ void debug_schedule_reopen_logs(void); 101 102 /** 103 control the name of the logfile and whether logging will be to stdout, stderr 104 or a file 105 */ 106 _PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype); 107 108 /** 109 Just run logging to stdout for this program 110 */ 111 _PUBLIC_ void setup_logging_stdout(void); 112 113 /** 114 return a string constant containing n tabs 115 no more than 10 tabs are returned 116 */ 117 _PUBLIC_ const char *do_debug_tab(int n); 200 enum debug_logtype {DEBUG_DEFAULT_STDERR = 0, DEBUG_STDOUT = 1, DEBUG_FILE = 2, DEBUG_STDERR = 3}; 201 202 struct debug_settings { 203 size_t max_log_size; 204 bool syslog; 205 bool syslog_only; 206 bool timestamp_logs; 207 bool debug_prefix_timestamp; 208 bool debug_hires_timestamp; 209 bool debug_pid; 210 bool debug_uid; 211 bool debug_class; 212 }; 213 214 void setup_logging(const char *prog_name, enum debug_logtype new_logtype); 215 216 void debug_close_dbf(void); 217 void gfree_debugsyms(void); 218 int debug_add_class(const char *classname); 219 int debug_lookup_classname(const char *classname); 220 bool debug_parse_levels(const char *params_str); 221 void debug_setup_talloc_log(void); 222 void debug_set_logfile(const char *name); 223 void debug_set_settings(struct debug_settings *settings); 224 bool reopen_logs_internal( void ); 225 void force_check_log_size( void ); 226 bool need_to_check_log_size( void ); 227 void check_log_size( void ); 228 void dbgflush( void ); 229 bool dbghdrclass(int level, int cls, const char *location, const char *func); 230 bool dbghdr(int level, const char *location, const char *func); 231 bool debug_get_output_is_stderr(void); 232 void debug_schedule_reopen_logs(void); 233 char *debug_list_class_names_and_levels(void); 118 234 119 235 /** … … 129 245 _PUBLIC_ void log_task_id(void); 130 246 247 /* the debug operations structure - contains function pointers to 248 various debug implementations of each operation */ 249 struct debug_ops { 250 /* function to log (using DEBUG) suspicious usage of data structure */ 251 void (*log_suspicious_usage)(const char* from, const char* info); 252 253 /* function to log (using printf) suspicious usage of data structure. 254 * To be used in circumstances when using DEBUG would cause loop. */ 255 void (*print_suspicious_usage)(const char* from, const char* info); 256 257 /* function to return process/thread id */ 258 uint32_t (*get_task_id)(void); 259 260 /* function to log process/thread id */ 261 void (*log_task_id)(int fd); 262 }; 263 131 264 /** 132 265 register a set of debug handlers. … … 134 267 _PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops); 135 268 136 /** 137 the backend for debug messages. Note that the DEBUG() macro has already 138 ensured that the log level has been met before this is called 139 140 @note You should never have to call this function directly. Call the DEBUG() 141 macro instead. 142 */ 143 _PUBLIC_ void dbgtext(const char *format, ...) PRINTF_ATTRIBUTE(1,2); 144 145 struct _XFILE; 146 extern struct _XFILE *dbf; 147 148 #endif 269 #endif -
vendor/current/lib/util/dlinklist.h
r414 r740 2 2 Unix SMB/CIFS implementation. 3 3 some simple double linked list macros 4 Copyright (C) Andrew Tridgell 1998 4 5 Copyright (C) Andrew Tridgell 1998-2010 5 6 6 7 This program is free software; you can redistribute it and/or modify … … 24 25 #define _DLINKLIST_H 25 26 27 /* 28 February 2010 - changed list format to have a prev pointer from the 29 list head. This makes DLIST_ADD_END() O(1) even though we only have 30 one list pointer. 26 31 27 /* hook into the front of the list */ 32 The scheme is as follows: 33 34 1) with no entries in the list: 35 list_head == NULL 36 37 2) with 1 entry in the list: 38 list_head->next == NULL 39 list_head->prev == list_head 40 41 3) with 2 entries in the list: 42 list_head->next == element2 43 list_head->prev == element2 44 element2->prev == list_head 45 element2->next == NULL 46 47 4) with N entries in the list: 48 list_head->next == element2 49 list_head->prev == elementN 50 elementN->prev == element{N-1} 51 elementN->next == NULL 52 53 This allows us to find the tail of the list by using 54 list_head->prev, which means we can add to the end of the list in 55 O(1) time 56 57 58 Note that the 'type' arguments below are no longer needed, but 59 are kept for now to prevent an incompatible argument change 60 */ 61 62 63 /* 64 add an element at the front of a list 65 */ 28 66 #define DLIST_ADD(list, p) \ 29 67 do { \ 30 68 if (!(list)) { \ 31 ( list) = (p);\32 (p)->next = (p)->prev =NULL; \69 (p)->prev = (list) = (p); \ 70 (p)->next = NULL; \ 33 71 } else { \ 72 (p)->prev = (list)->prev; \ 34 73 (list)->prev = (p); \ 35 74 (p)->next = (list); \ 36 (p)->prev = NULL; \37 75 (list) = (p); \ 38 } \76 } \ 39 77 } while (0) 40 78 41 /* remove an element from a list - element doesn't have to be in list. */ 79 /* 80 remove an element from a list 81 Note that the element doesn't have to be in the list. If it 82 isn't then this is a no-op 83 */ 42 84 #define DLIST_REMOVE(list, p) \ 43 85 do { \ 44 86 if ((p) == (list)) { \ 87 if ((p)->next) (p)->next->prev = (p)->prev; \ 45 88 (list) = (p)->next; \ 46 if (list) (list)->prev = NULL; \ 89 } else if ((list) && (p) == (list)->prev) { \ 90 (p)->prev->next = NULL; \ 91 (list)->prev = (p)->prev; \ 47 92 } else { \ 48 93 if ((p)->prev) (p)->prev->next = (p)->next; \ 49 94 if ((p)->next) (p)->next->prev = (p)->prev; \ 50 95 } \ 51 if ((p) != (list)) (p)->next = (p)->prev = NULL; 96 if ((p) != (list)) (p)->next = (p)->prev = NULL; \ 52 97 } while (0) 53 98 54 /* promote an element to the top of the list */ 55 #define DLIST_PROMOTE(list, p) \ 99 /* 100 find the head of the list given any element in it. 101 Note that this costs O(N), so you should avoid this macro 102 if at all possible! 103 */ 104 #define DLIST_HEAD(p, result_head) \ 56 105 do { \ 57 DLIST_REMOVE(list,p); \58 DLIST_ADD(list, p); \59 } while 106 (result_head) = (p); \ 107 while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ 108 } while(0) 60 109 61 /* hook into the end of the list - needs the entry type */ 62 #define DLIST_ADD_END(list, p, type) \ 63 do { \ 64 if (!(list)) { \ 65 (list) = (p); \ 66 (p)->next = (p)->prev = NULL; \ 67 } else { \ 68 type tmp; \ 69 for (tmp = (list); tmp->next; tmp = tmp->next) ; \ 70 tmp->next = (p); \ 71 (p)->next = NULL; \ 72 (p)->prev = tmp; \ 73 } \ 74 } while (0) 110 /* return the last element in the list */ 111 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL) 112 113 /* return the previous element in the list. */ 114 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) 75 115 76 116 /* insert 'p' after the given element 'el' in a list. If el is NULL then … … 81 121 DLIST_ADD(list, p); \ 82 122 } else { \ 83 p->prev = el; \ 84 p->next = el->next; \ 85 el->next = p; \ 86 if (p->next) p->next->prev = p; \ 123 (p)->prev = (el); \ 124 (p)->next = (el)->next; \ 125 (el)->next = (p); \ 126 if ((p)->next) (p)->next->prev = (p); \ 127 if ((list)->prev == (el)) (list)->prev = (p); \ 87 128 }\ 88 129 } while (0) 89 130 90 /* demote an element to the end of the list, needs the entry type */ 91 #define DLIST_DEMOTE(list, p, type) \ 131 132 /* 133 add to the end of a list. 134 Note that 'type' is ignored 135 */ 136 #define DLIST_ADD_END(list, p, type) \ 92 137 do { \ 93 DLIST_REMOVE(list, p); \ 94 DLIST_ADD_END(list, p, type); \ 138 if (!(list)) { \ 139 DLIST_ADD(list, p); \ 140 } else { \ 141 DLIST_ADD_AFTER(list, p, (list)->prev); \ 142 } \ 95 143 } while (0) 96 144 97 /* concatenate two lists - putting all elements of the 2nd list at the 98 end of the first list */ 99 #define DLIST_CONCATENATE(list1, list2, type) \ 145 /* promote an element to the from of a list */ 146 #define DLIST_PROMOTE(list, p) \ 100 147 do { \ 101 if (!(list1)) { \ 102 (list1) = (list2); \ 103 } else { \ 104 type tmp; \ 105 for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ 106 tmp->next = (list2); \ 107 if (list2) { \ 108 (list2)->prev = tmp; \ 109 } \ 148 DLIST_REMOVE(list, p); \ 149 DLIST_ADD(list, p); \ 150 } while (0) 151 152 /* 153 demote an element to the end of a list. 154 Note that 'type' is ignored 155 */ 156 #define DLIST_DEMOTE(list, p, type) \ 157 do { \ 158 DLIST_REMOVE(list, p); \ 159 DLIST_ADD_END(list, p, NULL); \ 160 } while (0) 161 162 /* 163 concatenate two lists - putting all elements of the 2nd list at the 164 end of the first list. 165 Note that 'type' is ignored 166 */ 167 #define DLIST_CONCATENATE(list1, list2, type) \ 168 do { \ 169 if (!(list1)) { \ 170 (list1) = (list2); \ 171 } else { \ 172 (list1)->prev->next = (list2); \ 173 if (list2) { \ 174 void *_tmplist = (void *)(list1)->prev; \ 175 (list1)->prev = (list2)->prev; \ 176 (list2)->prev = _tmplist; \ 110 177 } \ 178 } \ 111 179 } while (0) 112 180 -
vendor/current/lib/util/fault.c
r414 r740 52 52 #endif 53 53 void *backtrace_stack[BACKTRACE_STACK_SIZE]; 54 size_t backtrace_size;54 int backtrace_size; 55 55 char **backtrace_strings; 56 56 … … 126 126 char cmdstring[200]; 127 127 safe_strcpy(cmdstring, panic_action, sizeof(cmdstring)); 128 snprintf(pidstr, sizeof(pidstr), "% u",getpid());128 snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid()); 129 129 all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring)); 130 130 if (progname) { … … 146 146 147 147 #ifdef SIGABRT 148 CatchSignal(SIGABRT, SIGNAL_CASTSIG_DFL);148 CatchSignal(SIGABRT, SIG_DFL); 149 149 #endif 150 150 abort(); … … 188 188 _PUBLIC_ void fault_setup(const char *pname) 189 189 { 190 if (progname == NULL) { 191 progname = pname; 192 } 190 if (progname != NULL) { 191 return; 192 } 193 progname = pname; 193 194 #ifdef SIGSEGV 194 CatchSignal(SIGSEGV, SIGNAL_CASTsig_fault);195 CatchSignal(SIGSEGV, sig_fault); 195 196 #endif 196 197 #ifdef SIGBUS 197 CatchSignal(SIGBUS, SIGNAL_CASTsig_fault);198 CatchSignal(SIGBUS, sig_fault); 198 199 #endif 199 200 #ifdef SIGABRT 200 CatchSignal(SIGABRT, SIGNAL_CASTsig_fault);201 CatchSignal(SIGABRT, sig_fault); 201 202 #endif 202 203 #ifdef SIGFPE 203 CatchSignal(SIGFPE,SIGNAL_CAST sig_fault); 204 #endif 205 } 204 CatchSignal(SIGFPE, sig_fault); 205 #endif 206 } 207 208 /** 209 disable setting up fault handlers 210 **/ 211 _PUBLIC_ void fault_setup_disable(void) 212 { 213 progname = "fault disabled"; 214 } 215 206 216 207 217 /** -
vendor/current/lib/util/genrand.c
r414 r740 363 363 364 364 /** 365 * Generate a random text password. 366 */ 367 368 _PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max) 369 { 370 char *retstr; 371 /* This list does not include { or } because they cause 372 * problems for our provision (it can create a substring 373 * ${...}, and for Fedora DS (which treats {...} at the start 374 * of a stored password as special 375 * -- Andrew Bartlett 2010-03-11 376 */ 377 const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~"; 378 size_t len = max; 379 size_t diff; 380 381 if (min > max) { 382 errno = EINVAL; 383 return NULL; 384 } 385 386 diff = max - min; 387 388 if (diff > 0 ) { 389 size_t tmp; 390 391 generate_random_buffer((uint8_t *)&tmp, sizeof(tmp)); 392 393 tmp %= diff; 394 395 len = min + tmp; 396 } 397 398 again: 399 retstr = generate_random_str_list(mem_ctx, len, c_list); 400 if (!retstr) return NULL; 401 402 /* we need to make sure the random string passes basic quality tests 403 or it might be rejected by windows as a password */ 404 if (len >= 7 && !check_password_quality(retstr)) { 405 talloc_free(retstr); 406 goto again; 407 } 408 409 return retstr; 410 } 411 412 /** 365 413 * Generate an array of unique text strings all of the same length. 366 414 * The returned string will be allocated. -
vendor/current/lib/util/idtree.c
r414 r740 105 105 int n, m, sh; 106 106 struct idr_layer *p, *pn; 107 struct idr_layer *pa[MAX_LEVEL ];108 int l, id, oid;107 struct idr_layer *pa[MAX_LEVEL+1]; 108 unsigned int l, id, oid; 109 109 uint32_t bm; 110 110 … … 241 241 { 242 242 struct idr_layer *p = idp->top; 243 struct idr_layer **pa[ MAX_LEVEL];243 struct idr_layer **pa[1+MAX_LEVEL]; 244 244 struct idr_layer ***paa = &pa[0]; 245 245 int n; … … 281 281 * present. If so, tain't one of ours! 282 282 */ 283 if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)) 284 return NULL; 283 if (n + IDR_BITS < 31 && 284 ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))) { 285 return NULL; 286 } 285 287 286 288 /* Mask off upper bits we don't use for the search. */ -
vendor/current/lib/util/memory.h
r414 r740 29 29 * always be ignored. 30 30 **/ 31 #define SAFE_FREE(x) do { if ((x) != NULL) {free( discard_const_p(void *, (x))); (x)=NULL;} } while(0)31 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) 32 32 #endif 33 33 -
vendor/current/lib/util/params.c
r594 r740 489 489 } /* Parse */ 490 490 491 static myFILE *OpenConfFile( const char *FileName )491 static myFILE *OpenConfFile(TALLOC_CTX *mem_ctx, const char *FileName ) 492 492 /* ------------------------------------------------------------------------ ** 493 493 * Open a configuration file. … … 503 503 myFILE *ret; 504 504 505 ret = talloc( talloc_autofree_context(), myFILE);505 ret = talloc(mem_ctx, myFILE); 506 506 if (!ret) return NULL; 507 507 … … 544 544 const char *func = "params.c:pm_process() -"; 545 545 546 InFile = OpenConfFile( FileName );/* Open the config file. */546 InFile = OpenConfFile(NULL, FileName); /* Open the config file. */ 547 547 if( NULL == InFile ) 548 548 return( false ); -
vendor/current/lib/util/system.c
r414 r740 118 118 return mypid; 119 119 } 120 121 122 _PUBLIC_ int sys_getpeereid( int s, uid_t *uid) 123 { 124 #if defined(HAVE_PEERCRED) 125 struct ucred cred; 126 socklen_t cred_len = sizeof(struct ucred); 127 int ret; 128 129 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); 130 if (ret != 0) { 131 return -1; 132 } 133 134 if (cred_len != sizeof(struct ucred)) { 135 errno = EINVAL; 136 return -1; 137 } 138 139 *uid = cred.uid; 140 return 0; 141 #else 142 #if defined(HAVE_GETPEEREID) 143 gid_t gid; 144 return getpeereid(s, uid, &gid); 145 #endif 146 errno = ENOSYS; 147 return -1; 148 #endif 149 } 150 151 _PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, 152 int salen, 153 char *host, 154 size_t hostlen, 155 char *service, 156 size_t servlen, 157 int flags) 158 { 159 /* 160 * For Solaris we must make sure salen is the 161 * correct length for the incoming sa_family. 162 */ 163 164 if (salen == sizeof(struct sockaddr_storage)) { 165 salen = sizeof(struct sockaddr_in); 166 #if defined(HAVE_IPV6) 167 if (psa->sa_family == AF_INET6) { 168 salen = sizeof(struct sockaddr_in6); 169 } 170 #endif 171 } 172 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags); 173 } 174 175 _PUBLIC_ int sys_connect(int fd, const struct sockaddr * addr) 176 { 177 socklen_t salen = (socklen_t)-1; 178 179 if (addr->sa_family == AF_INET) { 180 salen = sizeof(struct sockaddr_in); 181 } else if (addr->sa_family == AF_UNIX) { 182 salen = sizeof(struct sockaddr_un); 183 } 184 #if defined(HAVE_IPV6) 185 else if (addr->sa_family == AF_INET6) { 186 salen = sizeof(struct sockaddr_in6); 187 } 188 #endif 189 190 return connect(fd, addr, salen); 191 } -
vendor/current/lib/util/talloc_stack.c
r427 r740 69 69 { 70 70 #if defined(PARANOID_MALLOC_CHECKER) 71 #ifdef malloc72 #undef malloc71 #ifdef calloc 72 #undef calloc 73 73 #endif 74 74 #endif 75 struct talloc_stackframe *ts = 76 (struct talloc_stackframe *)malloc(sizeof(struct talloc_stackframe));75 struct talloc_stackframe *ts = (struct talloc_stackframe *)calloc( 76 1, sizeof(struct talloc_stackframe)); 77 77 #if defined(PARANOID_MALLOC_CHECKER) 78 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY78 #define calloc(n, s) __ERROR_DONT_USE_MALLOC_DIRECTLY 79 79 #endif 80 80 … … 82 82 smb_panic("talloc_stackframe_init malloc failed"); 83 83 } 84 85 ZERO_STRUCTP(ts);86 84 87 85 SMB_THREAD_ONCE(&ts_initialized, talloc_stackframe_init, NULL); … … 103 101 break; 104 102 } 105 talloc_free(ts->talloc_stack[i]); 106 ts->talloc_stack[i] = NULL; 103 TALLOC_FREE(ts->talloc_stack[i]); 107 104 } 108 105 -
vendor/current/lib/util/talloc_stack.h
r414 r740 36 36 #define _TALLOC_STACK_H 37 37 38 #include "talloc.h"38 #include <talloc.h> 39 39 40 40 /* -
vendor/current/lib/util/tests/data_blob.c
r414 r740 79 79 { 80 80 DATA_BLOB a = data_blob_string_const("\xC\xA\xF\xE"); 81 torture_assert_str_equal(tctx, data_blob_hex_string(tctx, &a), "0C0A0F0E", "hex string"); 81 torture_assert_str_equal(tctx, data_blob_hex_string_lower(tctx, &a), "0c0a0f0e", "hex string"); 82 torture_assert_str_equal(tctx, data_blob_hex_string_upper(tctx, &a), "0C0A0F0E", "hex string"); 82 83 return true; 83 84 } … … 85 86 struct torture_suite *torture_local_util_data_blob(TALLOC_CTX *mem_ctx) 86 87 { 87 struct torture_suite *suite = torture_suite_create(mem_ctx, " DATABLOB");88 struct torture_suite *suite = torture_suite_create(mem_ctx, "datablob"); 88 89 89 90 torture_suite_add_simple_test(suite, "string", test_string); -
vendor/current/lib/util/tests/file.c
r414 r740 92 92 struct torture_suite *torture_local_util_file(TALLOC_CTX *mem_ctx) 93 93 { 94 struct torture_suite *suite = torture_suite_create(mem_ctx, " FILE");94 struct torture_suite *suite = torture_suite_create(mem_ctx, "file"); 95 95 96 96 torture_suite_add_simple_test(suite, "file_load_save", 97 97 test_file_load_save); 98 98 99 torture_suite_add_simple_test(suite, "afdgets", 100 test_afdgets); 99 torture_suite_add_simple_test(suite, "afdgets", test_afdgets); 101 100 102 101 return suite; -
vendor/current/lib/util/tests/genrand.c
r414 r740 60 60 struct torture_suite *torture_local_genrand(TALLOC_CTX *mem_ctx) 61 61 { 62 struct torture_suite *suite = torture_suite_create(mem_ctx, " GENRAND");62 struct torture_suite *suite = torture_suite_create(mem_ctx, "genrand"); 63 63 torture_suite_add_simple_test(suite, "reseed_callback", test_reseed_callback); 64 64 torture_suite_add_simple_test(suite, "check_password_quality", test_check_password_quality); -
vendor/current/lib/util/tests/idtree.c
r414 r740 116 116 struct torture_suite *torture_local_idtree(TALLOC_CTX *mem_ctx) 117 117 { 118 struct torture_suite *suite = torture_suite_create(mem_ctx, " IDTREE");118 struct torture_suite *suite = torture_suite_create(mem_ctx, "idtree"); 119 119 torture_suite_add_simple_test(suite, "idtree", torture_local_idtree_simple); 120 120 return suite; -
vendor/current/lib/util/tests/parmlist.c
r414 r740 60 60 torture_assert_str_equal(tctx, e->value, "mystring", "value"); 61 61 62 e = parmlist_get(pctx, "non existant");63 torture_assert(tctx, e == NULL, "non existant");62 e = parmlist_get(pctx, "non-existent"); 63 torture_assert(tctx, e == NULL, "non-existent"); 64 64 return true; 65 65 } … … 88 88 torture_assert_str_equal(tctx, "true", ret[0], "ret[0]"); 89 89 torture_assert_str_equal(tctx, "false", ret[1], "ret[1]"); 90 torture_assert(tctx, NULL == parmlist_get_string_list(pctx, "non existant", NULL), "nonexistant");90 torture_assert(tctx, NULL == parmlist_get_string_list(pctx, "non-existent", NULL), "non-existent"); 91 91 92 92 return true; … … 95 95 struct torture_suite *torture_local_util_parmlist(TALLOC_CTX *mem_ctx) 96 96 { 97 struct torture_suite *suite = torture_suite_create(mem_ctx, " PARMLIST");97 struct torture_suite *suite = torture_suite_create(mem_ctx, "parmlist"); 98 98 99 99 torture_suite_add_simple_test(suite, "get_int", test_get_int); -
vendor/current/lib/util/tests/str.c
r414 r740 95 95 struct torture_suite *torture_local_util_str(TALLOC_CTX *mem_ctx) 96 96 { 97 struct torture_suite *suite = torture_suite_create(mem_ctx, " STR");97 struct torture_suite *suite = torture_suite_create(mem_ctx, "str"); 98 98 99 99 torture_suite_add_simple_test(suite, "string_sub_simple", -
vendor/current/lib/util/tests/strlist.c
r414 r740 27 27 struct test_list_element { 28 28 const char *list_as_string; 29 const char *sep erators;29 const char *separators; 30 30 const char *list[5]; 31 31 }; 32 32 33 struct test_list_element test_lists_strings[] = {33 const struct test_list_element test_lists_strings[] = { 34 34 { 35 35 .list_as_string = "", … … 47 47 .list_as_string = "foo bar", 48 48 .list = { "foo bar", NULL }, 49 .sep erators = ";"49 .separators = ";" 50 50 }, 51 51 { … … 60 60 .list_as_string = "\"foo bar\",comma;semicolon", 61 61 .list = { "\"foo bar\",comma", "semicolon", NULL }, 62 .sep erators = ";"62 .separators = ";" 63 63 } 64 64 }; 65 65 66 struct test_list_element test_lists_shell_strings[] = {66 const struct test_list_element test_lists_shell_strings[] = { 67 67 { 68 68 .list_as_string = "", … … 80 80 .list_as_string = "foo bar", 81 81 .list = { "foo bar", NULL }, 82 .sep erators = ";"82 .separators = ";" 83 83 }, 84 84 { … … 100 100 }; 101 101 102 static bool test_lists_shell(struct torture_context *tctx, 103 const void *data) 102 static bool test_lists_shell(struct torture_context *tctx, const void *data) 104 103 { 105 104 const struct test_list_element *element = data; 106 const char **ret1, **ret2, *tmp; 105 106 char **ret1, **ret2, *tmp; 107 107 bool match = true; 108 108 TALLOC_CTX *mem_ctx = tctx; 109 109 110 ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->sep erators);110 ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->separators); 111 111 112 112 torture_assert(tctx, ret1, "str_list_make_shell() must not return NULL"); 113 tmp = str_list_join_shell(mem_ctx, ret1, element->seperators ? *element->seperators : ' ');114 ret2 = str_list_make_shell(mem_ctx, tmp, element->sep erators);113 tmp = str_list_join_shell(mem_ctx, (const char **) ret1, element->separators ? *element->separators : ' '); 114 ret2 = str_list_make_shell(mem_ctx, tmp, element->separators); 115 115 116 116 if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) { … … 131 131 torture_assert(tctx, match, talloc_asprintf(tctx, 132 132 "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", element->list_as_string, tmp)); 133 torture_assert(tctx, str_list_equal(ret1, element->list), 133 torture_assert(tctx, str_list_equal((const char * const *) ret1, 134 element->list), 134 135 talloc_asprintf(tctx, 135 136 "str_list_make_shell(%s) failed to create correct list", … … 142 143 { 143 144 const struct test_list_element *element = data; 145 144 146 char **result; 145 result = str_list_make(tctx, element->list_as_string, element->sep erators);147 result = str_list_make(tctx, element->list_as_string, element->separators); 146 148 torture_assert(tctx, result, "str_list_make() must not return NULL"); 147 torture_assert(tctx, str_list_equal((const char **)result, element->list), 149 torture_assert(tctx, str_list_equal((const char * const *) result, 150 element->list), 148 151 talloc_asprintf(tctx, 149 152 "str_list_make(%s) failed to create correct list", … … 251 254 static bool test_list_add(struct torture_context *tctx) 252 255 { 253 c har **result, **result2;256 const char **result, **result2; 254 257 const char *list[] = { 255 258 "element_0", … … 259 262 NULL 260 263 }; 261 result = str_list_make(tctx, "element_0, element_1, element_2", NULL);264 result = (const char **) str_list_make(tctx, "element_0, element_1, element_2", NULL); 262 265 torture_assert(tctx, result, "str_list_make() must not return NULL"); 263 result2 = str_list_add( result, "element_3");266 result2 = str_list_add((const char **) result, "element_3"); 264 267 torture_assert(tctx, result2, "str_list_add() must not return NULL"); 265 268 torture_assert(tctx, str_list_equal(result2, list), … … 271 274 static bool test_list_add_const(struct torture_context *tctx) 272 275 { 273 c har **result, **result2;276 const char **result, **result2; 274 277 const char *list[] = { 275 278 "element_0", … … 279 282 NULL 280 283 }; 281 result = str_list_make(tctx, "element_0, element_1, element_2", NULL);284 result = (const char **) str_list_make(tctx, "element_0, element_1, element_2", NULL); 282 285 torture_assert(tctx, result, "str_list_make() must not return NULL"); 283 286 result2 = str_list_add_const(result, "element_3"); … … 291 294 static bool test_list_remove(struct torture_context *tctx) 292 295 { 293 c har **result;296 const char **result; 294 297 const char *list[] = { 295 298 "element_0", … … 298 301 NULL 299 302 }; 300 result = str_list_make(tctx, "element_0, element_1, element_2, element_3", NULL);303 result = (const char **) str_list_make(tctx, "element_0, element_1, element_2, element_3", NULL); 301 304 torture_assert(tctx, result, "str_list_make() must not return NULL"); 302 305 str_list_remove(result, "element_2"); … … 337 340 static bool test_list_unique(struct torture_context *tctx) 338 341 { 339 c har **result;342 const char **result; 340 343 const char *list[] = { 341 344 "element_0", … … 355 358 NULL 356 359 }; 357 result = str_list_copy(tctx, list_dup);360 result = (const char **) str_list_copy(tctx, list_dup); 358 361 /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */ 359 362 result = str_list_unique(result); … … 374 377 const char **list_dup = (const char **)str_list_make_empty(tctx); 375 378 376 count = lp _parm_int(tctx->lp_ctx, NULL, "list_unique", "count", 9);377 num_dups = lp _parm_int(tctx->lp_ctx, NULL, "list_unique", "dups", 7);379 count = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "count", 9); 380 num_dups = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "dups", 7); 378 381 torture_comment(tctx, "test_list_unique_2() with %d elements and %d dups\n", count, num_dups); 379 382 … … 399 402 static bool test_list_append(struct torture_context *tctx) 400 403 { 401 c har **result;404 const char **result; 402 405 const char *list[] = { 403 406 "element_0", … … 421 424 NULL 422 425 }; 423 result = str_list_copy(tctx, list);426 result = (const char **) str_list_copy(tctx, list); 424 427 torture_assert(tctx, result, "str_list_copy() must not return NULL"); 425 428 result = str_list_append(result, list2); … … 433 436 static bool test_list_append_const(struct torture_context *tctx) 434 437 { 435 c har **result;438 const char **result; 436 439 const char *list[] = { 437 440 "element_0", … … 455 458 NULL 456 459 }; 457 result = str_list_copy(tctx, list);460 result = (const char **) str_list_copy(tctx, list); 458 461 torture_assert(tctx, result, "str_list_copy() must not return NULL"); 459 462 result = str_list_append_const(result, list2); … … 467 470 struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) 468 471 { 469 struct torture_suite *suite = torture_suite_create(mem_ctx, " STRLIST");472 struct torture_suite *suite = torture_suite_create(mem_ctx, "strlist"); 470 473 int i; 471 474 472 475 for (i = 0; i < ARRAY_SIZE(test_lists_shell_strings); i++) { 473 torture_suite_add_simple_tcase_const(suite, "lists_shell", 474 test_lists_shell, &test_lists_shell_strings[i]); 476 char *name; 477 name = talloc_asprintf(suite, "lists_shell(%s)", 478 test_lists_shell_strings[i].list_as_string); 479 torture_suite_add_simple_tcase_const(suite, name, 480 test_lists_shell, &test_lists_shell_strings[i]); 475 481 } 476 482 477 483 for (i = 0; i < ARRAY_SIZE(test_lists_strings); i++) { 478 torture_suite_add_simple_tcase_const(suite, "lists", 479 test_list_make, &test_lists_strings[i]); 484 char *name; 485 name = talloc_asprintf(suite, "list_make(%s)", 486 test_lists_strings[i].list_as_string); 487 torture_suite_add_simple_tcase_const(suite, name, 488 test_list_make, &test_lists_strings[i]); 480 489 } 481 490 -
vendor/current/lib/util/tests/time.c
r414 r740 78 78 79 79 result = timestring(tctx, 42 - (utc_offset < 0 ? utc_offset : 0)); 80 torture_assert(tctx, !strncmp(start, result, strlen(start)), 81 result); 80 torture_assert(tctx, !strncmp(start, result, strlen(start)), result); 82 81 return true; 83 82 } … … 102 101 struct torture_suite *torture_local_util_time(TALLOC_CTX *mem_ctx) 103 102 { 104 struct torture_suite *suite = torture_suite_create(mem_ctx, " TIME");103 struct torture_suite *suite = torture_suite_create(mem_ctx, "time"); 105 104 106 105 torture_suite_add_simple_test(suite, "null_time", test_null_time); -
vendor/current/lib/util/tevent_ntstatus.c
r414 r740 21 21 #include "tevent_ntstatus.h" 22 22 23 bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status) 23 #define TEVENT_NTERROR_MAGIC (0x917b5acd) 24 25 bool _tevent_req_nterror(struct tevent_req *req, 26 NTSTATUS status, 27 const char *location) 24 28 { 25 return tevent_req_error(req, NT_STATUS_V(status)); 29 uint64_t err; 30 31 if (NT_STATUS_IS_OK(status)) { 32 return false; 33 } 34 35 /* 36 * I've put this variable here, because I'm not 100% certain 37 * how to correctly assign a 64-bit constant and left-shift it 38 * by 32 bits in a single expression. If anyone knows, feel 39 * free :-) 40 */ 41 err = TEVENT_NTERROR_MAGIC; 42 err <<= 32; 43 err |= NT_STATUS_V(status); 44 45 return _tevent_req_error(req, err, location); 26 46 } 27 47 … … 42 62 break; 43 63 case TEVENT_REQ_USER_ERROR: 44 *status = NT_STATUS(err); 64 if ((err >> 32) != TEVENT_NTERROR_MAGIC) { 65 abort(); 66 } 67 *status = NT_STATUS(err & 0xffffffff); 45 68 break; 46 69 default: … … 60 83 return NT_STATUS_OK; 61 84 } 85 86 void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq, 87 NTSTATUS subreq_status) 88 { 89 struct tevent_req *req = tevent_req_callback_data( 90 subreq, struct tevent_req); 91 92 TALLOC_FREE(subreq); 93 94 if (!NT_STATUS_IS_OK(subreq_status)) { 95 tevent_req_nterror(req, subreq_status); 96 return; 97 } 98 tevent_req_done(req); 99 } -
vendor/current/lib/util/tevent_ntstatus.h
r414 r740 24 24 #include <stdbool.h> 25 25 #include "../libcli/util/ntstatus.h" 26 #include "../tevent/tevent.h"26 #include <tevent.h> 27 27 28 bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status); 28 bool _tevent_req_nterror(struct tevent_req *req, 29 NTSTATUS status, 30 const char *location); 31 #define tevent_req_nterror(req, status) \ 32 _tevent_req_nterror(req, status, __location__) 29 33 bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus); 30 34 NTSTATUS tevent_req_simple_recv_ntstatus(struct tevent_req *req); 31 35 36 /* 37 * Helper routine to pass the subreq_ntstatus to the req embedded in 38 * tevent_req_callback_data(subreq), which will be freed. 39 */ 40 void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq, 41 NTSTATUS subreq_status); 42 32 43 #endif -
vendor/current/lib/util/tevent_unix.c
r414 r740 22 22 */ 23 23 24 #include "../replace/replace.h" 24 25 #include "tevent_unix.h" 25 #include "../replace/replace.h"26 26 27 27 bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno) -
vendor/current/lib/util/tevent_unix.h
r414 r740 25 25 #define _TEVENT_UNIX_H 26 26 27 #include "../tevent/tevent.h"27 #include <tevent.h> 28 28 29 29 bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno); -
vendor/current/lib/util/time.c
r478 r740 5 5 Copyright (C) Andrew Tridgell 1992-2004 6 6 Copyright (C) Stefan (metze) Metzmacher 2002 7 Copyright (C) Jeremy Allison 2007 8 Copyright (C) Andrew Bartlett 2011 7 9 8 10 This program is free software; you can redistribute it and/or modify … … 56 58 } 57 59 60 /** 61 a wrapper to preferably get the monotonic time 62 **/ 63 _PUBLIC_ void clock_gettime_mono(struct timespec *tp) 64 { 65 if (clock_gettime(CUSTOM_CLOCK_MONOTONIC,tp) != 0) { 66 clock_gettime(CLOCK_REALTIME,tp); 67 } 68 } 69 70 /** 71 a wrapper to preferably get the monotonic time in seconds 72 as this is only second resolution we can use the cached 73 (and much faster) COARSE clock variant 74 **/ 75 _PUBLIC_ time_t time_mono(time_t *t) 76 { 77 struct timespec tp; 78 int rc = -1; 79 #ifdef CLOCK_MONOTONIC_COARSE 80 rc = clock_gettime(CLOCK_MONOTONIC_COARSE,&tp); 81 #endif 82 if (rc != 0) { 83 clock_gettime_mono(&tp); 84 } 85 if (t != NULL) { 86 *t = tp.tv_sec; 87 } 88 return tp.tv_sec; 89 } 90 58 91 59 92 #define TIME_FIXUP_CONSTANT 11644473600LL … … 61 94 time_t convert_timespec_to_time_t(struct timespec ts) 62 95 { 96 /* Ensure tv_nsec is less than 1sec. */ 97 while (ts.tv_nsec > 1000000000) { 98 ts.tv_sec += 1; 99 ts.tv_nsec -= 1000000000; 100 } 101 63 102 /* 1 ns == 1,000,000,000 - one thousand millionths of a second. 64 103 increment if it's greater than 500 millionth of a second. */ 104 65 105 if (ts.tv_nsec > 500000000) { 66 106 return ts.tv_sec + 1; … … 300 340 301 341 342 /**************************************************************************** 343 Return the date and time as a string 344 ****************************************************************************/ 345 346 char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires) 347 { 348 time_t t; 349 struct tm *tm; 350 351 t = (time_t)tp->tv_sec; 352 tm = localtime(&t); 353 if (!tm) { 354 if (hires) { 355 return talloc_asprintf(ctx, 356 "%ld.%06ld seconds since the Epoch", 357 (long)tp->tv_sec, 358 (long)tp->tv_usec); 359 } else { 360 return talloc_asprintf(ctx, 361 "%ld seconds since the Epoch", 362 (long)t); 363 } 364 } else { 365 #ifdef HAVE_STRFTIME 366 char TimeBuf[60]; 367 if (hires) { 368 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm); 369 return talloc_asprintf(ctx, 370 "%s.%06ld", TimeBuf, 371 (long)tp->tv_usec); 372 } else { 373 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm); 374 return talloc_strdup(ctx, TimeBuf); 375 } 376 #else 377 if (hires) { 378 const char *asct = asctime(tm); 379 return talloc_asprintf(ctx, "%s.%06ld", 380 asct ? asct : "unknown", 381 (long)tp->tv_usec); 382 } else { 383 const char *asct = asctime(tm); 384 return talloc_asprintf(ctx, asct ? asct : "unknown"); 385 } 386 #endif 387 } 388 } 389 390 char *current_timestring(TALLOC_CTX *ctx, bool hires) 391 { 392 struct timeval tv; 393 394 GetTimeOfDay(&tv); 395 return timeval_string(ctx, &tv, hires); 396 } 397 398 302 399 /** 303 400 return a HTTP/1.0 time string … … 347 444 348 445 #ifdef HAVE_STRFTIME 349 /* some versions of gcc complain about using %c. This is a bug 350 in the gcc warning, not a bug in this code. See a recent 351 strftime() manual page for details. 352 */ 353 strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); 446 /* Some versions of gcc complain about using some special format 447 * specifiers. This is a bug in gcc, not a bug in this code. See a 448 * recent strftime() manual page for details. */ 449 strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm); 354 450 TimeBuf = talloc_strdup(mem_ctx, tempTime); 355 451 #else … … 398 494 int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; 399 495 return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); 496 } 497 498 /** 499 return (tp1 - tp2) in microseconds 500 */ 501 _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2) 502 { 503 int64_t sec_diff = tp1->tv_sec - tp2->tv_sec; 504 return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec); 400 505 } 401 506 -
vendor/current/lib/util/time.h
r478 r740 2 2 Unix SMB/CIFS implementation. 3 3 time utility functions 4 4 5 Copyright (C) Andrew Tridgell 1992-2004 6 Copyright (C) Stefan (metze) Metzmacher 2002 7 Copyright (C) Jeremy Allison 2007 8 Copyright (C) Andrew Bartlett 2011 9 5 10 This program is free software; you can redistribute it and/or modify 6 11 it under the terms of the GNU General Public License as published by … … 52 57 53 58 /** 59 a wrapper to preferably get the monotonic time 60 **/ 61 _PUBLIC_ void clock_gettime_mono(struct timespec *tp); 62 63 /** 64 a wrapper to preferably get the monotonic time in s 65 **/ 66 _PUBLIC_ time_t time_mono(time_t *t); 67 68 /** 54 69 interpret an 8 byte "filetime" structure to a time_t 55 70 It's originally in "100ns units since jan 1st 1601" … … 110 125 111 126 /** 127 Return a date and time as a string (optionally with microseconds) 128 129 format is %Y/%m/%d %H:%M:%S if strftime is available 130 **/ 131 132 char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires); 133 134 /** 135 Return the current date and time as a string (optionally with microseconds) 136 137 format is %Y/%m/%d %H:%M:%S if strftime is available 138 **/ 139 char *current_timestring(TALLOC_CTX *ctx, bool hires); 140 141 /** 112 142 return a HTTP/1.0 time string 113 143 **/ … … 116 146 /** 117 147 Return the date and time as a string 148 149 format is %a %b %e %X %Y %Z 118 150 **/ 119 151 _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t); … … 143 175 */ 144 176 _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2); 177 178 /** 179 return (tp1 - tp2) in nanoseconds 180 */ 181 _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2); 145 182 146 183 /** -
vendor/current/lib/util/unix_privs.c
r414 r740 21 21 22 22 #include "includes.h" 23 #include "system/ filesys.h"23 #include "system/passwd.h" 24 24 #include "../lib/util/unix_privs.h" 25 26 #if defined(UID_WRAPPER) 27 #if !defined(UID_WRAPPER_REPLACE) && !defined(UID_WRAPPER_NOT_REPLACE) 28 #define UID_WRAPPER_REPLACE 29 #include "../uid_wrapper/uid_wrapper.h" 30 #endif 31 #else 32 #define uwrap_enabled() 0 33 #endif 25 34 26 35 /** … … 77 86 return s; 78 87 } 88 89 uid_t root_privileges_original_uid(void *s) 90 { 91 struct saved_state *saved = talloc_get_type_abort(s, struct saved_state); 92 return saved->uid; 93 } -
vendor/current/lib/util/util.c
r414 r740 26 26 #include "system/filesys.h" 27 27 #include "system/locale.h" 28 #include "system/shmem.h" 29 28 30 #undef malloc 29 31 #undef strcasecmp … … 31 33 #undef strdup 32 34 #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 33 44 34 45 /** … … 155 166 **/ 156 167 157 _PUBLIC_ void msleep(unsigned int t) 158 { 159 struct timeval tval; 160 161 tval.tv_sec = t/1000; 162 tval.tv_usec = 1000*(t%1000); 163 /* this should be the real select - do NOT replace 164 with sys_select() */ 165 select(0,NULL,NULL,NULL,&tval); 168 _PUBLIC_ void smb_msleep(unsigned int t) 169 { 170 #if defined(HAVE_NANOSLEEP) 171 struct timespec ts; 172 int ret; 173 174 ts.tv_sec = t/1000; 175 ts.tv_nsec = 1000000*(t%1000); 176 177 do { 178 errno = 0; 179 ret = nanosleep(&ts, &ts); 180 } while (ret < 0 && errno == EINTR && (ts.tv_sec > 0 || ts.tv_nsec > 0)); 181 #else 182 unsigned int tdiff=0; 183 struct timeval tval,t1,t2; 184 fd_set fds; 185 186 GetTimeOfDay(&t1); 187 t2 = t1; 188 189 while (tdiff < t) { 190 tval.tv_sec = (t-tdiff)/1000; 191 tval.tv_usec = 1000*((t-tdiff)%1000); 192 193 /* Never wait for more than 1 sec. */ 194 if (tval.tv_sec > 1) { 195 tval.tv_sec = 1; 196 tval.tv_usec = 0; 197 } 198 199 FD_ZERO(&fds); 200 errno = 0; 201 select(0,&fds,NULL,NULL,&tval); 202 203 GetTimeOfDay(&t2); 204 if (t2.tv_sec < t1.tv_sec) { 205 /* Someone adjusted time... */ 206 t1 = t2; 207 } 208 209 tdiff = usec_time_diff(&t2,&t1)/1000; 210 } 211 #endif 166 212 } 167 213 … … 255 301 } 256 302 303 static void debugadd_cb(const char *buf, void *private_data) 304 { 305 int *plevel = (int *)private_data; 306 DEBUGADD(*plevel, ("%s", buf)); 307 } 308 309 void print_asc_cb(const uint8_t *buf, int len, 310 void (*cb)(const char *buf, void *private_data), 311 void *private_data) 312 { 313 int i; 314 char s[2]; 315 s[1] = 0; 316 317 for (i=0; i<len; i++) { 318 s[0] = isprint(buf[i]) ? buf[i] : '.'; 319 cb(s, private_data); 320 } 321 } 322 257 323 void print_asc(int level, const uint8_t *buf,int len) 258 324 { 259 int i; 260 for (i=0;i<len;i++) 261 DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.')); 262 } 263 264 /** 265 * Write dump of binary data to the log file. 266 * 267 * The data is only written if the log level is at least level. 325 print_asc_cb(buf, len, debugadd_cb, &level); 326 } 327 328 /** 329 * Write dump of binary data to a callback 268 330 */ 269 static void _dump_data(int level, const uint8_t *buf, int len, 270 bool omit_zero_bytes) 331 void dump_data_cb(const uint8_t *buf, int len, 332 bool omit_zero_bytes, 333 void (*cb)(const char *buf, void *private_data), 334 void *private_data) 271 335 { 272 336 int i=0; 273 337 static const uint8_t empty[16] = { 0, }; 274 338 bool skipped = false; 339 char tmp[16]; 275 340 276 341 if (len<=0) return; 277 278 if (!DEBUGLVL(level)) return;279 342 280 343 for (i=0;i<len;) { … … 291 354 292 355 if (i<len) { 293 DEBUGADD(level,("[%04X] ",i)); 356 snprintf(tmp, sizeof(tmp), "[%04X] ", i); 357 cb(tmp, private_data); 294 358 } 295 359 } 296 360 297 DEBUGADD(level,("%02X ",(int)buf[i])); 361 snprintf(tmp, sizeof(tmp), "%02X ", (int)buf[i]); 362 cb(tmp, private_data); 298 363 i++; 299 if (i%8 == 0) DEBUGADD(level,(" ")); 364 if (i%8 == 0) { 365 cb(" ", private_data); 366 } 300 367 if (i%16 == 0) { 301 368 302 print_asc(level,&buf[i-16],8); DEBUGADD(level,(" ")); 303 print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n")); 369 print_asc_cb(&buf[i-16], 8, cb, private_data); 370 cb(" ", private_data); 371 print_asc_cb(&buf[i-8], 8, cb, private_data); 372 cb("\n", private_data); 304 373 305 374 if ((omit_zero_bytes == true) && … … 307 376 (memcmp(&buf[i], &empty, 16) == 0)) { 308 377 if (!skipped) { 309 DEBUGADD(level,("skipping zero buffer bytes\n")); 378 cb("skipping zero buffer bytes\n", 379 private_data); 310 380 skipped = true; 311 381 } … … 317 387 int n; 318 388 n = 16 - (i%16); 319 DEBUGADD(level,(" ")); 320 if (n>8) DEBUGADD(level,(" ")); 321 while (n--) DEBUGADD(level,(" ")); 389 cb(" ", private_data); 390 if (n>8) { 391 cb(" ", private_data); 392 } 393 while (n--) { 394 cb(" ", private_data); 395 } 322 396 n = MIN(8,i%16); 323 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " )); 397 print_asc_cb(&buf[i-(i%16)], n, cb, private_data); 398 cb(" ", private_data); 324 399 n = (i%16) - n; 325 if (n>0) print_asc(level,&buf[i-n],n); 326 DEBUGADD(level,("\n")); 400 if (n>0) { 401 print_asc_cb(&buf[i-n], n, cb, private_data); 402 } 403 cb("\n", private_data); 327 404 } 328 405 … … 336 413 _PUBLIC_ void dump_data(int level, const uint8_t *buf, int len) 337 414 { 338 _dump_data(level, buf, len, false); 415 if (!DEBUGLVL(level)) { 416 return; 417 } 418 dump_data_cb(buf, len, false, debugadd_cb, &level); 339 419 } 340 420 … … 343 423 * 344 424 * The data is only written if the log level is at least level. 345 * 16 zero bytes in a row are om mited425 * 16 zero bytes in a row are omitted 346 426 */ 347 427 _PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len) 348 428 { 349 _dump_data(level, buf, len, true); 429 if (!DEBUGLVL(level)) { 430 return; 431 } 432 dump_data_cb(buf, len, true, debugadd_cb, &level); 350 433 } 351 434 … … 580 663 _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len) 581 664 { 582 size_t i ;665 size_t i = 0; 583 666 size_t num_chars = 0; 584 667 uint8_t lonybble, hinybble; … … 586 669 char *p1 = NULL, *p2 = NULL; 587 670 588 for (i = 0; i < strhex_len && strhex[i] != 0; i++) {589 if (strncasecmp(hexchars, "0x", 2) == 0) {590 i++; /* skip two chars */591 continue;592 } 593 671 /* skip leading 0x prefix */ 672 if (strncasecmp(strhex, "0x", 2) == 0) { 673 i += 2; /* skip two chars */ 674 } 675 676 for (; i < strhex_len && strhex[i] != 0; i++) { 594 677 if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) 595 678 break; … … 765 848 bool ltrim) 766 849 { 767 c har *s;768 c har *saved_s;850 const char *s; 851 const char *saved_s; 769 852 char *pbuf; 770 853 bool quoted; … … 776 859 } 777 860 778 s = (char *)*ptr;861 s = *ptr; 779 862 780 863 /* default to simple separators */ … … 854 937 } 855 938 856 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.au 945 **/ 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 } 984 985 struct anonymous_shared_header { 986 union { 987 size_t length; 988 uint8_t pad[16]; 989 } u; 990 }; 991 992 /* Map a shared memory buffer of at least nelem counters. */ 993 void *anonymous_shared_allocate(size_t orig_bufsz) 994 { 995 void *ptr; 996 void *buf; 997 size_t pagesz = getpagesize(); 998 size_t pagecnt; 999 size_t bufsz = orig_bufsz; 1000 struct anonymous_shared_header *hdr; 1001 1002 bufsz += sizeof(*hdr); 1003 1004 /* round up to full pages */ 1005 pagecnt = bufsz / pagesz; 1006 if (bufsz % pagesz) { 1007 pagecnt += 1; 1008 } 1009 bufsz = pagesz * pagecnt; 1010 1011 if (orig_bufsz >= bufsz) { 1012 /* integer wrap */ 1013 errno = ENOMEM; 1014 return NULL; 1015 } 1016 1017 #ifdef MAP_ANON 1018 /* BSD */ 1019 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, 1020 -1 /* fd */, 0 /* offset */); 1021 #else 1022 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 1023 open("/dev/zero", O_RDWR), 0 /* offset */); 1024 #endif 1025 1026 if (buf == MAP_FAILED) { 1027 return NULL; 1028 } 1029 1030 hdr = (struct anonymous_shared_header *)buf; 1031 hdr->u.length = bufsz; 1032 1033 ptr = (void *)(&hdr[1]); 1034 1035 return ptr; 1036 } 1037 1038 void anonymous_shared_free(void *ptr) 1039 { 1040 struct anonymous_shared_header *hdr; 1041 1042 if (ptr == NULL) { 1043 return; 1044 } 1045 1046 hdr = (struct anonymous_shared_header *)ptr; 1047 1048 hdr--; 1049 1050 munmap(hdr, hdr->u.length); 1051 } 1052 1053 #ifdef DEVELOPER 1054 /* used when you want a debugger started at a particular point in the 1055 code. Mostly useful in code that runs as a child process, where 1056 normal gdb attach is harder to organise. 1057 */ 1058 void samba_start_debugger(void) 1059 { 1060 char *cmd = NULL; 1061 if (asprintf(&cmd, "xterm -e \"gdb --pid %u\"&", getpid()) == -1) { 1062 return; 1063 } 1064 if (system(cmd) == -1) { 1065 free(cmd); 1066 return; 1067 } 1068 free(cmd); 1069 sleep(2); 1070 } 1071 #endif -
vendor/current/lib/util/util.h
r414 r740 22 22 #define _SAMBA_UTIL_H_ 23 23 24 #if _SAMBA_BUILD_ == 4 25 #include "../lib/util/charset/charset.h" 26 #endif 27 #include "../lib/util/attr.h" 24 #include "lib/util/charset/charset.h" 25 #include "lib/util/attr.h" 28 26 29 27 /* for TALLOC_CTX */ … … 40 38 extern const char *panic_action; 41 39 42 #include "../lib/util/time.h" 43 #include "../lib/util/data_blob.h" 44 #include "../lib/util/xfile.h" 45 #include "../lib/util/mutex.h" 46 #include "../lib/util/byteorder.h" 47 #include "../lib/util/talloc_stack.h" 40 #include "lib/util/time.h" 41 #include "lib/util/data_blob.h" 42 #include "lib/util/xfile.h" 43 #include "lib/util/byteorder.h" 44 #include "lib/util/talloc_stack.h" 48 45 49 46 /** … … 61 58 #endif 62 59 63 #if _SAMBA_BUILD_ == 464 #ifdef VALGRIND65 #define strlen(x) valgrind_strlen(x)66 size_t valgrind_strlen(const char *s);67 #endif68 #endif69 70 60 #ifndef ABS 71 61 #define ABS(a) ((a)>0?(a):(-(a))) 72 62 #endif 73 63 74 #include " ../lib/util/memory.h"64 #include "lib/util/memory.h" 75 65 76 66 /** … … 89 79 **/ 90 80 _PUBLIC_ void fault_setup(const char *pname); 81 _PUBLIC_ void fault_setup_disable(void); 91 82 #endif 92 83 … … 143 134 _PUBLIC_ pid_t sys_getpid(void); 144 135 136 _PUBLIC_ int sys_getpeereid( int s, uid_t *uid); 137 138 struct sockaddr; 139 140 _PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, 141 int salen, 142 char *host, 143 size_t hostlen, 144 char *service, 145 size_t servlen, 146 int flags); 147 _PUBLIC_ int sys_connect(int fd, const struct sockaddr * addr); 148 145 149 /* The following definitions come from lib/util/genrand.c */ 146 147 150 /** 148 151 Copy any user given reseed data. … … 177 180 **/ 178 181 _PUBLIC_ bool check_password_quality(const char *s); 182 183 /** 184 * Generate a random text password. 185 */ 186 _PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max); 179 187 180 188 /** … … 451 459 /** 452 460 * build a null terminated list of strings from an argv-like input string 453 * Entries are sep erated by spaces and can be enclosed by quotes.461 * Entries are separated by spaces and can be enclosed by quotes. 454 462 * Does NOT support escaping 455 463 */ … … 459 467 * join a list back to one string 460 468 */ 461 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char sep erator);469 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator); 462 470 463 471 /** join a list back to one (shell-like) string; entries 464 * sep erated by spaces, using quotes where necessary */472 * separated by spaces, using quotes where necessary */ 465 473 _PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep); 466 474 … … 478 486 Return true if all the elements of the list match exactly. 479 487 */ 480 _PUBLIC_ bool str_list_equal(const char * *list1, const char **list2);488 _PUBLIC_ bool str_list_equal(const char * const *list1, const char * const *list2); 481 489 482 490 /** … … 535 543 _PUBLIC_ const char **str_list_copy_const(TALLOC_CTX *mem_ctx, 536 544 const char **list); 545 546 /** 547 * Needed for making an "unconst" list "const" 548 */ 549 _PUBLIC_ const char **const_str_list(char **list); 537 550 538 551 … … 597 610 _PUBLIC_ bool large_file_support(const char *path); 598 611 612 /* 613 compare two files, return true if the two files have the same content 614 */ 615 bool file_compare(const char *path1, const char *path2); 616 599 617 /* The following definitions come from lib/util/util.c */ 600 618 … … 641 659 Sleep for a specified number of milliseconds. 642 660 **/ 643 _PUBLIC_ void msleep(unsigned int t);661 _PUBLIC_ void smb_msleep(unsigned int t); 644 662 645 663 /** … … 647 665 **/ 648 666 _PUBLIC_ char* get_myname(TALLOC_CTX *mem_ctx); 649 650 /**651 Return true if a string could be a pure IP address.652 **/653 _PUBLIC_ bool is_ipaddress(const char *str);654 655 /**656 Interpret an internet address or name into an IP address in 4 byte form.657 **/658 _PUBLIC_ uint32_t interpret_addr(const char *str);659 660 /**661 A convenient addition to interpret_addr().662 **/663 _PUBLIC_ struct in_addr interpret_addr2(const char *str);664 665 /**666 Check if an IP is the 0.0.0.0.667 **/668 _PUBLIC_ bool is_zero_ip_v4(struct in_addr ip);669 670 /**671 Are two IPs on the same subnet?672 **/673 _PUBLIC_ bool same_net_v4(struct in_addr ip1,struct in_addr ip2,struct in_addr mask);674 675 _PUBLIC_ bool is_ipaddress_v4(const char *str);676 667 677 668 /** … … 687 678 688 679 /** 680 * Write dump of binary data to a callback 681 */ 682 void dump_data_cb(const uint8_t *buf, int len, 683 bool omit_zero_bytes, 684 void (*cb)(const char *buf, void *private_data), 685 void *private_data); 686 687 /** 689 688 * Write dump of binary data to the log file. 690 689 * … … 697 696 * 698 697 * The data is only written if the log level is at least level. 699 * 16 zero bytes in a row are om mited698 * 16 zero bytes in a row are omitted 700 699 */ 701 700 _PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len); … … 784 783 #endif 785 784 786 /* The following definitions come from lib/util/mutex.c */787 788 789 /**790 register a set of mutex/rwlock handlers.791 Should only be called once in the execution of smbd.792 */793 _PUBLIC_ bool register_mutex_handlers(const char *name, struct mutex_ops *ops);794 795 785 /* The following definitions come from lib/util/idtree.c */ 796 786 … … 840 830 Become a daemon, discarding the controlling terminal. 841 831 **/ 842 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group );832 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout); 843 833 844 834 /** … … 853 843 854 844 void print_asc(int level, const uint8_t *buf,int len); 845 void print_asc_cb(const uint8_t *buf, int len, 846 void (*cb)(const char *buf, void *private_data), 847 void *private_data); 855 848 856 849 /** … … 862 855 863 856 bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, 864 uid_t **uids, size_t *num_uids);857 uid_t **uids, uint32_t *num_uids); 865 858 bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, 866 gid_t **gids, size_t *num_gids); 867 859 gid_t **gids, uint32_t *num_gids); 860 861 /** 862 * Allocate anonymous shared memory of the given size 863 */ 864 void *anonymous_shared_allocate(size_t bufsz); 865 void anonymous_shared_free(void *ptr); 866 867 /* 868 run a command as a child process, with a timeout. 869 870 any stdout/stderr from the child will appear in the Samba logs with 871 the specified log levels 872 873 If callback is set then the callback is called on completion 874 with the return code from the command 875 */ 876 struct tevent_context; 877 struct tevent_req; 878 struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx, 879 struct tevent_context *ev, 880 struct timeval endtime, 881 int stdout_log_level, 882 int stderr_log_level, 883 const char * const *argv0, ...); 884 int samba_runcmd_recv(struct tevent_req *req, int *perrno); 885 886 #ifdef DEVELOPER 887 void samba_start_debugger(void); 888 #endif 868 889 869 890 #endif /* _SAMBA_UTIL_H_ */ -
vendor/current/lib/util/util_file.c
r414 r740 236 236 #endif 237 237 if (!p) { 238 p = file_load(fname, &s2, 0, talloc_autofree_context());238 p = file_load(fname, &s2, 0, NULL); 239 239 if (!p) return NULL; 240 240 if (s2 != size) { … … 436 436 437 437 438 /* 439 compare two files, return true if the two files have the same content 440 */ 441 bool file_compare(const char *path1, const char *path2) 442 { 443 size_t size1, size2; 444 char *p1, *p2; 445 TALLOC_CTX *mem_ctx = talloc_new(NULL); 446 447 p1 = file_load(path1, &size1, 0, mem_ctx); 448 p2 = file_load(path2, &size2, 0, mem_ctx); 449 if (!p1 || !p2 || size1 != size2) { 450 talloc_free(mem_ctx); 451 return false; 452 } 453 if (memcmp(p1, p2, size1) != 0) { 454 talloc_free(mem_ctx); 455 return false; 456 } 457 talloc_free(mem_ctx); 458 return true; 459 } -
vendor/current/lib/util/util_id.c
r414 r740 27 27 28 28 bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, 29 gid_t **gids, size_t *num_gids)29 gid_t **gids, uint32_t *num_gids) 30 30 { 31 31 int i; … … 60 60 61 61 bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, 62 uid_t **uids, size_t *num_uids)62 uid_t **uids, uint32_t *num_uids) 63 63 { 64 64 int i; -
vendor/current/lib/util/util_ldb.c
r414 r740 22 22 23 23 #include "includes.h" 24 #include "lib/ldb/include/ldb.h"24 #include <ldb.h> 25 25 #include "../lib/util/util_ldb.h" 26 26 27 /* 27 search the samfor the specified attributes - va_list variant28 */28 * search the LDB for the specified attributes - va_list variant 29 */ 29 30 int gendb_search_v(struct ldb_context *ldb, 30 31 TALLOC_CTX *mem_ctx, … … 33 34 const char * const *attrs, 34 35 const char *format, 35 va_list ap) 36 va_list ap) 36 37 { 37 38 enum ldb_scope scope = LDB_SCOPE_SUBTREE; … … 55 56 56 57 if (ret == LDB_SUCCESS) { 57 talloc_steal(mem_ctx, res->msgs);58 59 58 DEBUG(6,("gendb_search_v: %s %s -> %d\n", 60 59 basedn?ldb_dn_get_linearized(basedn):"NULL", … … 62 61 63 62 ret = res->count; 64 *msgs = res->msgs; 63 if (msgs != NULL) { 64 *msgs = talloc_steal(mem_ctx, res->msgs); 65 } 65 66 talloc_free(res); 66 67 } else if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) { 67 68 ret = 0; 68 *msgs = NULL;69 if (msgs != NULL) *msgs = NULL; 69 70 } else { 70 71 DEBUG(4,("gendb_search_v: search failed: %s\n", 71 72 ldb_errstring(ldb))); 72 73 ret = -1; 74 if (msgs != NULL) *msgs = NULL; 73 75 } 74 76 … … 79 81 80 82 /* 81 search the LDB for the specified attributes - varargs variant82 */83 * search the LDB for the specified attributes - varargs variant 84 */ 83 85 int gendb_search(struct ldb_context *ldb, 84 86 TALLOC_CTX *mem_ctx, … … 86 88 struct ldb_message ***res, 87 89 const char * const *attrs, 88 const char *format, ...) 90 const char *format, ...) 89 91 { 90 92 va_list ap; … … 99 101 100 102 /* 101 search the LDB for a specified record (by DN) 102 */ 103 103 * search the LDB for a specified record (by DN) 104 */ 104 105 int gendb_search_dn(struct ldb_context *ldb, 105 106 TALLOC_CTX *mem_ctx, … … 111 112 } 112 113 113 /*114 setup some initial ldif in a ldb115 */116 int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string)117 {118 struct ldb_ldif *ldif;119 int ret;120 ldif = ldb_ldif_read_string(ldb, &ldif_string);121 if (ldif == NULL) return -1;122 ret = ldb_add(ldb, ldif->msg);123 talloc_free(ldif);124 return ret;125 }126 127 char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)128 {129 return strupper_talloc_n(mem_ctx, s, n);130 }131 132 133 134 /*135 search the LDB for a single record, with the extended_dn control136 return LDB_SUCCESS on success, or an ldb error code on error137 138 if the search returns 0 entries, return LDB_ERR_NO_SUCH_OBJECT139 if the search returns more than 1 entry, return LDB_ERR_CONSTRAINT_VIOLATION140 */141 int gendb_search_single_extended_dn(struct ldb_context *ldb,142 TALLOC_CTX *mem_ctx,143 struct ldb_dn *basedn,144 enum ldb_scope scope,145 struct ldb_message **msg,146 const char * const *attrs,147 const char *format, ...)148 {149 va_list ap;150 int ret;151 struct ldb_request *req;152 char *filter;153 TALLOC_CTX *tmp_ctx;154 struct ldb_result *res;155 struct ldb_extended_dn_control *ctrl;156 157 tmp_ctx = talloc_new(mem_ctx);158 159 res = talloc_zero(tmp_ctx, struct ldb_result);160 if (!res) {161 return LDB_ERR_OPERATIONS_ERROR;162 }163 164 va_start(ap, format);165 filter = talloc_vasprintf(tmp_ctx, format, ap);166 va_end(ap);167 168 if (filter == NULL) {169 talloc_free(tmp_ctx);170 return LDB_ERR_OPERATIONS_ERROR;171 }172 173 ret = ldb_build_search_req(&req, ldb, tmp_ctx,174 basedn,175 scope,176 filter,177 attrs,178 NULL,179 res,180 ldb_search_default_callback,181 NULL);182 if (ret != LDB_SUCCESS) {183 talloc_free(tmp_ctx);184 return ret;185 }186 187 ctrl = talloc(tmp_ctx, struct ldb_extended_dn_control);188 if (ctrl == NULL) {189 talloc_free(tmp_ctx);190 return LDB_ERR_OPERATIONS_ERROR;191 }192 193 ctrl->type = 1;194 195 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, ctrl);196 if (ret != LDB_SUCCESS) {197 return ret;198 }199 200 ret = ldb_request(ldb, req);201 if (ret == LDB_SUCCESS) {202 ret = ldb_wait(req->handle, LDB_WAIT_ALL);203 }204 205 if (ret != LDB_SUCCESS) {206 talloc_free(tmp_ctx);207 return ret;208 }209 210 if (res->count == 0) {211 talloc_free(tmp_ctx);212 return LDB_ERR_NO_SUCH_OBJECT;213 }214 215 if (res->count > 1) {216 /* the function is only supposed to return a single entry */217 DEBUG(0,(__location__ ": More than one return for baseDN %s filter %s\n",218 ldb_dn_get_linearized(basedn), filter));219 talloc_free(tmp_ctx);220 return LDB_ERR_CONSTRAINT_VIOLATION;221 }222 223 *msg = talloc_steal(mem_ctx, res->msgs[0]);224 225 talloc_free(tmp_ctx);226 227 return LDB_SUCCESS;228 } -
vendor/current/lib/util/util_ldb.h
r414 r740 1 /* 2 Unix SMB/CIFS implementation. 3 4 common share info functions 5 6 Copyright (C) Andrew Tridgell 2004 7 Copyright (C) Tim Potter 2004 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 1 24 #ifndef __LIB_UTIL_UTIL_LDB_H__ 2 25 #define __LIB_UTIL_UTIL_LDB_H__ … … 24 47 struct ldb_message ***res, 25 48 const char * const *attrs); 26 int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string);27 char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);28 29 int gendb_search_single_extended_dn(struct ldb_context *ldb,30 TALLOC_CTX *mem_ctx,31 struct ldb_dn *basedn,32 enum ldb_scope scope,33 struct ldb_message **msg,34 const char * const *attrs,35 const char *format, ...) PRINTF_ATTRIBUTE(7,8);36 49 37 50 #endif /* __LIB_UTIL_UTIL_LDB_H__ */ -
vendor/current/lib/util/util_net.c
r414 r740 28 28 #include "system/locale.h" 29 29 #include "system/filesys.h" 30 #include "lib/util/util_net.h" 30 31 #undef strcasecmp 31 32 … … 36 37 void zero_sockaddr(struct sockaddr_storage *pss) 37 38 { 38 memset(pss, '\0', sizeof(*pss));39 ZERO_STRUCTP(pss); 39 40 /* Ensure we're at least a valid sockaddr-storage. */ 40 41 pss->ss_family = AF_INET; … … 50 51 struct addrinfo hints; 51 52 52 memset(&hints, '\0', sizeof(hints)); 53 ZERO_STRUCT(hints); 54 53 55 /* By default make sure it supports TCP. */ 54 56 hints.ai_socktype = SOCK_STREAM; 55 57 hints.ai_flags = flags; 56 58 57 /* Linux man page on getadd info() says port will be58 uninitialized when service string i nNULL */59 /* Linux man page on getaddrinfo() says port will be 60 uninitialized when service string is NULL */ 59 61 60 62 ret = getaddrinfo(str, NULL, … … 383 385 * Check if a struct sockaddr has an unspecified address. 384 386 */ 385 bool is_zero_addr(const struct sockaddr *pss)386 { 387 #if defined(HAVE_IPV6) 388 if (pss->s a_family == AF_INET6) {387 bool is_zero_addr(const struct sockaddr_storage *pss) 388 { 389 #if defined(HAVE_IPV6) 390 if (pss->ss_family == AF_INET6) { 389 391 const struct in6_addr *pin6 = 390 392 &((const struct sockaddr_in6 *)pss)->sin6_addr; … … 392 394 } 393 395 #endif 394 if (pss->s a_family == AF_INET) {396 if (pss->ss_family == AF_INET) { 395 397 const struct in_addr *pin = &((const struct sockaddr_in *)pss)->sin_addr; 396 398 return is_zero_ip_v4(*pin); … … 539 541 540 542 543 /**************************************************************************** 544 Get a port number in host byte order from a sockaddr_storage. 545 ****************************************************************************/ 546 547 uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) 548 { 549 uint16_t port = 0; 550 551 if (pss->ss_family != AF_INET) { 552 #if defined(HAVE_IPV6) 553 /* IPv6 */ 554 const struct sockaddr_in6 *sa6 = 555 (const struct sockaddr_in6 *)pss; 556 port = ntohs(sa6->sin6_port); 557 #endif 558 } else { 559 const struct sockaddr_in *sa = 560 (const struct sockaddr_in *)pss; 561 port = ntohs(sa->sin_port); 562 } 563 return port; 564 } 565 566 /**************************************************************************** 567 Print out an IPv4 or IPv6 address from a struct sockaddr_storage. 568 ****************************************************************************/ 569 570 char *print_sockaddr_len(char *dest, 571 size_t destlen, 572 const struct sockaddr *psa, 573 socklen_t psalen) 574 { 575 if (destlen > 0) { 576 dest[0] = '\0'; 577 } 578 (void)sys_getnameinfo(psa, 579 psalen, 580 dest, destlen, 581 NULL, 0, 582 NI_NUMERICHOST); 583 return dest; 584 } 585 586 /**************************************************************************** 587 Print out an IPv4 or IPv6 address from a struct sockaddr_storage. 588 ****************************************************************************/ 589 590 char *print_sockaddr(char *dest, 591 size_t destlen, 592 const struct sockaddr_storage *psa) 593 { 594 return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa, 595 sizeof(struct sockaddr_storage)); 596 } 597 598 /**************************************************************************** 599 Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage. 600 ****************************************************************************/ 601 602 char *print_canonical_sockaddr(TALLOC_CTX *ctx, 603 const struct sockaddr_storage *pss) 604 { 605 char addr[INET6_ADDRSTRLEN]; 606 char *dest = NULL; 607 int ret; 608 609 /* Linux getnameinfo() man pages says port is unitialized if 610 service name is NULL. */ 611 612 ret = sys_getnameinfo((const struct sockaddr *)pss, 613 sizeof(struct sockaddr_storage), 614 addr, sizeof(addr), 615 NULL, 0, 616 NI_NUMERICHOST); 617 if (ret != 0) { 618 return NULL; 619 } 620 621 if (pss->ss_family != AF_INET) { 622 #if defined(HAVE_IPV6) 623 dest = talloc_asprintf(ctx, "[%s]", addr); 624 #else 625 return NULL; 626 #endif 627 } else { 628 dest = talloc_asprintf(ctx, "%s", addr); 629 } 630 631 return dest; 632 } 633 634 /**************************************************************************** 635 Return the port number we've bound to on a socket. 636 ****************************************************************************/ 637 638 int get_socket_port(int fd) 639 { 640 struct sockaddr_storage sa; 641 socklen_t length = sizeof(sa); 642 643 if (fd == -1) { 644 return -1; 645 } 646 647 if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { 648 int level = (errno == ENOTCONN) ? 2 : 0; 649 DEBUG(level, ("getsockname failed. Error was %s\n", 650 strerror(errno))); 651 return -1; 652 } 653 654 #if defined(HAVE_IPV6) 655 if (sa.ss_family == AF_INET6) { 656 return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port); 657 } 658 #endif 659 if (sa.ss_family == AF_INET) { 660 return ntohs(((struct sockaddr_in *)&sa)->sin_port); 661 } 662 return -1; 663 } 664 665 /**************************************************************************** 666 Return the string of an IP address (IPv4 or IPv6). 667 ****************************************************************************/ 668 669 static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len) 670 { 671 struct sockaddr_storage sa; 672 socklen_t length = sizeof(sa); 673 674 /* Ok, returning a hard coded IPv4 address 675 * is bogus, but it's just as bogus as a 676 * zero IPv6 address. No good choice here. 677 */ 678 679 strlcpy(addr_buf, "0.0.0.0", addr_len); 680 681 if (fd == -1) { 682 return addr_buf; 683 } 684 685 if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { 686 DEBUG(0,("getsockname failed. Error was %s\n", 687 strerror(errno) )); 688 return addr_buf; 689 } 690 691 return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length); 692 } 693 694 const char *client_socket_addr(int fd, char *addr, size_t addr_len) 695 { 696 return get_socket_addr(fd, addr, addr_len); 697 } -
vendor/current/lib/util/util_net.h
r414 r740 44 44 int flags); 45 45 46 void set_sockaddr_port(struct sockaddr *psa, uint16_t port); 47 48 /** 49 Check if an IP is the 0.0.0.0. 50 **/ 51 _PUBLIC_ bool is_zero_ip_v4(struct in_addr ip); 52 53 void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss, 54 struct in_addr ip); 55 #if defined(HAVE_IPV6) 56 /** 57 * Convert an IPv6 struct in_addr to a struct sockaddr_storage. 58 */ 59 void in6_addr_to_sockaddr_storage(struct sockaddr_storage *ss, 60 struct in6_addr ip); 61 #endif 62 /** 63 Are two IPs on the same subnet? 64 **/ 65 _PUBLIC_ bool same_net_v4(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); 66 67 /** 68 Return true if a string could be a pure IP address. 69 **/ 70 _PUBLIC_ bool is_ipaddress(const char *str); 71 72 bool is_broadcast_addr(const struct sockaddr *pss); 73 bool is_loopback_ip_v4(struct in_addr ip); 74 bool is_loopback_addr(const struct sockaddr *pss); 75 bool is_zero_addr(const struct sockaddr_storage *pss); 76 void zero_ip_v4(struct in_addr *ip); 77 /** 78 Interpret an internet address or name into an IP address in 4 byte form. 79 **/ 80 _PUBLIC_ uint32_t interpret_addr(const char *str); 81 82 /** 83 A convenient addition to interpret_addr(). 84 **/ 85 _PUBLIC_ struct in_addr interpret_addr2(const char *str); 86 87 _PUBLIC_ bool is_ipaddress_v4(const char *str); 88 89 bool is_address_any(const struct sockaddr *psa); 90 bool same_net(const struct sockaddr *ip1, 91 const struct sockaddr *ip2, 92 const struct sockaddr *mask); 93 bool sockaddr_equal(const struct sockaddr *ip1, 94 const struct sockaddr *ip2); 95 96 bool is_address_any(const struct sockaddr *psa); 97 uint16_t get_sockaddr_port(const struct sockaddr_storage *pss); 98 char *print_sockaddr_len(char *dest, 99 size_t destlen, 100 const struct sockaddr *psa, 101 socklen_t psalen); 102 char *print_sockaddr(char *dest, 103 size_t destlen, 104 const struct sockaddr_storage *psa); 105 char *print_canonical_sockaddr(TALLOC_CTX *ctx, 106 const struct sockaddr_storage *pss); 107 const char *client_name(int fd); 108 int get_socket_port(int fd); 109 const char *client_socket_addr(int fd, char *addr, size_t addr_len); 110 46 111 #endif /* _SAMBA_UTIL_NET_H_ */ -
vendor/current/lib/util/util_pw.c
r414 r740 4 4 Safe versions of getpw* calls 5 5 6 Copyright (C) Andrew Tridgell 1992-1998 7 Copyright (C) Jeremy Allison 1998-2005 6 8 Copyright (C) Andrew Bartlett 2002 9 Copyright (C) Timur Bakeyev 2005 10 Copyright (C) Bjoern Jacke 2006-2007 11 7 12 8 13 This program is free software; you can redistribute it and/or modify … … 21 26 22 27 #include "includes.h" 28 #include "system/passwd.h" 29 #include "lib/util/util_pw.h" 23 30 24 static struct passwd *alloc_copy_passwd(TALLOC_CTX *mem_ctx, 25 const struct passwd *from) 31 /************************************************************************** 32 Wrappers for setpwent(), getpwent() and endpwent() 33 ****************************************************************************/ 34 35 void sys_setpwent(void) 36 { 37 setpwent(); 38 } 39 40 struct passwd *sys_getpwent(void) 41 { 42 return getpwent(); 43 } 44 45 void sys_endpwent(void) 46 { 47 endpwent(); 48 } 49 50 /************************************************************************** 51 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid() 52 ****************************************************************************/ 53 54 struct passwd *sys_getpwnam(const char *name) 55 { 56 return getpwnam(name); 57 } 58 59 struct passwd *sys_getpwuid(uid_t uid) 60 { 61 return getpwuid(uid); 62 } 63 64 struct group *sys_getgrnam(const char *name) 65 { 66 return getgrnam(name); 67 } 68 69 struct group *sys_getgrgid(gid_t gid) 70 { 71 return getgrgid(gid); 72 } 73 74 struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, 75 const struct passwd *from) 26 76 { 27 77 struct passwd *ret = talloc_zero(mem_ctx, struct passwd); … … 41 91 } 42 92 43 struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) 93 struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) 44 94 { 45 95 struct passwd *temp; … … 56 106 } 57 107 58 return alloc_copy_passwd(mem_ctx, temp);108 return tcopy_passwd(mem_ctx, temp); 59 109 } 60 110 61 struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) 111 /**************************************************************************** 112 talloc'ed version of getpwuid. 113 ****************************************************************************/ 114 115 struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) 62 116 { 63 117 struct passwd *temp; … … 74 128 } 75 129 76 return alloc_copy_passwd(mem_ctx, temp);130 return tcopy_passwd(mem_ctx, temp); 77 131 } -
vendor/current/lib/util/util_str.c
r414 r740 65 65 if (len > maxlength) { 66 66 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", 67 (u int_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));67 (unsigned int)(len-maxlength), (unsigned)len, (unsigned)maxlength, src)); 68 68 len = maxlength; 69 69 } … … 112 112 return dest; 113 113 } 114 115 #ifdef VALGRIND116 size_t valgrind_strlen(const char *s)117 {118 size_t count;119 for(count = 0; *s++; count++)120 ;121 return count;122 }123 #endif124 125 114 126 115 /** -
vendor/current/lib/util/util_strlist.c
r414 r740 21 21 #include "includes.h" 22 22 #include "system/locale.h" 23 #include "lib/util/tsort.h" 23 24 24 25 #undef strcasecmp … … 121 122 /** 122 123 * build a null terminated list of strings from an argv-like input string 123 * Entries are sep erated by spaces and can be enclosed by quotes.124 * Entries are separated by spaces and can be enclosed by quotes. 124 125 * Does NOT support escaping 125 126 */ … … 183 184 * join a list back to one string 184 185 */ 185 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char sep erator)186 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator) 186 187 { 187 188 char *ret = NULL; … … 194 195 195 196 for (i = 1; list[i]; i++) { 196 ret = talloc_asprintf_append_buffer(ret, "%c%s", sep erator, list[i]);197 ret = talloc_asprintf_append_buffer(ret, "%c%s", separator, list[i]); 197 198 } 198 199 … … 201 202 202 203 /** join a list back to one (shell-like) string; entries 203 * sep erated by spaces, using quotes where necessary */204 * separated by spaces, using quotes where necessary */ 204 205 _PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) 205 206 { … … 265 266 Return true if all the elements of the list match exactly. 266 267 */ 267 _PUBLIC_ bool str_list_equal(const char **list1, const char **list2) 268 _PUBLIC_ bool str_list_equal(const char * const *list1, 269 const char * const *list2) 268 270 { 269 271 int i; … … 393 395 list2 = (const char **)talloc_memdup(list, list, 394 396 sizeof(list[0])*(len+1)); 395 qsort(list2, len, sizeof(list2[0]), QSORT_CASTlist_cmp);397 TYPESAFE_QSORT(list2, len, list_cmp); 396 398 list[0] = list2[0]; 397 399 for (i=j=1;i<len;i++) { … … 486 488 return ret; 487 489 } 490 491 /** 492 * Needed for making an "unconst" list "const" 493 */ 494 _PUBLIC_ const char **const_str_list(char **list) 495 { 496 return (const char **)list; 497 } 498 -
vendor/current/lib/util/util_tdb.c
r427 r740 21 21 22 22 #include "includes.h" 23 #include "tdb.h"23 #include <tdb.h> 24 24 #include "../lib/util/util_tdb.h" 25 25 … … 134 134 135 135 /**************************************************************************** 136 Store a int32_t value by an arbit ary blob key, return 0 on success, -1 on failure.136 Store a int32_t value by an arbitrary blob key, return 0 on success, -1 on failure. 137 137 Input is int32_t in native byte order. Output in tdb is in little-endian. 138 138 ****************************************************************************/ … … 191 191 192 192 /**************************************************************************** 193 Store a uint32_t value by an arbit ary blob key, return 0 on success, -1 on failure.193 Store a uint32_t value by an arbitrary blob key, return 0 on success, -1 on failure. 194 194 Input is uint32_t in native byte order. Output in tdb is in little-endian. 195 195 ****************************************************************************/ -
vendor/current/lib/util/util_tdb.h
r427 r740 1 /* 2 Unix SMB/CIFS implementation. 3 4 tdb utility functions 5 6 Copyright (C) Andrew Tridgell 1992-2006 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 1 22 #ifndef _____LIB_UTIL_UTIL_TDB_H__ 2 23 #define _____LIB_UTIL_UTIL_TDB_H__ 3 4 24 5 25 /*************************************************************** … … 44 64 45 65 /**************************************************************************** 46 Store a int32_t value by an arbit ary blob key, return 0 on success, -1 on failure.66 Store a int32_t value by an arbitrary blob key, return 0 on success, -1 on failure. 47 67 Input is int32_t in native byte order. Output in tdb is in little-endian. 48 68 ****************************************************************************/ … … 68 88 69 89 /**************************************************************************** 70 Store a uint32_t value by an arbit ary blob key, return 0 on success, -1 on failure.90 Store a uint32_t value by an arbitrary blob key, return 0 on success, -1 on failure. 71 91 Input is uint32_t in native byte order. Output in tdb is in little-endian. 72 92 ****************************************************************************/ -
vendor/current/lib/util/wrap_xattr.h
r414 r740 1 /* 2 Unix SMB/CIFS implementation. 3 4 POSIX NTVFS backend - xattr support using filesystem xattrs 5 6 Copyright (C) Andrew Tridgell 2004 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 1 22 #ifndef __LIB_UTIL_WRAP_XATTR_H__ 2 23 #define __LIB_UTIL_WRAP_XATTR_H__ -
vendor/current/lib/zlib/contrib/ada/zlib-streams.ads
r414 r740 32 32 -- Flush the written data to the back stream, 33 33 -- all data placed to the compressor is flushing to the Back stream. 34 -- Should not be used untill necessary, bec ouse it is decreasing34 -- Should not be used untill necessary, because it is decreasing 35 35 -- compression. 36 36 … … 98 98 -- Buffer for Read operation. 99 99 -- We need to have this buffer in the record 100 -- bec ouse not all read data from back stream100 -- because not all read data from back stream 101 101 -- could be processed during the read operation. 102 102 … … 104 104 -- Buffer size for write operation. 105 105 -- We do not need to have this buffer 106 -- in the record bec ouse all data could be106 -- in the record because all data could be 107 107 -- processed in the write operation. 108 108 -
vendor/current/lib/zlib/contrib/ada/zlib-thin.ads
r414 r740 437 437 pragma Import (C, inflateBackInit, "inflateBackInit_"); 438 438 439 -- I stopped binding the inflateBack routines, bec ouse realize that439 -- I stopped binding the inflateBack routines, because realize that 440 440 -- it does not support zlib and gzip headers for now, and have no 441 441 -- symmetric deflateBack routines. -
vendor/current/lib/zlib/contrib/minizip/miniunz.c
r414 r740 537 537 538 538 strncpy(filename_try, zipfilename,MAXFILENAME-1); 539 /* strncpy doesn t append the trailing NULL, of the string is too long. */539 /* strncpy doesn't append the trailing NULL, if the string is too long. */ 540 540 filename_try[ MAXFILENAME ] = '\0'; 541 541 -
vendor/current/lib/zlib/contrib/minizip/minizip.c
r414 r740 78 78 79 79 strncpy(name, f,MAXFILENAME-1); 80 /* strncpy doesn t append the trailing NULL, of the string is too long. */80 /* strncpy doesn't append the trailing NULL, if the string is too long. */ 81 81 name[ MAXFILENAME ] = '\0'; 82 82 … … 254 254 zipok = 1 ; 255 255 strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); 256 /* strncpy doesn t append the trailing NULL, of the string is too long. */256 /* strncpy doesn't append the trailing NULL, if the string is too long. */ 257 257 filename_try[ MAXFILENAME ] = '\0'; 258 258 -
vendor/current/lib/zlib/contrib/minizip/unzip.c
r414 r740 160 160 Read a byte from a gz_stream; update next_in and avail_in. Return EOF 161 161 for end of file. 162 IN assertion: the stream s has been suc essfully opened for reading.162 IN assertion: the stream s has been successfully opened for reading. 163 163 */ 164 164 … … 296 296 /* 297 297 Compare two filename (fileName1,fileName2). 298 If iCaseSen isivity = 1, comparision is case sensitivity(like strcmp)299 If iCaseSen isivity = 2, comparision is not case sensitivity(like strcmpi298 If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) 299 If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi 300 300 or strcasecmp) 301 If iCaseSen isivity = 0, case sensitivity is defaut of your operating system301 If iCaseSensitivity = 0, case sensitivity is default of your operating system 302 302 (like 1 on Unix, 2 on Windows) 303 303 -
vendor/current/lib/zlib/contrib/minizip/unzip.h
r414 r740 125 125 /* 126 126 Compare two filename (fileName1,fileName2). 127 If iCaseSen isivity = 1, comparision is case sensitivity(like strcmp)128 If iCaseSen isivity = 2, comparision is not case sensitivity(like strcmpi127 If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) 128 If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi 129 129 or strcasecmp) 130 If iCaseSen isivity = 0, case sensitivity is defaut of your operating system130 If iCaseSensitivity = 0, case sensitivity is default of your operating system 131 131 (like 1 on Unix, 2 on Windows) 132 132 */ -
vendor/current/lib/zlib/contrib/minizip/zip.c
r414 r740 100 100 uLong avail_in_this_block; 101 101 uLong filled_in_this_block; 102 uLong unused; /* for future use and align ement */102 uLong unused; /* for future use and alignment */ 103 103 unsigned char data[SIZEDATA_INDATABLOCK]; 104 104 } linkedlist_datablock_internal; … … 118 118 119 119 uLong pos_local_header; /* offset of the local header of the file 120 current y writing */120 currently writing */ 121 121 char* central_header; /* central header data for the current file */ 122 122 uLong size_centralheader; /* size of the central header for cur file */ 123 123 uLong flag; /* flag of the file currently writing */ 124 124 125 int method; /* compression method of file current y wr.*/125 int method; /* compression method of file currently wr.*/ 126 126 int raw; /* 1 for directly writing raw data */ 127 127 Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ -
vendor/current/lib/zlib/contrib/puff/puff.c
r414 r740 586 586 * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means 587 587 * that length, and the symbols 16, 17, and 18 are run-length instructions. 588 * Each of 16, 17, and 18 are foll wed by extra bits to define the length of588 * Each of 16, 17, and 18 are followed by extra bits to define the length of 589 589 * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 590 590 * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols -
vendor/current/lib/zlib/deflate.h
r414 r740 189 189 190 190 /* used by trees.c: */ 191 /* Didn't use ct_data typedef below to sup ress compiler warning */191 /* Didn't use ct_data typedef below to suppress compiler warning */ 192 192 struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ 193 193 struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ -
vendor/current/lib/zlib/examples/fitblk.c
r414 r740 18 18 nearly the requested output block size. The first pass generates 19 19 enough deflate blocks to produce output to fill the requested 20 output size plus a spec fied excess amount (see the EXCESS define20 output size plus a specified excess amount (see the EXCESS define 21 21 below). The last deflate block may go quite a bit past that, but 22 22 is discarded. The second pass decompresses and recompresses just -
vendor/current/lib/zlib/examples/gun.c
r414 r740 43 43 encountered in an input file, it is the last stream in that file. 44 44 45 Like gunzip and uncompress, the file attributes of the orig nal compressed45 Like gunzip and uncompress, the file attributes of the original compressed 46 46 file are maintained in the final uncompressed file, to the extent that the 47 47 user permissions allow it. -
vendor/current/lib/zlib/gzio.c
r414 r740 255 255 Read a byte from a gz_stream; update next_in and avail_in. Return EOF 256 256 for end of file. 257 IN assertion: the stream s has been suc essfully opened for reading.257 IN assertion: the stream s has been successfully opened for reading. 258 258 */ 259 259 local int get_byte(s) … … 280 280 to Z_DATA_ERROR if the magic header is present but the rest of the header 281 281 is incorrect. 282 IN assertion: the stream s has already been created suc essfully;282 IN assertion: the stream s has already been created successfully; 283 283 s->stream.avail_in is zero for the first time, but may be non-zero 284 284 for concatenated .gz files. -
vendor/current/lib/zlib/zlib.h
r414 r740 886 886 887 887 inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of 888 the param aters are invalid, Z_MEM_ERROR if the internal state could not888 the parameters are invalid, Z_MEM_ERROR if the internal state could not 889 889 be allocated, or Z_VERSION_ERROR if the version of the library does not 890 890 match the version of the header file.
Note:
See TracChangeset
for help on using the changeset viewer.