Changeset 740 for vendor/current/lib


Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

Location:
vendor/current/lib
Files:
379 added
66 deleted
189 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/README

    r414 r740  
    11compression - Various compression algorithms (MSZIP, lzxpress)
     2dnspython - Python module for working with DNS.
    23nss_wrapper - Wrapper for the user and group NSS API allowing the use
    34              of other data sources.
     
    78socket_wrapper - Wrapper library allowing TCP/IP traffic to be redirected
    89                 over Unix domain sockets.
     10subunit - Utilities and bindings for working with the Subunit test result
     11          reporting protocol.
    912talloc - Hierarchical pool based memory allocator
    1013tdb - Simple but fast key/value database library, supporting multiple writers
  • vendor/current/lib/async_req/async_sock.c

    r414 r740  
    3737#endif
    3838
    39 struct async_send_state {
     39struct sendto_state {
    4040        int fd;
    4141        const void *buf;
    4242        size_t len;
    4343        int flags;
     44        const struct sockaddr_storage *addr;
     45        socklen_t addr_len;
    4446        ssize_t sent;
    4547};
    4648
    47 static void async_send_handler(struct tevent_context *ev,
     49static void sendto_handler(struct tevent_context *ev,
    4850                               struct tevent_fd *fde,
    4951                               uint16_t flags, void *private_data);
    5052
    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)
     53struct 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)
    5556{
    5657        struct tevent_req *result;
    57         struct async_send_state *state;
     58        struct sendto_state *state;
    5859        struct tevent_fd *fde;
    5960
    60         result = tevent_req_create(mem_ctx, &state, struct async_send_state);
     61        result = tevent_req_create(mem_ctx, &state, struct sendto_state);
    6162        if (result == NULL) {
    6263                return result;
     
    6667        state->len = len;
    6768        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,
    7089                            result);
    7190        if (fde == NULL) {
     
    7695}
    7796
    78 static void async_send_handler(struct tevent_context *ev,
     97static void sendto_handler(struct tevent_context *ev,
    7998                               struct tevent_fd *fde,
    8099                               uint16_t flags, void *private_data)
     
    82101        struct tevent_req *req = talloc_get_type_abort(
    83102                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);
    88108        if ((state->sent == -1) && (errno == EINTR)) {
    89109                /* retry */
     
    97117}
    98118
    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);
     119ssize_t sendto_recv(struct tevent_req *req, int *perrno)
     120{
     121        struct sendto_state *state =
     122                tevent_req_data(req, struct sendto_state);
    103123
    104124        if (tevent_req_is_unix_error(req, perrno)) {
     
    108128}
    109129
    110 struct async_recv_state {
     130struct recvfrom_state {
    111131        int fd;
    112132        void *buf;
    113133        size_t len;
    114134        int flags;
     135        struct sockaddr_storage *addr;
     136        socklen_t *addr_len;
    115137        ssize_t received;
    116138};
    117139
    118 static void async_recv_handler(struct tevent_context *ev,
     140static void recvfrom_handler(struct tevent_context *ev,
    119141                               struct tevent_fd *fde,
    120142                               uint16_t flags, void *private_data);
    121143
    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)
     144struct 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)
    125149{
    126150        struct tevent_req *result;
    127         struct async_recv_state *state;
     151        struct recvfrom_state *state;
    128152        struct tevent_fd *fde;
    129153
    130         result = tevent_req_create(mem_ctx, &state, struct async_recv_state);
     154        result = tevent_req_create(mem_ctx, &state, struct recvfrom_state);
    131155        if (result == NULL) {
    132156                return result;
     
    136160        state->len = len;
    137161        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,
    140166                            result);
    141167        if (fde == NULL) {
     
    146172}
    147173
    148 static void async_recv_handler(struct tevent_context *ev,
     174static void recvfrom_handler(struct tevent_context *ev,
    149175                               struct tevent_fd *fde,
    150176                               uint16_t flags, void *private_data)
     
    152178        struct tevent_req *req = talloc_get_type_abort(
    153179                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);
    159186        if ((state->received == -1) && (errno == EINTR)) {
    160187                /* retry */
     
    172199}
    173200
    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);
     201ssize_t recvfrom_recv(struct tevent_req *req, int *perrno)
     202{
     203        struct recvfrom_state *state =
     204                tevent_req_data(req, struct recvfrom_state);
    178205
    179206        if (tevent_req_is_unix_error(req, perrno)) {
     
    359386        size_t total_size;
    360387        uint16_t flags;
     388        bool err_on_readability;
    361389};
    362390
     
    386414                goto fail;
    387415        }
    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;
    392418
    393419        if (queue == NULL) {
     
    435461
    436462        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                }
    439492        }
    440493
  • vendor/current/lib/async_req/async_sock.h

    r414 r740  
    2828#include <tevent.h>
    2929
    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);
     30struct 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);
     33ssize_t sendto_recv(struct tevent_req *req, int *perrno);
    3534
    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);
     35struct 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);
     40ssize_t recvfrom_recv(struct tevent_req *req, int *perrno);
    4041
    4142struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
  • vendor/current/lib/compression/lzxpress.c

    r414 r740  
    3535#include "replace.h"
    3636#include "lzxpress.h"
     37#include "../lib/util/byteorder.h"
    3738
    3839
     
    8182        uncompressed_pos = 0;
    8283        indic = 0;
     84        *(uint32_t *)compressed = 0;
    8385        compressed_pos = sizeof(uint32_t);
    8486        indic_pos = &compressed[0];
     
    130132                                /* Classical meta-data */
    131133                                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);
    133135                                metadata_size += sizeof(uint16_t);
    134136                        } else {
    135137                                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);
    137139                                metadata_size = sizeof(uint16_t);
    138140
     
    156158                                        }
    157159
    158                                         /* Additionnal best_len */
     160                                        /* Additional best_len */
    159161                                        compressed[compressed_pos + metadata_size] = (best_len - (3 + 7 + 15)) & 0xFF;
    160162                                        metadata_size += sizeof(uint8_t);
     
    168170                                        }
    169171
    170                                         /* Additionnal best_len */
     172                                        /* Additional best_len */
    171173                                        compressed[compressed_pos + metadata_size] = 255;
    172174
     
    199201
    200202                if ((indic_bit - 1) % 32 > (indic_bit % 32)) {
    201                         *(uint32_t *)indic_pos = indic;
     203                        SIVAL(indic_pos, 0, indic);
    202204                        indic = 0;
    203205                        indic_pos = &compressed[compressed_pos];
     
    213215                compressed_pos++;
    214216                if (((indic_bit - 1) % 32) > (indic_bit % 32)){
    215                         *(uint32_t *)indic_pos = indic;
     217                        SIVAL(indic_pos, 0, indic);
    216218                        indic = 0;
    217219                        indic_pos = &compressed[compressed_pos];
     
    224226                        indic |= 0 << (32 - ((indic_bit % 32) + 1));
    225227
    226                 *(uint32_t *)indic_pos = indic;
     228                *(uint32_t *)&compressed[compressed_pos] = 0;
     229                SIVAL(indic_pos, 0, indic);
    227230                compressed_pos += sizeof(uint32_t);
    228231        }
  • vendor/current/lib/compression/testsuite.c

    r414 r740  
    2121#include "includes.h"
    2222#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 */
     30static 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
    2469
    2570struct torture_suite *torture_local_compression(TALLOC_CTX *mem_ctx)
    2671{
    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);
    2875
    2976        return suite;
  • vendor/current/lib/crypto/aes.c

    r414 r740  
    113113    }
    114114}
     115
     116void 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  
    7373                     unsigned char *, int);
    7474
     75void 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
    7579#ifdef  __cplusplus
    7680}
  • vendor/current/lib/crypto/arcfour.c

    r414 r740  
    2020*/
    2121
    22 #include "includes.h"
     22#include "replace.h"
    2323#include "../lib/crypto/arcfour.h"
    2424
  • vendor/current/lib/crypto/arcfour.h

    r414 r740  
    11#ifndef ARCFOUR_HEADER_H
    22#define ARCFOUR_HEADER_H
     3
     4#include "../lib/util/data_blob.h"
    35
    46struct arcfour_state {
  • vendor/current/lib/crypto/crc32.c

    r414 r740  
    4141 */
    4242
    43 #include "includes.h"
     43#include "replace.h"
    4444#include "../lib/crypto/crc32.h"
    4545
  • vendor/current/lib/crypto/hmacmd5.c

    r414 r740  
    2323 */
    2424
    25 #include "includes.h"
     25#include "replace.h"
    2626#include "../lib/crypto/hmacmd5.h"
    2727
  • vendor/current/lib/crypto/hmacmd5test.c

    r414 r740  
    1717   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1818*/
    19 #include "includes.h"
     19#include "replace.h"
     20#include "../lib/util/util.h"
    2021#include "../lib/crypto/crypto.h"
    2122
  • vendor/current/lib/crypto/hmacsha256.c

    r414 r740  
    2727 */
    2828
    29 #include "includes.h"
     29#include "replace.h"
    3030#include "../lib/crypto/crypto.h"
    3131
  • vendor/current/lib/crypto/md4.c

    r414 r740  
    1818*/
    1919
    20 #include "includes.h"
     20#include "replace.h"
    2121#include "../lib/crypto/md4.h"
    2222
  • vendor/current/lib/crypto/md4test.c

    r414 r740  
    1818*/
    1919
    20 #include "includes.h"
     20#include "replace.h"
     21#include "../lib/util/util.h"
    2122#include "../lib/crypto/crypto.h"
    2223
     
    2627 This uses the test values from rfc1320
    2728*/
    28 bool torture_local_crypto_md4(struct torture_context *torture) 
     29bool torture_local_crypto_md4(struct torture_context *torture)
    2930{
    3031        bool ret = true;
  • vendor/current/lib/crypto/md5.c

    r414 r740  
    1919   abartlet@samba.org Jun 2001 */
    2020
    21 #include "includes.h"
     21#include "replace.h"
    2222
    2323#include "md5.h"
     
    2929 * Note: this code is harmless on little-endian machines.
    3030 */
    31 static void byteReverse(uint8_t *buf, uint_t longs)
     31static void byteReverse(uint8_t *buf, unsigned int longs)
    3232{
    3333    uint32_t t;
    3434    do {
    35         t = (uint32_t) ((uint_t) buf[3] << 8 | buf[2]) << 16 |
    36             ((uint_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]);
    3737        *(uint32_t *) buf = t;
    3838        buf += 4;
     
    109109_PUBLIC_ void MD5Final(uint8_t digest[16], struct MD5Context *ctx)
    110110{
    111     uint_t count;
     111    unsigned int count;
    112112    uint8_t *p;
    113113
     
    145145    byteReverse((uint8_t *) ctx->buf, 4);
    146146    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 */
    148148}
    149149
  • vendor/current/lib/crypto/md5test.c

    r414 r740  
    1818*/
    1919
    20 #include "includes.h"
     20#include "replace.h"
     21#include "../lib/util/util.h"
    2122#include "../lib/crypto/crypto.h"
    2223
  • vendor/current/lib/crypto/sha256.c

    r414 r740  
    3939 */
    4040
    41 #include "includes.h"
     41#include "replace.h"
    4242#include "sha256.h"
    4343
  • vendor/current/lib/nss_wrapper/nss_wrapper.c

    r414 r740  
    3434
    3535#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
    3640
    3741#define NSS_WRAPPER_NOT_REPLACE
     
    208212};
    209213
    210 /* protoypes for files backend */
     214/* prototypes for files backend */
    211215
    212216
     
    246250static void nwrap_files_endgrent(struct nwrap_backend *b);
    247251
    248 /* protoypes for module backend */
     252/* prototypes for module backend */
    249253
    250254static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
     
    461465                              struct nwrap_backend **backends)
    462466{
     467        struct nwrap_backend *b;
     468
    463469        *backends = (struct nwrap_backend *)realloc(*backends,
    464470                sizeof(struct nwrap_backend) * ((*num_backends) + 1));
     
    469475        }
    470476
    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        }
    476493
    477494        (*num_backends)++;
     
    21692186        gid_t *groups_tmp;
    21702187        int count = 1;
    2171         const char *name_of_group = NULL;
     2188        const char *name_of_group = "";
    21722189
    21732190        if (!nwrap_enabled()) {
  • vendor/current/lib/nss_wrapper/nss_wrapper.pl

    r414 r740  
    1414my $opt_name = undef;
    1515my $opt_member = undef;
     16my $opt_gid = 65534;# nogroup gid
    1617
    1718my $passwdfn = undef;
     
    2021my $actionfn = undef;
    2122
    22 sub passwd_add($$$$);
    23 sub passwd_delete($$$$);
    24 sub group_add($$$$);
    25 sub group_delete($$$$);
    26 sub member_add($$$$);
    27 sub member_delete($$$$);
     23sub passwd_add($$$$$);
     24sub passwd_delete($$$$$);
     25sub group_add($$$$$);
     26sub group_delete($$$$$);
     27sub member_add($$$$$);
     28sub member_delete($$$$$);
    2829
    2930sub check_path($$);
     
    3637        'type=s'        => \$opt_type,
    3738        'name=s'        => \$opt_name,
    38         'member=s'      => \$opt_member
     39        'member=s'      => \$opt_member,
     40        'gid=i'         => \$opt_gid
    3941);
    4042
     
    5961
    6062        --member <member>       The name of the member.
     63
     64        --gid <gid>             Primary Group ID for new users.
    6165";
    6266        exit($ret);
     
    111115}
    112116
    113 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name);
     117exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid);
    114118
    115119sub check_path($$)
     
    389393}
    390394
    391 sub passwd_add($$$$)
    392 {
    393         my ($path, $dummy, $dummy2, $name) = @_;
     395sub passwd_add($$$$$)
     396{
     397        my ($path, $dummy, $dummy2, $name, $gid) = @_;
    394398
    395399        #print "passwd_add: '$name' in '$path'\n";
     
    401405
    402406        my $uid = passwd_get_free_uid($passwd);
    403         my $gid = 65534;# nogroup gid
    404407
    405408        my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
     
    412415}
    413416
    414 sub passwd_delete($$$$)
    415 {
    416         my ($path, $dummy, $dummy2, $name) = @_;
     417sub passwd_delete($$$$$)
     418{
     419        my ($path, $dummy, $dummy2, $name, $dummy3) = @_;
    417420
    418421        #print "passwd_delete: '$name' in '$path'\n";
     
    430433}
    431434
    432 sub group_add($$$$)
    433 {
    434         my ($dummy, $dummy2, $path, $name) = @_;
     435sub group_add($$$$$)
     436{
     437        my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
    435438
    436439        #print "group_add: '$name' in '$path'\n";
     
    454457}
    455458
    456 sub group_delete($$$$)
    457 {
    458         my ($dummy, $dummy2, $path, $name) = @_;
     459sub group_delete($$$$$)
     460{
     461        my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
    459462
    460463        #print "group_delete: '$name' in '$path'\n";
     
    472475}
    473476
    474 sub member_add($$$$)
    475 {
    476         my ($passwd_path, $username, $group_path, $groupname) = @_;
     477sub member_add($$$$$)
     478{
     479        my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
    477480
    478481        #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
     
    495498}
    496499
    497 sub member_delete($$$$)
    498 {
    499         my ($passwd_path, $username, $group_path, $groupname) = @_;
     500sub member_delete($$$$$)
     501{
     502        my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
    500503
    501504        #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
  • vendor/current/lib/nss_wrapper/testsuite.c

    r414 r740  
    44   local testing of the nss wrapper
    55
    6    Copyright (C) Guenther Deschner 2009
     6   Copyright (C) Guenther Deschner 2009-2010
    77
    88   This program is free software; you can redistribute it and/or modify
     
    2121
    2222#include "includes.h"
     23
     24#ifndef NSS_WRAPPER
     25#define NSS_WRAPPER
     26#endif
     27
    2328#include "torture/torture.h"
    2429#include "lib/replace/system/passwd.h"
    25 #include "lib/nss_wrapper/nss_wrapper.h"
    2630
    2731static bool copy_passwd(struct torture_context *tctx,
     
    176180               (unsigned long)grp->gr_gid);
    177181
    178         if (!grp->gr_mem[0]) {
     182        if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) {
    179183                printf("\n");
    180184                return;
     
    773777
    774778        if (!old_pwd || !old_group) {
     779                torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
    775780                torture_skip(tctx, "nothing to test\n");
    776                 return true;
    777781        }
    778782
     
    798802
    799803        if (!old_pwd || !old_group) {
     804                torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
    800805                torture_skip(tctx, "nothing to test\n");
    801                 return true;
    802806        }
    803807
     
    816820
    817821        if (!old_pwd || !old_group) {
     822                torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
    818823                torture_skip(tctx, "nothing to test\n");
    819                 return true;
    820824        }
    821825
     
    836840
    837841        if (!old_pwd || !old_group) {
     842                torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
    838843                torture_skip(tctx, "nothing to test\n");
    839                 return true;
    840844        }
    841845
     
    850854}
    851855
     856static 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
     891static 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
     927static 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
    852946struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx)
    853947{
    854         struct torture_suite *suite = torture_suite_create(mem_ctx, "NSS-WRAPPER");
     948        struct torture_suite *suite = torture_suite_create(mem_ctx, "nss-wrapper");
    855949
    856950        torture_suite_add_simple_test(suite, "enumeration", test_nwrap_enumeration);
     
    858952        torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_nwrap_reentrant_enumeration_crosschecks);
    859953        torture_suite_add_simple_test(suite, "membership", test_nwrap_membership);
     954        torture_suite_add_simple_test(suite, "duplicates", test_nwrap_duplicates);
    860955
    861956        return suite;
  • vendor/current/lib/popt/popt.h

    r414 r740  
    459459 * Print detailed description of options.
    460460 * @param con           context
    461  * @param fp            ouput file handle
     461 * @param fp            output file handle
    462462 * @param flags         (unused)
    463463 */
     
    469469 * Print terse description of options.
    470470 * @param con           context
    471  * @param fp            ouput file handle
     471 * @param fp            output file handle
    472472 * @param flags         (unused)
    473473 */
  • vendor/current/lib/replace/README

    r414 r740  
    3434telldir
    3535seekdir
     36clock_gettime
    3637closedir
    3738dlopen
     
    7677bool
    7778socklen_t
    78 uint_t
    7979uint{8,16,32,64}_t
    8080int{8,16,32,64}_t
  • vendor/current/lib/replace/autoconf-2.60.m4

    r414 r740  
    182182m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[
    183183AC_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
     185AC_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
    191198
    192199  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.  */
    194217#ifndef __EXTENSIONS__
    195218# undef __EXTENSIONS__
    196219#endif
    197 #ifndef _POSIX_PTHREAD_SEMANTICS
    198 # undef _POSIX_PTHREAD_SEMANTICS
    199 #endif])
     220])
    200221  AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
    201222    [ac_cv_safe_to_define___extensions__],
    202223    [AC_COMPILE_IFELSE(
    203        [AC_LANG_PROGRAM([
     224       [AC_LANG_PROGRAM([[
    204225#         define __EXTENSIONS__ 1
    205           AC_INCLUDES_DEFAULT])],
     226          ]AC_INCLUDES_DEFAULT])],
    206227       [ac_cv_safe_to_define___extensions__=yes],
    207228       [ac_cv_safe_to_define___extensions__=no])])
    208229  test $ac_cv_safe_to_define___extensions__ = yes &&
    209230    AC_DEFINE([__EXTENSIONS__])
     231  AC_DEFINE([_ALL_SOURCE])
     232  AC_DEFINE([_GNU_SOURCE])
    210233  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  
    4747
    4848#ifndef long32
    49 #define long32 int32
     49#define long32 int32_t
    5050#endif
    5151
    5252#ifndef long64
    53 #define long64 int64
     53#define long64 int64_t
    5454#endif
    5555
     
    666666     */
    667667    clearmem(ktab, sizeof ktab);
    668     StrnCpy(ktab, key, 8);
     668    strncpy(ktab, key, 8);
    669669    ufc_mk_keytab(ktab);
    670670
  • vendor/current/lib/replace/getifaddrs.c

    r414 r740  
    283283
    284284        while (i > 0) {
    285                 uint_t inc;
     285                unsigned int inc;
    286286
    287287                inc = ifr->ifr_addr.sa_len;
  • vendor/current/lib/replace/getpass.c

    r414 r740  
    3535#endif
    3636
    37 #ifndef SIGNAL_CAST
    38 #define SIGNAL_CAST (RETSIGTYPE (*)(int))
    39 #endif
    40 
    4137#ifdef SYSV_TERMIO
    4238
     
    10096#endif /* SYSV_TERMIO */
    10197
    102 static void catch_signal(int signum,void (*handler)(int ))
     98static void catch_signal(int signum, void (*handler)(int ))
    10399{
    104100#ifdef HAVE_SIGACTION
     
    132128****************************************************************/
    133129
    134 static void gotintr_sig(void)
     130static void gotintr_sig(int signum)
    135131{
    136132        gotintr = 1;
     
    149145
    150146        /* Catch problematic signals */
    151         catch_signal(SIGINT, SIGNAL_CAST gotintr_sig);
     147        catch_signal(SIGINT, gotintr_sig);
    152148
    153149        /* Try to write to and read from the terminal if we can.
     
    212208
    213209        /* Catch problematic signals */
    214         catch_signal(SIGINT, SIGNAL_CAST SIG_DFL);
     210        catch_signal(SIGINT, SIG_DFL);
    215211
    216212        if (gotintr) {
    217                 printf("Interupted by signal.\n");
     213                printf("Interrupted by signal.\n");
    218214                fflush(stdout);
    219215                exit(1);
  • vendor/current/lib/replace/libreplace.m4

    r414 r740  
    5252LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/snprintf.o"
    5353
    54 AC_TYPE_SIGNAL
    5554AC_TYPE_UID_T
    5655AC_TYPE_MODE_T
     
    9190)
    9291
     92AC_CHECK_HEADERS(linux/types.h)
     93
    9394AC_CACHE_CHECK([for working mmap],libreplace_cv_HAVE_MMAP,[
    9495AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"],
     
    106107AC_CHECK_HEADERS(unix.h)
    107108
    108 AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror)
     109AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror strerror_r)
    109110AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename)
    110111AC_CHECK_FUNCS(waitpid wait4 strlcpy strlcat initgroups memmove strdup)
    111 AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2)
     112AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2 dprintf vdprintf)
    112113AC_CHECK_FUNCS(isatty chown lchown link readlink symlink realpath)
     114AC_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])
     120AC_HAVE_DECL(fdatasync, [#include <unistd.h>])
     121AC_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])
     127AC_CHECK_FUNCS(get_current_dir_name)
    113128AC_HAVE_DECL(setresuid, [#include <unistd.h>])
    114129AC_HAVE_DECL(setresgid, [#include <unistd.h>])
     
    229244AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq)
    230245
     246AC_CHECK_FUNCS(memmem)
     247
    231248# this test disabled as we don't actually need __VA_ARGS__ yet
    232249AC_TRY_CPP([
     
    281298m4_include(crypt.m4)
    282299
     300if 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)
     304fi
     305
     306AC_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)])
     325if test x"$libreplace_cv_struct_timespec" = x"yes"; then
     326   AC_DEFINE(HAVE_STRUCT_TIMESPEC,1,[Whether we have struct timespec])
     327fi
     328
    283329AC_CHECK_FUNCS([printf memset memcpy],,[AC_MSG_ERROR([Required function not found])])
    284330
     
    309355m4_include(libreplace_macros.m4)
    310356
     357
     358dnl SMB_CHECK_CLOCK_ID(clockid)
     359dnl Test whether the specified clock_gettime clock ID is available. If it
     360dnl is, we define HAVE_clockid
     361AC_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    [
     377clockid_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])
    311388m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[m4_include(autoconf-2.60.m4)])
  • vendor/current/lib/replace/libreplace_cc.m4

    r414 r740  
    116116AC_CHECK_SIZEOF(long long)
    117117
    118 AC_CHECK_TYPE(uint_t, unsigned int)
    119118AC_CHECK_TYPE(int8_t, char)
    120119AC_CHECK_TYPE(uint8_t, unsigned char)
  • vendor/current/lib/replace/libreplace_macros.m4

    r414 r740  
    294294                }
    295295        ])],[
    296                 AS_TR_SH([ac_cv_c_prototype_$1])=yes
     296                eval AS_TR_SH([ac_cv_c_prototype_$1])=yes
    297297        ],[
    298                 AS_TR_SH([ac_cv_c_prototype_$1])=no
     298                eval AS_TR_SH([ac_cv_c_prototype_$1])=no
    299299        ])
    300300)
  • vendor/current/lib/replace/libreplace_network.m4

    r478 r740  
    115115fi
    116116
    117 dnl The following test is roughl taken from the cvs sources.
     117dnl The following test is roughly taken from the cvs sources.
    118118dnl
    119119dnl If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
     
    227227],
    228228libreplace_cv_HAVE_GETADDRINFO=yes,libreplace_cv_HAVE_GETADDRINFO=no)])
     229
     230if 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)
     265fi
     266
    229267if test x"$libreplace_cv_HAVE_GETADDRINFO" = x"yes"; then
    230268        AC_DEFINE(HAVE_GETADDRINFO,1,[Whether the system has getaddrinfo])
  • vendor/current/lib/replace/replace.c

    r414 r740  
    44   Copyright (C) Andrew Tridgell 1992-1998
    55   Copyright (C) Jelmer Vernooij 2005-2008
     6   Copyright (C) Matthieu Patou  2010
    67
    78     ** NOTE! The following LGPL license applies to the replace
     
    410411{
    411412        /* have a reasonable go at emulating it. Hope that
    412            the system mktemp() isn't completly hopeless */
     413           the system mktemp() isn't completely hopeless */
    413414        char *p = mktemp(template);
    414415        if (!p)
     
    503504#endif
    504505
     506
    505507#ifndef HAVE_STRTOLL
    506508long long int rep_strtoll(const char *str, char **endptr, int base)
     
    516518#endif
    517519}
    518 #endif
     520#else
     521#ifdef HAVE_BSD_STRTOLL
     522#ifdef HAVE_STRTOQ
     523long 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 */
    519543
    520544
     
    532556#endif
    533557}
    534 #endif
     558#else
     559#ifdef HAVE_BSD_STRTOLL
     560#ifdef HAVE_STRTOUQ
     561unsigned 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 */
    535581
    536582#ifndef HAVE_SETENV
     
    682728}
    683729#endif
     730
     731
     732#ifndef HAVE_MEMMEM
     733void *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
     754int 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
     771int 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
     785char *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)
     798int 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
     811int 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  
    8282# define PRIi8          "i"
    8383#endif
    84 #ifndef PRIi8
     84#ifndef PRIi16
    8585# define PRIi16         "i"
    8686#endif
    87 #ifndef PRIi8
     87#ifndef PRIi32
    8888# define PRIi32         "i"
    8989#endif
    90 #ifndef PRIi8
     90#ifndef PRIi64
    9191# define PRIi64         __PRI64_PREFIX "i"
    9292#endif
     
    122122#endif
    123123
     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
    124131#ifndef HAVE_STRERROR
    125132extern char *sys_errlist[];
     
    139146#define memmove rep_memmove
    140147void *rep_memmove(void *dest,const void *src,int size);
     148#endif
     149
     150#ifndef HAVE_MEMMEM
     151#define memmem rep_memmem
     152void *rep_memmem(const void *haystack, size_t haystacklen,
     153                 const void *needle, size_t needlelen);
    141154#endif
    142155
     
    278291#endif
    279292
     293
     294
    280295#ifndef HAVE_STRTOLL
    281296#define strtoll rep_strtoll
    282297long long int rep_strtoll(const char *str, char **endptr, int base);
     298#else
     299#ifdef HAVE_BSD_STRTOLL
     300#define strtoll rep_strtoll
     301long long int rep_strtoll(const char *str, char **endptr, int base);
     302#endif
    283303#endif
    284304
     
    286306#define strtoull rep_strtoull
    287307unsigned 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
     311unsigned long long int rep_strtoull(const char *str, char **endptr, int base);
     312#endif
    288313#endif
    289314
     
    329354#define socketpair rep_socketpair
    330355/* prototype is in system/network.h */
     356#endif
     357
     358#ifndef HAVE_VDPRINTF
     359#define vdprintf rep_vdprintf
     360int rep_vdprintf(int fd, const char *format, va_list ap);
     361#endif
     362
     363#ifndef HAVE_DPRINTF
     364#define dprintf rep_dprintf
     365int rep_dprintf(int fd, const char *format, ...);
    331366#endif
    332367
     
    490525#define freeifaddrs rep_freeifaddrs
    491526/* 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
     531char *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
     537int 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
    492542#endif
    493543
     
    724774#endif
    725775
     776#ifndef HAVE_FDATASYNC
     777#define fdatasync(fd) fsync(fd)
     778#elif !defined(HAVE_DECL_FDATASYNC)
     779int 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
    726805#endif /* _LIBREPLACE_REPLACE_H */
  • vendor/current/lib/replace/system/config.m4

    r618 r740  
    77AC_CHECK_HEADERS(sys/select.h)
    88
     9# poll
     10AC_CHECK_HEADERS(poll.h)
     11AC_CHECK_FUNCS(poll,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/poll.o"])
     12
    913# time
    1014AC_CHECK_HEADERS(sys/time.h utime.h)
    1115AC_HEADER_TIME
    1216AC_CHECK_FUNCS(utime utimes)
     17
     18AC_CACHE_CHECK([if gettimeofday takes TZ argument],libreplace_cv_HAVE_GETTIMEOFDAY_TZ,[
     19AC_TRY_RUN([
     20#include <sys/time.h>
     21#include <unistd.h>
     22main() { 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)])
     24if test x"$libreplace_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
     25    AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available])
     26fi
    1327
    1428# wait
  • vendor/current/lib/replace/system/network.h

    r478 r740  
    308308#define ss_family sin6_family
    309309#define HAVE_SS_FAMILY 1
    310 #else
     310#else /*HAVE_STRUCT_SOCKADDR_IN6*/
    311311#define sockaddr_storage sockaddr_in
    312312#define ss_family sin_family
    313313#define HAVE_SS_FAMILY 1
    314 #endif
    315 #endif
     314#endif /*HAVE_STRUCT_SOCKADDR_IN6*/
     315#endif /*HAVE_STRUCT_SOCKADDR_STORAGE*/
    316316
    317317#ifndef HAVE_SS_FAMILY
     
    332332     */
    333333#   define IOV_MAX 512
    334 #  else
    335 #   error IOV_MAX and UIO_MAXIOV undefined
    336334#  endif
    337335# endif
  • vendor/current/lib/replace/system/passwd.h

    r414 r740  
    102102
    103103#ifdef NSS_WRAPPER
     104#ifndef NSS_WRAPPER_DISABLE
    104105#ifndef NSS_WRAPPER_NOT_REPLACE
    105106#define NSS_WRAPPER_REPLACE
    106 #endif
     107#endif /* NSS_WRAPPER_NOT_REPLACE */
    107108#include "../nss_wrapper/nss_wrapper.h"
    108 #endif
     109#endif /* NSS_WRAPPER_DISABLE */
     110#endif /* NSS_WRAPPER */
    109111
    110112#endif
  • vendor/current/lib/replace/system/readline.h

    r414 r740  
    4444
    4545#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
    4753#else
    4854/* This type is missing from libreadline<4.0  (approximately) */
  • vendor/current/lib/replace/system/select.h

    r414 r740  
    3939#endif
    4040
     41#ifdef HAVE_POLL
     42
     43#include <poll.h>
     44
     45#else
     46
     47/* Type used for the number of file descriptors.  */
     48typedef unsigned long int nfds_t;
     49
     50/* Data structure describing a polling request.  */
     51struct 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" */
     73int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout);
     74
    4175#endif
     76
     77#endif
  • vendor/current/lib/replace/system/time.h

    r414 r740  
    4747#endif
    4848
     49#ifndef HAVE_STRUCT_TIMESPEC
     50struct timespec {
     51        time_t tv_sec;            /* Seconds.  */
     52        long tv_nsec;           /* Nanoseconds.  */
     53};
     54#endif
     55
    4956#ifndef HAVE_MKTIME
    5057/* define is in "replace.h" */
     
    6774#endif
    6875
     76#ifndef HAVE_CLOCK_GETTIME
     77/* CLOCK_REALTIME is required by POSIX */
     78#define CLOCK_REALTIME 0
     79typedef int clockid_t;
     80int rep_clock_gettime(clockid_t clk_id, struct timespec *tp);
    6981#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  
    3737#endif
    3838
    39 #ifndef SIGNAL_CAST
    40 #define SIGNAL_CAST (RETSIGTYPE (*)(int))
    41 #endif
    42 
    4339#ifdef HAVE_SETJMP_H
    4440#include <setjmp.h>
  • vendor/current/lib/replace/test/os2_delete.c

    r414 r740  
    4747                char fname[40];
    4848                int fd;
    49                 sprintf(fname, TESTDIR "/test%u.txt", i);
     49                snprintf(fname, sizeof(fname), TESTDIR "/test%u.txt", i);
    5050                fd = open(fname, O_CREAT|O_RDWR, 0600);
    5151                if (fd < 0) {
     
    8080        for (j=0; j<MIN(i, DELETE_SIZE); j++) {
    8181                char fname[40];
    82                 sprintf(fname, TESTDIR "/%s", names[j]);
     82                snprintf(fname, sizeof(fname), TESTDIR "/%s", names[j]);
    8383                unlink(fname) == 0 || FAILED("unlink");
    8484        }
  • vendor/current/lib/replace/test/testsuite.c

    r414 r740  
    752752bool
    753753socklen_t
    754 uint_t
    755754uint{8,16,32,64}_t
    756755int{8,16,32,64}_t
     
    773772        printf("test: FUNCTION\n");
    774773        if (strcmp(__FUNCTION__, "test_FUNCTION") != 0) {
    775                 printf("failure: FAILURE [\nFAILURE invalid\n]\n");
     774                printf("failure: FUNCTION [\nFUNCTION invalid\n]\n");
    776775                return false;
    777776        }
     
    10151014        return true;
    10161015}
     1016
     1017static 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
    10171054
    10181055struct torture_context;
     
    10661103        ret &= test_utime();
    10671104        ret &= test_utimes();
     1105        ret &= test_memmem();
    10681106
    10691107        return ret;
  • vendor/current/lib/smbconf/smbconf.c

    r414 r740  
    2828 **********************************************************************/
    2929
    30 static WERROR smbconf_global_check(struct smbconf_ctx *ctx)
     30static sbcErr smbconf_global_check(struct smbconf_ctx *ctx)
    3131{
    3232        if (!smbconf_share_exists(ctx, GLOBAL_NAME)) {
    3333                return smbconf_create_share(ctx, GLOBAL_NAME);
    3434        }
    35         return WERR_OK;
     35
     36        return SBC_ERR_OK;
    3637}
    3738
     
    4243 *
    4344 **********************************************************************/
     45
     46const 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
    4480
    4581/**
     
    92128 * Drop the whole configuration (restarting empty).
    93129 */
    94 WERROR smbconf_drop(struct smbconf_ctx *ctx)
     130sbcErr smbconf_drop(struct smbconf_ctx *ctx)
    95131{
    96132        return ctx->ops->drop(ctx);
     
    106142 *  param_values : list of lists of parameter values for each share
    107143 */
    108 WERROR smbconf_get_config(struct smbconf_ctx *ctx,
     144sbcErr smbconf_get_config(struct smbconf_ctx *ctx,
    109145                          TALLOC_CTX *mem_ctx,
    110146                          uint32_t *num_shares,
    111147                          struct smbconf_service ***services)
    112148{
    113         WERROR werr = WERR_OK;
     149        sbcErr err;
    114150        TALLOC_CTX *tmp_ctx = NULL;
    115151        uint32_t tmp_num_shares;
     
    119155
    120156        if ((num_shares == NULL) || (services == NULL)) {
    121                 werr = WERR_INVALID_PARAM;
     157                err = SBC_ERR_INVALID_PARAM;
    122158                goto done;
    123159        }
     
    125161        tmp_ctx = talloc_stackframe();
    126162
    127         werr = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,
    128                                        &tmp_share_names);
    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)) {
    130166                goto done;
    131167        }
     
    133169        tmp_services = talloc_array(tmp_ctx, struct smbconf_service *,
    134170                                    tmp_num_shares);
    135 
    136171        if (tmp_services == NULL) {
    137                 werr = WERR_NOMEM;
     172                err = SBC_ERR_NOMEM;
    138173                goto done;
    139174        }
    140175
    141176        for (count = 0; count < tmp_num_shares; count++) {
    142                 werr = smbconf_get_share(ctx, tmp_services,
    143                                          tmp_share_names[count],
    144                                          &tmp_services[count]);
    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)) {
    146181                        goto done;
    147182                }
    148183        }
    149184
    150         werr = WERR_OK;
     185        err = SBC_ERR_OK;
    151186
    152187        *num_shares = tmp_num_shares;
     
    159194done:
    160195        talloc_free(tmp_ctx);
    161         return werr;
     196        return err;
    162197}
    163198
     
    165200 * get the list of share names defined in the configuration.
    166201 */
    167 WERROR smbconf_get_share_names(struct smbconf_ctx *ctx,
     202sbcErr smbconf_get_share_names(struct smbconf_ctx *ctx,
    168203                               TALLOC_CTX *mem_ctx,
    169204                               uint32_t *num_shares,
     
    186221 * Add a service if it does not already exist.
    187222 */
    188 WERROR smbconf_create_share(struct smbconf_ctx *ctx,
     223sbcErr smbconf_create_share(struct smbconf_ctx *ctx,
    189224                            const char *servicename)
    190225{
    191226        if ((servicename != NULL) && smbconf_share_exists(ctx, servicename)) {
    192                 return WERR_FILE_EXISTS;
     227                return SBC_ERR_FILE_EXISTS;
    193228        }
    194229
     
    199234 * get a definition of a share (service) from configuration.
    200235 */
    201 WERROR smbconf_get_share(struct smbconf_ctx *ctx,
     236sbcErr smbconf_get_share(struct smbconf_ctx *ctx,
    202237                         TALLOC_CTX *mem_ctx,
    203238                         const char *servicename,
     
    210245 * delete a service from configuration
    211246 */
    212 WERROR smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
     247sbcErr smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
    213248{
    214249        if (!smbconf_share_exists(ctx, servicename)) {
    215                 return WERR_NO_SUCH_SERVICE;
     250                return SBC_ERR_NO_SUCH_SERVICE;
    216251        }
    217252
     
    222257 * set a configuration parameter to the value provided.
    223258 */
    224 WERROR smbconf_set_parameter(struct smbconf_ctx *ctx,
     259sbcErr smbconf_set_parameter(struct smbconf_ctx *ctx,
    225260                             const char *service,
    226261                             const char *param,
     
    236271 * This also creates [global] when it does not exist.
    237272 */
    238 WERROR smbconf_set_global_parameter(struct smbconf_ctx *ctx,
     273sbcErr smbconf_set_global_parameter(struct smbconf_ctx *ctx,
    239274                                    const char *param, const char *val)
    240275{
    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;
    249285}
    250286
     
    252288 * get the value of a configuration parameter as a string
    253289 */
    254 WERROR smbconf_get_parameter(struct smbconf_ctx *ctx,
     290sbcErr smbconf_get_parameter(struct smbconf_ctx *ctx,
    255291                             TALLOC_CTX *mem_ctx,
    256292                             const char *service,
     
    259295{
    260296        if (valstr == NULL) {
    261                 return WERR_INVALID_PARAM;
     297                return SBC_ERR_INVALID_PARAM;
    262298        }
    263299
     
    270306 * Create [global] if it does not exist.
    271307 */
    272 WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx,
     308sbcErr smbconf_get_global_parameter(struct smbconf_ctx *ctx,
    273309                                    TALLOC_CTX *mem_ctx,
    274310                                    const char *param,
    275311                                    char **valstr)
    276312{
    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;
    286324}
    287325
     
    289327 * delete a parameter from configuration
    290328 */
    291 WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx,
     329sbcErr smbconf_delete_parameter(struct smbconf_ctx *ctx,
    292330                                const char *service, const char *param)
    293331{
     
    300338 * Create [global] if it does not exist.
    301339 */
    302 WERROR smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
     340sbcErr smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
    303341                                       const char *param)
    304342{
    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
     354sbcErr smbconf_get_includes(struct smbconf_ctx *ctx,
    316355                            TALLOC_CTX *mem_ctx,
    317356                            const char *service,
     
    322361}
    323362
    324 WERROR smbconf_get_global_includes(struct smbconf_ctx *ctx,
     363sbcErr smbconf_get_global_includes(struct smbconf_ctx *ctx,
    325364                                   TALLOC_CTX *mem_ctx,
    326365                                   uint32_t *num_includes, char ***includes)
    327366{
    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
     379sbcErr smbconf_set_includes(struct smbconf_ctx *ctx,
    340380                            const char *service,
    341381                            uint32_t num_includes, const char **includes)
     
    344384}
    345385
    346 WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx,
     386sbcErr smbconf_set_global_includes(struct smbconf_ctx *ctx,
    347387                                   uint32_t num_includes,
    348388                                   const char **includes)
    349389{
    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
     403sbcErr smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service)
    363404{
    364405        return ctx->ops->delete_includes(ctx, service);
    365406}
    366407
    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)
     408sbcErr 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
     421sbcErr smbconf_transaction_start(struct smbconf_ctx *ctx)
    380422{
    381423        return ctx->ops->transaction_start(ctx);
    382424}
    383425
    384 WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx)
     426sbcErr smbconf_transaction_commit(struct smbconf_ctx *ctx)
    385427{
    386428        return ctx->ops->transaction_commit(ctx);
    387429}
    388430
    389 WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx)
     431sbcErr smbconf_transaction_cancel(struct smbconf_ctx *ctx)
    390432{
    391433        return ctx->ops->transaction_cancel(ctx);
  • vendor/current/lib/smbconf/smbconf.h

    r414 r740  
    2121#define __LIBSMBCONF_H__
    2222
     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 */
     35enum _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
     51typedef 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
    2356struct smbconf_ctx;
    2457
     
    2861};
    2962
     63/** Information about a service */
    3064struct 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 */
    3569};
    3670
    3771/*
    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 **/
     82const 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.
    3993 */
    4094bool 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 */
    41103bool 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 */
    42110void 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 */
    43131bool smbconf_changed(struct smbconf_ctx *ctx, struct smbconf_csn *csn,
    44132                     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 */
     142sbcErr 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 */
     160sbcErr smbconf_get_config(struct smbconf_ctx *ctx,
    47161                          TALLOC_CTX *mem_ctx,
    48162                          uint32_t *num_shares,
    49163                          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 */
     179sbcErr smbconf_get_share_names(struct smbconf_ctx *ctx,
    51180                               TALLOC_CTX *mem_ctx,
    52181                               uint32_t *num_shares,
    53182                               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 */
    54193bool 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 */
     205sbcErr 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 */
     224sbcErr smbconf_get_share(struct smbconf_ctx *ctx,
    57225                         TALLOC_CTX *mem_ctx,
    58226                         const char *servicename,
    59227                         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 */
     239sbcErr smbconf_delete_share(struct smbconf_ctx *ctx,
    61240                            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 */
     256sbcErr smbconf_set_parameter(struct smbconf_ctx *ctx,
    63257                             const char *service,
    64258                             const char *param,
    65259                             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 */
     276sbcErr smbconf_set_global_parameter(struct smbconf_ctx *ctx,
    67277                                    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 */
     295sbcErr smbconf_get_parameter(struct smbconf_ctx *ctx,
    69296                             TALLOC_CTX *mem_ctx,
    70297                             const char *service,
    71298                             const char *param,
    72299                             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 */
     317sbcErr smbconf_get_global_parameter(struct smbconf_ctx *ctx,
    74318                                    TALLOC_CTX *mem_ctx,
    75319                                    const char *param,
    76320                                    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 */
     334sbcErr smbconf_delete_parameter(struct smbconf_ctx *ctx,
    78335                                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 */
     349sbcErr smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
    80350                                       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 */
     368sbcErr smbconf_get_includes(struct smbconf_ctx *ctx,
    82369                            TALLOC_CTX *mem_ctx,
    83370                            const char *service,
    84371                            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 */
     387sbcErr smbconf_get_global_includes(struct smbconf_ctx *ctx,
    86388                                   TALLOC_CTX *mem_ctx,
    87389                                   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 */
     405sbcErr smbconf_set_includes(struct smbconf_ctx *ctx,
    89406                            const char *service,
    90407                            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 */
     421sbcErr smbconf_set_global_includes(struct smbconf_ctx *ctx,
    92422                                   uint32_t num_includes,
    93423                                   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 */
     435sbcErr 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 */
     445sbcErr 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 */
     457sbcErr 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 */
     471sbcErr 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 */
     483sbcErr smbconf_transaction_cancel(struct smbconf_ctx *ctx);
     484
     485/* @} ******************************************************************/
    100486
    101487#endif /*  _LIBSMBCONF_H_  */
  • vendor/current/lib/smbconf/smbconf_private.h

    r414 r740  
    2828
    2929struct smbconf_ops {
    30         WERROR (*init)(struct smbconf_ctx *ctx, const char *path);
     30        sbcErr (*init)(struct smbconf_ctx *ctx, const char *path);
    3131        int (*shutdown)(struct smbconf_ctx *ctx);
    3232        bool (*requires_messaging)(struct smbconf_ctx *ctx);
    3333        bool (*is_writeable)(struct smbconf_ctx *ctx);
    34         WERROR (*open_conf)(struct smbconf_ctx *ctx);
     34        sbcErr (*open_conf)(struct smbconf_ctx *ctx);
    3535        int (*close_conf)(struct smbconf_ctx *ctx);
    3636        void (*get_csn)(struct smbconf_ctx *ctx, struct smbconf_csn *csn,
    3737                        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,
    4040                                  TALLOC_CTX *mem_ctx,
    4141                                  uint32_t *num_shares,
    4242                                  char ***share_names);
    4343        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,
    4646                            TALLOC_CTX *mem_ctx,
    4747                            const char *servicename,
    4848                            struct smbconf_service **service);
    49         WERROR (*delete_share)(struct smbconf_ctx *ctx,
     49        sbcErr (*delete_share)(struct smbconf_ctx *ctx,
    5050                                    const char *servicename);
    51         WERROR (*set_parameter)(struct smbconf_ctx *ctx,
     51        sbcErr (*set_parameter)(struct smbconf_ctx *ctx,
    5252                                const char *service,
    5353                                const char *param,
    5454                                const char *valstr);
    55         WERROR (*get_parameter)(struct smbconf_ctx *ctx,
     55        sbcErr (*get_parameter)(struct smbconf_ctx *ctx,
    5656                                TALLOC_CTX *mem_ctx,
    5757                                const char *service,
    5858                                const char *param,
    5959                                char **valstr);
    60         WERROR (*delete_parameter)(struct smbconf_ctx *ctx,
     60        sbcErr (*delete_parameter)(struct smbconf_ctx *ctx,
    6161                                   const char *service, const char *param);
    62         WERROR (*get_includes)(struct smbconf_ctx *ctx,
     62        sbcErr (*get_includes)(struct smbconf_ctx *ctx,
    6363                               TALLOC_CTX *mem_ctx,
    6464                               const char *service,
    6565                               uint32_t *num_includes, char ***includes);
    66         WERROR (*set_includes)(struct smbconf_ctx *ctx,
     66        sbcErr (*set_includes)(struct smbconf_ctx *ctx,
    6767                               const char *service,
    6868                               uint32_t num_includes, const char **includes);
    69         WERROR (*delete_includes)(struct smbconf_ctx *ctx,
     69        sbcErr (*delete_includes)(struct smbconf_ctx *ctx,
    7070                                  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);
    7474};
    7575
     
    8080};
    8181
    82 WERROR smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
     82sbcErr smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
    8383                             const char *path, struct smbconf_ops *ops);
    8484
    85 WERROR smbconf_add_string_to_array(TALLOC_CTX *mem_ctx,
     85sbcErr smbconf_add_string_to_array(TALLOC_CTX *mem_ctx,
    8686                                   char ***array,
    8787                                   uint32_t count,
  • vendor/current/lib/smbconf/smbconf_txt.c

    r414 r740  
    2828#include "includes.h"
    2929#include "smbconf_private.h"
     30#include "lib/smbconf/smbconf_txt.h"
    3031
    3132struct txt_cache {
     
    6061static bool smbconf_txt_do_section(const char *section, void *private_data)
    6162{
    62         WERROR werr;
     63        sbcErr err;
    6364        uint32_t idx;
    6465        struct txt_private_data *tpd = (struct txt_private_data *)private_data;
     
    7273        }
    7374
    74         werr = smbconf_add_string_to_array(cache, &(cache->share_names),
    75                                            cache->num_shares, section);
    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)) {
    7778                return false;
    7879        }
     
    114115                                     void *private_data)
    115116{
    116         WERROR werr;
     117        sbcErr err;
    117118        char **param_names, **param_values;
    118119        uint32_t num_params;
     
    146147                return true;
    147148        }
    148         werr = smbconf_add_string_to_array(cache,
     149        err = smbconf_add_string_to_array(cache,
    149150                                &(cache->param_names[cache->current_share]),
    150151                                num_params, param_name);
    151         if (!W_ERROR_IS_OK(werr)) {
     152        if (!SBC_ERROR_IS_OK(err)) {
    152153                return false;
    153154        }
    154         werr = smbconf_add_string_to_array(cache,
     155        err = smbconf_add_string_to_array(cache,
    155156                                &(cache->param_values[cache->current_share]),
    156157                                num_params, param_value);
    157158        cache->num_params[cache->current_share]++;
    158         return W_ERROR_IS_OK(werr);
     159        return SBC_ERROR_IS_OK(err);
    159160}
    160161
     
    165166}
    166167
    167 static WERROR smbconf_txt_init_cache(struct smbconf_ctx *ctx)
     168static sbcErr smbconf_txt_init_cache(struct smbconf_ctx *ctx)
    168169{
    169170        if (pd(ctx)->cache != NULL) {
     
    174175
    175176        if (pd(ctx)->cache == NULL) {
    176                 return WERR_NOMEM;
    177         }
    178 
    179         return WERR_OK;
    180 }
    181 
    182 static WERROR smbconf_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
     183static sbcErr smbconf_txt_load_file(struct smbconf_ctx *ctx)
     184{
     185        sbcErr err;
    185186        uint64_t new_csn;
    186187
    187188        if (!file_exist(ctx->path)) {
    188                 return WERR_BADFILE;
     189                return SBC_ERR_BADFILE;
    189190        }
    190191
    191192        new_csn = (uint64_t)file_modtime(ctx->path);
    192193        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;
    199200        }
    200201
     
    202203                        smbconf_txt_do_parameter, pd(ctx)))
    203204        {
    204                 return WERR_CAN_NOT_COMPLETE;
     205                return SBC_ERR_CAN_NOT_COMPLETE;
    205206        }
    206207
    207208        pd(ctx)->csn = new_csn;
    208209
    209         return WERR_OK;
     210        return SBC_ERR_OK;
    210211}
    211212
     
    220221 * initialize the text based smbconf backend
    221222 */
    222 static WERROR smbconf_txt_init(struct smbconf_ctx *ctx, const char *path)
     223static sbcErr smbconf_txt_init(struct smbconf_ctx *ctx, const char *path)
    223224{
    224225        if (path == NULL) {
    225                 return WERR_BADFILE;
     226                return SBC_ERR_BADFILE;
    226227        }
    227228        ctx->path = talloc_strdup(ctx, path);
    228229        if (ctx->path == NULL) {
    229                 return WERR_NOMEM;
     230                return SBC_ERR_NOMEM;
    230231        }
    231232
    232233        ctx->data = talloc_zero(ctx, struct txt_private_data);
    233234        if (ctx->data == NULL) {
    234                 return WERR_NOMEM;
     235                return SBC_ERR_NOMEM;
    235236        }
    236237
    237238        pd(ctx)->verbatim = true;
    238239
    239         return WERR_OK;
     240        return SBC_ERR_OK;
    240241}
    241242
     
    256257}
    257258
    258 static WERROR smbconf_txt_open(struct smbconf_ctx *ctx)
     259static sbcErr smbconf_txt_open(struct smbconf_ctx *ctx)
    259260{
    260261        return smbconf_txt_load_file(ctx);
     
    285286 * Drop the whole configuration (restarting empty)
    286287 */
    287 static WERROR smbconf_txt_drop(struct smbconf_ctx *ctx)
    288 {
    289         return WERR_NOT_SUPPORTED;
     288static sbcErr smbconf_txt_drop(struct smbconf_ctx *ctx)
     289{
     290        return SBC_ERR_NOT_SUPPORTED;
    290291}
    291292
     
    293294 * get the list of share names defined in the configuration.
    294295 */
    295 static WERROR smbconf_txt_get_share_names(struct smbconf_ctx *ctx,
     296static sbcErr smbconf_txt_get_share_names(struct smbconf_ctx *ctx,
    296297                                          TALLOC_CTX *mem_ctx,
    297298                                          uint32_t *num_shares,
     
    301302        uint32_t added_count = 0;
    302303        TALLOC_CTX *tmp_ctx = NULL;
    303         WERROR werr = WERR_OK;
     304        sbcErr err = SBC_ERR_OK;
    304305        char **tmp_share_names = NULL;
    305306
    306307        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;
    314314        }
    315315
     
    320320
    321321        if (smbconf_share_exists(ctx, NULL)) {
    322                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
    323                                                    0, NULL);
    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)) {
    325325                        goto done;
    326326                }
     
    329329
    330330        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,
    332332                                                   added_count, GLOBAL_NAME);
    333                 if (!W_ERROR_IS_OK(werr)) {
     333                if (!SBC_ERROR_IS_OK(err)) {
    334334                        goto done;
    335335                }
     
    344344                }
    345345
    346                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
     346                err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
    347347                                        added_count,
    348348                                        pd(ctx)->cache->share_names[count]);
    349                 if (!W_ERROR_IS_OK(werr)) {
     349                if (!SBC_ERROR_IS_OK(err)) {
    350350                        goto done;
    351351                }
     
    362362done:
    363363        talloc_free(tmp_ctx);
    364         return werr;
     364        return err;
    365365}
    366366
     
    371371                                     const char *servicename)
    372372{
    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)) {
    377377                return false;
    378378        }
     
    386386 * Add a service if it does not already exist
    387387 */
    388 static WERROR smbconf_txt_create_share(struct smbconf_ctx *ctx,
     388static sbcErr smbconf_txt_create_share(struct smbconf_ctx *ctx,
    389389                                       const char *servicename)
    390390{
    391         return WERR_NOT_SUPPORTED;
     391        return SBC_ERR_NOT_SUPPORTED;
    392392}
    393393
     
    395395 * get a definition of a share (service) from configuration.
    396396 */
    397 static WERROR smbconf_txt_get_share(struct smbconf_ctx *ctx,
     397static sbcErr smbconf_txt_get_share(struct smbconf_ctx *ctx,
    398398                                    TALLOC_CTX *mem_ctx,
    399399                                    const char *servicename,
    400400                                    struct smbconf_service **service)
    401401{
    402         WERROR werr;
     402        sbcErr err;
    403403        uint32_t sidx, count;
    404404        bool found;
     
    406406        struct smbconf_service *tmp_service = NULL;
    407407
    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;
    411411        }
    412412
     
    416416                                      &sidx);
    417417        if (!found) {
    418                 return WERR_NO_SUCH_SERVICE;
     418                return SBC_ERR_NO_SUCH_SERVICE;
    419419        }
    420420
     
    423423        tmp_service = talloc_zero(tmp_ctx, struct smbconf_service);
    424424        if (tmp_service == NULL) {
    425                 werr = WERR_NOMEM;
     425                err = SBC_ERR_NOMEM;
    426426                goto done;
    427427        }
     
    430430                tmp_service->name = talloc_strdup(tmp_service, servicename);
    431431                if (tmp_service->name == NULL) {
    432                         werr = WERR_NOMEM;
     432                        err = SBC_ERR_NOMEM;
    433433                        goto done;
    434434                }
     
    436436
    437437        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,
    439439                                &(tmp_service->param_names),
    440440                                count,
    441441                                pd(ctx)->cache->param_names[sidx][count]);
    442                 if (!W_ERROR_IS_OK(werr)) {
     442                if (!SBC_ERROR_IS_OK(err)) {
    443443                        goto done;
    444444                }
    445                 werr = smbconf_add_string_to_array(tmp_service,
     445                err = smbconf_add_string_to_array(tmp_service,
    446446                                &(tmp_service->param_values),
    447447                                count,
    448448                                pd(ctx)->cache->param_values[sidx][count]);
    449                 if (!W_ERROR_IS_OK(werr)) {
     449                if (!SBC_ERROR_IS_OK(err)) {
    450450                        goto done;
    451451                }
     
    453453
    454454        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);
    460456
    461457done:
    462458        talloc_free(tmp_ctx);
    463         return werr;
     459        return err;
    464460}
    465461
     
    467463 * delete a service from configuration
    468464 */
    469 static WERROR smbconf_txt_delete_share(struct smbconf_ctx *ctx,
     465static sbcErr smbconf_txt_delete_share(struct smbconf_ctx *ctx,
    470466                                       const char *servicename)
    471467{
    472         return WERR_NOT_SUPPORTED;
     468        return SBC_ERR_NOT_SUPPORTED;
    473469}
    474470
     
    476472 * set a configuration parameter to the value provided.
    477473 */
    478 static WERROR smbconf_txt_set_parameter(struct smbconf_ctx *ctx,
     474static sbcErr smbconf_txt_set_parameter(struct smbconf_ctx *ctx,
    479475                                        const char *service,
    480476                                        const char *param,
    481477                                        const char *valstr)
    482478{
    483         return WERR_NOT_SUPPORTED;
     479        return SBC_ERR_NOT_SUPPORTED;
    484480}
    485481
     
    487483 * get the value of a configuration parameter as a string
    488484 */
    489 static WERROR smbconf_txt_get_parameter(struct smbconf_ctx *ctx,
     485static sbcErr smbconf_txt_get_parameter(struct smbconf_ctx *ctx,
    490486                                        TALLOC_CTX *mem_ctx,
    491487                                        const char *service,
     
    493489                                        char **valstr)
    494490{
    495         WERROR werr;
     491        sbcErr err;
    496492        bool found;
    497493        uint32_t share_index, param_index;
    498494
    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;
    502498        }
    503499
     
    507503                                      &share_index);
    508504        if (!found) {
    509                 return WERR_NO_SUCH_SERVICE;
     505                return SBC_ERR_NO_SUCH_SERVICE;
    510506        }
    511507
     
    515511                                &param_index);
    516512        if (!found) {
    517                 return WERR_INVALID_PARAM;
     513                return SBC_ERR_INVALID_PARAM;
    518514        }
    519515
     
    522518
    523519        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;
    528524}
    529525
     
    531527 * delete a parameter from configuration
    532528 */
    533 static WERROR smbconf_txt_delete_parameter(struct smbconf_ctx *ctx,
     529static sbcErr smbconf_txt_delete_parameter(struct smbconf_ctx *ctx,
    534530                                           const char *service,
    535531                                           const char *param)
    536532{
    537         return WERR_NOT_SUPPORTED;
    538 }
    539 
    540 static WERROR smbconf_txt_get_includes(struct smbconf_ctx *ctx,
     533        return SBC_ERR_NOT_SUPPORTED;
     534}
     535
     536static sbcErr smbconf_txt_get_includes(struct smbconf_ctx *ctx,
    541537                                       TALLOC_CTX *mem_ctx,
    542538                                       const char *service,
     
    544540                                       char ***includes)
    545541{
    546         WERROR werr;
     542        sbcErr err;
    547543        bool found;
    548544        uint32_t sidx, count;
     
    551547        char **tmp_includes = NULL;
    552548
    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;
    556552        }
    557553
     
    561557                                      &sidx);
    562558        if (!found) {
    563                 return WERR_NO_SUCH_SERVICE;
     559                return SBC_ERR_NO_SUCH_SERVICE;
    564560        }
    565561
     
    570566                             "include"))
    571567                {
    572                         werr = smbconf_add_string_to_array(tmp_ctx,
     568                        err = smbconf_add_string_to_array(tmp_ctx,
    573569                                &tmp_includes,
    574570                                tmp_num_includes,
    575571                                pd(ctx)->cache->param_values[sidx][count]);
    576                         if (!W_ERROR_IS_OK(werr)) {
     572                        if (!SBC_ERROR_IS_OK(err)) {
    577573                                goto done;
    578574                        }
     
    585581                *includes = talloc_move(mem_ctx, &tmp_includes);
    586582                if (*includes == NULL) {
    587                         werr = WERR_NOMEM;
     583                        err = SBC_ERR_NOMEM;
    588584                        goto done;
    589585                }
     
    592588        }
    593589
    594         werr = WERR_OK;
     590        err = SBC_ERR_OK;
    595591
    596592done:
    597593        talloc_free(tmp_ctx);
    598         return werr;
    599 }
    600 
    601 static WERROR smbconf_txt_set_includes(struct smbconf_ctx *ctx,
     594        return err;
     595}
     596
     597static sbcErr smbconf_txt_set_includes(struct smbconf_ctx *ctx,
    602598                                       const char *service,
    603599                                       uint32_t num_includes,
    604600                                       const char **includes)
    605601{
    606         return WERR_NOT_SUPPORTED;
    607 }
    608 
    609 static WERROR smbconf_txt_delete_includes(struct smbconf_ctx *ctx,
     602        return SBC_ERR_NOT_SUPPORTED;
     603}
     604
     605static sbcErr smbconf_txt_delete_includes(struct smbconf_ctx *ctx,
    610606                                          const char *service)
    611607{
    612         return WERR_NOT_SUPPORTED;
    613 }
    614 
    615 static WERROR smbconf_txt_transaction_start(struct smbconf_ctx *ctx)
    616 {
    617         return WERR_OK;
    618 }
    619 
    620 static WERROR smbconf_txt_transaction_commit(struct smbconf_ctx *ctx)
    621 {
    622         return WERR_OK;
    623 }
    624 
    625 static WERROR smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)
    626 {
    627         return WERR_OK;
     608        return SBC_ERR_NOT_SUPPORTED;
     609}
     610
     611static sbcErr smbconf_txt_transaction_start(struct smbconf_ctx *ctx)
     612{
     613        return SBC_ERR_OK;
     614}
     615
     616static sbcErr smbconf_txt_transaction_commit(struct smbconf_ctx *ctx)
     617{
     618        return SBC_ERR_OK;
     619}
     620
     621static sbcErr smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)
     622{
     623        return SBC_ERR_OK;
    628624}
    629625
     
    658654 * the only function that is exported from this module
    659655 */
    660 WERROR smbconf_init_txt(TALLOC_CTX *mem_ctx,
     656sbcErr smbconf_init_txt(TALLOC_CTX *mem_ctx,
    661657                        struct smbconf_ctx **conf_ctx,
    662658                        const char *path)
    663659{
    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;
    669665        }
    670666
  • vendor/current/lib/smbconf/smbconf_txt.h

    r414 r740  
    2727 */
    2828
    29 WERROR smbconf_init_txt(TALLOC_CTX *mem_ctx,
     29sbcErr smbconf_init_txt(TALLOC_CTX *mem_ctx,
    3030                        struct smbconf_ctx **conf_ctx,
    3131                        const char *path);
  • vendor/current/lib/smbconf/smbconf_util.c

    r414 r740  
    4040 * should be called.
    4141 */
    42 WERROR smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
     42sbcErr smbconf_init_internal(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
    4343                             const char *path, struct smbconf_ops *ops)
    4444{
    45         WERROR werr = WERR_OK;
     45        sbcErr err = SBC_ERR_OK;
    4646        struct smbconf_ctx *ctx;
    4747
    4848        if (conf_ctx == NULL) {
    49                 return WERR_INVALID_PARAM;
     49                return SBC_ERR_INVALID_PARAM;
    5050        }
    5151
    5252        ctx = talloc_zero(mem_ctx, struct smbconf_ctx);
    5353        if (ctx == NULL) {
    54                 return WERR_NOMEM;
     54                return SBC_ERR_NOMEM;
    5555        }
    5656
    5757        ctx->ops = ops;
    5858
    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)) {
    6161                goto fail;
    6262        }
     
    6565
    6666        *conf_ctx = ctx;
    67         return werr;
     67        return err;
    6868
    6969fail:
    7070        talloc_free(ctx);
    71         return werr;
     71        return err;
    7272}
    7373
     
    7676 * add a string to a talloced array of strings.
    7777 */
    78 WERROR smbconf_add_string_to_array(TALLOC_CTX *mem_ctx,
     78sbcErr smbconf_add_string_to_array(TALLOC_CTX *mem_ctx,
    7979                                   char ***array,
    8080                                   uint32_t count,
     
    8484
    8585        if (array == NULL) {
    86                 return WERR_INVALID_PARAM;
     86                return SBC_ERR_INVALID_PARAM;
    8787        }
    8888
    8989        new_array = talloc_realloc(mem_ctx, *array, char *, count + 1);
    9090        if (new_array == NULL) {
    91                 return WERR_NOMEM;
     91                return SBC_ERR_NOMEM;
    9292        }
    9393
     
    9898                if (new_array[count] == NULL) {
    9999                        talloc_free(new_array);
    100                         return WERR_NOMEM;
     100                        return SBC_ERR_NOMEM;
    101101                }
    102102        }
     
    104104        *array = new_array;
    105105
    106         return WERR_OK;
     106        return SBC_ERR_OK;
    107107}
    108108
  • vendor/current/lib/socket_wrapper/socket_wrapper.c

    r414 r740  
    297297        case SOCKET_TYPE_CHAR_TCP:
    298298        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
    301301                if ((*len) < sizeof(*in2)) {
    302302                    errno = EINVAL;
     
    315315        case SOCKET_TYPE_CHAR_TCP_V6:
    316316        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
    319319                if ((*len) < sizeof(*in2)) {
    320320                        errno = EINVAL;
     
    353353        case AF_INET: {
    354354                const struct sockaddr_in *in =
    355                     (const struct sockaddr_in *)inaddr;
     355                    (const struct sockaddr_in *)(const void *)inaddr;
    356356                unsigned int addr = ntohl(in->sin_addr.s_addr);
    357357                char u_type = '\0';
     
    396396        case AF_INET6: {
    397397                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;
    400400
    401401                switch (si->type) {
     
    412412                prt = ntohs(in->sin6_port);
    413413
    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)) {
    417418                        iface = in->sin6_addr.s6_addr[15];
    418419                } else {
     
    461462        case AF_INET: {
    462463                const struct sockaddr_in *in =
    463                     (const struct sockaddr_in *)inaddr;
     464                    (const struct sockaddr_in *)(const void *)inaddr;
    464465                unsigned int addr = ntohl(in->sin_addr.s_addr);
    465466                char u_type = '\0';
     
    512513        case AF_INET6: {
    513514                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;
    516517
    517518                switch (si->type) {
     
    528529                prt = ntohs(in->sin6_port);
    529530
    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;
    532534                if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
    533535                        iface = socket_wrapper_default_iface();
    534                 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
     536                } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
    535537                        iface = in->sin6_addr.s6_addr[15];
    536538                } else {
     
    585587                                  struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
    586588{
     589        struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
    587590        if (!out_addr)
    588591                return 0;
    589592
    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
    591597
    592598        switch (in_addr->sa_family) {
     
    611617                break;
    612618        }
    613        
     619
    614620        errno = EAFNOSUPPORT;
    615621        return -1;
     
    623629                                    socklen_t *out_addrlen)
    624630{
     631        int ret;
     632
    625633        if (out_addr == NULL || out_addrlen == NULL)
    626634                return 0;
     
    644652                        return -1;
    645653                }
    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;
    647659        default:
    648660                break;
     
    960972                ip->v6.flow_label_high  = 0x00;
    961973                ip->v6.flow_label_low   = 0x0000;
    962                 ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
     974                ip->v6.payload_length   = htons(wire_len - icmp_truncate_len); /* TODO */
    963975                ip->v6.next_header      = protocol;
    964976                memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
     
    10101022                        ip->v6.flow_label_high  = 0x00;
    10111023                        ip->v6.flow_label_low   = 0x0000;
    1012                         ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
     1024                        ip->v6.payload_length   = htons(wire_len - icmp_truncate_len); /* TODO */
    10131025                        ip->v6.next_header      = protocol;
    10141026                        memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
     
    14951507        memset(&un_my_addr, 0, sizeof(un_my_addr));
    14961508
    1497         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
     1509        ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
    14981510        if (ret == -1) {
    14991511                free(my_addr);
     
    15271539
    15281540        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);
    15361550        if (ret == -1) {
    15371551                free(child_si);
     
    16601674                         type, socket_wrapper_default_iface(), port);
    16611675                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));
    16641679                if (ret == -1) return ret;
    16651680
     
    16861701        struct sockaddr_un un_addr;
    16871702        struct socket_info *si = find_socket_info(s);
     1703        int bcast = 0;
    16881704
    16891705        if (!si) {
     
    17011717        }
    17021718
    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);
    17041721        if (ret == -1) return -1;
     1722
     1723        if (bcast) {
     1724                errno = ENETUNREACH;
     1725                return -1;
     1726        }
    17051727
    17061728        if (si->type == SOCK_DGRAM) {
     
    17101732                swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
    17111733
    1712                 ret = real_connect(s, (struct sockaddr *)&un_addr,
     1734                ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
    17131735                                   sizeof(struct sockaddr_un));
    17141736        }
     
    17461768        si->myname = sockaddr_dup(myaddr, addrlen);
    17471769
    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);
    17491771        if (ret == -1) return -1;
    17501772
    17511773        unlink(un_addr.sun_path);
    17521774
    1753         ret = real_bind(s, (struct sockaddr *)&un_addr,
     1775        ret = real_bind(s, (struct sockaddr *)(void *)&un_addr,
    17541776                        sizeof(struct sockaddr_un));
    17551777
     
    18481870                return -1;
    18491871        }
    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 files
    1873                  * (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 files
    1919                  * (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;
    19911872}
    19921873
     
    20171898}
    20181899
     1900static 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
     2019static 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
    20192199_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
    20202200{
     
    20762256_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
    20772257{
    2078         int ret;
     2258        struct msghdr msg;
     2259        struct iovec tmp;
     2260        struct sockaddr_un un_addr;
     2261        ssize_t ret;
    20792262        struct socket_info *si = find_socket_info(s);
    20802263
     
    20832266        }
    20842267
    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;
    21182287
    21192288        ret = real_send(s, buf, len, flags);
    21202289
    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);
    21272291
    21282292        return ret;
    21292293}
    21302294
    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;
    21392303        struct socket_info *si = find_socket_info(s);
     2304        int bcast = 0;
    21402305
    21412306        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);
    21972384
    21982385        return ret;
     
    22072394        if (!si) {
    22082395                return real_readv(s, vector, count);
     2396        }
     2397
     2398        if (!si->connected) {
     2399                errno = ENOTCONN;
     2400                return -1;
    22092401        }
    22102402
     
    22142406                 * (as the caller will simply continue from here) */
    22152407                size_t i, len = 0;
    2216                
     2408
    22172409                for (i=0; i < count; i++) {
    22182410                        size_t nlen;
     
    22682460int swrap_writev(int s, const struct iovec *vector, size_t count)
    22692461{
    2270         int ret;
     2462        struct msghdr msg;
     2463        struct iovec tmp;
     2464        struct sockaddr_un un_addr;
     2465        ssize_t ret;
    22712466        struct socket_info *si = find_socket_info(s);
    2272         struct iovec v;
    22732467
    22742468        if (!si) {
     
    22762470        }
    22772471
    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);
    23292492
    23302493        return ret;
  • vendor/current/lib/socket_wrapper/socket_wrapper.h

    r414 r740  
    5151ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
    5252ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags);
     53ssize_t swrap_recvmsg(int s, struct msghdr *msg, int flags);
    5354int swrap_ioctl(int s, int req, void *ptr);
    5455ssize_t swrap_recv(int s, void *buf, size_t len, int flags);
     
    116117#define sendmsg(s,msg,flags)            swrap_sendmsg(s,msg,flags)
    117118
     119#ifdef recvmsg
     120#undef recvmsg
     121#endif
     122#define recvmsg(s,msg,flags)            swrap_recvmsg(s,msg,flags)
     123
    118124#ifdef ioctl
    119125#undef ioctl
  • vendor/current/lib/socket_wrapper/testsuite.c

    r414 r740  
    9696{
    9797        struct torture_suite *suite = torture_suite_create(mem_ctx,
    98                                                                                                            "SOCKET-WRAPPER");
     98                                                                                                           "socket-wrapper");
    9999
    100100        torture_suite_add_simple_test(suite, "socket_wrapper_dir", test_socket_wrapper_dir);
  • vendor/current/lib/subunit/python/subunit/__init__.py

    r414 r740  
    11#
    2 #  subunit: extensions to python unittest to get test results from subprocesses.
     2#  subunit: extensions to Python unittest to get test results from subprocesses.
    33#  Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
    4 #  Copyright (C) 2007  Jelmer Vernooij <jelmer@samba.org>
    54#
    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.
    1015#
    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
     19Overview
     20++++++++
     21
     22The ``subunit`` Python package provides a number of ``unittest`` extensions
     23which can be used to cause tests to output Subunit, to parse Subunit streams
     24into test activity, perform seamless test isolation within a regular test
     25case and variously sort, filter and report on test runs.
     26
     27
     28Key Classes
     29-----------
     30
     31The ``subunit.TestProtocolClient`` class is a ``unittest.TestResult``
     32extension which will translate a test run into a Subunit stream.
     33
     34The ``subunit.ProtocolTestCase`` class is an adapter between the Subunit wire
     35protocol and the ``unittest.TestCase`` object protocol. It is used to translate
     36a stream into a test run, which regular ``unittest.TestResult`` objects can
     37process and report/inspect.
     38
     39Subunit has support for non-blocking usage too, for use with asyncore or
     40Twisted. See the ``TestProtocolServer`` parser class for more details.
     41
     42Subunit includes extensions to the Python ``TestResult`` protocol. These are
     43all done in a compatible manner: ``TestResult`` objects that do not implement
     44the extension methods will not cause errors to be raised, instead the extension
     45will either lose fidelity (for instance, folding expected failures to success
     46in Python versions < 2.7 or 3.1), or discard the extended data (for extra
     47details, tags, timestamping and progress markers).
     48
     49The test outcome methods ``addSuccess``, ``addError``, ``addExpectedFailure``,
     50``addFailure``, ``addSkip`` take an optional keyword parameter ``details``
     51which can be used instead of the usual python unittest parameter.
     52When 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
     54the Python Testing In Python mail list, with the goal of permitting a common
     55way to provide additional data beyond a traceback, such as captured data from
     56disk, logging messages etc. The reference for this API is in testtools (0.9.0
     57and newer).
     58
     59The ``tags(new_tags, gone_tags)`` method is called (if present) to add or
     60remove tags in the test run that is currently executing. If called when no
     61test is in progress (that is, if called outside of the ``startTest``,
     62``stopTest`` pair), the the tags apply to all sebsequent tests. If called
     63when a test is in progress, then the tags only apply to that test.
     64
     65The ``time(a_datetime)`` method is called (if present) when a ``time:``
     66directive is encountered in a Subunit stream. This is used to tell a TestResult
     67about the time that events in the stream occured at, to allow reconstructing
     68test timing from a stream.
     69
     70The ``progress(offset, whence)`` method controls progress data for a stream.
     71The offset parameter is an int, and whence is one of subunit.PROGRESS_CUR,
     72subunit.PROGRESS_SET, PROGRESS_PUSH, PROGRESS_POP. Push and pop operations
     73ignore the offset parameter.
     74
     75
     76Python test support
     77-------------------
     78
     79``subunit.run`` is a convenience wrapper to run a Python test suite via
     80the command line, reporting via Subunit::
     81
     82  $ python -m subunit.run mylib.tests.test_suite
     83
     84The ``IsolatedTestSuite`` class is a TestSuite that forks before running its
     85tests, allowing isolation between the test runner and some tests.
     86
     87Similarly, ``IsolatedTestCase`` is a base class which can be subclassed to get
     88tests that will fork() before that individual test is run.
     89
     90`ExecTestCase`` is a convenience wrapper for running an external
     91program to get a Subunit stream and then report that back to an arbitrary
     92result 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
     112Utility modules
     113---------------
     114
     115* subunit.chunked contains HTTP chunked encoding/decoding logic.
     116* subunit.test_results contains TestResult helper classes.
     117"""
     118
     119import datetime
    21120import os
     121import re
    22122from StringIO import StringIO
     123import subprocess
    23124import sys
    24125import unittest
     126
     127import iso8601
     128from testtools import content, content_type, ExtendedToOriginalDecorator
     129try:
     130    from testtools.testresult.real import _StringException
     131    RemoteException = _StringException
     132    _remote_exception_str = '_StringException' # For testing.
     133except ImportError:
     134    raise ImportError ("testtools.testresult.real does not contain "
     135        "_StringException, check your version.")
     136from testtools import testresult
     137
     138import chunked, details, test_results
     139
     140
     141PROGRESS_SET = 0
     142PROGRESS_CUR = 1
     143PROGRESS_PUSH = 2
     144PROGRESS_POP = 3
     145
    25146
    26147def test_suite():
     
    43164
    44165
     166def 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
     178class DiscardStream(object):
     179    """A filelike object which discards what is written to it."""
     180
     181    def write(self, bytes):
     182        pass
     183
     184
     185class _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
     252class _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
     328class _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
     343class _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
     376class _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
     387class _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
     398class _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
     409class _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
     420class _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
    45431class TestProtocolServer(object):
    46     """A class for receiving results from a TestProtocol client."""
    47 
    48     OUTSIDE_TEST = 0
    49     TEST_STARTED = 1
    50     READING_FAILURE = 2
    51     READING_ERROR = 3
    52 
    53     def __init__(self, client, stream=sys.stdout):
    54         """Create a TestProtocol server instance.
    55 
    56         client should be an object that provides
    57          - startTest
    58          - addSuccess
    59          - addFailure
    60          - addError
    61          - stopTest
    62         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.
    63449        """
    64         self.state = TestProtocolServer.OUTSIDE_TEST
    65         self.client = client
     450        self.client = ExtendedToOriginalDecorator(client)
     451        if stream is None:
     452            stream = sys.stdout
    66453        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
    80478        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)
    130496
    131497    def lineReceived(self, line):
    132498        """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)
    156506
    157507    def lostConnection(self):
    158508        """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()
    178510
    179511    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        """
    180517        for line in pipe.readlines():
    181518            self.lineReceived(line)
     
    184521    def _startTest(self, offset, line):
    185522        """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)
    193527
    194528    def stdOutLineReceived(self, line):
     
    196530
    197531
    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."""
     532class 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    """
    210549
    211550    def __init__(self, stream):
    212         super(TestProtocolClient, self).__init__()
     551        testresult.TestResult.__init__(self)
    213552        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)
    220626        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):
    232638        """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
    235646
    236647    def startTest(self, test):
    237648        """Mark a test as starting its test run."""
    238         self._stream.write("test: %s\n" % (test.shortDescription() or str(test)))
    239649        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
     714def RemoteError(description=u""):
     715    return (_StringException, _StringException(description), None)
    246716
    247717
    248718class 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    """
    250727
    251728    def __eq__ (self, other):
     
    273750
    274751    def id(self):
    275         return "%s.%s" % (self._strclass(), self.__description)
     752        return "%s" % (self.__description,)
    276753
    277754    def __str__(self):
     
    285762        if result is None: result = self.defaultTestResult()
    286763        result.startTest(self)
    287         result.addError(self, RemoteError("Cannot run RemotedTestCases.\n"))
     764        result.addError(self, RemoteError(u"Cannot run RemotedTestCases.\n"))
    288765        result.stopTest(self)
    289766
     
    315792    def debug(self):
    316793        """Run the test without collecting errors in a TestResult"""
    317         self._run(unittest.TestResult())
     794        self._run(testresult.TestResult())
    318795
    319796    def _run(self, result):
    320797        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))
    323801
    324802
    325803class 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    """
    327810
    328811    def run(self, result=None):
     
    332815
    333816class 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    """
    335824
    336825    def run(self, result=None):
    337         if result is None: result = unittest.TestResult()
     826        if result is None: result = testresult.TestResult()
    338827        run_isolated(unittest.TestSuite, self, result)
    339828
     
    377866
    378867
    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 
     868def 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
     974def 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
     1019class 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
     1074class 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
     1125def 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
     1137def _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
     1142def _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  
    33#  Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
    44#
    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.
    1815#
    1916
    20 from subunit.tests import TestUtil, test_test_protocol
     17from 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    )
    2129
    2230def test_suite():
    2331    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())
    2436    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())
    2541    return result
  • vendor/current/lib/subunit/python/subunit/tests/sample-script.py

    r414 r740  
    11#!/usr/bin/env python
    22import sys
     3if 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)
    310print "test old mcdonald"
    411print "success old mcdonald"
  • vendor/current/lib/subunit/python/subunit/tests/test_test_protocol.py

    r414 r740  
    11#
    2 #  subunit: extensions to python unittest to get test results from subprocesses.
     2#  subunit: extensions to Python unittest to get test results from subprocesses.
    33#  Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
    44#
    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.
    915#
    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
     17import datetime
    2018import unittest
    2119from StringIO import StringIO
    2220import os
     21import sys
     22
     23from testtools.content import Content, TracebackContent
     24from testtools.content_type import ContentType
     25from testtools.tests.helpers import (
     26    Python26TestResult,
     27    Python27TestResult,
     28    ExtendedTestResult,
     29    )
     30
    2331import 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, [])
     32from subunit import _remote_exception_str
     33import subunit.iso8601 as iso8601
    11234
    11335
     
    11537
    11638    def test_imports(self):
     39        from subunit import DiscardStream
    11740        from subunit import TestProtocolServer
    11841        from subunit import RemotedTestCase
     
    12144        from subunit import IsolatedTestCase
    12245        from subunit import TestProtocolClient
    123 
     46        from subunit import ProtocolTestCase
     47
     48
     49class TestDiscardStream(unittest.TestCase):
     50
     51    def test_write(self):
     52        subunit.DiscardStream().write("content")
     53
     54
     55class 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       
    12478
    12579class TestTestProtocolServerPipe(unittest.TestCase):
     
    14195        an_error = subunit.RemotedTestCase("an error")
    14296        self.assertEqual(client.errors,
    143                          [(an_error, 'RemoteException: \n\n')])
     97                         [(an_error, _remote_exception_str + '\n')])
    14498        self.assertEqual(
    14599            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")])
    147103        self.assertEqual(client.testsRun, 3)
    148104
     105    def test_non_test_characters_forwarded_immediately(self):
     106        pass
     107
    149108
    150109class TestTestProtocolServerStartTest(unittest.TestCase):
    151110
    152111    def setUp(self):
    153         self.client = MockTestProtocolServerClient()
     112        self.client = Python26TestResult()
    154113        self.protocol = subunit.TestProtocolServer(self.client)
    155114
    156115    def test_start_test(self):
    157116        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"))])
    160119
    161120    def test_start_testing(self):
    162121        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"))])
    165124
    166125    def test_start_test_colon(self):
    167126        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)
    170133
    171134    def test_start_testing_colon(self):
    172135        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"))])
    175138
    176139
     
    178141
    179142    def setUp(self):
    180         from StringIO import StringIO
    181143        self.stdout = StringIO()
    182144        self.test = subunit.RemotedTestCase("old mcdonald")
    183         self.client = MockTestProtocolServerClient()
     145        self.client = ExtendedTestResult()
    184146        self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
    185147
     
    206168    def test_keywords_before_test(self):
    207169        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, [])
    212171
    213172    def test_keywords_after_error(self):
     
    215174        self.protocol.lineReceived("error old mcdonald\n")
    216175        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)
    223181
    224182    def test_keywords_after_failure(self):
     
    226184        self.protocol.lineReceived("failure old mcdonald\n")
    227185        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            ])
    234191
    235192    def test_keywords_after_success(self):
     
    237194        self.protocol.lineReceived("success old mcdonald\n")
    238195        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)
    244201
    245202    def test_keywords_after_test(self):
     
    266223                                                 "successful: a\n"
    267224                                                 "]\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            ])
    274230
    275231    def test_keywords_during_failure(self):
     232        # A smoke test to make sure that the details parsers have control
     233        # appropriately.
    276234        self.protocol.lineReceived("test old mcdonald\n")
    277235        self.protocol.lineReceived("failure: old mcdonald [\n")
     
    288246        self.protocol.lineReceived("]\n")
    289247        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            ])
    305267
    306268    def test_stdout_passthrough(self):
     
    316278
    317279    def setUp(self):
    318         self.client = MockTestProtocolServerClient()
     280        self.client = Python26TestResult()
    319281        self.protocol = subunit.TestProtocolServer(self.client)
    320282        self.test = subunit.RemotedTestCase("old mcdonald")
     
    322284    def test_lost_connection_no_input(self):
    323285        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)
    328287
    329288    def test_lost_connection_after_start(self):
    330289        self.protocol.lineReceived("test old mcdonald\n")
    331290        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)
    339298
    340299    def test_lost_connected_after_error(self):
     
    342301        self.protocol.lineReceived("error old mcdonald\n")
    343302        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)
    350321
    351322    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")
    362327
    363328    def test_lost_connected_after_failure(self):
     
    365330        self.protocol.lineReceived("failure old mcdonald\n")
    366331        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)
    374337
    375338    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")
    388343
    389344    def test_lost_connection_after_success(self):
     
    391346        self.protocol.lineReceived("success old mcdonald\n")
    392347        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
     373class TestInTestMultipart(unittest.TestCase):
    401374
    402375    def setUp(self):
    403         self.client = MockTestProtocolServerClient()
     376        self.client = ExtendedTestResult()
    404377        self.protocol = subunit.TestProtocolServer(self.client)
    405378        self.protocol.lineReceived("test mcdonalds farm\n")
    406379        self.test = subunit.RemotedTestCase("mcdonalds farm")
    407380
     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
     391class 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
    408399    def simple_error_keyword(self, keyword):
    409400        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)
    415407
    416408    def test_simple_error(self):
     
    423415        self.protocol.lineReceived("error mcdonalds farm [\n")
    424416        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)
    430425
    431426    def error_quoted_bracket(self, keyword):
     
    433428        self.protocol.lineReceived(" ]\n")
    434429        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)
    440438
    441439    def test_error_quoted_bracket(self):
     
    449447
    450448    def setUp(self):
    451         self.client = MockTestProtocolServerClient()
     449        self.client = ExtendedTestResult()
    452450        self.protocol = subunit.TestProtocolServer(self.client)
    453451        self.protocol.lineReceived("test mcdonalds farm\n")
    454452        self.test = subunit.RemotedTestCase("mcdonalds farm")
    455453
     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
    456461    def simple_failure_keyword(self, keyword):
    457462        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)
    463465
    464466    def test_simple_failure(self):
     
    471473        self.protocol.lineReceived("failure mcdonalds farm [\n")
    472474        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)
    478479
    479480    def failure_quoted_bracket(self, keyword):
     
    481482        self.protocol.lineReceived(" ]\n")
    482483        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)
    488488
    489489    def test_failure_quoted_bracket(self):
     
    494494
    495495
     496class 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
     612class 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
    496667class TestTestProtocolServerAddSuccess(unittest.TestCase):
    497668
    498669    def setUp(self):
    499         self.client = MockTestProtocolServerClient()
     670        self.client = ExtendedTestResult()
    500671        self.protocol = subunit.TestProtocolServer(self.client)
    501672        self.protocol.lineReceived("test mcdonalds farm\n")
     
    504675    def simple_success_keyword(self, keyword):
    505676        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)
    510682
    511683    def test_simple_success(self):
     
    520692    def test_simple_success_colon(self):
    521693        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
     728class 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
     762class 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
     800class 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)
    522822
    523823
     
    530830        self.assertEqual("A test description",
    531831                         test.shortDescription())
    532         self.assertEqual("subunit.RemotedTestCase.A test description",
     832        self.assertEqual("A test description",
    533833                         test.id())
    534834        self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
     
    537837        result = unittest.TestResult()
    538838        test.run(result)
    539         self.assertEqual([(test, "RemoteException: "
     839        self.assertEqual([(test, _remote_exception_str + ": "
    540840                                 "Cannot run RemotedTestCases.\n\n")],
    541841                         result.errors)
     
    551851
    552852    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!")
    556856        self.assertEqual(error, another_error)
    557857        self.assertNotEqual(error, different_error)
     
    559859
    560860    def test_empty_constructor(self):
    561         self.assertEqual(subunit.RemoteError(), subunit.RemoteError(""))
     861        self.assertEqual(subunit.RemoteError(), subunit.RemoteError(u""))
    562862
    563863
     
    571871            # that fails, errors and succeeds
    572872
     873        def test_sample_method_args(self):
     874            """sample-script.py foo"""
     875            # sample that will run just one test.
    573876
    574877    def test_construct(self):
     
    577880                         subunit.join_dir(__file__, 'sample-script.py'))
    578881
     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
    579888    def test_run(self):
    580         runner = MockTestProtocolServerClient()
     889        result = ExtendedTestResult()
    581890        test = self.SampleExecTestCase("test_sample_method")
    582         test.run(runner)
     891        test.run(result)
    583892        mcdonald = subunit.RemotedTestCase("old mcdonald")
    584893        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"])
    585897        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)
    594910
    595911    def test_debug(self):
     
    6901006        self.protocol = subunit.TestProtocolClient(self.io)
    6911007        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)
    6931013
    6941014    def test_start_test(self):
     
    6981018
    6991019    def test_stop_test(self):
    700         """Test stopTest on a TestProtocolClient."""
     1020        # stopTest doesn't output anything.
    7011021        self.protocol.stopTest(self.test)
    7021022        self.assertEqual(self.io.getvalue(), "")
     
    7081028            self.io.getvalue(), "successful: %s\n" % self.test.id())
    7091029
     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
    7101039    def test_add_failure(self):
    7111040        """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"))
    7131043        self.assertEqual(
    7141044            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())
    7161062
    7171063    def test_add_error(self):
    7181064        """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"))
    7201067        self.assertEqual(
    7211068            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"
    7241133            "]\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())
    7251177
    7261178
  • vendor/current/lib/talloc/pytalloc.c

    r414 r740  
    11/*
    22   Unix SMB/CIFS implementation.
    3    Python/Talloc glue
    4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
    5    
     3   Python Talloc Module
     4   Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010
     5
    66   This program is free software; you can redistribute it and/or modify
    77   it under the terms of the GNU General Public License as published by
    88   the Free Software Foundation; either version 3 of the License, or
    99   (at your option) any later version.
    10    
     10
    1111   This program is distributed in the hope that it will be useful,
    1212   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1313   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1414   GNU General Public License for more details.
    15    
     15
    1616   You should have received a copy of the GNU General Public License
    1717   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1818*/
    1919
    20 #include "replace.h"
     20#include <Python.h>
    2121#include <talloc.h>
    2222#include <pytalloc.h>
    2323
    24 /**
    25  * Simple dealloc for talloc-wrapping PyObjects
    26  */
    27 void py_talloc_dealloc(PyObject* self)
     24void inittalloc(void);
     25
     26/* print a talloc tree report for a talloc python object */
     27static PyObject *py_talloc_report_full(PyObject *self, PyObject *args)
    2828{
    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;
    3342}
    3443
    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 */
     45static PyObject *py_talloc_enable_null_tracking(PyObject *self)
    4046{
    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;
    5149}
    5250
     51/* return the number of talloc blocks */
     52static 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
     69static 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};
    5378
    5479/**
    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().
    5881 */
    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)
     82static PyObject *py_talloc_default_repr(PyObject *obj)
    7783{
    7884        py_talloc_Object *talloc_obj = (py_talloc_Object *)obj;
     
    8389}
    8490
    85 static void py_cobject_talloc_free(void *ptr)
     91/**
     92 * Simple dealloc for talloc-wrapping PyObjects
     93 */
     94static void py_talloc_dealloc(PyObject* self)
    8695{
    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);
    88100}
    89101
    90 PyObject *PyCObject_FromTallocPtr(void *ptr)
     102/**
     103 * Default (but only slightly more useful than the default) implementation of cmp.
     104 */
     105static int py_talloc_default_cmp(PyObject *_obj1, PyObject *_obj2)
    91106{
    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));
    93113}
     114
     115static 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
     125void 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  
    3030} py_talloc_Object;
    3131
    32 /* Deallocate a py_talloc_Object */
    33 void py_talloc_dealloc(PyObject* self);
     32PyTypeObject *PyTalloc_GetObjectType(void);
     33int PyTalloc_Check(PyObject *);
    3434
    3535/* Retrieve the pointer for a py_talloc_object. Like talloc_get_type()
     
    4444
    4545PyObject *py_talloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr);
     46PyObject *py_talloc_steal(PyTypeObject *py_type, void *ptr);
    4647PyObject *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)
    4848#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);
    5249
    5350#define py_talloc_new(type, typeobj) py_talloc_steal(typeobj, talloc_zero(NULL, type))
     
    5552PyObject *PyCObject_FromTallocPtr(void *);
    5653
     54PyObject *PyString_FromString_check_null(const char *ptr);
     55
    5756#endif /* _PY_TALLOC_H_ */
  • vendor/current/lib/talloc/script/mksigs.pl

    r414 r740  
    2828
    2929my $in_comment = 0;
     30my $in_doxygen = 0;
    3031my $extern_C_block = 0;
    3132
     
    4041                        next;
    4142                }
     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;
    4251        }
    4352
     
    6978                $LINE .= " " . $LINE2;
    7079        }
     80
     81        # remove DOXYGEN sections
     82        if ($LINE =~ /^#\s*ifdef\s+DOXYGEN(?:\s+.*)?$/) {
     83                $in_doxygen = 1;
     84                next;
     85        }
     86
    7187
    7288        # remove all preprocessor directives
  • vendor/current/lib/talloc/script/mksyms.awk

    r414 r740  
    99BEGIN {
    1010        inheader=0;
     11        indoxygen=0;
    1112}
    1213
     
    2122                next;
    2223        }
     24        if (indoxygen) {
     25                if (match($0,"^#[ \t]*else[ \t]*.*$")) {
     26                        indoxygen = 0;
     27                }
     28                next;
     29        }
    2330}
    2431
    25 /^static/ || /^[ \t]*typedef/ || !/^[a-zA-Z\_]/ {
     32/^static/ || /^[ \t]*typedef/ || !/^[a-zA-Z\_\#]/ {
    2633        next;
    2734}
     
    3441}
    3542
     43/^#[ \t]*ifdef[ \t]*DOXYGEN[ \t]*.*$/ {
     44        indoxygen=1;
     45        next;
     46}
     47
    3648# look for function headers:
    3749{
    3850        gotstart = 0;
    3951        if ($0 ~ /^[A-Za-z_][A-Za-z0-9_]+/) {
    40         gotstart = 1;
     52                gotstart = 1;
    4153        }
    4254        if(!gotstart) {
  • vendor/current/lib/talloc/script/release-script.sh

    r414 r740  
    11#!/bin/bash
     2
     3LNAME=talloc
     4LINCLUDE=talloc.h
    25
    36if [ "$1" = "" ]; then
     
    69fi
    710
    8 if [ ! -d "lib/talloc" ]; then
     11if [ ! -d "lib/${LNAME}" ]; then
    912    echo "Run this script from the samba base directory."
    1013    exit 1
    1114fi
    12 
    13 # Check exports and signatures are up to date
    14 pushd lib/talloc
    15 ./script/abi_checks.sh talloc talloc.h
    16 abicheck=$?
    17 popd
    18 if [ ! "$abicheck" = "0" ]; then
    19     echo "ERROR: ABI Checks produced warnings!"
    20     exit 1
    21 fi
    22 
    23 git clean -f -x -d lib/talloc
    24 git clean -f -x -d lib/replace
    2515
    2616curbranch=`git branch |grep "^*" | tr -d "* "`
     
    3020
    3121# Checkout the release tag
    32 git branch -f talloc-release-script-${strver} talloc-${strver}
     22git branch -f ${LNAME}-release-script-${strver} ${LNAME}-${strver}
    3323if [ ! "$?" = "0" ];  then
    34     echo "Unable to checkout talloc-${strver} release"
     24    echo "Unable to checkout ${LNAME}-${strver} release"
    3525    exit 1
    3626fi
    3727
    38 git checkout talloc-release-script-${strver}
     28function 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
     36git checkout ${LNAME}-release-script-${strver}
    3937
    4038# Test configure agrees with us
    41 confver=`grep "^AC_INIT" lib/talloc/configure.ac | tr -d "AC_INIT(talloc, " | tr -d ")"`
     39confver=`grep "^AC_INIT" lib/${LNAME}/configure.ac | tr -d "AC_INIT(${LNAME}, " | tr -d ")"`
    4240if [ ! "$confver" = "$version" ]; then
    4341    echo "Wrong version, requested release for ${version}, found ${confver}"
    44     exit 1
     42    cleanquit 1
    4543fi
    4644
     45# Check exports and signatures are up to date
     46pushd lib/${LNAME}
     47./script/abi_checks.sh ${LNAME} ${LINCLUDE}
     48abicheck=$?
     49popd
     50if [ ! "$abicheck" = "0" ]; then
     51    echo "ERROR: ABI Checks produced warnings!"
     52    cleanquit 1
     53fi
     54
     55git clean -f -x -d lib/${LNAME}
     56git clean -f -x -d lib/replace
     57
    4758# Now build tarball
    48 cp -a lib/talloc talloc-${version}
    49 cp -a lib/replace talloc-${version}/libreplace
    50 pushd talloc-${version}
     59cp -a lib/${LNAME} ${LNAME}-${version}
     60cp -a lib/replace ${LNAME}-${version}/libreplace
     61pushd ${LNAME}-${version}
    5162./autogen.sh
    5263popd
    53 tar cvzf talloc-${version}.tar.gz talloc-${version}
    54 rm -fr talloc-${version}
     64tar cvzf ${LNAME}-${version}.tar.gz ${LNAME}-${version}
     65rm -fr ${LNAME}-${version}
    5566
    56 #Clean up
    57 git checkout $curbranch
    58 git branch -d talloc-release-script-${strver}
     67cleanquit 0
     68
  • vendor/current/lib/talloc/talloc.3.xml

    r414 r740  
    1111  </refnamediv>
    1212  <refsynopsisdiv>
    13 <synopsis>#include &lt;talloc/talloc.h&gt;</synopsis>
     13<synopsis>#include &lt;talloc.h&gt;</synopsis>
    1414  </refsynopsisdiv>
    1515  <refsect1><title>DESCRIPTION</title>
     
    363363        <para>
    364364          This is a utility macro that creates a new memory context hanging
    365           off an exiting context, automatically naming it "talloc_new:
     365          off an existing context, automatically naming it "talloc_new:
    366366          __location__" where __location__ is the source line it is called
    367367          from.  It is particularly useful for creating a new temporary
     
    646646        <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
    647647    </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 formatted
    651           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).
    652652        </para>
    653653        <para>
     
    657657        <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
    658658    </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.
    663674        </para>
    664675        <para>
     
    668679        <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
    669680    </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>
    693682        <para>
    694683          The talloc_array() macro is equivalent to:
     
    700689        </para>
    701690    </refsect2>
    702     <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, uint_t count);</title>
     691    <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, unsigned int count);</title>
    703692        <para>
    704693          The talloc_array_size() function is useful when the type is not
     
    707696        </para>
    708697    </refsect2>
    709     <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);</title>
     698    <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);</title>
    710699        <para>
    711700          The talloc_ptrtype() macro should be used when you have a pointer to an array
  • vendor/current/lib/talloc/talloc.c

    r414 r740  
    4646#endif
    4747
     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
    4857/* use this to force every realloc to change the pointer, to stress test
    4958   code that might not cope */
     
    104113static void *null_context;
    105114static 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 */
     119static 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)
    106223
    107224struct talloc_reference_handle {
     
    137254
    138255/* 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))
    140258#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
    141259
    142 int talloc_version_major(void)
     260_PUBLIC_ int talloc_version_major(void)
    143261{
    144262        return TALLOC_VERSION_MAJOR;
    145263}
    146264
    147 int talloc_version_minor(void)
     265_PUBLIC_ int talloc_version_minor(void)
    148266{
    149267        return TALLOC_VERSION_MINOR;
     
    152270static void (*talloc_log_fn)(const char *message);
    153271
    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))
    155273{
    156274        talloc_log_fn = log_fn;
     
    180298}
    181299
    182 void talloc_set_log_stderr(void)
     300_PUBLIC_ void talloc_set_log_stderr(void)
    183301{
    184302        talloc_set_log_fn(talloc_log_stderr);
     
    187305static void (*talloc_abort_fn)(const char *reason);
    188306
    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))
    190308{
    191309        talloc_abort_fn = abort_fn;
     
    214332}
    215333
    216 static void talloc_abort_double_free(void)
    217 {
    218         talloc_abort("Bad talloc magic value - double free");
     334static void talloc_abort_access_after_free(void)
     335{
     336        talloc_abort("Bad talloc magic value - access after free");
    219337}
    220338
     
    236354
    237355                if (tc->flags & TALLOC_FLAG_FREE) {
    238                         talloc_log("talloc: double free 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();
    240358                        return NULL;
    241359                } else {
     
    292410}
    293411
    294 void *talloc_parent(const void *ptr)
     412_PUBLIC_ void *talloc_parent(const void *ptr)
    295413{
    296414        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
     
    301419  find parents name
    302420*/
    303 const char *talloc_parent_name(const void *ptr)
     421_PUBLIC_ const char *talloc_parent_name(const void *ptr)
    304422{
    305423        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
     
    322440#define TALLOC_POOL_HDR_SIZE 16
    323441
     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
    324480static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
    325481{
    326         return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
     482        return (unsigned int *)((char *)tc + TC_HDR_SIZE);
    327483}
    328484
     
    354510        }
    355511
    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);
    358513
    359514        /*
    360515         * Align size to 16 bytes
    361516         */
    362         chunk_size = ((size + 15) & ~15);
     517        chunk_size = TC_ALIGN16(size);
    363518
    364519        if (space_left < chunk_size) {
     
    439594 */
    440595
    441 void *talloc_pool(const void *context, size_t size)
     596_PUBLIC_ void *talloc_pool(const void *context, size_t size)
    442597{
    443598        void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
     
    451606
    452607        tc->flags |= TALLOC_FLAG_POOL;
    453         tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
     608        tc->pool = TC_POOL_FIRST_CHUNK(tc);
    454609
    455610        *talloc_pool_objectcount(tc) = 1;
    456611
    457 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
    458         VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
    459 #endif
     612        TC_INVALIDATE_POOL(tc);
    460613
    461614        return result;
     
    468621  be continued to be used
    469622*/
    470 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
     623_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
    471624{
    472625        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    477630  increase the reference count on a piece of memory.
    478631*/
    479 int talloc_increase_ref_count(const void *ptr)
     632_PUBLIC_ int talloc_increase_ref_count(const void *ptr)
    480633{
    481634        if (unlikely(!talloc_reference(null_context, ptr))) {
     
    533686  and in either order
    534687*/
    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)
    536689{
    537690        struct talloc_chunk *tc;
     
    557710static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
    558711
     712static 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
     771static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
     772                                                  void *ptr,
     773                                                  const char *location);
     774
    559775/*
    560776   internal talloc_free call
     
    568784        }
    569785
     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
    570796        tc = talloc_chunk_from_ptr(ptr);
    571797
    572798        if (unlikely(tc->refs)) {
    573799                int is_child;
    574                 /* check this is a reference from a child or grantchild
    575                  * back to it's parent or grantparent
     800                /* check if this is a reference from a child or
     801                 * grandchild back to it's parent or grandparent
    576802                 *
    577803                 * in that case we need to remove the reference and
     
    617843        tc->flags |= TALLOC_FLAG_LOOP;
    618844
    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);
    639846
    640847        tc->flags |= TALLOC_FLAG_FREE;
     
    646853        tc->name = location;
    647854
    648         if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
    649                 struct talloc_chunk *pool;
     855        if (tc->flags & TALLOC_FLAG_POOL) {
    650856                unsigned int *pool_object_count;
    651857
    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)) {
    658861                        talloc_abort("Pool object count zero!");
    659862                        return 0;
     
    662865                *pool_object_count -= 1;
    663866
    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);
    669875                free(tc);
    670876        }
     
    734940   passing NULL as ptr will always return NULL with no side effects.
    735941*/
    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)
    737943{
    738944        struct talloc_chunk *tc;
     
    755961                }
    756962        }
     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
    757971       
    758972        return _talloc_steal_internal(new_ctx, ptr);
     
    766980   The old parent can be either a reference or a parent
    767981*/
    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)
    769983{
    770984        struct talloc_chunk *tc;
     
    8261040  controlled varient of talloc_free()
    8271041*/
    828 int talloc_unlink(const void *context, void *ptr)
     1042_PUBLIC_ int talloc_unlink(const void *context, void *ptr)
    8291043{
    8301044        struct talloc_chunk *tc_p, *new_p;
     
    8931107  add a name to an existing pointer
    8941108*/
    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, ...)
    8961110{
    8971111        const char *name;
     
    9091123  to name the pointer.
    9101124*/
    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, ...)
    9121126{
    9131127        va_list ap;
     
    9331147  return the name of a talloc ptr, or "UNNAMED"
    9341148*/
    935 const char *talloc_get_name(const void *ptr)
     1149_PUBLIC_ const char *talloc_get_name(const void *ptr)
    9361150{
    9371151        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    9501164  otherwise return NULL
    9511165*/
    952 void *talloc_check_name(const void *ptr, const char *name)
     1166_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
    9531167{
    9541168        const char *pname;
     
    9791193}
    9801194
    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)
    9821196{
    9831197        const char *pname;
     
    10001214  this is for compatibility with older versions of talloc
    10011215*/
    1002 void *talloc_init(const char *fmt, ...)
     1216_PUBLIC_ void *talloc_init(const char *fmt, ...)
    10031217{
    10041218        va_list ap;
     
    10061220        const char *name;
    10071221
    1008         /*
    1009          * samba3 expects talloc_report_depth_cb(NULL, ...)
    1010          * reports all talloc'ed memory, so we need to enable
    1011          * null_tracking
    1012          */
    1013         talloc_enable_null_tracking();
    1014 
    10151222        ptr = __talloc(NULL, 0);
    10161223        if (unlikely(ptr == NULL)) return NULL;
     
    10281235}
    10291236
    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 
     1237static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
     1238                                                  void *ptr,
     1239                                                  const char *location)
     1240{
    10451241        while (tc->child) {
    10461242                /* we need to work out who will own an abandoned child
     
    10511247                void *child = TC_PTR_FROM_CHUNK(tc->child);
    10521248                const void *new_parent = null_context;
     1249                struct talloc_chunk *old_parent = NULL;
    10531250                if (unlikely(tc->child->refs)) {
    10541251                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
    10551252                        if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    10561253                }
    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)) {
    10581269                        if (new_parent == null_context) {
    1059                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
     1270                                struct talloc_chunk *p = old_parent;
    10601271                                if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    10611272                        }
     
    10631274                }
    10641275        }
    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__);
    10741294}
    10751295
     
    10771297   Allocate a bit of memory as a child of an existing pointer
    10781298*/
    1079 void *_talloc(const void *context, size_t size)
     1299_PUBLIC_ void *_talloc(const void *context, size_t size)
    10801300{
    10811301        return __talloc(context, size);
     
    10851305  externally callable talloc_set_name_const()
    10861306*/
    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)
    10881308{
    10891309        _talloc_set_name_const(ptr, name);
     
    10951315  to name the pointer.
    10961316*/
    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)
    10981318{
    10991319        return _talloc_named_const(context, size, name);
     
    11081328   any) returns non-zero
    11091329*/
    1110 int _talloc_free(void *ptr, const char *location)
     1330_PUBLIC_ int _talloc_free(void *ptr, const char *location)
    11111331{
    11121332        struct talloc_chunk *tc;
     
    11211341                struct talloc_reference_handle *h;
    11221342
     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
    11231350                talloc_log("ERROR: talloc_free with references at %s\n",
    11241351                           location);
     
    11401367  ptr is NULL
    11411368*/
    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)
    11431370{
    11441371        struct talloc_chunk *tc;
    11451372        void *new_ptr;
    11461373        bool malloced = false;
     1374        struct talloc_chunk *pool_tc = NULL;
    11471375
    11481376        /* size zero is equivalent to free() */
     
    11731401        }
    11741402
     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)
    11751409        /* 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                 */
    11781439                return ptr;
    11791440        }
     1441#endif
    11801442
    11811443        /* by resetting magic we catch users of the old memory */
     
    11831445
    11841446#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) {
    11931448                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;
    11961450
    11971451                if (new_ptr == NULL) {
     
    12021456                if (new_ptr) {
    12031457                        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");
    12041561                }
    12051562        }
     
    12071564                new_ptr = realloc(tc, size + TC_HDR_SIZE);
    12081565        }
     1566got_new_ptr:
    12091567#endif
    12101568        if (unlikely(!new_ptr)) {       
     
    12421600  between two structures, and want the old pointer to be set to NULL
    12431601*/
    1244 void *_talloc_move(const void *new_ctx, const void *_pptr)
     1602_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
    12451603{
    12461604        const void **pptr = discard_const_p(const void *,_pptr);
     
    12531611  return the total size of a talloc pool (subtree)
    12541612*/
    1255 size_t talloc_total_size(const void *ptr)
     1613_PUBLIC_ size_t talloc_total_size(const void *ptr)
    12561614{
    12571615        size_t total = 0;
     
    12881646  return the total number of blocks in a talloc pool (subtree)
    12891647*/
    1290 size_t talloc_total_blocks(const void *ptr)
     1648_PUBLIC_ size_t talloc_total_blocks(const void *ptr)
    12911649{
    12921650        size_t total = 0;
     
    13211679  return the number of external references to a pointer
    13221680*/
    1323 size_t talloc_reference_count(const void *ptr)
     1681_PUBLIC_ size_t talloc_reference_count(const void *ptr)
    13241682{
    13251683        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    13361694  report on memory usage by all children of a pointer, giving a full tree view
    13371695*/
    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,
    13391697                            void (*callback)(const void *ptr,
    13401698                                             int depth, int max_depth,
     
    14201778  report on memory usage by all children of a pointer, giving a full tree view
    14211779*/
    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)
    14231781{
    14241782        if (f) {
     
    14311789  report on memory usage by all children of a pointer, giving a full tree view
    14321790*/
    1433 void talloc_report_full(const void *ptr, FILE *f)
     1791_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
    14341792{
    14351793        talloc_report_depth_file(ptr, 0, -1, f);
     
    14391797  report on memory usage by all children of a pointer
    14401798*/
    1441 void talloc_report(const void *ptr, FILE *f)
     1799_PUBLIC_ void talloc_report(const void *ptr, FILE *f)
    14421800{
    14431801        talloc_report_depth_file(ptr, 0, 1, f);
     
    14671825  enable tracking of the NULL context
    14681826*/
    1469 void talloc_enable_null_tracking(void)
     1827_PUBLIC_ void talloc_enable_null_tracking(void)
    14701828{
    14711829        if (null_context == NULL) {
     
    14811839  into the NULL context. This is needed for the talloc testsuite
    14821840*/
    1483 void talloc_enable_null_tracking_no_autofree(void)
     1841_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
    14841842{
    14851843        if (null_context == NULL) {
     
    14911849  disable tracking of the NULL context
    14921850*/
    1493 void talloc_disable_null_tracking(void)
     1851_PUBLIC_ void talloc_disable_null_tracking(void)
    14941852{
    14951853        if (null_context != NULL) {
     
    15161874  enable leak reporting on exit
    15171875*/
    1518 void talloc_enable_leak_report(void)
     1876_PUBLIC_ void talloc_enable_leak_report(void)
    15191877{
    15201878        talloc_enable_null_tracking();
     
    15251883  enable full leak reporting on exit
    15261884*/
    1527 void talloc_enable_leak_report_full(void)
     1885_PUBLIC_ void talloc_enable_leak_report_full(void)
    15281886{
    15291887        talloc_enable_null_tracking();
     
    15341892   talloc and zero memory.
    15351893*/
    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)
    15371895{
    15381896        void *p = _talloc_named_const(ctx, size, name);
     
    15481906  memdup with a talloc.
    15491907*/
    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)
    15511909{
    15521910        void *newp = _talloc_named_const(t, size, name);
     
    15761934  strdup with a talloc
    15771935*/
    1578 char *talloc_strdup(const void *t, const char *p)
     1936_PUBLIC_ char *talloc_strdup(const void *t, const char *p)
    15791937{
    15801938        if (unlikely(!p)) return NULL;
     
    15851943  strndup with a talloc
    15861944*/
    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)
    15881946{
    15891947        if (unlikely(!p)) return NULL;
     
    16101968 * Appends at the end of the string.
    16111969 */
    1612 char *talloc_strdup_append(char *s, const char *a)
     1970_PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
    16131971{
    16141972        if (unlikely(!s)) {
     
    16271985 * not the end of the string.
    16281986 */
    1629 char *talloc_strdup_append_buffer(char *s, const char *a)
     1987_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
    16301988{
    16311989        size_t slen;
     
    16502008 * Appends at the end of the string.
    16512009 */
    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)
    16532011{
    16542012        if (unlikely(!s)) {
     
    16672025 * not the end of the string.
    16682026 */
    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)
    16702028{
    16712029        size_t slen;
     
    16952053#endif
    16962054
    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)
    16982056{
    16992057        int len;
     
    17262084  memory holding the result, inside a memory pool.
    17272085 */
    1728 char *talloc_asprintf(const void *t, const char *fmt, ...)
     2086_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
    17292087{
    17302088        va_list ap;
     
    17792137 * of the string.
    17802138 **/
    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)
    17822140{
    17832141        if (unlikely(!s)) {
     
    17932151 * end of the talloc'ed buffer, not the end of the string.
    17942152 **/
    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)
    17962154{
    17972155        size_t slen;
     
    18142172  into a string buffer.
    18152173 */
    1816 char *talloc_asprintf_append(char *s, const char *fmt, ...)
     2174_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
    18172175{
    18182176        va_list ap;
     
    18292187  into a buffer.
    18302188 */
    1831 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
     2189_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
    18322190{
    18332191        va_list ap;
     
    18422200  alloc an array, checking for integer overflow in the array size
    18432201*/
    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)
    18452203{
    18462204        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18532211  alloc an zero array, checking for integer overflow in the array size
    18542212*/
    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)
    18562214{
    18572215        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18642222  realloc an array, checking for integer overflow in the array size
    18652223*/
    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)
    18672225{
    18682226        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18772235  all the basic capabilities of an allocation library, which is why this is useful)
    18782236*/
    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)
    18802238{
    18812239        return _talloc_realloc(context, ptr, size, NULL);
     
    18982256  this is useful for reducing the noise in leak reports
    18992257*/
    1900 void *talloc_autofree_context(void)
     2258_PUBLIC_ void *talloc_autofree_context(void)
    19012259{
    19022260        if (autofree_context == NULL) {
     
    19082266}
    19092267
    1910 size_t talloc_get_size(const void *context)
     2268_PUBLIC_ size_t talloc_get_size(const void *context)
    19112269{
    19122270        struct talloc_chunk *tc;
     
    19272285  find a parent of this context that has the given name, if any
    19282286*/
    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)
    19302288{
    19312289        struct talloc_chunk *tc;
     
    19512309  show the parentage of a context
    19522310*/
    1953 void talloc_show_parents(const void *context, FILE *file)
     2311_PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
    19542312{
    19552313        struct talloc_chunk *tc;
     
    19752333  return 1 if ptr is a parent of context
    19762334*/
    1977 int talloc_is_parent(const void *context, const void *ptr)
     2335static int _talloc_is_parent(const void *context, const void *ptr, int depth)
    19782336{
    19792337        struct talloc_chunk *tc;
     
    19842342
    19852343        tc = talloc_chunk_from_ptr(context);
    1986         while (tc) {
     2344        while (tc && depth > 0) {
    19872345                if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
    19882346                while (tc && tc->prev) tc = tc->prev;
    19892347                if (tc) {
    19902348                        tc = tc->parent;
     2349                        depth--;
    19912350                }
    19922351        }
    19932352        return 0;
    19942353}
     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  
    3030#include <stdarg.h>
    3131
     32#ifdef __cplusplus
     33extern "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
    3245#define TALLOC_VERSION_MAJOR 2
    3346#define TALLOC_VERSION_MINOR 0
     
    3649int talloc_version_minor(void);
    3750
    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 */
    3974typedef void TALLOC_CTX;
    4075
     
    65100#endif
    66101
     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 */
     136void *talloc(const void *ctx, #type);
     137#else
     138#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
     139void *_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 */
     159void *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 */
     224int talloc_free(void *ptr);
     225#else
     226#define talloc_free(ctx) _talloc_free(ctx, __location__)
     227int _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 */
     238void 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 */
     294void 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 */
     334void *talloc_steal(const void *new_ctx, const void *ptr);
     335#else /* DOXYGEN */
    67336/* try to make talloc_set_destructor() and talloc_steal() type safe,
    68337   if we have a recent gcc */
     
    77346   stupidity in gcc 4.1.x */
    78347#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 */
    80349#define talloc_set_destructor(ptr, function) \
    81350        _talloc_set_destructor((ptr), (int (*)(void *))(function))
    82351#define _TALLOC_TYPEOF(ptr) void *
    83352#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 */
     354void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
     355void *_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 */
     388const 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 */
     410void *talloc_move(const void *new_ctx, const void *ptr);
     411#else
    87412#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)
     413void *_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 */
     432void 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 */
     457void *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 */
     478void *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 */
     501void *talloc_size(const void *ctx, size_t size);
     502#else
    91503#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 */
     528void *talloc_ptrtype(const void *ctx, #type);
     529#else
    92530#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 */
     546void *talloc_new(const void *ctx);
     547#else
    94548#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 */
     580void *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 */
     591void *talloc_zero_size(const void *ctx, size_t size);
     592#else
    96593#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
    97594#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 
     595void *_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 */
     607const 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 */
     621void *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 */
     630void *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 */
     639const 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 */
     655size_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 */
     672size_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 */
     695void *talloc_memdup(const void *t, const void *p, size_t size);
     696#else
    108697#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
    109 
     698void *_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 */
     719void 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 */
     738type *talloc_get_type(const void *ptr, #type);
     739#else
    110740#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
    111741#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 */
     759void *talloc_get_type_abort(const void *ptr, #type);
     760#else
    112761#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
    113 
     762void *_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 */
     780void *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 */
     800void *talloc_find_parent_bytype(const void *ptr, #type);
     801#else
    114802#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 */
     841void *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 */
     881int 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 */
     890size_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 */
     932void *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__)
     935void *_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 */
     970int 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 */
     990void *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 */
     1003size_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 */
     1012void 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 */
     1025int 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 */
     1045void *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 */
     1090void *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)
     1093void *_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 */
     1108void *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 */
     1132void *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 */
     1148size_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 */
     1172void *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)
     1175void *_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 */
     1212void *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)
     1215void *_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 */
     1233void *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__)
     1236void *_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 */
     1256void *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 */
     1291char *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 */
     1304char *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 */
     1317char *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 */
     1339char *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 */
     1356char *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 */
     1373char *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 */
     1396char *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 */
     1412char *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 */
     1428char *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 */
     1450char *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 */
     1474char *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 */
     1487char *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 */
     1527void 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 */
     1548void 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 */
     1578void 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 */
     1606void 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 */
     1615void 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 */
     1624void 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 */
     1631void 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 */
     1659void 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 */
     1687void talloc_enable_leak_report_full(void);
     1688
     1689/* @} ******************************************************************/
     1690
     1691void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
     1692void talloc_set_log_fn(void (*log_fn)(const char *message));
     1693void talloc_set_log_stderr(void);
    1171694
    1181695#if TALLOC_DEPRECATED
     
    1251702#endif
    1261703
    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  
    77Description: A hierarchical pool based memory system with destructors
    88Version: @TALLOC_VERSION@
    9 Libs: -L${libdir} -ltalloc
     9Libs: @LIB_RPATH@ -L${libdir} -ltalloc
    1010Cflags: -I${includedir}
    1111URL: http://talloc.samba.org/
  • vendor/current/lib/talloc/talloc_guide.txt

    r414 r740  
    7575synchronization.
    7676
     77talloc and shared objects
     78-------------------------
     79
     80talloc can be used in shared objects. Special care needs to be taken
     81to never use talloc_autofree_context() in code that might be loaded
     82with dlopen() and unloaded with dlclose(), as talloc_autofree_context()
     83internally uses atexit(3). Some platforms like modern Linux handles
     84this fine, but for example FreeBSD does not deal well with dlopen()
     85and atexit() used simultaneously: dlclose() does not clean up the list
     86of atexit-handlers, so when the program exits the code that was
     87registered from within talloc_autofree_context() is gone, the program
     88crashes at exit.
     89
    7790
    7891=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
     
    118131
    119132The 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.
     133returned for success and -1 for failure. A possible failure condition
     134is if the pointer had a destructor attached to it and the destructor
     135returned -1. See talloc_set_destructor() for details on
     136destructors. Likewise, if "ptr" is NULL, then the function will make
     137no modifications and returns -1.
    124138
    125139If this pointer has an additional parent when talloc_free() is called
     
    653667
    654668=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    655 ((type *)talloc_array(const void *ctx, type, uint_t count);
     669((type *)talloc_array(const void *ctx, type, unsigned int count);
    656670
    657671The talloc_array() macro is equivalent to::
     
    664678
    665679=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    666 void *talloc_array_size(const void *ctx, size_t size, uint_t count);
     680void *talloc_array_size(const void *ctx, size_t size, unsigned int count);
    667681
    668682The talloc_array_size() function is useful when the type is not
     
    671685
    672686=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    673 (typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);
     687(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);
    674688
    675689The talloc_ptrtype() macro should be used when you have a pointer to an array
  • vendor/current/lib/talloc/testsuite.c

    r414 r740  
    2626#include "replace.h"
    2727#include "system/time.h"
    28 #include "talloc.h"
     28#include <talloc.h>
     29
     30#include "talloc_testsuite.h"
    2931
    3032static struct timeval timeval_current(void)
     
    102104static unsigned int test_abort_count;
    103105
     106#if 0
    104107static void test_abort_fn(const char *reason)
    105108{
     
    113116        talloc_set_abort_fn(test_abort_fn);
    114117}
     118#endif
    115119
    116120static void test_abort_stop(void)
     
    11201124        void *pool;
    11211125        void *p1, *p2, *p3, *p4;
     1126        void *p2_2;
    11221127
    11231128        pool = talloc_pool(NULL, 1024);
    11241129
    11251130        p1 = talloc_size(pool, 80);
     1131        memset(p1, 0x11, talloc_get_size(p1));
    11261132        p2 = talloc_size(pool, 20);
     1133        memset(p2, 0x11, talloc_get_size(p2));
    11271134        p3 = talloc_size(p1, 50);
     1135        memset(p3, 0x11, talloc_get_size(p3));
    11281136        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 */
    11291205
    11301206        talloc_free(pool);
     
    11321208        return true;
    11331209}
     1210
     1211static 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
     1279static 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
     1309static 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
    11341323
    11351324static void test_reset(void)
     
    11411330}
    11421331
    1143 struct torture_context;
    11441332bool torture_local_talloc(struct torture_context *tctx)
    11451333{
     
    11861374        test_reset();
    11871375        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();
    11881382
    11891383        if (ret) {
     
    11951389
    11961390        test_reset();
    1197 
     1391        talloc_disable_null_tracking();
    11981392        return ret;
    11991393}
  • vendor/current/lib/talloc/testsuite_main.c

    r414 r740  
    2626#include "replace.h"
    2727
    28 struct torture_context;
    29 bool torture_local_talloc(struct torture_context *tctx);
     28#include "talloc_testsuite.h"
    3029
    3130int main(void)
  • vendor/current/lib/tdb/common/check.c

    r414 r740  
    2929{
    3030        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)
    3334                return false;
    3435        if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0)
     
    3940                goto corrupt;
    4041
    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))
    4248                goto corrupt;
    4349
     
    302308}
    303309
    304 int tdb_check(struct tdb_context *tdb,
     310/* Slow, but should be very rare. */
     311size_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,
    305326              int (*check)(TDB_DATA key, TDB_DATA data, void *private_data),
    306327              void *private_data)
     
    311332        struct tdb_record rec;
    312333        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        }
    316346
    317347        /* Make sure we know true size of the underlying file. */
     
    370400                                goto free;
    371401                        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;
    372418                case TDB_RECOVERY_MAGIC:
    373                 case 0: /* Used for invalid (or in-progress) recovery area. */
    374419                        if (recovery_start != off) {
    375420                                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    380425                        found_recovery = true;
    381426                        break;
    382                 default:
     427                default: ;
     428                corrupt:
    383429                        tdb->ecode = TDB_ERR_CORRUPT;
    384430                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    406452        if (recovery_start != 0 && !found_recovery) {
    407453                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));
    411456                goto free;
    412457        }
    413458
    414459        free(hashes);
    415         tdb_unlockall(tdb);
     460        if (locked) {
     461                tdb_unlockall_read(tdb);
     462        }
    416463        return 0;
    417464
     
    419466        free(hashes);
    420467unlock:
    421         tdb_unlockall(tdb);
     468        if (locked) {
     469                tdb_unlockall_read(tdb);
     470        }
    422471        return -1;
    423472}
  • vendor/current/lib/tdb/common/dump.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    8181}
    8282
    83 void tdb_dump_all(struct tdb_context *tdb)
     83_PUBLIC_ void tdb_dump_all(struct tdb_context *tdb)
    8484{
    8585        int i;
     
    9191}
    9292
    93 int tdb_printfreelist(struct tdb_context *tdb)
     93_PUBLIC_ int tdb_printfreelist(struct tdb_context *tdb)
    9494{
    9595        int ret;
  • vendor/current/lib/tdb/common/error.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 enum TDB_ERROR tdb_error(struct tdb_context *tdb)
     30_PUBLIC_ enum TDB_ERROR tdb_error(struct tdb_context *tdb)
    3131{
    3232        return tdb->ecode;
     
    4747
    4848/* 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)
    5050{
    5151        uint32_t i;
  • vendor/current/lib/tdb/common/freelist.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    9999
    100100/* Add an element into the freelist. Merge adjacent records if
    101    neccessary. */
     101   necessary. */
    102102int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec)
    103103{
     
    144144                struct tdb_record l;
    145145                tdb_off_t leftsize;
    146                
     146
    147147                /* Read in tailer and jump back to header */
    148148                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
     
    335335                        break;
    336336                }
    337                
     337
    338338                /* this multiplier means we only extremely rarely
    339339                   search more than 50 or so records. At 50 records we
     
    368368   return the size of the freelist - used to decide if we should repack
    369369*/
    370 int tdb_freelist_size(struct tdb_context *tdb)
     370_PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb)
    371371{
    372372        tdb_off_t ptr;
  • vendor/current/lib/tdb/common/freelistcheck.c

    r414 r740  
    4444}
    4545
    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)
    4747{
    4848        struct tdb_context *mem_tdb = NULL;
  • vendor/current/lib/tdb/common/io.c

    r597 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    477477        tdb_oob,
    478478        tdb_expand_file,
    479         tdb_brlock
    480479};
    481480
  • vendor/current/lib/tdb/common/lock.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    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)
    3331{
    3432        tdb->interrupt_sig_ptr = ptr;
     33}
     34
     35static 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
     52static 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. */
     123static tdb_off_t lock_offset(int list)
     124{
     125        return FREELIST_TOP + 4*list;
    35126}
    36127
     
    43134   note that a len of zero means lock to end of file
    44135*/
    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;
     136int tdb_brlock(struct tdb_context *tdb,
     137               int rw_type, tdb_off_t offset, size_t len,
     138               enum tdb_lock_flags flags)
     139{
    49140        int ret;
    50141
    51142        if (tdb->flags & TDB_NOLOCK) {
     143                return 0;
     144        }
     145
     146        if (flags & TDB_LOCK_MARK_ONLY) {
    52147                return 0;
    53148        }
     
    58153        }
    59154
    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 
    66155        do {
    67                 ret = fcntl(tdb->fd,lck_type,&fl);
    68 
     156                ret = fcntl_lock(tdb, rw_type, offset, len,
     157                                 flags & TDB_LOCK_WAIT);
    69158                /* Check for a sigalarm break. */
    70159                if (ret == -1 && errno == EINTR &&
     
    80169                 * EAGAIN is an expected return from non-blocking
    81170                 * 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));
    85174                }
    86175                return -1;
     
    89178}
    90179
     180int 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}
    91199
    92200/*
     
    96204  made. For those OSes we may loop for a while. 
    97205*/
    98 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
     206int tdb_allrecord_upgrade(struct tdb_context *tdb)
    99207{
    100208        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
    101223        while (count--) {
    102224                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;
    104229                        return 0;
    105230                }
     
    112237                select(0, NULL, NULL, NULL, &tv);
    113238        }
    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"));
    115240        return -1;
    116241}
    117242
    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)
     243static 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. */
     257int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     258                  enum tdb_lock_flags flags)
    121259{
    122260        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));
    143266                return -1;
    144267        }
     
    146269                return 0;
    147270
    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;
    165279        }
    166280
     
    176290        /* Since fcntl locks don't nest, we do a lock for the first one,
    177291           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;
    187297        tdb->lockrecs[tdb->num_lockrecs].count = 1;
    188298        tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
    189         tdb->num_lockrecs += 1;
     299        tdb->num_lockrecs++;
    190300
    191301        return 0;
     302}
     303
     304static 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
     326static 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
     337static 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;
    192367}
    193368
     
    196371{
    197372        int ret;
    198         ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
     373
     374        ret = tdb_lock_list(tdb, list, ltype, TDB_LOCK_WAIT);
    199375        if (ret) {
    200376                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
     
    207383int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
    208384{
    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
     389int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     390                    bool mark_lock)
    217391{
    218392        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;
    235394
    236395        if (tdb->flags & TDB_NOLOCK)
     
    238397
    239398        /* 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));
    242401                return ret;
    243402        }
    244403
    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);
    252405        if ((lck == NULL) || (lck->count == 0)) {
    253406                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
     
    270423                ret = 0;
    271424        } 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        }
    276427
    277428        /*
     
    279430         * last array element.
    280431         */
    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];
    286433
    287434        /*
     
    299446}
    300447
     448int 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
    301464/*
    302465  get the transaction lock
    303466 */
    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;
     467int 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);
    322471}
    323472
     
    325474  release the transaction lock
    326475 */
    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 
     476int 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. */
     482static int tdb_allrecord_check(struct tdb_context *tdb, int ltype,
     483                               enum tdb_lock_flags flags, bool upgradable)
     484{
    354485        /* There are no locks on read-only dbs */
    355486        if (tdb->read_only || tdb->traverse_read) {
     
    358489        }
    359490
    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) {
    366497                /* a global lock of a different type exists */
    367498                tdb->ecode = TDB_ERR_LOCK;
    368499                return -1;
    369500        }
    370        
    371         if (tdb->num_locks != 0) {
     501
     502        if (tdb_have_extra_locks(tdb)) {
    372503                /* can't combine global and chain locks */
    373504                tdb->ecode = TDB_ERR_LOCK;
     
    375506        }
    376507
    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. */
     518static 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        }
    389547        return 0;
    390548}
    391549
     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. */
     553int 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
    392607
    393608
    394609/* 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 
     610int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock)
     611{
    401612        /* There are no locks on read-only dbs */
    402613        if (tdb->read_only || tdb->traverse_read) {
     
    405616        }
    406617
    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)) {
    420636                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
    421637                return -1;
    422638        }
    423639
    424         tdb->global_lock.count = 0;
    425         tdb->global_lock.ltype = 0;
     640        tdb->allrecord_lock.count = 0;
     641        tdb->allrecord_lock.ltype = 0;
    426642
    427643        return 0;
     
    429645
    430646/* lock entire database with write lock */
    431 int tdb_lockall(struct tdb_context *tdb)
     647_PUBLIC_ int tdb_lockall(struct tdb_context *tdb)
    432648{
    433649        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);
    435651}
    436652
    437653/* 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)
    439655{
    440656        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);
    442658}
    443659
    444660/* 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)
    446662{
    447663        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);
    449665}
    450666
    451667/* 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);
    455671        tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret);
    456672        return ret;
     
    458674
    459675/* unlock entire database with write lock */
    460 int tdb_unlockall(struct tdb_context *tdb)
     676_PUBLIC_ int tdb_unlockall(struct tdb_context *tdb)
    461677{
    462678        tdb_trace(tdb, "tdb_unlockall");
    463         return _tdb_unlockall(tdb, F_WRLCK);
     679        return tdb_allrecord_unlock(tdb, F_WRLCK, false);
    464680}
    465681
    466682/* 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)
    468684{
    469685        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);
    471687}
    472688
    473689/* 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);
    477693        tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret);
    478694        return ret;
     
    480696
    481697/* 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)
    483699{
    484700        tdb_trace(tdb, "tdb_unlockall_read");
    485         return _tdb_unlockall(tdb, F_RDLCK);
     701        return tdb_allrecord_unlock(tdb, F_RDLCK, false);
    486702}
    487703
    488704/* lock/unlock one hash chain. This is meant to be used to reduce
    489705   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)
    491707{
    492708        int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    498714   to reduce contention - it cannot guarantee how many records will be
    499715   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)
    501717{
    502718        int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    506722
    507723/* 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);
    511728        tdb_trace_1rec(tdb, "tdb_chainlock_mark", key);
    512729        return ret;
     
    514731
    515732/* 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)
    517734{
    518735        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)
    523741{
    524742        tdb_trace_1rec(tdb, "tdb_chainunlock", key);
     
    526744}
    527745
    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)
    529747{
    530748        int ret;
     
    534752}
    535753
    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)
    537755{
    538756        tdb_trace_1rec(tdb, "tdb_chainunlock_read", key);
     
    540758}
    541759
    542 
    543 
    544760/* record lock stops delete underneath */
    545761int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
    546762{
    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;
    551767}
    552768
     
    562778                if (i->off == off)
    563779                        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
    571789int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
    572790{
    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);
    574795}
    575796
     
    580801        uint32_t count = 0;
    581802
    582         if (tdb->global_lock.count) {
     803        if (tdb->allrecord_lock.count) {
    583804                return 0;
    584805        }
     
    589810                if (i->off == off)
    590811                        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
     815bool 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. */
     838void 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  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    3131static struct tdb_context *tdbs = NULL;
    3232
    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. */
     34void 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}
    4752
    4853/* initialise a new database with a specified hash size */
     
    5257        size_t size;
    5358        int ret = -1;
    54         ssize_t written;
    5559
    5660        /* We make it up in memory, then write it out if not internal */
     
    6468        newdb->version = TDB_VERSION;
    6569        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
    6678        if (tdb->flags & TDB_INTERNAL) {
    6779                tdb->map_size = size;
     
    8496        memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
    8597        /* 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))
    8899                ret = 0;
    89         } else if (written != -1) {
    90                 /* call write once again, this usually should return -1 and
    91                  * 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         }
    102100
    103101  fail:
     
    112110{
    113111        struct tdb_context *i;
    114        
     112
    115113        for (i = tdbs; i; i = i->next) {
    116114                if (i->device == device && i->inode == ino) {
     
    132130
    133131   @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,
    135133                      int open_flags, mode_t mode)
    136134{
     
    144142}
    145143
    146 
    147 struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
     144static 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,
    148166                                int open_flags, mode_t mode,
    149167                                const struct tdb_logging_context *log_ctx,
     
    156174        uint32_t vertest;
    157175        unsigned v;
     176        const char *hash_alg;
     177        uint32_t magic1, magic2;
    158178
    159179        if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
     
    177197                tdb->log.log_private = NULL;
    178198        }
    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        }
    180238
    181239        /* cache the page size */
     
    193251                goto fail;
    194252        }
    195        
     253
    196254        if (hash_size == 0)
    197255                hash_size = DEFAULT_HASH_SIZE;
     
    212270        }
    213271
     272        if (getenv("TDB_NO_FSYNC")) {
     273                tdb->flags |= TDB_NOSYNC;
     274        }
     275
    214276        /*
    215277         * TDB_ALLOW_NESTING is the default behavior.
     
    242304
    243305        /* 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 global lock 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",
    246308                         name, strerror(errno)));
    247309                goto fail;      /* errno set by tdb_brlock */
     
    251313        if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
    252314            (!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))) {
    254316                open_flags |= O_CREAT;
    255317                if (ftruncate(tdb->fd, 0) == -1) {
     
    290352                goto fail;
    291353
    292         if (tdb->header.rwlocks != 0) {
     354        if (tdb->header.rwlocks != 0 &&
     355            tdb->header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
    293356                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;
    294376                goto fail;
    295377        }
     
    304386        }
    305387
    306         if (!(tdb->name = (char *)strdup(name))) {
    307                 errno = ENOMEM;
    308                 goto fail;
    309         }
    310 
    311388        tdb->map_size = st.st_size;
    312389        tdb->device = st.st_dev;
     
    314391        tdb_mmap(tdb);
    315392        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) {
    317394                        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",
    319396                                 name, strerror(errno)));
    320397                        goto fail;
     
    329406        if (tdb_flags & TDB_CLEAR_IF_FIRST) {
    330407                /* 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) {
    332409                        goto fail;
     410                }
    333411        }
    334412
     
    357435        /* Internal (memory-only) databases skip all the code above to
    358436         * 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        }
    362441        tdb->next = tdbs;
    363442        tdbs = tdb;
     
    379458                        tdb_munmap(tdb);
    380459        }
    381         SAFE_FREE(tdb->name);
    382460        if (tdb->fd != -1)
    383461                if (close(tdb->fd) != 0)
    384462                        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);
    385465        SAFE_FREE(tdb);
    386466        errno = save_errno;
     
    393473 */
    394474
    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)
    396476{
    397477        tdb->max_dead_records = max_dead;
     
    403483 * @returns -1 for error; 0 for success.
    404484 **/
    405 int tdb_close(struct tdb_context *tdb)
     485_PUBLIC_ int tdb_close(struct tdb_context *tdb)
    406486{
    407487        struct tdb_context **i;
    408488        int ret = 0;
    409489
     490        if (tdb->transaction) {
     491                tdb_transaction_cancel(tdb);
     492        }
    410493        tdb_trace(tdb, "tdb_close");
    411         if (tdb->transaction) {
    412                 _tdb_transaction_cancel(tdb);
    413         }
    414494
    415495        if (tdb->map_ptr) {
     
    444524
    445525/* 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)
    448528{
    449529        tdb->log = *log_ctx;
    450530}
    451531
    452 void *tdb_get_logging_private(struct tdb_context *tdb)
     532_PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb)
    453533{
    454534        return tdb->log.log_private;
     
    466546        }
    467547
    468         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     548        if (tdb_have_extra_locks(tdb)) {
    469549                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
    470550                goto fail;
     
    501581#endif /* fake pread or pwrite */
    502582
    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) {
    505588                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
    506589                goto fail;
     
    516599/* reopen a tdb - this can be used after a fork to ensure that we have an independent
    517600   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)
    519602{
    520603        return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
     
    522605
    523606/* reopen all tdb's */
    524 int tdb_reopen_all(int parent_longlived)
     607_PUBLIC_ int tdb_reopen_all(int parent_longlived)
    525608{
    526609        struct tdb_context *tdb;
  • vendor/current/lib/tdb/common/tdb.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 TDB_DATA tdb_null;
     30_PUBLIC_ TDB_DATA tdb_null;
    3131
    3232/*
     
    3434  the TDB_SEQNUM flag
    3535*/
    36 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
     36_PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
    3737{
    3838        tdb_off_t seqnum=0;
    39        
     39
    4040        if (!(tdb->flags & TDB_SEQNUM)) {
    4141                return;
     
    6060        }
    6161
    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) {
    6364                return;
    6465        }
     
    6667        tdb_increment_seqnum_nonblock(tdb);
    6768
    68         tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
     69        tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false);
    6970}
    7071
     
    8081{
    8182        tdb_off_t rec_ptr;
    82        
     83
    8384        /* read in the hash top */
    8485        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    154155                }
    155156        }
    156          
    157157
    158158        /* must be long enough key, data and tailer */
     
    171171                return tdb_rec_write(tdb, rec_ptr, &rec);
    172172        }
    173  
     173
    174174        return 0;
    175175}
     
    200200}
    201201
    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)
    203203{
    204204        TDB_DATA ret = _tdb_fetch(tdb, key);
     
    213213 * should be fast and should not block on other syscalls.
    214214 *
    215  * DONT 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.
    216216 *
    217217 * For mmapped tdb's that do not have a transaction open it points the parsing
     
    222222 * This is interesting for all readers of potentially large data structures in
    223223 * the tdb records, ldb indexes being one example.
     224 *
     225 * Return -1 if the record was not found.
    224226 */
    225227
    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,
    227229                     int (*parser)(TDB_DATA key, TDB_DATA data,
    228230                                   void *private_data),
     
    238240
    239241        if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
     242                /* record not found */
    240243                tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
    241244                tdb->ecode = TDB_ERR_NOEXIST;
    242                 return 0;
     245                return -1;
    243246        }
    244247        tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0);
     
    261264{
    262265        struct tdb_record rec;
    263        
     266
    264267        if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
    265268                return 0;
     
    268271}
    269272
    270 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
     273_PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
    271274{
    272275        uint32_t hash = tdb->hash_fn(&key);
     
    319322        tdb_off_t rec_ptr;
    320323        struct tdb_record rec;
    321        
     324
    322325        /* read in the hash top */
    323326        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    348351                return -1;
    349352        }
    350        
     353
    351354        /* read in the hash top */
    352355        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    427430}
    428431
    429 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
     432_PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
    430433{
    431434        uint32_t hash = tdb->hash_fn(&key);
     
    444447{
    445448        tdb_off_t rec_ptr;
    446        
     449
    447450        /* read in the hash top */
    448451        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    597600   return 0 on success, -1 on failure
    598601*/
    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)
    600603{
    601604        uint32_t hash;
     
    620623
    621624/* 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)
    623626{
    624627        uint32_t hash;
     
    659662        ret = _tdb_store(tdb, key, dbuf, 0, hash);
    660663        tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
    661        
     664
    662665failed:
    663666        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
     
    671674  useful for external logging functions
    672675*/
    673 const char *tdb_name(struct tdb_context *tdb)
     676_PUBLIC_ const char *tdb_name(struct tdb_context *tdb)
    674677{
    675678        return tdb->name;
     
    681684  of the fd
    682685*/
    683 int tdb_fd(struct tdb_context *tdb)
     686_PUBLIC_ int tdb_fd(struct tdb_context *tdb)
    684687{
    685688        return tdb->fd;
     
    690693  useful for external tdb routines that wish to log tdb errors
    691694*/
    692 tdb_log_func tdb_log_fn(struct tdb_context *tdb)
     695_PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
    693696{
    694697        return tdb->log.log_fn;
     
    706709  test of a possible tdb change.
    707710*/
    708 int tdb_get_seqnum(struct tdb_context *tdb)
     711_PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb)
    709712{
    710713        tdb_off_t seqnum=0;
     
    714717}
    715718
    716 int tdb_hash_size(struct tdb_context *tdb)
     719_PUBLIC_ int tdb_hash_size(struct tdb_context *tdb)
    717720{
    718721        return tdb->header.hash_size;
    719722}
    720723
    721 size_t tdb_map_size(struct tdb_context *tdb)
     724_PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb)
    722725{
    723726        return tdb->map_size;
    724727}
    725728
    726 int tdb_get_flags(struct tdb_context *tdb)
     729_PUBLIC_ int tdb_get_flags(struct tdb_context *tdb)
    727730{
    728731        return tdb->flags;
    729732}
    730733
    731 void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
     734_PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
    732735{
    733736        if ((flags & TDB_ALLOW_NESTING) &&
     
    749752}
    750753
    751 void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
     754_PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
    752755{
    753756        if ((flags & TDB_ALLOW_NESTING) &&
     
    773776  enable sequence number handling on an open tdb
    774777*/
    775 void tdb_enable_seqnum(struct tdb_context *tdb)
     778_PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb)
    776779{
    777780        tdb->flags |= TDB_SEQNUM;
     
    805808/*
    806809  wipe the entire database, deleting all records. This can be done
    807   very fast by using a global lock. The entire data portion of the
     810  very fast by using a allrecord lock. The entire data portion of the
    808811  file becomes a single entry in the freelist.
    809812
    810813  This code carefully steps around the recovery area, leaving it alone
    811814 */
    812 int tdb_wipe_all(struct tdb_context *tdb)
     815_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
    813816{
    814817        int i;
     
    917920  repack a tdb
    918921 */
    919 int tdb_repack(struct tdb_context *tdb)
     922_PUBLIC_ int tdb_repack(struct tdb_context *tdb)
    920923{
    921924        struct tdb_context *tmp_db;
     
    987990}
    988991
     992/* Even on files, we can get partial writes due to signals. */
     993bool 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
    9891006#ifdef TDB_TRACE
    9901007static void tdb_trace_write(struct tdb_context *tdb, const char *str)
    9911008{
    992         if (write(tdb->tracefd, str, strlen(str)) != strlen(str)) {
     1009        if (!tdb_write_alltdb->tracefd, str, strlen(str)) {
    9931010                close(tdb->tracefd);
    9941011                tdb->tracefd = -1;
  • vendor/current/lib/tdb/common/tdb_private.h

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell              2005
    7    
     7
    88     ** NOTE! The following LGPL license applies to the tdb
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    5050#define TDB_DEAD_MAGIC (0xFEE1DEAD)
    5151#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
     52#define TDB_RECOVERY_INVALID_MAGIC (0x0)
     53#define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U)
    5254#define TDB_ALIGNMENT 4
    5355#define DEFAULT_HASH_SIZE 131
     
    102104
    103105/* lock offsets */
    104 #define GLOBAL_LOCK      0
     106#define OPEN_LOCK        0
    105107#define ACTIVE_LOCK      4
    106108#define TRANSACTION_LOCK 8
     
    147149        tdb_off_t recovery_start; /* offset of transaction recovery region */
    148150        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];
    150154};
    151155
    152156struct tdb_lock_type {
    153         int list;
     157        uint32_t off;
    154158        uint32_t count;
    155159        uint32_t ltype;
     
    163167};
    164168
     169enum 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};
    165178
    166179struct tdb_methods {
     
    170183        int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
    171184        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);
    173185};
    174186
     
    181193        int traverse_read; /* read-only traversal */
    182194        int traverse_write; /* read-write traversal */
    183         struct tdb_lock_type global_lock;
     195        struct tdb_lock_type allrecord_lock; /* .offset == upgradable */
    184196        int num_lockrecs;
    185197        struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
     
    194206        unsigned int (*hash_fn)(TDB_DATA *key);
    195207        int open_flags; /* flags used in the open - needed by reopen */
    196         unsigned int num_locks; /* number of chain locks held */
    197208        const struct tdb_methods *methods;
    198209        struct tdb_transaction *transaction;
    199210        int page_size;
    200211        int max_dead_records;
    201         int transaction_lock_count;
    202212#ifdef TDB_TRACE
    203213        int tracefd;
     
    214224int tdb_lock(struct tdb_context *tdb, int list, int ltype);
    215225int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
     226int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     227                  enum tdb_lock_flags flags);
     228int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     229                    bool mark_lock);
    216230int 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);
     231int tdb_brlock(struct tdb_context *tdb,
     232               int rw_type, tdb_off_t offset, size_t len,
     233               enum tdb_lock_flags flags);
     234int tdb_brunlock(struct tdb_context *tdb,
     235                 int rw_type, tdb_off_t offset, size_t len);
     236bool tdb_have_extra_locks(struct tdb_context *tdb);
     237void tdb_release_transaction_locks(struct tdb_context *tdb);
     238int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     239                         enum tdb_lock_flags lockflags);
     240int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
     241int tdb_recovery_area(struct tdb_context *tdb,
     242                      const struct tdb_methods *methods,
     243                      tdb_off_t *recovery_offset,
     244                      struct tdb_record *rec);
     245int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     246                       enum tdb_lock_flags flags, bool upgradable);
     247int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock);
     248int tdb_allrecord_upgrade(struct tdb_context *tdb);
    221249int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
    222250int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
     
    230258int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
    231259int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
    232 int _tdb_transaction_cancel(struct tdb_context *tdb);
     260bool tdb_needs_recovery(struct tdb_context *tdb);
    233261int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
    234262int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     
    246274int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
    247275                      struct tdb_record *rec);
    248 
    249 
     276bool tdb_write_all(int fd, const void *buf, size_t count);
     277int tdb_transaction_recover(struct tdb_context *tdb);
     278void tdb_header_hash(struct tdb_context *tdb,
     279                     uint32_t *magic1_hash, uint32_t *magic2_hash);
     280unsigned int tdb_old_hash(TDB_DATA *key);
     281size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off);
  • vendor/current/lib/tdb/common/transaction.c

    r414 r740  
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    6060    existing transaction record. If the inner transaction is cancelled
    6161    then a subsequent commit will fail
    62  
     62
    6363  - keep a mirrored copy of the tdb hash chain heads to allow for the
    6464    fast hash heads scan on traverse, updating the mirrored copy in
     
    7777
    7878  - check for a valid recovery record on open of the tdb, while the
    79     global lock is held. Automatically recover from the transaction
     79    open lock is held. Automatically recover from the transaction
    8080    recovery area if needed, then continue with the open as
    8181    usual. This allows for smooth crash recovery with no administrator
     
    136136        tdb_off_t magic_offset;
    137137
    138         /* set when the GLOBAL_LOCK has been taken */
    139         bool global_lock_taken;
    140 
    141138        /* old file size before transaction */
    142139        tdb_len_t old_map_size;
    143140
    144         /* we should re-pack on commit */
    145         bool need_repack;
     141        /* did we expand in this transaction */
     142        bool expanded;
    146143};
    147144
     
    189186                }
    190187        }
    191        
     188
    192189        /* now copy it out of this block */
    193190        memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len);
     
    296293                }
    297294        }
    298        
     295
    299296        /* overwrite part of an existing block */
    300297        if (buf == NULL) {
     
    407404        }
    408405
    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
    420408        return 0;
    421409}
     
    427415        transaction_oob,
    428416        transaction_expand_file,
    429         transaction_brlock
    430417};
    431418
     
    435422  transaction is allowed to be pending per tdb_context
    436423*/
    437 int tdb_transaction_start(struct tdb_context *tdb)
     424static int _tdb_transaction_start(struct tdb_context *tdb,
     425                                  enum tdb_lock_flags lockflags)
    438426{
    439427        /* some sanity checks */
     
    456444        }
    457445
    458         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     446        if (tdb_have_extra_locks(tdb)) {
    459447                /* the caller must not have any locks when starting a
    460448                   transaction as otherwise we'll be screwed by lack
     
    487475           discussed with Volker, there are a number of ways we could
    488476           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) {
    490478                SAFE_FREE(tdb->transaction->blocks);
    491479                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
    495486        /* get a read lock from the freelist to the end of file. This
    496487           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) {
    498489                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;
    501491        }
    502492
     
    529519        tdb_trace(tdb, "tdb_transaction_start");
    530520        return 0;
    531        
     521
    532522fail:
    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);
     524fail_allrecord_lock:
     525        tdb_transaction_unlock(tdb, F_WRLCK);
    535526        SAFE_FREE(tdb->transaction->blocks);
    536527        SAFE_FREE(tdb->transaction->hash_heads);
     
    539530}
    540531
     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}
    541541
    542542/*
     
    549549        }
    550550
     551#ifdef HAVE_FDATASYNC
     552        if (fdatasync(tdb->fd) != 0) {
     553#else
    551554        if (fsync(tdb->fd) != 0) {
     555#endif
    552556                tdb->ecode = TDB_ERR_IO;
    553557                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
     
    570574
    571575
    572 int _tdb_transaction_cancel(struct tdb_context *tdb)
     576static int _tdb_transaction_cancel(struct tdb_context *tdb)
    573577{       
    574578        int i, ret = 0;
     
    597601        if (tdb->transaction->magic_offset) {
    598602                const struct tdb_methods *methods = tdb->transaction->io_methods;
    599                 uint32_t zero = 0;
     603                const uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC;
    600604
    601605                /* 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 ||
    603607                transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) {
    604608                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n"));
     
    607611        }
    608612
    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);
    630615
    631616        /* restore the normal io methods */
    632617        tdb->methods = tdb->transaction->io_methods;
    633618
    634         tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
    635         tdb_transaction_unlock(tdb);
    636619        SAFE_FREE(tdb->transaction->hash_heads);
    637620        SAFE_FREE(tdb->transaction);
    638        
     621
    639622        return ret;
    640623}
     
    643626  cancel the current transaction
    644627*/
    645 int tdb_transaction_cancel(struct tdb_context *tdb)
     628_PUBLIC_ int tdb_transaction_cancel(struct tdb_context *tdb)
    646629{
    647630        tdb_trace(tdb, "tdb_transaction_cancel");
     
    676659}
    677660
     661int 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
    678689/*
    679690  allocate the recovery area, or use an existing recovery area if it is
     
    689700        tdb_off_t recovery_head;
    690701
    691         if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
     702        if (tdb_recovery_area(tdb, methods, &recovery_head, &rec) == -1) {
    692703                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"));
    701704                return -1;
    702705        }
     
    794797        memset(rec, 0, sizeof(*rec));
    795798
    796         rec->magic    = 0;
     799        rec->magic    = TDB_RECOVERY_INVALID_MAGIC;
    797800        rec->data_len = recovery_size;
    798801        rec->rec_len  = recovery_max_size;
    799802        rec->key_len  = old_map_size;
    800         CONVERT(rec);
     803        CONVERT(*rec);
    801804
    802805        /* build the recovery data into a single blob to allow us to do a single
     
    816819                        length = tdb->transaction->last_block_size;
    817820                }
    818                
     821
    819822                if (offset >= old_map_size) {
    820823                        continue;
     
    845848        tailer = sizeof(*rec) + recovery_max_size;
    846849        memcpy(p, &tailer, 4);
    847         CONVERT(p);
     850        if (DOCONV()) {
     851                tdb_convert(p, 4);
     852        }
    848853
    849854        /* write the recovery data to the recovery area */
     
    929934
    930935        methods = tdb->transaction->io_methods;
    931        
     936
    932937        /* if there are any locks pending then the caller has not
    933938           nested their locks properly, so fail the transaction */
    934         if (tdb->num_locks || tdb->global_lock.count) {
     939        if (tdb_have_extra_locks(tdb)) {
    935940                tdb->ecode = TDB_ERR_LOCK;
    936941                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n"));
     
    940945
    941946        /* 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) {
    943948                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to upgrade hash locks\n"));
    944                 tdb->ecode = TDB_ERR_LOCK;
    945949                _tdb_transaction_cancel(tdb);
    946950                return -1;
    947951        }
    948952
    949         /* get the global lock - this prevents new users attaching to the database
     953        /* get the open lock - this prevents new users attaching to the database
    950954           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"));
    954957                _tdb_transaction_cancel(tdb);
    955958                return -1;
    956959        }
    957 
    958         tdb->transaction->global_lock_taken = true;
    959960
    960961        if (!(tdb->flags & TDB_NOSYNC)) {
     
    983984        }
    984985
    985         /* Keep the global lock until the actual commit */
     986        /* Keep the open lock until the actual commit */
    986987
    987988        return 0;
     
    991992   prepare to commit the current transaction
    992993*/
    993 int tdb_transaction_prepare_commit(struct tdb_context *tdb)
    994 {       
     994_PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb)
     995{
    995996        tdb_trace(tdb, "tdb_transaction_prepare_commit");
    996997        return _tdb_transaction_prepare_commit(tdb);
    997998}
    998999
     1000/* A repack is worthwhile if the largest is less than half total free. */
     1001static 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
    9991022/*
    10001023  commit the current transaction
    10011024*/
    1002 int tdb_transaction_commit(struct tdb_context *tdb)
    1003 {       
     1025_PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
     1026{
    10041027        const struct tdb_methods *methods;
    10051028        int i;
    1006         bool need_repack;
     1029        bool need_repack = false;
    10071030
    10081031        if (tdb->transaction == NULL) {
     
    10571080                if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) {
    10581081                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
    1059                        
     1082
    10601083                        /* we've overwritten part of the data and
    10611084                           possibly expanded the file, so we need to
     
    10711094                SAFE_FREE(tdb->transaction->blocks[i]);
    10721095        }
     1096
     1097        /* Do this before we drop lock or blocks. */
     1098        if (tdb->transaction->expanded) {
     1099                need_repack = repack_worthwhile(tdb);
     1100        }
    10731101
    10741102        SAFE_FREE(tdb->transaction->blocks);
     
    10951123#endif
    10961124
    1097         need_repack = tdb->transaction->need_repack;
    1098 
    10991125        /* use a transaction cancel to free memory and remove the
    11001126           transaction locks */
     
    11111137/*
    11121138  recover from an aborted transaction. Must be called with exclusive
    1113   database write access already established (including the global
     1139  database write access already established (including the open
    11141140  lock to prevent new processes attaching)
    11151141*/
     
    12121238                return -1;                     
    12131239        }
    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);
    12241240
    12251241        if (transaction_sync(tdb, 0, recovery_eof) == -1) {
     
    12351251        return 0;
    12361252}
     1253
     1254/* Any I/O failures we say "needs recovery". */
     1255bool 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  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    4545                           hashes are used. In that case we spend most of our
    4646                           time in tdb_brlock(), locking empty hash chains.
    47                            
     47
    4848                           To avoid this, we do an unlocked pre-check to see
    4949                           if the hash chain is empty before starting to look
     
    5353                           lock, so instead we get the lock and re-fetch the
    5454                           value below.
    55                            
     55
    5656                           Notice that not doing this optimisation on the
    5757                           first hash chain is critical. We must guarantee
     
    6363                           could miss them anyway without this trick, so the
    6464                           semantics don't change.
    65                            
     65
    6666                           With a non-indexed ldb search this trick gains us a
    6767                           factor of around 80 in speed on a linux 2.6.x
     
    213213  a write style traverse - temporarily marks the db read only
    214214*/
    215 int tdb_traverse_read(struct tdb_context *tdb,
     215_PUBLIC_ int tdb_traverse_read(struct tdb_context *tdb,
    216216                      tdb_traverse_func fn, void *private_data)
    217217{
     
    221221        /* we need to get a read lock on the transaction lock here to
    222222           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)) {
    224224                return -1;
    225225        }
     
    230230        tdb->traverse_read--;
    231231
    232         tdb_transaction_unlock(tdb);
     232        tdb_transaction_unlock(tdb, F_RDLCK);
    233233
    234234        return ret;
     
    242242  alignment restrictions malloc gives you.
    243243*/
    244 int tdb_traverse(struct tdb_context *tdb,
     244_PUBLIC_ int tdb_traverse(struct tdb_context *tdb,
    245245                 tdb_traverse_func fn, void *private_data)
    246246{
     
    252252        }
    253253
    254         if (tdb_transaction_lock(tdb, F_WRLCK)) {
     254        if (tdb_transaction_lock(tdb, F_WRLCK, TDB_LOCK_WAIT)) {
    255255                return -1;
    256256        }
     
    261261        tdb->traverse_write--;
    262262
    263         tdb_transaction_unlock(tdb);
     263        tdb_transaction_unlock(tdb, F_WRLCK);
    264264
    265265        return ret;
     
    268268
    269269/* 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)
    271271{
    272272        TDB_DATA key;
     
    299299
    300300/* 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)
    302302{
    303303        uint32_t oldhash;
  • vendor/current/lib/tdb/docs/README

    r414 r740  
    106106
    107107----------------------------------------------------------------------
     108int 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----------------------------------------------------------------------
    108127int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
    109128
  • vendor/current/lib/tdb/include/tdb.h

    r414 r740  
    3131#endif
    3232
    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 */
    5585enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
    5686                TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
     
    5888                TDB_ERR_NESTING};
    5989
    60 /* debugging uses one of the following levels */
     90/** Debugging uses one of the following levels */
    6191enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR,
    6292                      TDB_DEBUG_WARNING, TDB_DEBUG_TRACE};
    6393
     94/** The tdb data structure */
    6495typedef struct TDB_DATA {
    6596        unsigned char *dptr;
     
    79110#endif
    80111
    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. */
    82113typedef struct tdb_context TDB_CONTEXT;
    83114
     
    91122};
    92123
     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 */
    93153struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
    94154                      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 */
    95195struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
    96196                         int open_flags, mode_t mode,
    97197                         const struct tdb_logging_context *log_ctx,
    98198                         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 */
    99207void tdb_set_max_dead(struct tdb_context *tdb, int max_dead);
    100208
     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 */
    101219int 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 */
    102234int 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 */
    103243void 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 */
    104254enum 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 */
    105263const 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 */
    106280TDB_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 */
    107305int 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 */
    111319int 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 */
    112341int 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 */
    113359int 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 */
    114368int 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 */
    115380TDB_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 */
    116394TDB_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 */
     416int 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 */
     435int 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 */
    119450int 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 */
    120462int 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 */
    121477int 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 */
    122490int 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 */
    123502int 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 */
    124517int 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 */
    125530int 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 */
    126544int 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 */
    127558int 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 */
    128569const 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 */
    129581int 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 */
    130594tdb_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 */
    131605void *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 */
    132635int 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 */
     648int 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 */
    133665int 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 */
    134679int 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 */
    135694int 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 */
    137714int 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 */
    138723int 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 */
    139732size_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 */
    140741int 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 */
    141750void 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 */
    142759void 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 */
    143768void 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 */
    144781void 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 */
     790unsigned 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 */
    145813int tdb_check(struct tdb_context *tdb,
    146814              int (*check) (TDB_DATA key, TDB_DATA data, void *private_data),
    147815              void *private_data);
     816
     817/* @} ******************************************************************/
    148818
    149819/* Low level locking functions: use with care */
     
    167837int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
    168838int tdb_freelist_size(struct tdb_context *tdb);
     839char *tdb_summary(struct tdb_context *tdb);
    169840
    170841extern TDB_DATA tdb_null;
  • vendor/current/lib/tdb/libtdb.m4

    r414 r740  
    1414fi
    1515TDB_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"
     16TDB_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"
    1717AC_SUBST(TDB_OBJ)
    1818AC_SUBST(LIBREPLACEOBJ)
     
    2020TDB_LIBS=""
    2121AC_SUBST(TDB_LIBS)
     22
     23TDB_DEPS=""
     24if test x$libreplace_cv_HAVE_FDATASYNC_IN_LIBRT = xyes ; then
     25        TDB_DEPS="$TDB_DEPS -lrt"
     26fi
     27AC_SUBST(TDB_DEPS)
    2228
    2329TDB_CFLAGS="-I$tdbdir/include"
  • vendor/current/lib/tdb/manpages/tdbbackup.8.xml

    r414 r740  
    11<?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">
    33<refentry id="tdbbackup.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/manpages/tdbdump.8.xml

    r414 r740  
    11<?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">
    33<refentry id="tdbdump.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/manpages/tdbtool.8.xml

    r414 r740  
    11<?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">
    33<refentry id="tdbtool.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/pytdb.c

    r414 r740  
    1010     ** library. This does NOT imply that all of Samba is released
    1111     ** under the LGPL
    12    
     12
    1313   This library is free software; you can redistribute it and/or
    1414   modify it under the terms of the GNU Lesser General Public
     
    2525*/
    2626
     27#include <Python.h>
    2728#include "replace.h"
    2829#include "system/filesys.h"
    2930
    30 #include <Python.h>
    3131#ifndef Py_RETURN_NONE
    3232#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
     
    4242} PyTdbObject;
    4343
    44 PyAPI_DATA(PyTypeObject) PyTdb;
     44staticforward PyTypeObject PyTdb;
    4545
    4646static void PyErr_SetTDBError(TDB_CONTEXT *tdb)
     
    7878static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    7979{
    80         char *name;
     80        char *name = NULL;
    8181        int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600;
    8282        TDB_CONTEXT *ctx;
     
    8484        const char *kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL };
    8585
    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        }
    8892
    8993        ctx = tdb_open(name, hash_size, tdb_flags, flags, mode);
     
    9498
    9599        ret = PyObject_New(PyTdbObject, &PyTdb);
     100        if (!ret) {
     101                tdb_close(ctx);
     102                return NULL;
     103        }
     104
    96105        ret->ctx = ctx;
    97106        ret->closed = false;
     
    113122}
    114123
    115 static PyObject *obj_transaction_recover(PyTdbObject *self)
    116 {
    117         int ret = tdb_transaction_recover(self->ctx);
     124static PyObject *obj_transaction_prepare_commit(PyTdbObject *self)
     125{
     126        int ret = tdb_transaction_prepare_commit(self->ctx);
    118127        PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
    119128        Py_RETURN_NONE;
     
    267276}
    268277
     278static 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
     289static 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}
    269299
    270300typedef struct {
     
    306336
    307337        ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator);
     338        if (!ret)
     339                return NULL;
    308340        ret->current = tdb_firstkey(self->ctx);
    309341        ret->iteratee = self;
     
    316348        int ret = tdb_wipe_all(self->ctx);
    317349        PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
     350        Py_RETURN_NONE;
     351}
     352
     353static 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
     360static PyObject *obj_enable_seqnum(PyTdbObject *self)
     361{
     362        tdb_enable_seqnum(self->ctx);
     363        Py_RETURN_NONE;
     364}
     365
     366static PyObject *obj_increment_seqnum_nonblock(PyTdbObject *self)
     367{
     368        tdb_increment_seqnum_nonblock(self->ctx);
    318369        Py_RETURN_NONE;
    319370}
     
    326377                "S.transaction_commit() -> None\n"
    327378                "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" },
    331382        { "transaction_start", (PyCFunction)obj_transaction_start, METH_NOARGS,
    332383                "S.transaction_start() -> None\n"
     
    352403        { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None"
    353404                "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" },
    354407        { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" },
    355408        { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n"
    356409                "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" },
    357416        { NULL }
    358417};
     
    376435}
    377436
     437static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure)
     438{
     439        return PyInt_FromLong(tdb_freelist_size(self->ctx));
     440}
     441
    378442static PyObject *obj_get_flags(PyTdbObject *self, void *closure)
    379443{
     
    385449        return PyString_FromString(tdb_name(self->ctx));
    386450}
     451
     452static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure)
     453{
     454        return PyInt_FromLong(tdb_get_seqnum(self->ctx));
     455}
     456
    387457
    388458static PyGetSetDef tdb_object_getsetters[] = {
    389459        { (char *)"hash_size", (getter)obj_get_hash_size, NULL, NULL },
    390460        { (char *)"map_size", (getter)obj_get_map_size, NULL, NULL },
     461        { (char *)"freelist_size", (getter)obj_get_freelist_size, NULL, NULL },
    391462        { (char *)"flags", (getter)obj_get_flags, NULL, NULL },
    392463        { (char *)"max_dead", NULL, (setter)obj_set_max_dead, NULL },
    393464        { (char *)"filename", (getter)obj_get_filename, NULL, (char *)"The filename of this TDB file."},
     465        { (char *)"seqnum", (getter)obj_get_seqnum, NULL, NULL },
    394466        { NULL }
    395467};
     
    397469static PyObject *tdb_object_repr(PyTdbObject *self)
    398470{
    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        }
    400476}
    401477
     
    404480        if (!self->closed)
    405481                tdb_close(self->ctx);
    406         PyObject_Del(self);
     482        self->ob_type->tp_free(self);
    407483}
    408484
     
    463539        .mp_ass_subscript = (objobjargproc)obj_setitem,
    464540};
    465 PyTypeObject PyTdb = {
     541static PyTypeObject PyTdb = {
    466542        .tp_name = "Tdb",
    467543        .tp_basicsize = sizeof(PyTdbObject),
     
    483559};
    484560
     561void inittdb(void);
    485562void inittdb(void)
    486563{
     
    508585        PyModule_AddObject(m, "CONVERT", PyInt_FromLong(TDB_CONVERT));
    509586        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
    510594        PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
     595
     596        PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
    511597
    512598        Py_INCREF(&PyTdb);
  • vendor/current/lib/tdb/python/tdbdump.py

    r414 r740  
    1 #!/usr/bin/python
     1#!/usr/bin/env python
    22# Trivial reimplementation of tdbdump in Python
    33
  • vendor/current/lib/tdb/python/tests/simple.py

    r414 r740  
    1 #!/usr/bin/python
     1#!/usr/bin/env python
    22# Some simple tests for the Python bindings for TDB
    33# Note that this tests the interface of the Python bindings
     
    1313
    1414class OpenTdbTests(TestCase):
     15
    1516    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)
    1719
    1820class CloseTdbTests(TestCase):
     21
    1922    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)
    2125        self.assertNotEqual(None, self.tdb)
    2226
     
    2630
    2731
     32class 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
    2841class SimpleTdbTests(TestCase):
     42
    2943    def setUp(self):
    3044        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)
    3247        self.assertNotEqual(None, self.tdb)
    3348
     
    8297        self.tdb.map_size
    8398
     99    def test_freelist_size(self):
     100        self.tdb.freelist_size
     101
    84102    def test_name(self):
    85103        self.tdb.filename
     
    104122        self.assertEquals("1", self.tdb["bloe"])
    105123
    106     def test_iterator(self):
     124    def test_transaction_prepare_commit(self):
    107125        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"])
    111131
    112132    def test_iterkeys(self):
     
    123143        self.assertEquals(0, len(list(self.tdb)))
    124144
     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
    125158    def test_len(self):
    126159        self.assertEquals(0, len(list(self.tdb)))
     
    128161        self.assertEquals(1, len(list(self.tdb)))
    129162
     163    def test_add_flags(self):
     164        self.tdb.add_flags(tdb.NOMMAP)
     165        self.tdb.remove_flags(tdb.NOMMAP)
     166
     167
     168class VersionTests(TestCase):
     169
     170    def test_present(self):
     171        self.assertTrue(isinstance(tdb.__version__, str))
     172
    130173
    131174if __name__ == '__main__':
  • vendor/current/lib/tdb/tdb.pc.in

    r414 r740  
    77Description: A trivial database
    88Version: @PACKAGE_VERSION@
    9 Libs: -L${libdir} -ltdb
     9Libs: @LIB_RPATH@ -L${libdir} -ltdb
    1010Cflags: -I${includedir}
    1111URL: http://tdb.samba.org/
  • vendor/current/lib/tdb/tools/tdbbackup.c

    r414 r740  
    153153        }
    154154
    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");
    157158                tdb_close(tdb);
    158159                tdb_close(tdb_new);
     
    178179        tdb_close(tdb);
    179180
    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");
    186191        }
    187192
  • vendor/current/lib/tdb/tools/tdbtest.c

    r414 r740  
    216216}
    217217
     218static 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
    218236 int main(int argc, const char *argv[])
    219237{
     
    221239        int loops = 10000;
    222240        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,
    228250                      O_RDWR | O_CREAT | O_TRUNC, 0600);
    229251        gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
     
    262284        gdbm_close(gdbm);
    263285
     286        free(test_gdbm[0]);
     287        free(test_tdb);
     288
    264289        return 0;
    265290}
  • vendor/current/lib/tdb/tools/tdbtool.c

    r414 r740  
    410410static void info_tdb(void)
    411411{
    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) {
    415415                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        }
    418420}
    419421
  • vendor/current/lib/tdb/tools/tdbtorture.c

    r414 r740  
    3131static int error_count;
    3232static int always_transaction = 0;
     33static int hash_size = 2;
     34static int loopnum;
     35static int count_pipe;
     36static struct tdb_logging_context log_ctx;
    3337
    3438#ifdef PRINTF_ATTRIBUTE
     
    4953        fflush(stdout);
    5054#if 0
    51         {
     55        if (level != TDB_DEBUG_TRACE) {
    5256                char *ptr;
     57                signal(SIGUSR1, SIG_IGN);
    5358                asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
    5459                system(ptr);
     
    212217static void usage(void)
    213218{
    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");
    215220        exit(0);
    216221}
    217222
    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,
     223static 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
     231static 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,
    263234                         O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
    264235        if (!db) {
     
    266237        }
    267238
    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 
    277239        srand(seed + i);
    278240        srandom(seed + i);
    279241
    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++) {
    281247                addrec_db();
    282248        }
     
    302268        tdb_close(db);
    303269
    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
     273static 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
     291int 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) {
    309365                int status, j;
    310366                pid_t pid;
     367
    311368                if (error_count != 0) {
    312369                        /* try and stop the test on any failure */
    313                         for (j=1;j<num_procs;j++) {
     370                        for (j=0;j<num_procs;j++) {
    314371                                if (pids[j] != 0) {
    315372                                        kill(pids[j], SIGTERM);
     
    317374                        }
    318375                }
    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
    320391                if (pid == -1) {
    321392                        perror("failed to wait for child\n");
    322393                        exit(1);
    323394                }
    324                 for (j=1;j<num_procs;j++) {
     395
     396                for (j=0;j<num_procs;j++) {
    325397                        if (pids[j] == pid) break;
    326398                }
     
    329401                        exit(1);
    330402                }
    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));
    334421                        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--;
    337432        }
    338433
    339434        free(pids);
    340435
     436done:
    341437        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);
    342448                printf("OK\n");
    343449        }
    344450
     451        free(test_tdb);
    345452        return error_count;
    346453}
  • vendor/current/lib/tdr/tdr.c

    r414 r740  
    164164        TDR_PULL_NEED_BYTES(tdr, el_size*length);
    165165       
    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)) {
    167167                return NT_STATUS_INVALID_PARAMETER;
    168168        }
     
    184184        TDR_PUSH_NEED_BYTES(tdr, required);
    185185
    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) {
    187188                return NT_STATUS_INVALID_PARAMETER;
    188189        }
     
    344345}
    345346
    346 struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *ic)
     347struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx)
    347348{
    348349        struct tdr_push *push = talloc_zero(mem_ctx, struct tdr_push);
     
    351352                return NULL;
    352353
    353         push->iconv_convenience = talloc_reference(push, ic);
    354 
    355354        return push;
    356355}
    357356
    358 struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *ic)
     357struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx)
    359358{
    360359        struct tdr_pull *pull = talloc_zero(mem_ctx, struct tdr_pull);
     
    363362                return NULL;
    364363
    365         pull->iconv_convenience = talloc_reference(pull, ic);
    366 
    367364        return pull;
    368365}
    369366
    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);
     367NTSTATUS 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);
    373370
    374371        if (push == NULL)
     
    391388}
    392389
    393 void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
     390void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...)
    394391{
    395392        va_list ap;
  • vendor/current/lib/tdr/tdr.h

    r414 r740  
    33   TDR definitions
    44   Copyright (C) Jelmer Vernooij 2005
    5    
     5
    66   This program is free software; you can redistribute it and/or modify
    77   it under the terms of the GNU General Public License as published by
    88   the Free Software Foundation; either version 3 of the License, or
    99   (at your option) any later version.
    10    
     10
    1111   This program is distributed in the hope that it will be useful,
    1212   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1313   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1414   GNU General Public License for more details.
    15    
     15
    1616   You should have received a copy of the GNU General Public License
    1717   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    3434        uint32_t offset;
    3535        int flags;
    36         struct smb_iconv_convenience *iconv_convenience;
    3736};
    3837
     
    4039        DATA_BLOB data;
    4140        int flags;
    42         struct smb_iconv_convenience *iconv_convenience;
    4341};
    4442
     
    6361typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, TALLOC_CTX *, void *);
    6462
    65 #include "../lib/tdr/tdr_proto.h"
     63NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size);
     64NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v);
     65NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v);
     66NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v);
     67NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v);
     68NTSTATUS tdr_pull_uint1632(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v);
     69NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v);
     70NTSTATUS tdr_push_uint1632(struct tdr_push *tdr, const uint16_t *v);
     71NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v);
     72NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v);
     73NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v);
     74NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v);
     75NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, charset_t chset);
     76NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, charset_t chset);
     77NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, charset_t chset);
     78
     79NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v);
     80NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v);
     81
     82NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t);
     83NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t);
     84NTSTATUS tdr_print_NTTIME(struct tdr_print *tdr, const char *name, NTTIME *t);
     85
     86NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t);
     87NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t);
     88NTSTATUS tdr_print_time_t(struct tdr_print *tdr, const char *name, time_t *t);
     89
     90NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB *r);
     91NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob);
     92NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob);
     93
     94struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx);
     95struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx);
     96
     97NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p);
     98void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
    6699
    67100#endif /* __TDR_H__ */
  • vendor/current/lib/tdr/testsuite.c

    r414 r740  
    2626{
    2727        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);
    2929
    3030        torture_assert_ntstatus_ok(tctx, tdr_push_uint8(tdr, &v), "push failed");
     
    3838        uint8_t d = 2;
    3939        uint8_t l;
    40         struct tdr_pull *tdr = tdr_pull_init(tctx, global_iconv_convenience);
     40        struct tdr_pull *tdr = tdr_pull_init(tctx);
    4141        tdr->data.data = &d;
    4242        tdr->data.length = 1;
     
    5353{
    5454        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);
    5656
    5757        torture_assert_ntstatus_ok(tctx, tdr_push_uint16(tdr, &v), "push failed");
     
    6666        uint8_t d[2] = { 782 & 0xFF, (782 & 0xFF00) / 0x100 };
    6767        uint16_t l;
    68         struct tdr_pull *tdr = tdr_pull_init(tctx, global_iconv_convenience);
     68        struct tdr_pull *tdr = tdr_pull_init(tctx);
    6969        tdr->data.data = d;
    7070        tdr->data.length = 2;
     
    8181{
    8282        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);
    8484
    8585        torture_assert_ntstatus_ok(tctx, tdr_push_uint32(tdr, &v), "push failed");
     
    9696        uint8_t d[4] = { 782 & 0xFF, (782 & 0xFF00) / 0x100, 0, 0 };
    9797        uint32_t l;
    98         struct tdr_pull *tdr = tdr_pull_init(tctx, global_iconv_convenience);
     98        struct tdr_pull *tdr = tdr_pull_init(tctx);
    9999        tdr->data.data = d;
    100100        tdr->data.length = 4;
     
    110110static bool test_pull_charset(struct torture_context *tctx)
    111111{
    112         struct tdr_pull *tdr = tdr_pull_init(tctx, global_iconv_convenience);
     112        struct tdr_pull *tdr = tdr_pull_init(tctx);
    113113        const char *l = NULL;
    114114        tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla");
     
    132132static bool test_pull_charset_empty(struct torture_context *tctx)
    133133{
    134         struct tdr_pull *tdr = tdr_pull_init(tctx, global_iconv_convenience);
     134        struct tdr_pull *tdr = tdr_pull_init(tctx);
    135135        const char *l = NULL;
    136136        tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla");
     
    151151{
    152152        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);
    154154        torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, 4, 1, CH_UTF8),
    155155                                                           "push failed");
    156156        torture_assert_int_equal(tctx, 4, tdr->data.length, "offset invalid");
    157         torture_assert(tctx, strcmp("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");
    158158
    159159        torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, -1, 1, CH_UTF8),
     
    167167struct torture_suite *torture_local_tdr(TALLOC_CTX *mem_ctx)
    168168{
    169         struct torture_suite *suite = torture_suite_create(mem_ctx, "TDR");
     169        struct torture_suite *suite = torture_suite_create(mem_ctx, "tdr");
    170170
    171171        torture_suite_add_simple_test(suite, "pull_uint8", test_pull_uint8);
  • vendor/current/lib/tevent/libtevent.m4

    r414 r740  
    3131TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o"
    3232TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o"
     33TEVENT_OBJ="$TEVENT_OBJ tevent_poll.o"
    3334
    3435AC_CHECK_HEADERS(sys/epoll.h)
  • vendor/current/lib/tevent/testsuite.c

    r618 r740  
    149149struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
    150150{
    151         struct torture_suite *suite = torture_suite_create(mem_ctx, "EVENT");
     151        struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
    152152        const char **list = event_backend_list(suite);
    153153        int i;
  • vendor/current/lib/tevent/tevent.c

    r427 r740  
    8989        }
    9090
    91         e = talloc(talloc_autofree_context(), struct tevent_ops_list);
     91        e = talloc(NULL, struct tevent_ops_list);
    9292        if (e == NULL) return false;
    9393
     
    105105{
    106106        talloc_free(tevent_default_backend);
    107         tevent_default_backend = talloc_strdup(talloc_autofree_context(),
    108                                                backend);
     107        tevent_default_backend = talloc_strdup(NULL, backend);
    109108}
    110109
     
    115114{
    116115        tevent_select_init();
     116        tevent_poll_init();
    117117        tevent_standard_init();
    118118#ifdef HAVE_EPOLL
     
    263263  add a fd based event
    264264  return NULL on failure (memory allocation error)
    265 
    266   if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when
    267   the returned fd_event context is freed
    268265*/
    269266struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
     
    617614        return ev->ops->loop_wait(ev, location);
    618615}
     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*/
     625int 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  
    4141struct tevent_signal;
    4242
     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
    4355/* event handler types */
     56/**
     57 * Called when a file descriptor monitored by tevent has
     58 * data to be read or written on it.
     59 */
    4460typedef void (*tevent_fd_handler_t)(struct tevent_context *ev,
    4561                                    struct tevent_fd *fde,
    4662                                    uint16_t flags,
    4763                                    void *private_data);
     64
     65/**
     66 * Called when tevent is ceasing the monitoring of a file descriptor.
     67 */
    4868typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev,
    4969                                     struct tevent_fd *fde,
    5070                                     int fd,
    5171                                     void *private_data);
     72
     73/**
     74 * Called when a tevent timer has fired.
     75 */
    5276typedef void (*tevent_timer_handler_t)(struct tevent_context *ev,
    5377                                       struct tevent_timer *te,
    5478                                       struct timeval current_time,
    5579                                       void *private_data);
     80
     81/**
     82 * Called when a tevent immediate event is invoked.
     83 */
    5684typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx,
    5785                                           struct tevent_immediate *im,
    5886                                           void *private_data);
     87
     88/**
     89 * Called after tevent detects the specified signal.
     90 */
    5991typedef void (*tevent_signal_handler_t)(struct tevent_context *ev,
    6092                                        struct tevent_signal *se,
     
    6496                                        void *private_data);
    6597
     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 */
    66111struct 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 */
    67126struct 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 */
    68136const 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 */
    69143void tevent_set_default_backend(const char *backend);
    70144
     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 */
     166struct 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
    71173struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
    72174                                 TALLOC_CTX *mem_ctx,
     
    80182        _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \
    81183                       #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 */
     216struct 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
    83222struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
    84223                                       TALLOC_CTX *mem_ctx,
     
    91230        _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \
    92231                          #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 */
     248struct tevent_immediate *tevent_create_immediate(TALLOC_CTX *mem_ctx);
     249#else
    94250struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
    95251                                                  const char *location);
    96252#define tevent_create_immediate(mem_ctx) \
    97253        _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 */
     268void tevent_schedule_immediate(struct tevent_immediate *im,
     269                struct tevent_context *ctx,
     270                tevent_immediate_handler_t handler,
     271                void *private_data);
     272#else
    99273void _tevent_schedule_immediate(struct tevent_immediate *im,
    100274                                struct tevent_context *ctx,
     
    106280        _tevent_schedule_immediate(im, ctx, handler, private_data, \
    107281                                   #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 */
     309struct 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
    109316struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
    110317                                         TALLOC_CTX *mem_ctx,
     
    118325        _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \
    119326                           #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 */
     339int tevent_loop_once(struct tevent_context *ev);
     340#else
    121341int _tevent_loop_once(struct tevent_context *ev, const char *location);
    122342#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 */
     357int tevent_loop_wait(struct tevent_context *ev);
     358#else
    125359int _tevent_loop_wait(struct tevent_context *ev, const char *location);
    126360#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 */
    129375void tevent_fd_set_close_fn(struct tevent_fd *fde,
    130376                            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 */
    131385void 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 */
    132395uint16_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 */
    133404void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags);
    134405
     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 */
    135413bool tevent_signal_support(struct tevent_context *ev);
    136414
     
    138416
    139417/* bits for file descriptor event flags */
     418
     419/**
     420 * Monitor a file descriptor for write availability
     421 */
    140422#define TEVENT_FD_READ 1
     423/**
     424 * Monitor a file descriptor for data to be read
     425 */
    141426#define TEVENT_FD_WRITE 2
    142427
     428/**
     429 * Convenience function for declaring a tevent_fd writable
     430 */
    143431#define TEVENT_FD_WRITEABLE(fde) \
    144432        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 */
    145437#define TEVENT_FD_READABLE(fde) \
    146438        tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_READ)
    147439
     440/**
     441 * Convenience function for declaring a tevent_fd non-writable
     442 */
    148443#define TEVENT_FD_NOT_WRITEABLE(fde) \
    149444        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 */
    150449#define TEVENT_FD_NOT_READABLE(fde) \
    151450        tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ)
    152451
    153 /* DEBUG */
     452/**
     453 * Debug level of tevent
     454 */
    154455enum tevent_debug_level {
    155456        TEVENT_DEBUG_FATAL,
     
    159460};
    160461
     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 */
     473typedef 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 */
    161489int 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,
    166491                     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 */
    167502int tevent_set_debug_stderr(struct tevent_context *ev);
    168503
    169504/**
    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.
    171595 */
    172596enum tevent_req_state {
    173597        /**
    174          * we are creating the request
     598         * We are creating the request
    175599         */
    176600        TEVENT_REQ_INIT,
    177601        /**
    178          * we are waiting the request to complete
     602         * We are waiting the request to complete
    179603         */
    180604        TEVENT_REQ_IN_PROGRESS,
    181605        /**
    182          * the request is finished
     606         * The request is finished successfully
    183607         */
    184608        TEVENT_REQ_DONE,
    185609        /**
    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().
    187613         */
    188614        TEVENT_REQ_USER_ERROR,
    189615        /**
    190          * Request timed out
     616         * Request timed out after the timeout set by tevent_req_set_endtime.
    191617         */
    192618        TEVENT_REQ_TIMED_OUT,
    193619        /**
    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.
    195622         */
    196623        TEVENT_REQ_NO_MEMORY,
    197624        /**
    198          * the request is already received by the caller
     625         * The request has been received by the caller. No further
     626         * action is valid.
    199627         */
    200628        TEVENT_REQ_RECEIVED
     
    203631/**
    204632 * @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 */
    218634struct tevent_req;
    219635
    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 */
     641typedef 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 */
    222656void 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 */
     677void *tevent_req_callback_data(struct tevent_req *req, #type);
     678#else
    223679void *_tevent_req_callback_data(struct tevent_req *req);
    224 void *_tevent_req_data(struct tevent_req *req);
    225 
    226680#define tevent_req_callback_data(_req, _type) \
    227681        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 */
     694void *tevent_req_callback_data_void(struct tevent_req *req);
     695#else
    228696#define tevent_req_callback_data_void(_req) \
    229697        _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 */
     714void *tevent_req_data(struct tevent_req *req, #type);
     715#else
     716void *_tevent_req_data(struct tevent_req *req);
    230717#define tevent_req_data(_req, _type) \
    231718        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 */
     748typedef 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 */
    235763void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn);
    236764
     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 */
    237779char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx);
    238780
     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 */
    239792char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req);
    240793
    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 */
     801typedef 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 */
    243814void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn);
    244815
     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 */
     835bool tevent_req_cancel(struct tevent_req *req);
     836#else
    245837bool _tevent_req_cancel(struct tevent_req *req, const char *location);
    246838#define tevent_req_cancel(req) \
    247839        _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 */
     867struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx,
     868                                     void **pstate, #type);
     869#else
    249870struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
    250871                                      void *pstate,
     
    256877        _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \
    257878                           #_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 */
    259892bool tevent_req_set_endtime(struct tevent_req *req,
    260893                            struct tevent_context *ev,
    261894                            struct timeval endtime);
    262895
     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 */
     904void tevent_req_notify_callback(struct tevent_req *req);
     905#else
    263906void _tevent_req_notify_callback(struct tevent_req *req, const char *location);
    264907#define tevent_req_notify_callback(req)         \
    265908        _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 */
     921void tevent_req_done(struct tevent_req *req);
     922#else
    267923void _tevent_req_done(struct tevent_req *req,
    268924                      const char *location);
    269925#define tevent_req_done(req) \
    270926        _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 */
     960bool tevent_req_error(struct tevent_req *req,
     961                      uint64_t error);
     962#else
    272963bool _tevent_req_error(struct tevent_req *req,
    273964                       uint64_t error,
     
    275966#define tevent_req_error(req, error) \
    276967        _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 */
     988bool tevent_req_nomem(const void *p,
     989                      struct tevent_req *req);
     990#else
    278991bool _tevent_req_nomem(const void *p,
    279992                       struct tevent_req *req,
     
    281994#define tevent_req_nomem(p, req) \
    282995        _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 */
    2841033struct tevent_req *tevent_req_post(struct tevent_req *req,
    2851034                                   struct tevent_context *ev);
    2861035
     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 */
    2871045bool tevent_req_is_in_progress(struct tevent_req *req);
    2881046
     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 */
    2891074bool tevent_req_poll(struct tevent_req *req,
    2901075                     struct tevent_context *ev);
    2911076
     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 */
    2921105bool tevent_req_is_error(struct tevent_req *req,
    2931106                         enum tevent_req_state *state,
    2941107                         uint64_t *error);
    2951108
     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 */
    2961116void tevent_req_received(struct tevent_req *req);
    2971117
     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 */
    2981159struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx,
    2991160                                      struct tevent_context *ev,
    3001161                                      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 */
    3011175bool tevent_wakeup_recv(struct tevent_req *req);
    3021176
     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 */
    3031199int tevent_timeval_compare(const struct timeval *tv1,
    3041200                           const struct timeval *tv2);
    3051201
     1202/**
     1203 * @brief Get a zero timval value.
     1204 *
     1205 * @return              A zero timval value.
     1206 */
    3061207struct timeval tevent_timeval_zero(void);
    3071208
     1209/**
     1210 * @brief Get a timeval value for the current time.
     1211 *
     1212 * @return              A timval value with the current time.
     1213 */
    3081214struct timeval tevent_timeval_current(void);
    3091215
     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 */
    3101225struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs);
    3111226
     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 */
    3121237struct timeval tevent_timeval_until(const struct timeval *tv1,
    3131238                                    const struct timeval *tv2);
    3141239
     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 */
    3151247bool tevent_timeval_is_zero(const struct timeval *tv);
    3161248
     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 */
    3171260struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs,
    3181261                                  uint32_t usecs);
    3191262
     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 */
    3201272struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs);
    3211273
     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
    3221293struct tevent_queue;
    3231294
     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 */
     1308struct tevent_queue *tevent_queue_create(TALLOC_CTX *mem_ctx,
     1309                                         const char *name);
     1310#else
    3241311struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
    3251312                                          const char *name,
     
    3281315#define tevent_queue_create(_mem_ctx, _name) \
    3291316        _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 */
    3311329typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req,
    3321330                                          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 */
    3331349bool tevent_queue_add(struct tevent_queue *queue,
    3341350                      struct tevent_context *ev,
     
    3361352                      tevent_queue_trigger_fn_t trigger,
    3371353                      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 */
    3381362void 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 */
    3391371void tevent_queue_stop(struct tevent_queue *queue);
    3401372
     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 */
    3411380size_t tevent_queue_length(struct tevent_queue *queue);
    3421381
     
    3671406#endif
    3681407
    369 
    370 /**
     1408int tevent_re_initialise(struct tevent_context *ev);
     1409
     1410/* @} */
     1411
     1412/**
     1413 * @defgroup tevent_ops The tevent operation functions
     1414 * @ingroup tevent
     1415 *
    3711416 * The following structure and registration functions are exclusively
    3721417 * needed for people writing and pluggin a different event engine.
    3731418 * There is nothing useful for normal tevent user in here.
     1419 * @{
    3741420 */
    3751421
     
    4241470bool tevent_register_backend(const char *name, const struct tevent_ops *ops);
    4251471
    426 
    427 /**
     1472/* @} */
     1473
     1474/**
     1475 * @defgroup tevent_compat The tevent compatibility functions
     1476 * @ingroup tevent
     1477 *
    4281478 * The following definitions are usueful only for compatibility with the
    4291479 * implementation originally developed within the samba4 code and will be
    4301480 * soon removed. Please NEVER use in new code.
     1481 *
     1482 * @todo Ignore it?
     1483 *
     1484 * @{
    4311485 */
    4321486
     
    5051559#endif /* TEVENT_COMPAT_DEFINES */
    5061560
     1561/* @} */
     1562
    5071563#endif /* __TEVENT_H__ */
  • vendor/current/lib/tevent/tevent.pc.in

    r414 r740  
    99Requires: talloc
    1010Libs: -L${libdir} -ltevent
    11 Cflags: -I${includedir}
     11Cflags: @LIB_RPATH@ -I${includedir}
    1212URL: http://samba.org/
  • vendor/current/lib/tevent/tevent_epoll.c

    r414 r740  
    4343
    4444/*
    45   called when a epoll call fails, and we should fallback
    46   to using select
     45  called when a epoll call fails
    4746*/
    4847static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason)
     
    438437};
    439438
    440 bool tevent_epoll_init(void)
     439_PRIVATE_ bool tevent_epoll_init(void)
    441440{
    442441        return tevent_register_backend("epoll", &epoll_event_ops);
  • vendor/current/lib/tevent/tevent_fd.c

    r414 r740  
    5252        struct tevent_fd *fde;
    5353
     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
    5460        fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd);
    5561        if (!fde) return NULL;
  • vendor/current/lib/tevent/tevent_internal.h

    r427 r740  
    163163        const char *location;
    164164        /* this is private for the events_ops implementation */
    165         uint16_t additional_flags;
     165        uint64_t additional_flags;
    166166        void *additional_data;
    167167};
     
    304304bool tevent_standard_init(void);
    305305bool tevent_select_init(void);
     306bool tevent_poll_init(void);
    306307#ifdef HAVE_EPOLL
    307308bool tevent_epoll_init(void);
  • vendor/current/lib/tevent/tevent_liboop.c

    r414 r740  
    3232 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    3333
    34  NOTE: this code compiles fine, but is completly *UNTESTED*
    35        and is only commited as example
     34 NOTE: this code compiles fine, but is completely *UNTESTED*
     35       and is only committed as an example
    3636
    3737 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   
  • vendor/current/lib/tevent/tevent_req.c

    r414 r740  
    2727#include "tevent_internal.h"
    2828#include "tevent_util.h"
    29 
    30 /**
    31  * @brief The default print function for creating debug messages
    32  * @param[in] req       The request to be printed
    33  * @param[in] mem_ctx   The memory context for the result
    34  * @retval              Text representation of req
    35  *
    36  * The function should not be used by users of the asynx API,
    37  * but custom print function can use it and append custom text
    38  * to the string.
    39  */
    4029
    4130char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
     
    5443}
    5544
    56 /**
    57  * @brief Print an tevent_req structure in debug messages
    58  * @param[in] mem_ctx   The memory context for the result
    59  * @param[in] req       The request to be printed
    60  * @retval              Text representation of req
    61  *
    62  * This function should be used by callers of the async API
    63  */
    64 
    6545char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
    6646{
     
    7151        return req->private_print(req, mem_ctx);
    7252}
    73 
    74 /**
    75  * @brief Create an async request
    76  * @param[in] mem_ctx   The memory context for the result
    77  * @param[in] ev        The event context this async request will be driven by
    78  * @retval              A new async request
    79  *
    80  * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS
    81  */
    8253
    8354struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
     
    134105}
    135106
    136 /**
    137  * @brief An async request has successfully finished
    138  * @param[in] req       The finished request
    139  *
    140  * tevent_req_done is to be used by implementors of async requests. When a
    141  * request is successfully finished, this function calls the user's completion
    142  * function.
    143  */
    144 
    145107void _tevent_req_done(struct tevent_req *req,
    146108                      const char *location)
     
    148110        tevent_req_finish(req, TEVENT_REQ_DONE, location);
    149111}
    150 
    151 /**
    152  * @brief An async request has seen an error
    153  * @param[in] req       The request with an error
    154  * @param[in] error     The error code
    155  *
    156  * tevent_req_done is to be used by implementors of async requests. When a
    157  * request can not successfully completed, the implementation should call this
    158  * 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 be
    163  * \code
    164  * 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  * \endcode
    177  */
    178112
    179113bool _tevent_req_error(struct tevent_req *req,
     
    190124}
    191125
    192 /**
    193  * @brief Helper function for nomem check
    194  * @param[in] p         The pointer to be checked
    195  * @param[in] req       The request being processed
    196  *
    197  * Convenience helper to easily check alloc failure within a callback
    198  * implementing the next step of an async request.
    199  *
    200  * Call pattern would be
    201  * \code
    202  * p = talloc(mem_ctx, bla);
    203  * if (tevent_req_nomem(p, req)) {
    204  *      return;
    205  * }
    206  * \endcode
    207  */
    208 
    209126bool _tevent_req_nomem(const void *p,
    210127                       struct tevent_req *req,
     
    219136
    220137/**
    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.
    225147 */
    226148static void tevent_req_trigger(struct tevent_context *ev,
     
    235157}
    236158
    237 /**
    238  * @brief Finish a request before the caller had the change to set the callback
    239  * @param[in] req       The finished request
    240  * @param[in] ev        The tevent_context for the timed event
    241  * @retval              req will be returned
    242  *
    243  * An implementation of an async request might find that it can either finish
    244  * the request without waiting for an external event, or it can't even start
    245  * 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 an
    247  * immediate timed event. This way the caller can use the same calling
    248  * conventions, independent of whether the request was actually deferred.
    249  */
    250 
    251159struct tevent_req *tevent_req_post(struct tevent_req *req,
    252160                                   struct tevent_context *ev)
     
    257165}
    258166
    259 /**
    260  * @brief This function destroys the attached private data
    261  * @param[in] req       The request to poll
    262  * @retval              The boolean form of "is in progress".
    263  *
    264  * This function can be used to ask if the given request
    265  * is still in progress.
    266  *
    267  * This function is typically used by sync wrapper functions.
    268  */
    269167bool tevent_req_is_in_progress(struct tevent_req *req)
    270168{
     
    276174}
    277175
    278 /**
    279  * @brief This function destroys the attached private data
    280  * @param[in] req       The finished request
    281  *
    282  * This function can be called as last action of a _recv()
    283  * function, it destroys the data attached to the tevent_req.
    284  */
    285176void tevent_req_received(struct tevent_req *req)
    286177{
     
    294185}
    295186
    296 /**
    297  * @brief This function destroys the attached private data
    298  * @param[in] req       The request to poll
    299  * @param[in] ev        The tevent_context to be used
    300  * @retval              If a critical error has happened in the
    301  *                      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 the
    306  * given request to finish.
    307  *
    308  * Note: this should only be used if the given tevent context
    309  *       was created by the caller, to avoid event loop nesting.
    310  *
    311  * This function is typically used by sync wrapper functions.
    312  */
    313187bool tevent_req_poll(struct tevent_req *req,
    314188                     struct tevent_context *ev)
     
    384258}
    385259
    386 /**
    387  * @brief This function sets a print function for the given request
    388  * @param[in] req       The given request
    389  * @param[in] fn        A pointer to the print function
    390  *
    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 was
    393  * called on the given request.
    394  *
    395  * Note: this function should only be used for debugging.
    396  */
    397260void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn)
    398261{
     
    400263}
    401264
    402 /**
    403  * @brief This function sets a cancel function for the given request
    404  * @param[in] req       The given request
    405  * @param[in] fn        A pointer to the cancel function
    406  *
    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 was
    409  * called on the given request.
    410  *
    411  */
    412265void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn)
    413266{
     
    415268}
    416269
    417 /**
    418  * @brief This function tries to cancel the given request
    419  * @param[in] req       The given request
    420  * @param[in] location  Automaticly filled with the __location__ macro
    421  *                      via the tevent_req_cancel() macro. This is for debugging
    422  *                      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 implementation
    429  * 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 wait
    432  *       for the function to complete normally.
    433  *       Only the _recv() function of the given request indicates
    434  *       if the request was really canceled.
    435  */
    436270bool _tevent_req_cancel(struct tevent_req *req, const char *location)
    437271{
  • vendor/current/lib/tevent/tevent_select.c

    r591 r740  
    122122        if (!fde) return NULL;
    123123
    124         if (fde->fd > select_ev->maxfd) {
     124        if ((select_ev->maxfd != EVENT_INVALID_MAXFD)
     125            && (fde->fd > select_ev->maxfd)) {
    125126                select_ev->maxfd = fde->fd;
    126127        }
     
    252253};
    253254
    254 bool tevent_select_init(void)
     255_PRIVATE_ bool tevent_select_init(void)
    255256{
    256257        return tevent_register_backend("select", &select_event_ops);
  • vendor/current/lib/tevent/tevent_signal.c

    r618 r740  
    211211           multiple event contexts */
    212212        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);
    214214                if (sig_state == NULL) {
    215215                        return NULL;
  • vendor/current/lib/tevent/tevent_standard.c

    r591 r740  
    462462                        return -1;
    463463                }
    464 
    465464                if (fde->flags & TEVENT_FD_READ) {
    466465                        FD_SET(fde->fd, &r_fds);
     
    511510                        if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
    512511                        if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
    513                         if (flags) {
     512                        if (flags & fde->flags) {
    514513                                fde->handler(std_ev->ev, fde, flags, fde->private_data);
    515514                                break;
     
    568567
    569568
    570 bool tevent_standard_init(void)
     569_PRIVATE_ bool tevent_standard_init(void)
    571570{
    572571        return tevent_register_backend("standard", &std_event_ops);
  • vendor/current/lib/tevent/tevent_timed.c

    r414 r740  
    198198  do a single event loop using the events defined in ev
    199199
    200   return the delay untill the next timed event,
     200  return the delay until the next timed event,
    201201  or zero if a timed event was triggered
    202202*/
     
    209209                /* have a default tick time of 30 seconds. This guarantees
    210210                   that code that uses its own timeout checking will be
    211                    able to proceeed eventually */
     211                   able to proceed eventually */
    212212                return tevent_timeval_set(30, 0);
    213213        }
  • vendor/current/lib/tevent/tevent_util.h

    r414 r740  
    22   Unix SMB/CIFS implementation.
    33
    4    Copyright (C) Andrew Tridgell 1998-2005
     4   Copyright (C) Andrew Tridgell 1998-2010
    55   Copyright (C) Jelmer Vernooij 2005
    66
     
    2525#define _DLINKLIST_H
    2626
     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.
    2731
    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*/
    2966#define DLIST_ADD(list, p) \
    3067do { \
    3168        if (!(list)) { \
    32                 (list) = (p); \
    33                 (p)->next = (p)->prev = NULL; \
     69                (p)->prev = (list) = (p); \
     70                (p)->next = NULL; \
    3471        } else { \
     72                (p)->prev = (list)->prev; \
    3573                (list)->prev = (p); \
    3674                (p)->next = (list); \
    37                 (p)->prev = NULL; \
    3875                (list) = (p); \
    39         }\
     76        } \
    4077} while (0)
    4178
    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*/
    4384#define DLIST_REMOVE(list, p) \
    4485do { \
    4586        if ((p) == (list)) { \
     87                if ((p)->next) (p)->next->prev = (p)->prev; \
    4688                (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; \
    4892        } else { \
    4993                if ((p)->prev) (p)->prev->next = (p)->next; \
    5094                if ((p)->next) (p)->next->prev = (p)->prev; \
    5195        } \
    52         if ((p) != (list)) (p)->next = (p)->prev = NULL; \
     96        if ((p) != (list)) (p)->next = (p)->prev = NULL;        \
    5397} while (0)
    5498
    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) \
    57105do { \
    58           DLIST_REMOVE(list, p); \
    59           DLIST_ADD(list, p); \
    60 } while (0)
     106       (result_head) = (p); \
     107       while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
     108} while(0)
    61109
    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)
    76115
    77116/* insert 'p' after the given element 'el' in a list. If el is NULL then
     
    82121                DLIST_ADD(list, p); \
    83122        } 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); \
    88128        }\
    89129} while (0)
    90130
    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)                    \
    93137do { \
    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        } \
    96143} while (0)
    97144
    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) \
    101147do { \
    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)                     \
     157do { \
     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)   \
     168do { \
     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; \
    111177                } \
     178        } \
    112179} while (0)
    113180
  • vendor/current/lib/torture/subunit.c

    r414 r740  
    2020#include "includes.h"
    2121#include "lib/torture/torture.h"
     22#include <subunit/child.h>
    2223
    23 static void subunit_suite_start(struct torture_context *ctx,
     24static void torture_subunit_suite_start(struct torture_context *ctx,
    2425                                struct torture_suite *suite)
    2526{
    2627}
    2728
    28 static void subunit_print_testname(struct torture_context *ctx,
     29static char *torture_subunit_test_name(struct torture_context *ctx,
    2930                                   struct torture_tcase *tcase,
    3031                                   struct torture_test *test)
    3132{
    3233        if (!strcmp(tcase->name, test->name)) {
    33                 printf("%s", test->name);
     34                return talloc_strdup(ctx, test->name);
    3435        } else {
    35                 printf("%s.%s", tcase->name, test->name);
     36                return talloc_asprintf(ctx, "%s.%s", tcase->name, test->name);
    3637        }
    3738}
    3839
    39 static void subunit_test_start(struct torture_context *ctx,
     40static 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
     64static void torture_subunit_test_start(struct torture_context *context,
    4065                               struct torture_tcase *tcase,
    4166                               struct torture_test *test)
    4267{
    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);
    4672}
    4773
    48 static void subunit_test_result(struct torture_context *context,
     74static void torture_subunit_test_result(struct torture_context *context,
    4975                                enum torture_result res, const char *reason)
    5076{
     77        char *fullname = torture_subunit_test_name(context, context->active_tcase, context->active_test);
     78        torture_subunit_report_time(context);
    5179        switch (res) {
    5280        case TORTURE_OK:
    53                 printf("success: ");
     81                subunit_test_pass(fullname);
    5482                break;
    5583        case TORTURE_FAIL:
    56                 printf("failure: ");
     84                subunit_test_fail(fullname, reason);
    5785                break;
    5886        case TORTURE_ERROR:
    59                 printf("error: ");
     87                subunit_test_error(fullname, reason);
    6088                break;
    6189        case TORTURE_SKIP:
    62                 printf("skip: ");
     90                subunit_test_skip(fullname, reason);
    6391                break;
    6492        }
    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);
    7094}
    7195
    72 static void subunit_comment(struct torture_context *test,
     96static void torture_subunit_comment(struct torture_context *test,
    7397                            const char *comment)
    7498{
     
    76100}
    77101
    78 static void subunit_warning(struct torture_context *test,
     102static void torture_subunit_warning(struct torture_context *test,
    79103                            const char *comment)
    80104{
     
    82106}
    83107
     108static 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
    84129const 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,
    90137};
  • vendor/current/lib/torture/torture.c

    r414 r740  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33   SMB torture UI functions
    44
    55   Copyright (C) Jelmer Vernooij 2006-2008
    6    
     6
    77   This program is free software; you can redistribute it and/or modify
    88   it under the terms of the GNU General Public License as published by
    99   the Free Software Foundation; either version 3 of the License, or
    1010   (at your option) any later version.
    11    
     11
    1212   This program is distributed in the hope that it will be useful,
    1313   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515   GNU General Public License for more details.
    16    
     16
    1717   You should have received a copy of the GNU General Public License
    1818   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424#include "param/param.h"
    2525#include "system/filesys.h"
     26#include "system/dir.h"
     27
    2628
    2729struct torture_results *torture_results_init(TALLOC_CTX *mem_ctx, const struct torture_ui_ops *ui_ops)
     
    7274
    7375        return subtorture;
    74 }       
    75 
    76 /**
    77  create a temporary directory.
     76}
     77
     78/**
     79 create a temporary directory under the output dir
    7880*/
    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)
    8283{
    8384        SMB_ASSERT(tctx->outputdir != NULL);
    8485
    85         *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir, 
     86        *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir,
    8687                                   prefix);
    8788        NT_STATUS_HAVE_NO_MEMORY(*tempdir);
     
    9192        }
    9293
     94        return NT_STATUS_OK;
     95}
     96
     97static 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        }
    93161        return NT_STATUS_OK;
    94162}
     
    108176        tmp = talloc_vasprintf(context, comment, ap);
    109177        va_end(ap);
    110                
     178
    111179        context->results->ui_ops->comment(context, tmp);
    112        
     180
    113181        talloc_free(tmp);
    114182}
     
    246314}
    247315
     316int 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
    248333/**
    249334 * Run a torture test suite.
     
    251336bool torture_run_suite(struct torture_context *context,
    252337                       struct torture_suite *suite)
     338{
     339        return torture_run_suite_restricted(context, suite, NULL);
     340}
     341
     342bool torture_run_suite_restricted(struct torture_context *context,
     343                       struct torture_suite *suite, const char **restricted)
    253344{
    254345        bool ret = true;
    255346        struct torture_tcase *tcase;
    256347        struct torture_suite *tsuite;
    257         char *old_testname;
    258348
    259349        if (context->results->ui_ops->suite_start)
    260350                context->results->ui_ops->suite_start(context, suite);
    261351
    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);
    268355
    269356        for (tcase = suite->testcases; tcase; tcase = tcase->next) {
    270                 ret &= torture_run_tcase(context, tcase);
     357                ret &= torture_run_tcase_restricted(context, tcase, restricted);
    271358        }
    272359
    273360        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        }
    279365
    280366        if (context->results->ui_ops->suite_finish)
     
    303389}
    304390
     391static 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
    305403static bool internal_torture_run_test(struct torture_context *context,
    306404                                          struct torture_tcase *tcase,
    307405                                          struct torture_test *test,
    308                                           bool already_setup)
     406                                          bool already_setup,
     407                                          const char **restricted)
    309408{
    310409        bool success;
    311         char *old_testname = NULL;
     410        char *subunit_testname = NULL;
    312411
    313412        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;
    317420
    318421        context->active_tcase = tcase;
     
    358461        talloc_free(context->last_reason);
    359462
    360         if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {
    361                 talloc_free(context->active_testname);
    362                 context->active_testname = old_testname;
    363         }
    364463        context->active_test = NULL;
    365464        context->active_tcase = NULL;
     
    368467}
    369468
    370 bool torture_run_tcase(struct torture_context *context, 
     469bool torture_run_tcase(struct torture_context *context,
    371470                       struct torture_tcase *tcase)
    372471{
     472        return torture_run_tcase_restricted(context, tcase, NULL);
     473}
     474
     475bool torture_run_tcase_restricted(struct torture_context *context,
     476                       struct torture_tcase *tcase, const char **restricted)
     477{
    373478        bool ret = true;
    374         char *old_testname;
    375479        struct torture_test *test;
     480        bool setup_succeeded = true;
     481        const char * setup_reason = "Setup failed";
    376482
    377483        context->active_tcase = tcase;
     
    379485                context->results->ui_ops->tcase_start(context, tcase);
    380486
    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)) {
    388517                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
    407520        context->active_tcase = NULL;
     521        context->active_test = NULL;
    408522
    409523        if (context->results->ui_ops->tcase_finish)
    410524                context->results->ui_ops->tcase_finish(context, tcase);
    411525
    412         return ret;
     526        return (!setup_succeeded) ? false : ret;
    413527}
    414528
     
    417531                                          struct torture_test *test)
    418532{
    419         return internal_torture_run_test(context, tcase, test, false);
     533        return internal_torture_run_test(context, tcase, test, false, NULL);
     534}
     535
     536bool 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);
    420542}
    421543
     
    423545                                                        int default_value)
    424546{
    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
     550unsigned 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);
    426556}
    427557
     
    429559                                                        double default_value)
    430560{
    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);
    432562}
    433563
     
    435565                                                        bool default_value)
    436566{
    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);
    438568}
    439569
     
    447577        SMB_ASSERT(test->lp_ctx != NULL);
    448578       
    449         ret = lp_parm_string(test->lp_ctx, NULL, "torture", name);
     579        ret = lpcfg_parm_string(test->lp_ctx, NULL, "torture", name);
    450580
    451581        if (ret == NULL)
     
    620750        return test;
    621751}
     752
     753void 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  
    3333        TORTURE_ERROR=2,
    3434        TORTURE_SKIP=3
     35};
     36
     37enum torture_progress_whence {
     38        TORTURE_PROGRESS_SET,
     39        TORTURE_PROGRESS_CUR,
     40        TORTURE_PROGRESS_POP,
     41        TORTURE_PROGRESS_PUSH,
    3542};
    3643
     
    5360        void (*test_result) (struct torture_context *,
    5461                                                 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 *);
    5564};
    5665
     
    6271                                                                enum torture_result result,
    6372                                                                const char *comment);
     73
     74void torture_ui_report_time(struct torture_context *context);
    6475
    6576/*
     
    7788        struct torture_results *results;
    7889
    79         char *active_testname;
    8090        struct torture_test *active_test;
    8191        struct torture_tcase *active_tcase;
     
    8696        /** Directory used for temporary test data */
    8797        const char *outputdir;
    88        
     98
    8999        /** Event context */
    90100        struct tevent_context *ev;
     
    211221                                           struct torture_suite *suite);
    212222
     223/* Run the specified testsuite recursively, but only the specified
     224 * tests */
     225bool torture_run_suite_restricted(struct torture_context *context,
     226                       struct torture_suite *suite, const char **restricted);
     227
    213228/* Run the specified testcase */
    214229bool torture_run_tcase(struct torture_context *context,
    215230                                           struct torture_tcase *tcase);
     231
     232bool torture_run_tcase_restricted(struct torture_context *context,
     233                       struct torture_tcase *tcase, const char **restricted);
    216234
    217235/* Run the specified test */
     
    220238                                          struct torture_test *test);
    221239
     240bool torture_run_test_restricted(struct torture_context *context,
     241                                          struct torture_tcase *tcase,
     242                                          struct torture_test *test,
     243                                          const char **restricted);
     244
    222245void torture_comment(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
    223246void torture_warning(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
     
    229252                torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \
    230253                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; \
    231261        }
    232262
     
    278308                                           __location__": "#got" was %s, expected %s: %s", \
    279309                                           __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); \
    280320                return false; \
    281321        } \
     
    358398        if (__got != __expected) { \
    359399                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); \
    362402                return false; \
    363403        } \
     
    368408        if (__got != __expected) { \
    369409                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); \
    372412                ret = false; \
    373413                goto label; \
     
    379419        if (__got != __expected) { \
    380420                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; \
    384439        } \
    385440        } while(0)
     
    396451        } while(0)
    397452
    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)
    399460
    400461#define torture_skip(torture_ctx,cmt) do {\
     
    450511                                                                                 const char *name);
    451512
     513unsigned long torture_setting_ulong(struct torture_context *test,
     514                                    const char *name,
     515                                    unsigned long default_value);
     516
    452517NTSTATUS torture_temp_dir(struct torture_context *tctx,
    453518                                   const char *prefix,
    454519                                   char **tempdir);
     520NTSTATUS torture_deltree_outputdir(struct torture_context *tctx);
    455521
    456522struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase,
     
    462528                              struct torture_tcase *tcase,
    463529                              const char *name);
     530int torture_suite_children_count(const struct torture_suite *suite);
    464531
    465532struct torture_context *torture_context_init(struct tevent_context *event_ctx, struct torture_results *results);
  • vendor/current/lib/torture/torture.pc.in

    r414 r740  
    99Requires: talloc
    1010Version: 0.0.1
    11 Libs: -L${libdir} -ltorture
     11Libs: @LIB_RPATH@ -L${libdir} -ltorture
    1212Cflags: -I${includedir}  -DHAVE_IMMEDIATE_STRUCTURES=1
  • vendor/current/lib/tsocket/tsocket.c

    r414 r740  
    4747                return -1;
    4848        default:
    49                 *perrno = EIO;
    50                 return -1;
     49                break;
    5150        }
    5251
  • vendor/current/lib/tsocket/tsocket.h

    r478 r740  
    8484
    8585/**
    86  * @brief Get a string representaion of the endpoint.
     86 * @brief Get a string representation of the endpoint.
    8787 *
    8888 * This function creates a string representation of the endpoint for debugging.
     
    102102 * @return              The address as a string representation, NULL on error.
    103103 *
     104 * @see tsocket_address_is_inet()
    104105 * @see tsocket_address_inet_addr_string()
    105106 * @see tsocket_address_inet_port()
     
    486487 * @{
    487488 */
     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 */
     502bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam);
    488503
    489504#if DOXYGEN
     
    534549 * @return              A newly allocated string of the address, NULL on error
    535550 *                      with errno set.
     551 *
     552 * @see tsocket_address_is_inet()
    536553 */
    537554char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
     
    559576                                  uint16_t port);
    560577
     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 */
     586bool tsocket_address_is_unix(const struct tsocket_address *addr);
     587
    561588#ifdef DOXYGEN
    562589/**
     
    570597 *
    571598 * @return              0 on success, -1 on error with errno set.
     599 *
     600 * @see tsocket_address_is_unix()
    572601 */
    573602int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
     
    696725 * @param[in]  mem_ctx  The talloc memory context to use.
    697726 *
    698  * @param[in] stream   A tstream_context pointer to setup the tcp communication
     727 * @param[out] stream   A tstream_context pointer to setup the tcp communication
    699728 *                      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.
    700732 *
    701733 * @return              0 on success, -1 on error with perrno set.
     
    704736                                  int *perrno,
    705737                                  TALLOC_CTX *mem_ctx,
    706                                   struct tstream_context **stream);
     738                                  struct tstream_context **stream,
     739                                  struct tsocket_address **local)
    707740#else
    708741int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
     
    710743                                   TALLOC_CTX *mem_ctx,
    711744                                   struct tstream_context **stream,
     745                                   struct tsocket_address **local,
    712746                                   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, \
    715749                                       __location__)
    716750#endif
     
    874908 * freed. If you still want to use the fd you have have to create a duplicate.
    875909 *
    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.
    886930 */
    887931int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
  • vendor/current/lib/tsocket/tsocket_bsd.c

    r478 r740  
    264264
    265265        bsda->sa_socklen = sa_socklen;
     266#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
     267        bsda->u.sa.sa_len = bsda->sa_socklen;
     268#endif
    266269
    267270        *_addr = addr;
     
    292295
    293296        memcpy(sa, &bsda->u.ss, sa_socklen);
     297#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
     298        sa->sa_len = sa_socklen;
     299#endif
    294300        return sa_socklen;
     301}
     302
     303bool 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;
    295338}
    296339
     
    465508
    466509        return 0;
     510}
     511
     512bool 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;
    467527}
    468528
     
    847907        ZERO_STRUCTP(bsda);
    848908        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
    849912
    850913        ret = recvfrom(bsds->fd, state->buf, state->len, 0,
     
    10541117        }
    10551118
     1119        TALLOC_FREE(bsds->fde);
    10561120        ret = close(bsds->fd);
    10571121        bsds->fd = -1;
     
    11841248        fd = socket(sa_fam, SOCK_DGRAM, 0);
    11851249        if (fd < 0) {
    1186                 return fd;
     1250                return -1;
    11871251        }
    11881252
    11891253        fd = tsocket_bsd_common_prepare_fd(fd, true);
    11901254        if (fd < 0) {
    1191                 return fd;
     1255                return -1;
    11921256        }
    11931257
     
    12171281                        talloc_free(dgram);
    12181282                        errno = saved_errno;
    1219                         return ret;
     1283                        return -1;
    12201284                }
    12211285        }
     
    12311295                        talloc_free(dgram);
    12321296                        errno = saved_errno;
    1233                         return ret;
     1297                        return -1;
    12341298                }
    12351299        }
     
    12441308                        talloc_free(dgram);
    12451309                        errno = saved_errno;
    1246                         return ret;
     1310                        return -1;
    12471311                }
    12481312        }
     
    12541318                        talloc_free(dgram);
    12551319                        errno = saved_errno;
    1256                         return ret;
     1320                        return -1;
    12571321                }
    12581322        }
     
    12701334                        talloc_free(dgram);
    12711335                        errno = saved_errno;
    1272                         return ret;
     1336                        return -1;
    12731337                }
    12741338        }
     
    16101674                        base = (uint8_t *)state->vector[0].iov_base;
    16111675                        base += ret;
    1612                         state->vector[0].iov_base = base;
     1676                        state->vector[0].iov_base = (void *)base;
    16131677                        state->vector[0].iov_len -= ret;
    16141678                        break;
     
    17701834                        base = (uint8_t *)state->vector[0].iov_base;
    17711835                        base += ret;
    1772                         state->vector[0].iov_base = base;
     1836                        state->vector[0].iov_base = (void *)base;
    17731837                        state->vector[0].iov_len -= ret;
    17741838                        break;
     
    18411905        }
    18421906
     1907        TALLOC_FREE(bsds->fde);
    18431908        ret = close(bsds->fd);
    18441909        bsds->fd = -1;
     
    19181983        struct tevent_fd *fde;
    19191984        struct tstream_conext *stream;
     1985        struct tsocket_address *local;
    19201986};
    19211987
     
    19362002                                            void *private_data);
    19372003
    1938 static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
     2004static struct tevent_req *tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
    19392005                                        struct tevent_context *ev,
    19402006                                        int sys_errno,
     
    19472013                talloc_get_type_abort(local->private_data,
    19482014                struct tsocket_address_bsd);
     2015        struct tsocket_address_bsd *lrbsda = NULL;
    19492016        struct tsocket_address_bsd *rbsda =
    19502017                talloc_get_type_abort(remote->private_data,
     
    20262093        }
    20272094
     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
    20282112        state->fd = socket(sa_fam, SOCK_STREAM, 0);
    20292113        if (state->fd == -1) {
     
    20822166        }
    20832167        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);
    20842179                goto post;
    20852180        }
     
    21142209        struct tstream_bsd_connect_state *state = tevent_req_data(req,
    21152210                                        struct tstream_bsd_connect_state);
     2211        struct tsocket_address_bsd *lrbsda = NULL;
    21162212        int ret;
    21172213        int error=0;
     
    21362232        }
    21372233
     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
    21382248        tevent_req_done(req);
    21392249}
     
    21432253                                    TALLOC_CTX *mem_ctx,
    21442254                                    struct tstream_context **stream,
     2255                                    struct tsocket_address **local,
    21452256                                    const char *location)
    21462257{
     
    21612272                TALLOC_FREE(state->fde);
    21622273                state->fd = -1;
     2274
     2275                if (local) {
     2276                        *local = talloc_move(mem_ctx, &state->local);
     2277                }
    21632278        }
    21642279
     
    22002315                                   TALLOC_CTX *mem_ctx,
    22012316                                   struct tstream_context **stream,
     2317                                   struct tsocket_address **local,
    22022318                                   const char *location)
    22032319{
    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);
    22052323}
    22062324
     
    22352353                                      const char *location)
    22362354{
    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);
    22382358}
    22392359
  • vendor/current/lib/tsocket/tsocket_guide.txt

    r414 r740  
    2424===============================
    2525
    26 The tsocket_address represents an socket endpoint genericly.
    27 As it's like an abstract class it has no specific constructor.
    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 parse
    32 the string! The should use additional methods of the specific
    33 tsocket_address implemention to get more details.
     26A tsocket_address represents a generic socket endpoint.
     27It behaves like an abstract class, therefore it has no direct constructor.
     28Constructors are described in later sections of this document.
     29
     30A function get the string representation of an endpoint for debugging is
     31available but callers SHOULD NOT try to parse this string. To get more
     32details callers should use getter methods of the specific tsocket_address
     33implemention.
    3434
    3535  char *tsocket_address_string(const struct tsocket_address *addr,
    3636      TALLOC_CTX *mem_ctx);
    3737
    38 There's a function to create a copy of the tsocket_address.
    39 This is useful when before doing modifications to a socket
     38A function to create a copy of the tsocket_address is also avilable.
     39This is useful before doing modifications to a socket
    4040via additional methods of the specific tsocket_address implementation.
    4141
     
    4848The tdgram_context is like an abstract class for datagram
    4949based 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.
     50functions similar to recvfrom(2)/sendto(2)/close(2) syscalls.
    5251
    5352The tdgram_recvfrom_send() method can be called to ask for the
    54 next available datagram on the abstracted tdgram_context.
     53next available datagram from the abstracted tdgram_context.
    5554It returns a 'tevent_req' handle, where the caller can register
    5655a callback with tevent_req_set_callback(). The callback is triggered
    57 when a datagram is available or an error happened.
     56when a datagram is available or an error occurs.
    5857
    5958The callback is then supposed to get the result by calling
     
    123122===============================
    124123
    125 The tstream_context is like an abstract class for stream
     124A tstream_context is like an abstract class for stream
    126125based 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!).
     126functions similar to the readv(2)/writev(2)/close(2) syscalls.
     127
     128The tstream_pending_bytes() function is able to report how many bytes of
     129the incoming stream have been received but have not been consumed yet.
     130It returns -1 and sets 'errno' on failure.
     131Otherwise it returns the number of uncomsumed bytes (it can return 0!).
    135132
    136133  ssize_t tstream_pending_bytes(struct tstream_context *stream);
    137134
    138 The tstream_readv_send() method can be called to read for a
     135The tstream_readv_send() method can be called to read a
    139136specific amount of bytes from the stream into the buffers
    140137of the given iovec vector. The caller has to preallocate the buffers
     
    144141where the caller can register a callback with tevent_req_set_callback().
    145142The callback is triggered when all iovec buffers are completely
    146 filled with bytes from the socket or an error happened.
     143filled with bytes from the socket or an error occurs.
    147144
    148145The callback is then supposed to get the result by calling
    149146tstream_readv_recv() on the 'tevent_req'. It returns -1
    150147and sets '*perrno' to the actual 'errno' on failure.
    151 Otherwise it returns the length of the datagram
    152 (0 is never returned!).
     148Otherwise it returns the length of the datagram (0 is never returned!).
    153149
    154150The caller can only have one outstanding tstream_readv_send()
     
    166162The tstream_writev_send() method can be called to write
    167163buffers in the given iovec vector into the stream socket.
    168 It's invalid to pass an empty vector.
     164It is invalid to pass an empty vector.
    169165tstream_writev_send() returns a 'tevent_req' handle,
    170166where the caller can register a callback with tevent_req_set_callback().
     
    190186      int *perrno);
    191187
    192 The tstream_disconnect_send() method should be used to normally
     188The tstream_disconnect_send() method should normally be used to
    193189shutdown/close the abstracted socket.
    194190
     
    209205============================
    210206
    211 In order to make the live easier for callers which want to implement
     207In order to simplify the job, for callers that want to implement
    212208a function to receive a full PDU with a single async function pair,
    213 there're some helper functions.
     209some helper functions are provided.
    214210
    215211The caller can use the tstream_readv_pdu_send() function
     
    217213The caller needs to provide a "next_vector" function and a private
    218214state for this function. The tstream_readv_pdu engine will ask
    219 the next_vector function for the next iovec vetor to be filled.
     215the next_vector function for the next iovec vector to be used.
    220216There's a tstream_readv_send/recv pair for each vector returned
    221217by the next_vector function. If the next_vector function detects
     
    223219of the tevent_req (returned by tstream_readv_pdu_send()) is triggered.
    224220Note: the buffer allocation is completely up to the next_vector function
    225 and it's private state.
     221and its private state.
    226222
    227223See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
     
    245241===========================================
    246242
    247 There're some cases where the caller wants doesn't care about the
    248 order of doing IO on the abstracted sockets.
     243In some cases the caller doesn't care about the IO ordering on the
     244abstracted socket.
    249245(Remember at the low level there's always only one IO in a specific
    250246 direction allowed, only one tdgram_sendto_send() at a time).
    251247
    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 the operations.
     248Some helpers that use 'tevent_queue' are avilable to simplify handling
     249multiple IO requests. The functions just get a 'queue' argument and
     250internally serialize all operations.
    255251
    256252  struct tevent_req *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx,
     
    296292(dns names are not allowed!). But it's valid to pass NULL,
    297293which gets mapped to "0.0.0.0" or "::".
    298 It return -1 and set errno on error. Otherwise it returns 0.
     294It returns -1 and sets errno on error. Otherwise it returns 0.
    299295
    300296  int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
     
    343339you can use the tsocket_address_unix_path() function.
    344340It will return NULL and set errno to EINVAL if the tsocket_address
    345 doesn't represent an unix domain endpoint path.
     341doesn't represent a unix domain endpoint path.
    346342
    347343  char *tsocket_address_unix_path(const struct tsocket_address *addr,
     
    372368      struct tdgram_context **dgram);
    373369
    374 You can use tstream_inet_tcp_connect_send to async
     370You can use tstream_inet_tcp_connect_send to asynchronously
    375371connect to a remote ipv4 or ipv6 TCP endpoint and create a
    376372tstream_context for the stream based communication. "local_address" has to be
     
    398394      struct tstream_context **stream);
    399395
    400 You can use tstream_unix_connect_send to async
     396You can use tstream_unix_connect_send to asynchronously
    401397connect to a unix domain endpoint and create a
    402398tstream_context for the stream based communication.
     
    439435for that. This should only be used if really needed, because of
    440436already existing fixed APIs. Only AF_INET, AF_INET6 and AF_UNIX
    441 sockets are allowed. The function returns -1 and set errno on error.
     437sockets are allowed. The function returns -1 and sets errno on error.
    442438Otherwise it returns 0.
    443439
  • vendor/current/lib/uid_wrapper/uid_wrapper.c

    r414 r740  
    1616 */
    1717
     18#ifdef _SAMBA_BUILD_
     19
    1820#define UID_WRAPPER_NOT_REPLACE
    19 #include "includes.h"
     21#include "../replace/replace.h"
     22#include <talloc.h>
    2023#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
    2230
    2331#ifndef _PUBLIC_
     
    4553                /* put us in one group */
    4654                uwrap.ngroups = 1;
    47                 uwrap.groups = talloc_array(talloc_autofree_context(), gid_t, 1);
     55                uwrap.groups = talloc_array(NULL, gid_t, 1);
    4856                uwrap.groups[0] = 0;
    4957        }
     
    109117
    110118        if (size != 0) {
    111                 uwrap.groups = talloc_array(talloc_autofree_context(), gid_t, size);
     119                uwrap.groups = talloc_array(NULL, gid_t, size);
    112120                if (uwrap.groups == NULL) {
    113121                        errno = ENOMEM;
  • vendor/current/lib/uid_wrapper/uid_wrapper.h

    r414 r740  
    1818#ifndef __UID_WRAPPER_H__
    1919#define __UID_WRAPPER_H__
     20#ifndef uwrap_enabled
     21
     22int uwrap_enabled(void);
     23int uwrap_seteuid(uid_t euid);
     24uid_t uwrap_geteuid(void);
     25int uwrap_setegid(gid_t egid);
     26uid_t uwrap_getegid(void);
     27int uwrap_setgroups(size_t size, const gid_t *list);
     28int uwrap_getgroups(int size, gid_t *list);
     29uid_t uwrap_getuid(void);
     30gid_t uwrap_getgid(void);
    2031
    2132#ifdef seteuid
     
    5970#define getgid  uwrap_getgid
    6071
    61 int uwrap_enabled(void);
    62 
     72#endif
    6373#endif /* __UID_WRAPPER_H__ */
  • vendor/current/lib/util/asn1.c

    r597 r740  
    215215}
    216216
    217 bool ber_write_OID_String(DATA_BLOB *blob, const char *OID)
    218 {
    219         uint_t v, v2;
     217bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
     218{
     219        unsigned int v, v2;
    220220        const char *p = (const char *)OID;
    221221        char *newp;
    222222        int i;
    223223
     224        if (!isdigit(*p)) return false;
    224225        v = strtoul(p, &newp, 10);
    225226        if (newp[0] != '.') return false;
    226227        p = newp + 1;
    227228
     229        if (!isdigit(*p)) return false;
    228230        v2 = strtoul(p, &newp, 10);
    229231        if (newp[0] != '.') return false;
     
    231233
    232234        /*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));
    234236        if (!blob->data) return false;
    235237
     
    238240        i = 1;
    239241        while (*p) {
     242                if (!isdigit(*p)) return false;
    240243                v = strtoul(p, &newp, 10);
    241244                if (newp[0] == '.') {
    242245                        p = newp + 1;
     246                        /* check for empty last component */
     247                        if (!*p) return false;
    243248                } else if (newp[0] == '\0') {
    244249                        p = newp;
     
    259264}
    260265
     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 */
     272bool 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
    261305/* write an object ID to a ASN1 buffer */
    262306bool asn1_write_OID(struct asn1_data *data, const char *OID)
     
    266310        if (!asn1_push_tag(data, ASN1_OID)) return false;
    267311
    268         if (!ber_write_OID_String(&blob, OID)) {
     312        if (!ber_write_OID_String(NULL, &blob, OID)) {
    269313                data->has_error = true;
    270314                return false;
     
    453497
    454498        return (b == tag);
     499}
     500
     501/*
     502 * just get the needed size the tag would consume
     503 */
     504bool 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;
    455570}
    456571
     
    544659}
    545660
    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 */
     666static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
     667                                      char **OID, size_t *bytes_eaten)
    548668{
    549669        int i;
    550670        uint8_t *b;
    551         uint_t v;
     671        unsigned int v;
    552672        char *tmp_oid = NULL;
    553673
     
    560680        tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  b[0]%40);
    561681        if (!tmp_oid) goto nomem;
     682
     683        if (bytes_eaten != NULL) {
     684                *bytes_eaten = 0;
     685        }
    562686
    563687        for(i = 1, v = 0; i < blob.length; i++) {
     
    566690                        tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  v);
    567691                        v = 0;
     692                        if (bytes_eaten)
     693                                *bytes_eaten = i+1;
    568694                }
    569695                if (!tmp_oid) goto nomem;
    570696        }
    571697
    572         if (v != 0) {
    573                 talloc_free(tmp_oid);
    574                 return false;
    575         }
    576 
    577698        *OID = tmp_oid;
    578699        return true;
    579700
    580 nomem: 
     701nomem:
    581702        return false;
    582703}
    583704
     705/* read an object ID from a data blob */
     706bool 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 */
     722bool 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
     747nomem:
     748        TALLOC_FREE(identifier);
     749        TALLOC_FREE(tmp_oid);
     750        return false;
     751}
     752
    584753/* read an object ID from a ASN1 buffer */
    585 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID)
     754bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID)
    586755{
    587756        DATA_BLOB blob;
     
    622791bool asn1_check_OID(struct asn1_data *data, const char *OID)
    623792{
    624         const char *id;
     793        char *id;
    625794
    626795        if (!asn1_read_OID(data, data, &id)) return false;
    627796
    628797        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);
    634803        return true;
    635804}
     
    8651034        if (size > blob.length) {
    8661035                return STATUS_MORE_ENTRIES;
    867         }               
     1036        }
    8681037
    8691038        *packet_size = size;
    8701039        return NT_STATUS_OK;
    8711040}
     1041
     1042NTSTATUS 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  
    6262bool asn1_write_Integer(struct asn1_data *data, int i);
    6363bool 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);
     64bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID);
     65bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid);
    6566bool asn1_write_OID(struct asn1_data *data, const char *OID);
    6667bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length);
     
    7980bool asn1_read_uint8(struct asn1_data *data, uint8_t *v);
    8081bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v);
     82bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size);
    8183bool asn1_peek_tag(struct asn1_data *data, uint8_t tag);
    8284bool asn1_start_tag(struct asn1_data *data, uint8_t tag);
    8385bool asn1_end_tag(struct asn1_data *data);
    8486int 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);
     87bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID);
     88bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **partial_oid);
     89bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID);
    8790bool asn1_check_OID(struct asn1_data *data, const char *OID);
    8891bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s);
     
    99102void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len);
    100103NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
     104NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
    101105
    102106#endif /* _ASN_1_H */
  • vendor/current/lib/util/attr.h

    r414 r740  
    2828#  define UNUSED(param) param
    2929/** Feel free to add definitions for other compilers here. */
    30 #endif
    31 
    32 #ifdef HAVE_VISIBILITY_ATTR
    33 #  define _PUBLIC_ __attribute__((visibility("default")))
    34 #else
    35 #  define _PUBLIC_
    3630#endif
    3731
     
    8882#endif
    8983
     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
    9096#endif /* __UTIL_ATTR_H__ */
  • vendor/current/lib/util/become_daemon.c

    r414 r740  
    6767****************************************************************************/
    6868
    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)
    7070{
    7171        if (do_fork) {
     
    8888#endif /* HAVE_SETSID */
    8989
    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        }
    9395}
  • vendor/current/lib/util/binsearch.h

    r414 r740  
    6666        }} } while (0)
    6767
     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
    6884#endif
  • vendor/current/lib/util/byteorder.h

    r414 r740  
    5555
    5656#define CVAL(buf,pos) (((uint8_t *)(buf))[pos])
    57 #define PVAL(buf,pos) ((uint_t)CVAL(buf,pos))
     57#define PVAL(buf,pos) ((unsigned int)CVAL(buf,pos))
    5858#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
    5959
     
    145145#endif
    146146
    147 #define CVAL(buf,pos) ((uint_t)(((const uint8_t *)(buf))[pos]))
     147#define CVAL(buf,pos) ((unsigned int)(((const uint8_t *)(buf))[pos]))
    148148#define CVAL_NC(buf,pos) (((uint8_t *)(buf))[pos]) /* Non-const version of CVAL */
    149149#define PVAL(buf,pos) (CVAL(buf,pos))
     
    186186/* get single value from an SMB buffer */
    187187#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. */
    189189#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. */
    191191#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. */
    193193#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. */
    195195
    196196/* store single value in an SMB buffer */
     
    202202#endif /* not CAREFUL_ALIGNMENT */
    203203
    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 
    225204/* 64 bit macros */
    226205#define BVAL(p, ofs) (IVAL(p,ofs) | (((uint64_t)IVAL(p,(ofs)+4)) << 32))
     
    229208#define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)v))
    230209
     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
    231236#endif /* _BYTEORDER_H */
  • vendor/current/lib/util/charset/charcnv.c

    r414 r740  
    3939 */
    4040
    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 descriptors
    68 **/
    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 handles
    109 */
    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_ALL
    120                 /* we set back the locale to C to get ASCII-compatible
    121                    toupper/lower functions.  For now we do not need
    122                    any other POSIX localisations anyway. When we
    123                    should really need localized string functions one
    124                    day we need to write our own ascii_tolower etc.
    125                 */
    126                 setlocale(LC_ALL, "C");
    127 #endif
    128         }
    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 
    15841/**
    15942 * Convert string from one encoding to another, making error checking etc
     
    21497                                break;
    21598                }
    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);
    217101                talloc_free(ob);
    218102                return (size_t)-1;
     
    349233}
    350234
    351 /*
    352   return the unicode codepoint for the next multi-byte CH_UNIX character
    353   in the string
    354 
    355   also return the number of bytes consumed (which tells the caller
    356   how many bytes to skip to get to the next CH_UNIX character)
    357 
    358   return INVALID_CODEPOINT if the next character cannot be converted
    359 */
    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 take
    377            more than 5 bytes. This is OK as we only
    378            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 cope
    389            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 must
    425   be able to hold the full character, which is guaranteed if it is at
    426   least 5 bytes in size. The caller may pass less than 5 bytes if they
    427   are sure the character will fit (for example, you can assume that
    428   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, or
    431   -1 on failure
    432 */
    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  
    4040typedef uint16_t smb_ucs2_t;
    4141
     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
    4260/*
    4361 *   for each charset we have a function that pulls from that charset to
     
    103121
    104122char *strchr_m(const char *s, char c);
     123size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset);
     124size_t strlen_m_ext_term(const char *s, charset_t src_charset,
     125                         charset_t dst_charset);
    105126size_t strlen_m_term(const char *s);
    106127size_t strlen_m_term_null(const char *s);
     
    150171
    151172extern struct smb_iconv_convenience *global_iconv_convenience;
    152 
     173struct smb_iconv_convenience *get_iconv_convenience(void);
     174smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic,
     175                            charset_t from, charset_t to);
     176const char *charset_name(struct smb_iconv_convenience *ic, charset_t ch);
     177
     178codepoint_t next_codepoint_ext(const char *str, charset_t src_charset,
     179                               size_t *size);
    153180codepoint_t next_codepoint(const char *str, size_t *size);
    154181ssize_t push_codepoint(char *str, codepoint_t c);
    155182
    156183/* codepoints */
     184codepoint_t next_codepoint_convenience_ext(struct smb_iconv_convenience *ic,
     185                            const char *str, charset_t src_charset,
     186                            size_t *size);
    157187codepoint_t next_codepoint_convenience(struct smb_iconv_convenience *ic,
    158188                            const char *str, size_t *size);
    159189ssize_t push_codepoint_convenience(struct smb_iconv_convenience *ic,
    160190                                char *str, codepoint_t c);
     191
    161192codepoint_t toupper_m(codepoint_t val);
    162193codepoint_t tolower_m(codepoint_t val);
     194bool islower_m(codepoint_t val);
     195bool isupper_m(codepoint_t val);
    163196int codepoint_cmpi(codepoint_t c1, codepoint_t c2);
    164197
    165198/* 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);
     199struct 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);
    170205
    171206bool convert_string_convenience(struct smb_iconv_convenience *ic,
     
    189224
    190225void load_case_tables(void);
    191 bool charset_register_backend(const void *_funcs);
     226void load_case_tables_library(void);
     227bool smb_register_charset(const struct charset_functions *funcs_in);
    192228
    193229/*
     
    264300NTSTATUS charset_ ## CHARSETNAME ## _init(void)                                                 \
    265301{                                                                                               \
    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}                                               \
    268307
    269308
  • vendor/current/lib/util/charset/codepoints.c

    r414 r740  
    11/*
    22   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
    56   Copyright (C) Simo Sorce 2001
     7   Copyright (C) Jelmer Vernooij 2007
    68   
    79   This program is free software; you can redistribute it and/or modify
     
    1719   You should have received a copy of the GNU General Public License
    1820   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     21
    1922*/
    20 
    2123#include "includes.h"
     24#include "lib/util/charset/charset.h"
    2225#include "system/locale.h"
    23 #include "dynconfig/dynconfig.h"
     26#include "dynconfig.h"
     27
     28#ifdef strcasecmp
     29#undef strcasecmp
     30#endif
    2431
    2532/**
     
    3643/*******************************************************************
    3744load the case handling tables
     45
     46This is the function that should be called from library code.
    3847********************************************************************/
    39 void load_case_tables(void)
     48void load_case_tables_library(void)
    4049{
    4150        TALLOC_CTX *mem_ctx;
     
    4554                smb_panic("No memory for case_tables");
    4655        }
    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);
    4958        talloc_free(mem_ctx);
    5059        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;
    5662        }
    5763        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/*******************************************************************
     70load the case handling tables
     71
     72This MUST only be called from main() in application code, never from a
     73library.  We don't know if the calling program has already done
     74setlocale() to another value, and can't tell if they have.
     75********************************************************************/
     76void 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();
    6485}
    6586
     
    7394        }
    7495        if (upcase_table == NULL) {
    75                 load_case_tables();
     96                load_case_tables_library();
    7697        }
    7798        if (upcase_table == (void *)-1) {
     
    93114        }
    94115        if (lowcase_table == NULL) {
    95                 load_case_tables();
     116                load_case_tables_library();
    96117        }
    97118        if (lowcase_table == (void *)-1) {
     
    102123        }
    103124        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);
    104141}
    105142
     
    117154
    118155
     156struct 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
     165struct smb_iconv_convenience *global_iconv_convenience = NULL;
     166
     167struct 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 **/
     178const 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**/
     196static 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
     213static 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*/
     295smb_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  
    2424#include "system/filesys.h"
    2525
     26#ifdef strcasecmp
     27#undef strcasecmp
     28#endif
     29
     30#ifdef static_decl_charset
     31static_decl_charset;
     32#endif
    2633
    2734/**
     
    5057static size_t ascii_pull  (void *,const char **, size_t *, char **, size_t *);
    5158static size_t ascii_push  (void *,const char **, size_t *, char **, size_t *);
     59static size_t latin1_push(void *,const char **, size_t *, char **, size_t *);
    5260static size_t utf8_pull   (void *,const char **, size_t *, char **, size_t *);
    5361static size_t utf8_push   (void *,const char **, size_t *, char **, size_t *);
     
    7381
    7482        {"ASCII", ascii_pull, ascii_push},
     83        {"646", ascii_pull, ascii_push},
     84        {"ISO-8859-1", ascii_pull, latin1_push},
    7585        {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}
    7686};
     
    7888static struct charset_functions *charsets = NULL;
    7989
    80 bool charset_register_backend(const void *_funcs)
    81 {
    82         struct charset_functions *funcs = (struct charset_functions *)memdup(_funcs,sizeof(struct charset_functions));
     90static struct charset_functions *find_charset_functions(const char *name)
     91{
    8392        struct charset_functions *c;
    8493
    8594        /* Check whether we already have this charset... */
    8695        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
     105bool 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;
    92122
    93123        funcs->next = funcs->prev = NULL;
     124        DEBUG(5, ("Registered charset %s\n", funcs->name));
    94125        DLIST_ADD(charsets, funcs);
    95126        return true;
     127}
     128
     129static 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
    96139}
    97140
     
    159202}
    160203
    161 int smb_iconv_t_destructor(smb_iconv_t hwd)
    162 { 
     204static int smb_iconv_t_destructor(smb_iconv_t hwd)
     205{
    163206#ifdef HAVE_NATIVE_ICONV
    164207        if (hwd->cd_pull != NULL && hwd->cd_pull != (iconv_t)-1)
     
    180223        int i;
    181224
     225        lazy_initialize_iconv();
     226
    182227        ret = (smb_iconv_t)talloc_named(mem_ctx,
    183228                                        sizeof(*ret),
     
    261306        if (is_utf16(tocode)) {
    262307                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);
    266308                ret->cd_direct = ret->cd_pull;
    267309                ret->cd_pull = NULL;
     
    286328_PUBLIC_ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
    287329{
    288         return smb_iconv_open_ex(talloc_autofree_context(), tocode, fromcode, true);
     330        return smb_iconv_open_ex(NULL, tocode, fromcode, true);
    289331}
    290332
     
    351393}
    352394
     395static 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}
    353421
    354422static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft,
     
    356424{
    357425        while (*inbytesleft >= 1 && *outbytesleft >= 2) {
    358                 uint_t v;
     426                unsigned int v;
    359427
    360428                if ((*inbuf)[0] != '@') {
  • vendor/current/lib/util/charset/tests/charset.c

    r414 r740  
    247247struct torture_suite *torture_local_charset(TALLOC_CTX *mem_ctx)
    248248{
    249         struct torture_suite *suite = torture_suite_create(mem_ctx, "CHARSET");
     249        struct torture_suite *suite = torture_suite_create(mem_ctx, "charset");
    250250
    251251        torture_suite_add_simple_test(suite, "toupper_m", test_toupper_m);
  • vendor/current/lib/util/charset/tests/iconv.c

    r414 r740  
    3636        iconv_t cd;
    3737
    38         if (!lp_parm_bool(tctx->lp_ctx, NULL, "iconv", "native", true))
     38        if (!lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "native", true))
    3939                torture_skip(tctx, "system iconv disabled - skipping test");
    4040
     
    135135        uint8_t buf1[1000], buf2[1000], buf3[1000];
    136136        size_t outsize1, outsize2, outsize3;
    137         const char *ptr_in;
     137        char *ptr_in;
    138138        char *ptr_out;
    139139        size_t size_in1, size_in2, size_in3;
     
    159159                                                     charset));
    160160                }
    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));
    163163                last_charset = charset;
    164164        }
    165165
    166166        /* internal convert to charset - placing result in buf1 */
    167         ptr_in = (const char *)inbuf;
     167        ptr_in = (char *)inbuf;
    168168        ptr_out = (char *)buf1;
    169169        size_in1 = size;
     
    172172        memset(ptr_out, 0, outsize1);
    173173        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);
    175175        errno1 = errno;
    176176
    177177        /* system convert to charset - placing result in buf2 */
    178         ptr_in = (const char *)inbuf;
     178        ptr_in = (char *)inbuf;
    179179        ptr_out = (char *)buf2;
    180180        size_in2 = size;
     
    183183        memset(ptr_out, 0, outsize2);
    184184        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);
    186186        errno2 = errno;
    187187
     
    237237        /* convert back to UTF-16, putting result in buf3 */
    238238        size = size - size_in1;
    239         ptr_in = (const char *)buf1;
     239        ptr_in = (char *)buf1;
    240240        ptr_out = (char *)buf3;
    241241        size_in3 = len1;
     
    243243
    244244        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);
    246246
    247247        /* we only internally support the first 1M codepoints */
     
    290290        codepoint_t c;
    291291
    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);
    293293        torture_assert(tctx, size != -1 || (codepoint >= 0xd800 && codepoint <= 0x10000),
    294294                       "Invalid Codepoint range");
     
    301301        buf[size+3] = random();
    302302
    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);
    304304
    305305        torture_assert(tctx, c == codepoint,
     
    452452struct torture_suite *torture_local_iconv(TALLOC_CTX *mem_ctx)
    453453{
    454         struct torture_suite *suite = torture_suite_create(mem_ctx, "ICONV");
     454        struct torture_suite *suite = torture_suite_create(mem_ctx, "iconv");
    455455
    456456        torture_suite_add_simple_test(suite, "string2key",
  • vendor/current/lib/util/charset/util_unistr.c

    r414 r740  
    2222#include "system/locale.h"
    2323
    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 
    3324/**
    3425 Case insensitive string compararison
     
    6859
    6960        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.au
    78  **/
    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;
    11661}
    11762
     
    249194
    250195/**
    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)
    256202{
    257203        size_t count = 0;
     
    273219        while (*s) {
    274220                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                         */
    277255                        count += 1;
    278                 } else {
    279                         count += 2;
    280                 }
    281                 s += c_size;
     256                }
    282257        }
    283258
    284259        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);
    285281}
    286282
     
    430426        char *dest;
    431427        struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
     428
     429        if(src == NULL) {
     430                return NULL;
     431        }
    432432
    433433        /* this takes advantage of the fact that upper/lower can't
     
    988988}
    989989
    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  
    3434_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
    3535{
     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{
    3644        DATA_BLOB ret;
    3745
     
    4250
    4351        if (p) {
    44                 ret.data = (uint8_t *)talloc_memdup(NULL, p, length);
     52                ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
    4553        } else {
    46                 ret.data = talloc_array(NULL, uint8_t, length);
     54                ret.data = talloc_array(mem_ctx, uint8_t, length);
    4755        }
    4856        if (ret.data == NULL) {
     
    5260        talloc_set_name_const(ret.data, name);
    5361        ret.length = length;
    54         return ret;
    55 }
    56 
    57 /**
    58  construct a data blob, using supplied TALLOC_CTX
    59 **/
    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 failure
    74 **/
    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         }
    8462        return ret;
    8563}
     
    154132print the data_blob as hex string
    155133**/
    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)
    157135{
    158136        int i;
     
    174152}
    175153
     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
    176171/**
    177172  useful for constructing data blobs in test suites, while
  • vendor/current/lib/util/data_blob.h

    r414 r740  
    22   Unix SMB/CIFS implementation.
    33   DATA BLOB
    4    
     4
     5   Copyright (C) Andrew Tridgell 2001
     6   Copyright (C) Andrew Bartlett 2001
     7
    58   This program is free software; you can redistribute it and/or modify
    69   it under the terms of the GNU General Public License as published by
     
    6265
    6366/**
    64  reference a data blob, to the supplied TALLOC_CTX. 
    65  Returns a NULL DATA_BLOB on failure
    66 **/
    67 _PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob);
    68 
    69 /**
    7067 construct a zero data blob, using supplied TALLOC_CTX.
    7168 use this sparingly as it initialises data - better to initialise
     
    9794print the data_blob as hex string
    9895**/
    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/**
     99print the data_blob as hex string
     100**/
     101_PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob);
    100102
    101103/**
  • vendor/current/lib/util/debug.c

    r414 r740  
    11/*
    22   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
    67
    78   This program is free software; you can redistribute it and/or modify
     
    2122#include "includes.h"
    2223#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 */
     81static 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*/
     109bool    override_logfile;
     110
     111/*
     112 * This is to allow reading of DEBUGLEVEL_CLASS before the debug
     113 * system has been initialized.
     114 */
     115static const int debug_class_list_initial[DBGC_MAX_FIXED + 1];
     116
     117static int debug_num_classes = 0;
     118int     *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
     144static int     debug_count    = 0;
     145#ifdef WITH_SYSLOG
     146static int     syslog_level   = 0;
     147#endif
     148static char *format_bufr = NULL;
     149static size_t     format_pos     = 0;
     150static 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 */
     157static 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
     181static char **classname_table = NULL;
     182
     183
     184/* -------------------------------------------------------------------------- **
     185 * Functions...
     186 */
     187
     188static void debug_init(void);
     189
     190/***************************************************************************
     191 Free memory pointed to by global pointers.
     192****************************************************************************/
     193
     194void 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/****************************************************************************
     211utility lists registered debug class names's
     212****************************************************************************/
     213
     214char *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
     236static 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
     253int 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
     305int 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
     326static 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
     344static 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
     391bool 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 */
     411static void talloc_log_fn(const char *msg)
     412{
     413        DEBUG(0,("%s", msg));
     414}
     415
     416void debug_setup_talloc_log(void)
     417{
     418        talloc_set_log_fn(talloc_log_fn);
     419}
     420
     421
     422/****************************************************************************
     423Init debugging (one time stuff)
     424****************************************************************************/
     425
     426static 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 */
     449void debug_set_settings(struct debug_settings *settings)
     450{
     451        state.settings = *settings;
     452}
    25453
    26454/**
    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*/
     464void 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
     494void 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
     504static void debug_close_fd(int fd)
     505{
     506        if (fd > 2) {
     507                close(fd);
     508        }
     509}
     510
     511bool 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*/
     527bool 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
     602void 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
     617bool 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
     636void 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
     808static 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
     831static 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
     875void 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
     903bool 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
    411014
    421015/* the registered mutex handlers */
     
    461019} debug_handlers;
    471020
    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 already
    97   ensured that the log level has been met before this is called
    98 */
    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 already
    114   ensured that the log level has been met before this is called
    115 
    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, stderr
    187   or a file
    188 */
    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 program
    202 */
    203 _PUBLIC_ void setup_logging_stdout(void)
    204 {
    205         setup_logging(NULL, DEBUG_STDOUT);
    206 }
    207 
    208 /**
    209   return a string constant containing n tabs
    210   no more than 10 tabs are returned
    211 */
    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 
    2211021/**
    2221022  log suspicious usage - print comments and backtrace
     
    2521052        if (!debug_handlers.ops.log_task_id) return;
    2531053
    254         if (!check_reopen_logs()) return;
     1054        if (!reopen_logs_internal()) return;
    2551055
    2561056        debug_handlers.ops.log_task_id(state.fd);
  • vendor/current/lib/util/debug.h

    r414 r740  
    11/*
    22   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
    58
    69   This program is free software; you can redistribute it and/or modify
     
    811   the Free Software Foundation; either version 3 of the License, or
    912   (at your option) any later version.
    10    
     13
    1114   This program is distributed in the hope that it will be useful,
    1215   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1316   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1417   GNU General Public License for more details.
    15    
     18
    1619   You should have received a copy of the GNU General Public License
    1720   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1821*/
    1922
    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
     39int  Debug1( const char *, ... ) PRINTF_ATTRIBUTE(1,2);
     40bool dbgtext( const char *, ... ) PRINTF_ATTRIBUTE(1,2);
     41bool dbghdrclass( int level, int cls, const char *location, const char *func);
     42bool 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
     91extern 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  */
    76194
    77195/** Possible destinations for the debug log (in order of precedence -
     
    80198 * the command line, as the smb.conf cannot reset it back to
    81199 * 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);
     200enum debug_logtype {DEBUG_DEFAULT_STDERR = 0, DEBUG_STDOUT = 1, DEBUG_FILE = 2, DEBUG_STDERR = 3};
     201
     202struct 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
     214void setup_logging(const char *prog_name, enum debug_logtype new_logtype);
     215
     216void debug_close_dbf(void);
     217void gfree_debugsyms(void);
     218int debug_add_class(const char *classname);
     219int debug_lookup_classname(const char *classname);
     220bool debug_parse_levels(const char *params_str);
     221void debug_setup_talloc_log(void);
     222void debug_set_logfile(const char *name);
     223void debug_set_settings(struct debug_settings *settings);
     224bool reopen_logs_internal( void );
     225void force_check_log_size( void );
     226bool need_to_check_log_size( void );
     227void check_log_size( void );
     228void dbgflush( void );
     229bool dbghdrclass(int level, int cls, const char *location, const char *func);
     230bool dbghdr(int level, const char *location, const char *func);
     231bool debug_get_output_is_stderr(void);
     232void debug_schedule_reopen_logs(void);
     233char *debug_list_class_names_and_levels(void);
    118234
    119235/**
     
    129245_PUBLIC_ void log_task_id(void);
    130246
     247/* the debug operations structure - contains function pointers to
     248   various debug implementations of each operation */
     249struct 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
    131264/**
    132265  register a set of debug handlers.
     
    134267_PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops);
    135268
    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  
    22   Unix SMB/CIFS implementation.
    33   some simple double linked list macros
    4    Copyright (C) Andrew Tridgell 1998
     4
     5   Copyright (C) Andrew Tridgell 1998-2010
    56   
    67   This program is free software; you can redistribute it and/or modify
     
    2425#define _DLINKLIST_H
    2526
     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.
    2631
    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*/
    2866#define DLIST_ADD(list, p) \
    2967do { \
    3068        if (!(list)) { \
    31                 (list) = (p); \
    32                 (p)->next = (p)->prev = NULL; \
     69                (p)->prev = (list) = (p); \
     70                (p)->next = NULL; \
    3371        } else { \
     72                (p)->prev = (list)->prev; \
    3473                (list)->prev = (p); \
    3574                (p)->next = (list); \
    36                 (p)->prev = NULL; \
    3775                (list) = (p); \
    38         }\
     76        } \
    3977} while (0)
    4078
    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*/
    4284#define DLIST_REMOVE(list, p) \
    4385do { \
    4486        if ((p) == (list)) { \
     87                if ((p)->next) (p)->next->prev = (p)->prev; \
    4588                (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; \
    4792        } else { \
    4893                if ((p)->prev) (p)->prev->next = (p)->next; \
    4994                if ((p)->next) (p)->next->prev = (p)->prev; \
    5095        } \
    51         if ((p) != (list)) (p)->next = (p)->prev = NULL; \
     96        if ((p) != (list)) (p)->next = (p)->prev = NULL;        \
    5297} while (0)
    5398
    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) \
    56105do { \
    57           DLIST_REMOVE(list, p); \
    58           DLIST_ADD(list, p); \
    59 } while (0)
     106       (result_head) = (p); \
     107       while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
     108} while(0)
    60109
    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)
    75115
    76116/* insert 'p' after the given element 'el' in a list. If el is NULL then
     
    81121                DLIST_ADD(list, p); \
    82122        } 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); \
    87128        }\
    88129} while (0)
    89130
    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)                    \
    92137do { \
    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        } \
    95143} while (0)
    96144
    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) \
    100147do { \
    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)                     \
     157do { \
     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)   \
     168do { \
     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; \
    110177                } \
     178        } \
    111179} while (0)
    112180
  • vendor/current/lib/util/fault.c

    r414 r740  
    5252#endif
    5353        void *backtrace_stack[BACKTRACE_STACK_SIZE];
    54         size_t backtrace_size;
     54        int backtrace_size;
    5555        char **backtrace_strings;
    5656
     
    126126                char cmdstring[200];
    127127                safe_strcpy(cmdstring, panic_action, sizeof(cmdstring));
    128                 snprintf(pidstr, sizeof(pidstr), "%u", getpid());
     128                snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid());
    129129                all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring));
    130130                if (progname) {
     
    146146
    147147#ifdef SIGABRT
    148         CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
     148        CatchSignal(SIGABRT, SIG_DFL);
    149149#endif
    150150        abort();
     
    188188_PUBLIC_ void fault_setup(const char *pname)
    189189{
    190         if (progname == NULL) {
    191                 progname = pname;
    192         }
     190        if (progname != NULL) {
     191                return;
     192        }
     193        progname = pname;
    193194#ifdef SIGSEGV
    194         CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault);
     195        CatchSignal(SIGSEGV, sig_fault);
    195196#endif
    196197#ifdef SIGBUS
    197         CatchSignal(SIGBUS,SIGNAL_CAST sig_fault);
     198        CatchSignal(SIGBUS, sig_fault);
    198199#endif
    199200#ifdef SIGABRT
    200         CatchSignal(SIGABRT,SIGNAL_CAST sig_fault);
     201        CatchSignal(SIGABRT, sig_fault);
    201202#endif
    202203#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
    206216
    207217/**
  • vendor/current/lib/util/genrand.c

    r414 r740  
    363363
    364364/**
     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
     398again:
     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/**
    365413 * Generate an array of unique text strings all of the same length.
    366414 * The returned string will be allocated.
  • vendor/current/lib/util/idtree.c

    r414 r740  
    105105        int n, m, sh;
    106106        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;
    109109        uint32_t bm;
    110110
     
    241241{
    242242        struct idr_layer *p = idp->top;
    243         struct idr_layer **pa[MAX_LEVEL];
     243        struct idr_layer **pa[1+MAX_LEVEL];
    244244        struct idr_layer ***paa = &pa[0];
    245245        int n;
     
    281281         * present.  If so, tain't one of ours!
    282282         */
    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        }
    285287
    286288        /* Mask off upper bits we don't use for the search. */
  • vendor/current/lib/util/memory.h

    r414 r740  
    2929 * always be ignored.
    3030 **/
    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)
    3232#endif
    3333
  • vendor/current/lib/util/params.c

    r594 r740  
    489489  } /* Parse */
    490490
    491 static myFILE *OpenConfFile( const char *FileName )
     491static myFILE *OpenConfFile(TALLOC_CTX *mem_ctx, const char *FileName )
    492492  /* ------------------------------------------------------------------------ **
    493493   * Open a configuration file.
     
    503503  myFILE *ret;
    504504
    505   ret = talloc(talloc_autofree_context(), myFILE);
     505  ret = talloc(mem_ctx, myFILE);
    506506  if (!ret) return NULL;
    507507
     
    544544  const char *func = "params.c:pm_process() -";
    545545
    546   InFile = OpenConfFile( FileName );          /* Open the config file. */
     546  InFile = OpenConfFile(NULL, FileName); /* Open the config file. */
    547547  if( NULL == InFile )
    548548    return( false );
  • vendor/current/lib/util/system.c

    r414 r740  
    118118        return mypid;
    119119}
     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  
    6969{
    7070#if defined(PARANOID_MALLOC_CHECKER)
    71 #ifdef malloc
    72 #undef malloc
     71#ifdef calloc
     72#undef calloc
    7373#endif
    7474#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));
    7777#if defined(PARANOID_MALLOC_CHECKER)
    78 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
     78#define calloc(n, s) __ERROR_DONT_USE_MALLOC_DIRECTLY
    7979#endif
    8080
     
    8282                smb_panic("talloc_stackframe_init malloc failed");
    8383        }
    84 
    85         ZERO_STRUCTP(ts);
    8684
    8785        SMB_THREAD_ONCE(&ts_initialized, talloc_stackframe_init, NULL);
     
    103101                        break;
    104102                }
    105                 talloc_free(ts->talloc_stack[i]);
    106                 ts->talloc_stack[i] = NULL;
     103                TALLOC_FREE(ts->talloc_stack[i]);
    107104        }
    108105
  • vendor/current/lib/util/talloc_stack.h

    r414 r740  
    3636#define _TALLOC_STACK_H
    3737
    38 #include "talloc.h"
     38#include <talloc.h>
    3939
    4040/*
  • vendor/current/lib/util/tests/data_blob.c

    r414 r740  
    7979{
    8080        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");
    8283        return true;
    8384}
     
    8586struct torture_suite *torture_local_util_data_blob(TALLOC_CTX *mem_ctx)
    8687{
    87         struct torture_suite *suite = torture_suite_create(mem_ctx, "DATABLOB");
     88        struct torture_suite *suite = torture_suite_create(mem_ctx, "datablob");
    8889
    8990        torture_suite_add_simple_test(suite, "string", test_string);
  • vendor/current/lib/util/tests/file.c

    r414 r740  
    9292struct torture_suite *torture_local_util_file(TALLOC_CTX *mem_ctx)
    9393{
    94         struct torture_suite *suite = torture_suite_create(mem_ctx, "FILE");
     94        struct torture_suite *suite = torture_suite_create(mem_ctx, "file");
    9595
    9696        torture_suite_add_simple_test(suite, "file_load_save",
    9797                                      test_file_load_save);
    9898
    99         torture_suite_add_simple_test(suite, "afdgets",
    100                                       test_afdgets);
     99        torture_suite_add_simple_test(suite, "afdgets", test_afdgets);
    101100
    102101        return suite;
  • vendor/current/lib/util/tests/genrand.c

    r414 r740  
    6060struct torture_suite *torture_local_genrand(TALLOC_CTX *mem_ctx)
    6161{
    62         struct torture_suite *suite = torture_suite_create(mem_ctx, "GENRAND");
     62        struct torture_suite *suite = torture_suite_create(mem_ctx, "genrand");
    6363        torture_suite_add_simple_test(suite, "reseed_callback", test_reseed_callback);
    6464        torture_suite_add_simple_test(suite, "check_password_quality", test_check_password_quality);
  • vendor/current/lib/util/tests/idtree.c

    r414 r740  
    116116struct torture_suite *torture_local_idtree(TALLOC_CTX *mem_ctx)
    117117{
    118         struct torture_suite *suite = torture_suite_create(mem_ctx, "IDTREE");
     118        struct torture_suite *suite = torture_suite_create(mem_ctx, "idtree");
    119119        torture_suite_add_simple_test(suite, "idtree", torture_local_idtree_simple);
    120120        return suite;
  • vendor/current/lib/util/tests/parmlist.c

    r414 r740  
    6060        torture_assert_str_equal(tctx, e->value, "mystring", "value");
    6161
    62         e = parmlist_get(pctx, "nonexistant");
    63         torture_assert(tctx, e == NULL, "nonexistant");
     62        e = parmlist_get(pctx, "non-existent");
     63        torture_assert(tctx, e == NULL, "non-existent");
    6464        return true;
    6565}
     
    8888        torture_assert_str_equal(tctx, "true", ret[0], "ret[0]");
    8989        torture_assert_str_equal(tctx, "false", ret[1], "ret[1]");
    90         torture_assert(tctx, NULL == parmlist_get_string_list(pctx, "nonexistant", NULL), "nonexistant");
     90        torture_assert(tctx, NULL == parmlist_get_string_list(pctx, "non-existent", NULL), "non-existent");
    9191
    9292        return true;
     
    9595struct torture_suite *torture_local_util_parmlist(TALLOC_CTX *mem_ctx)
    9696{
    97         struct torture_suite *suite = torture_suite_create(mem_ctx, "PARMLIST");
     97        struct torture_suite *suite = torture_suite_create(mem_ctx, "parmlist");
    9898
    9999        torture_suite_add_simple_test(suite, "get_int", test_get_int);
  • vendor/current/lib/util/tests/str.c

    r414 r740  
    9595struct torture_suite *torture_local_util_str(TALLOC_CTX *mem_ctx)
    9696{
    97         struct torture_suite *suite = torture_suite_create(mem_ctx, "STR");
     97        struct torture_suite *suite = torture_suite_create(mem_ctx, "str");
    9898
    9999        torture_suite_add_simple_test(suite, "string_sub_simple",
  • vendor/current/lib/util/tests/strlist.c

    r414 r740  
    2727struct test_list_element {
    2828        const char *list_as_string;
    29         const char *seperators;
     29        const char *separators;
    3030        const char *list[5];
    3131};
    3232
    33 struct test_list_element test_lists_strings[] = {
     33const struct test_list_element test_lists_strings[] = {
    3434        {
    3535                .list_as_string = "",
     
    4747                .list_as_string = "foo bar",
    4848                .list = { "foo bar", NULL },
    49                 .seperators = ";"
     49                .separators = ";"
    5050        },
    5151        {
     
    6060                .list_as_string = "\"foo bar\",comma;semicolon",
    6161                .list = { "\"foo bar\",comma", "semicolon", NULL },
    62                 .seperators = ";"
     62                .separators = ";"
    6363        }
    6464};
    6565
    66 struct test_list_element test_lists_shell_strings[] = {
     66const struct test_list_element test_lists_shell_strings[] = {
    6767        {
    6868                .list_as_string = "",
     
    8080                .list_as_string = "foo bar",
    8181                .list = { "foo bar", NULL },
    82                 .seperators = ";"
     82                .separators = ";"
    8383        },
    8484        {
     
    100100};
    101101
    102 static bool test_lists_shell(struct torture_context *tctx,
    103                              const void *data)
     102static bool test_lists_shell(struct torture_context *tctx, const void *data)
    104103{
    105104        const struct test_list_element *element = data;
    106         const char **ret1, **ret2, *tmp;
     105
     106        char **ret1, **ret2, *tmp;
    107107        bool match = true;
    108108        TALLOC_CTX *mem_ctx = tctx;
    109109
    110         ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->seperators);
     110        ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->separators);
    111111       
    112112        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->seperators);
     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);
    115115
    116116        if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) {
     
    131131        torture_assert(tctx, match, talloc_asprintf(tctx,
    132132                "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),
    134135                       talloc_asprintf(tctx,
    135136                                       "str_list_make_shell(%s) failed to create correct list",
     
    142143{
    143144        const struct test_list_element *element = data;
     145
    144146        char **result;
    145         result = str_list_make(tctx, element->list_as_string, element->seperators);
     147        result = str_list_make(tctx, element->list_as_string, element->separators);
    146148        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),
    148151                       talloc_asprintf(tctx,
    149152                                       "str_list_make(%s) failed to create correct list",
     
    251254static bool test_list_add(struct torture_context *tctx)
    252255{
    253         char **result, **result2;
     256        const char **result, **result2;
    254257        const char *list[] = {
    255258                "element_0",
     
    259262                NULL
    260263        };
    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);
    262265        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");
    264267        torture_assert(tctx, result2, "str_list_add() must not return NULL");
    265268        torture_assert(tctx, str_list_equal(result2, list),
     
    271274static bool test_list_add_const(struct torture_context *tctx)
    272275{
    273         char **result, **result2;
     276        const char **result, **result2;
    274277        const char *list[] = {
    275278                "element_0",
     
    279282                NULL
    280283        };
    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);
    282285        torture_assert(tctx, result, "str_list_make() must not return NULL");
    283286        result2 = str_list_add_const(result, "element_3");
     
    291294static bool test_list_remove(struct torture_context *tctx)
    292295{
    293         char **result;
     296        const char **result;
    294297        const char *list[] = {
    295298                "element_0",
     
    298301                NULL
    299302        };
    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);
    301304        torture_assert(tctx, result, "str_list_make() must not return NULL");
    302305        str_list_remove(result, "element_2");
     
    337340static bool test_list_unique(struct torture_context *tctx)
    338341{
    339         char **result;
     342        const char **result;
    340343        const char *list[] = {
    341344                "element_0",
     
    355358                NULL
    356359        };
    357         result = str_list_copy(tctx, list_dup);
     360        result = (const char **) str_list_copy(tctx, list_dup);
    358361        /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */
    359362        result = str_list_unique(result);
     
    374377        const char **list_dup = (const char **)str_list_make_empty(tctx);
    375378
    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);
    378381        torture_comment(tctx, "test_list_unique_2() with %d elements and %d dups\n", count, num_dups);
    379382
     
    399402static bool test_list_append(struct torture_context *tctx)
    400403{
    401         char **result;
     404        const char **result;
    402405        const char *list[] = {
    403406                "element_0",
     
    421424                NULL
    422425        };
    423         result = str_list_copy(tctx, list);
     426        result = (const char **) str_list_copy(tctx, list);
    424427        torture_assert(tctx, result, "str_list_copy() must not return NULL");
    425428        result = str_list_append(result, list2);
     
    433436static bool test_list_append_const(struct torture_context *tctx)
    434437{
    435         char **result;
     438        const char **result;
    436439        const char *list[] = {
    437440                "element_0",
     
    455458                NULL
    456459        };
    457         result = str_list_copy(tctx, list);
     460        result = (const char **) str_list_copy(tctx, list);
    458461        torture_assert(tctx, result, "str_list_copy() must not return NULL");
    459462        result = str_list_append_const(result, list2);
     
    467470struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx)
    468471{
    469         struct torture_suite *suite = torture_suite_create(mem_ctx, "STRLIST");
     472        struct torture_suite *suite = torture_suite_create(mem_ctx, "strlist");
    470473        int i;
    471474
    472475        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]);
    475481        }
    476482
    477483        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]);
    480489        }
    481490
  • vendor/current/lib/util/tests/time.c

    r414 r740  
    7878
    7979        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);
    8281        return true;
    8382}
     
    102101struct torture_suite *torture_local_util_time(TALLOC_CTX *mem_ctx)
    103102{
    104         struct torture_suite *suite = torture_suite_create(mem_ctx, "TIME");
     103        struct torture_suite *suite = torture_suite_create(mem_ctx, "time");
    105104
    106105        torture_suite_add_simple_test(suite, "null_time", test_null_time);
  • vendor/current/lib/util/tevent_ntstatus.c

    r414 r740  
    2121#include "tevent_ntstatus.h"
    2222
    23 bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status)
     23#define TEVENT_NTERROR_MAGIC (0x917b5acd)
     24
     25bool _tevent_req_nterror(struct tevent_req *req,
     26                         NTSTATUS status,
     27                         const char *location)
    2428{
    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);
    2646}
    2747
     
    4262                break;
    4363        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);
    4568                break;
    4669        default:
     
    6083        return NT_STATUS_OK;
    6184}
     85
     86void 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  
    2424#include <stdbool.h>
    2525#include "../libcli/util/ntstatus.h"
    26 #include "../tevent/tevent.h"
     26#include <tevent.h>
    2727
    28 bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status);
     28bool _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__)
    2933bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus);
    3034NTSTATUS tevent_req_simple_recv_ntstatus(struct tevent_req *req);
    3135
     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 */
     40void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq,
     41                                       NTSTATUS subreq_status);
     42
    3243#endif
  • vendor/current/lib/util/tevent_unix.c

    r414 r740  
    2222*/
    2323
     24#include "../replace/replace.h"
    2425#include "tevent_unix.h"
    25 #include "../replace/replace.h"
    2626
    2727bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno)
  • vendor/current/lib/util/tevent_unix.h

    r414 r740  
    2525#define _TEVENT_UNIX_H
    2626
    27 #include "../tevent/tevent.h"
     27#include <tevent.h>
    2828
    2929bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno);
  • vendor/current/lib/util/time.c

    r478 r740  
    55   Copyright (C) Andrew Tridgell                1992-2004
    66   Copyright (C) Stefan (metze) Metzmacher      2002   
     7   Copyright (C) Jeremy Allison                 2007
     8   Copyright (C) Andrew Bartlett                2011
    79
    810   This program is free software; you can redistribute it and/or modify
     
    5658}
    5759
     60/**
     61a 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/**
     71a wrapper to preferably get the monotonic time in seconds
     72as 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
    5891
    5992#define TIME_FIXUP_CONSTANT 11644473600LL
     
    6194time_t convert_timespec_to_time_t(struct timespec ts)
    6295{
     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
    63102        /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
    64103           increment if it's greater than 500 millionth of a second. */
     104
    65105        if (ts.tv_nsec > 500000000) {
    66106                return ts.tv_sec + 1;
     
    300340
    301341
     342/****************************************************************************
     343 Return the date and time as a string
     344****************************************************************************/
     345
     346char *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
     390char *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
    302399/**
    303400return a HTTP/1.0 time string
     
    347444
    348445#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);
    354450        TimeBuf = talloc_strdup(mem_ctx, tempTime);
    355451#else
     
    398494        int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
    399495        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);
    400505}
    401506
  • vendor/current/lib/util/time.h

    r478 r740  
    22   Unix SMB/CIFS implementation.
    33   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
    510   This program is free software; you can redistribute it and/or modify
    611   it under the terms of the GNU General Public License as published by
     
    5257
    5358/**
     59a wrapper to preferably get the monotonic time
     60**/
     61_PUBLIC_ void clock_gettime_mono(struct timespec *tp);
     62
     63/**
     64a wrapper to preferably get the monotonic time in s
     65**/
     66_PUBLIC_ time_t time_mono(time_t *t);
     67
     68/**
    5469interpret an 8 byte "filetime" structure to a time_t
    5570It's originally in "100ns units since jan 1st 1601"
     
    110125
    111126/**
     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
     132char *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**/
     139char *current_timestring(TALLOC_CTX *ctx, bool hires);
     140
     141/**
    112142return a HTTP/1.0 time string
    113143**/
     
    116146/**
    117147 Return the date and time as a string
     148
     149 format is %a %b %e %X %Y %Z
    118150**/
    119151_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t);
     
    143175*/
    144176_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);
    145182
    146183/**
  • vendor/current/lib/util/unix_privs.c

    r414 r740  
    2121
    2222#include "includes.h"
    23 #include "system/filesys.h"
     23#include "system/passwd.h"
    2424#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
    2534
    2635/**
     
    7786        return s;
    7887}
     88
     89uid_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  
    2626#include "system/filesys.h"
    2727#include "system/locale.h"
     28#include "system/shmem.h"
     29
    2830#undef malloc
    2931#undef strcasecmp
     
    3133#undef strdup
    3234#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
    3344
    3445/**
     
    155166**/
    156167
    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
    166212}
    167213
     
    255301}
    256302
     303static void debugadd_cb(const char *buf, void *private_data)
     304{
     305        int *plevel = (int *)private_data;
     306        DEBUGADD(*plevel, ("%s", buf));
     307}
     308
     309void 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
    257323void print_asc(int level, const uint8_t *buf,int len)
    258324{
    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
    268330 */
    269 static void _dump_data(int level, const uint8_t *buf, int len,
    270                        bool omit_zero_bytes)
     331void 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)
    271335{
    272336        int i=0;
    273337        static const uint8_t empty[16] = { 0, };
    274338        bool skipped = false;
     339        char tmp[16];
    275340
    276341        if (len<=0) return;
    277 
    278         if (!DEBUGLVL(level)) return;
    279342
    280343        for (i=0;i<len;) {
     
    291354
    292355                        if (i<len)  {
    293                                 DEBUGADD(level,("[%04X] ",i));
     356                                snprintf(tmp, sizeof(tmp), "[%04X] ", i);
     357                                cb(tmp, private_data);
    294358                        }
    295359                }
    296360
    297                 DEBUGADD(level,("%02X ",(int)buf[i]));
     361                snprintf(tmp, sizeof(tmp), "%02X ", (int)buf[i]);
     362                cb(tmp, private_data);
    298363                i++;
    299                 if (i%8 == 0) DEBUGADD(level,("  "));
     364                if (i%8 == 0) {
     365                        cb("  ", private_data);
     366                }
    300367                if (i%16 == 0) {
    301368
    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);
    304373
    305374                        if ((omit_zero_bytes == true) &&
     
    307376                            (memcmp(&buf[i], &empty, 16) == 0)) {
    308377                                if (!skipped) {
    309                                         DEBUGADD(level,("skipping zero buffer bytes\n"));
     378                                        cb("skipping zero buffer bytes\n",
     379                                           private_data);
    310380                                        skipped = true;
    311381                                }
     
    317387                int n;
    318388                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                }
    322396                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);
    324399                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);
    327404        }
    328405
     
    336413_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
    337414{
    338         _dump_data(level, buf, len, false);
     415        if (!DEBUGLVL(level)) {
     416                return;
     417        }
     418        dump_data_cb(buf, len, false, debugadd_cb, &level);
    339419}
    340420
     
    343423 *
    344424 * The data is only written if the log level is at least level.
    345  * 16 zero bytes in a row are ommited
     425 * 16 zero bytes in a row are omitted
    346426 */
    347427_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
    348428{
    349         _dump_data(level, buf, len, true);
     429        if (!DEBUGLVL(level)) {
     430                return;
     431        }
     432        dump_data_cb(buf, len, true, debugadd_cb, &level);
    350433}
    351434
     
    580663_PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
    581664{
    582         size_t i;
     665        size_t i = 0;
    583666        size_t num_chars = 0;
    584667        uint8_t   lonybble, hinybble;
     
    586669        char           *p1 = NULL, *p2 = NULL;
    587670
    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++) {
    594677                if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
    595678                        break;
     
    765848                                bool ltrim)
    766849{
    767         char *s;
    768         char *saved_s;
     850        const char *s;
     851        const char *saved_s;
    769852        char *pbuf;
    770853        bool quoted;
     
    776859        }
    777860
    778         s = (char *)*ptr;
     861        s = *ptr;
    779862
    780863        /* default to simple separators */
     
    854937}
    855938
    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
     985struct 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. */
     993void *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
     1038void 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*/
     1058void 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  
    2222#define _SAMBA_UTIL_H_
    2323
    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"
    2826
    2927/* for TALLOC_CTX */
     
    4038extern const char *panic_action;
    4139
    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"
    4845
    4946/**
     
    6158#endif
    6259
    63 #if _SAMBA_BUILD_ == 4
    64 #ifdef VALGRIND
    65 #define strlen(x) valgrind_strlen(x)
    66 size_t valgrind_strlen(const char *s);
    67 #endif
    68 #endif
    69 
    7060#ifndef ABS
    7161#define ABS(a) ((a)>0?(a):(-(a)))
    7262#endif
    7363
    74 #include "../lib/util/memory.h"
     64#include "lib/util/memory.h"
    7565
    7666/**
     
    8979**/
    9080_PUBLIC_ void fault_setup(const char *pname);
     81_PUBLIC_ void fault_setup_disable(void);
    9182#endif
    9283
     
    143134_PUBLIC_ pid_t sys_getpid(void);
    144135
     136_PUBLIC_ int sys_getpeereid( int s, uid_t *uid);
     137
     138struct 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
    145149/* The following definitions come from lib/util/genrand.c  */
    146 
    147150/**
    148151 Copy any user given reseed data.
     
    177180**/
    178181_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);
    179187
    180188/**
     
    451459/**
    452460 * build a null terminated list of strings from an argv-like input string
    453  * Entries are seperated by spaces and can be enclosed by quotes.
     461 * Entries are separated by spaces and can be enclosed by quotes.
    454462 * Does NOT support escaping
    455463 */
     
    459467 * join a list back to one string
    460468 */
    461 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator);
     469_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator);
    462470
    463471/** join a list back to one (shell-like) string; entries
    464  * seperated by spaces, using quotes where necessary */
     472 * separated by spaces, using quotes where necessary */
    465473_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep);
    466474
     
    478486   Return true if all the elements of the list match exactly.
    479487 */
    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);
    481489
    482490/**
     
    535543_PUBLIC_ const char **str_list_copy_const(TALLOC_CTX *mem_ctx,
    536544                                          const char **list);
     545
     546/**
     547 * Needed for making an "unconst" list "const"
     548 */
     549_PUBLIC_ const char **const_str_list(char **list);
    537550
    538551
     
    597610_PUBLIC_ bool large_file_support(const char *path);
    598611
     612/*
     613  compare two files, return true if the two files have the same content
     614 */
     615bool file_compare(const char *path1, const char *path2);
     616
    599617/* The following definitions come from lib/util/util.c  */
    600618
     
    641659 Sleep for a specified number of milliseconds.
    642660**/
    643 _PUBLIC_ void msleep(unsigned int t);
     661_PUBLIC_ void smb_msleep(unsigned int t);
    644662
    645663/**
     
    647665**/
    648666_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);
    676667
    677668/**
     
    687678
    688679/**
     680 * Write dump of binary data to a callback
     681 */
     682void 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/**
    689688 * Write dump of binary data to the log file.
    690689 *
     
    697696 *
    698697 * The data is only written if the log level is at least level.
    699  * 16 zero bytes in a row are ommited
     698 * 16 zero bytes in a row are omitted
    700699 */
    701700_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len);
     
    784783#endif
    785784
    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 
    795785/* The following definitions come from lib/util/idtree.c  */
    796786
     
    840830 Become a daemon, discarding the controlling terminal.
    841831**/
    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);
    843833
    844834/**
     
    853843
    854844void print_asc(int level, const uint8_t *buf,int len);
     845void print_asc_cb(const uint8_t *buf, int len,
     846                  void (*cb)(const char *buf, void *private_data),
     847                  void *private_data);
    855848
    856849/**
     
    862855
    863856bool 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);
    865858bool 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 */
     864void *anonymous_shared_allocate(size_t bufsz);
     865void 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 */
     876struct tevent_context;
     877struct tevent_req;
     878struct 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, ...);
     884int samba_runcmd_recv(struct tevent_req *req, int *perrno);
     885
     886#ifdef DEVELOPER
     887void samba_start_debugger(void);
     888#endif
    868889
    869890#endif /* _SAMBA_UTIL_H_ */
  • vendor/current/lib/util/util_file.c

    r414 r740  
    236236#endif
    237237        if (!p) {
    238                 p = file_load(fname, &s2, 0, talloc_autofree_context());
     238                p = file_load(fname, &s2, 0, NULL);
    239239                if (!p) return NULL;
    240240                if (s2 != size) {
     
    436436
    437437
     438/*
     439  compare two files, return true if the two files have the same content
     440 */
     441bool 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  
    2727
    2828bool 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)
    3030{
    3131        int i;
     
    6060
    6161bool 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)
    6363{
    6464        int i;
  • vendor/current/lib/util/util_ldb.c

    r414 r740  
    2222
    2323#include "includes.h"
    24 #include "lib/ldb/include/ldb.h"
     24#include <ldb.h>
    2525#include "../lib/util/util_ldb.h"
     26
    2627/*
    27   search the sam for the specified attributes - va_list variant
    28 */
     28 * search the LDB for the specified attributes - va_list variant
     29 */
    2930int gendb_search_v(struct ldb_context *ldb,
    3031                   TALLOC_CTX *mem_ctx,
     
    3334                   const char * const *attrs,
    3435                   const char *format,
    35                    va_list ap) 
     36                   va_list ap)
    3637{
    3738        enum ldb_scope scope = LDB_SCOPE_SUBTREE;
     
    5556
    5657        if (ret == LDB_SUCCESS) {
    57                 talloc_steal(mem_ctx, res->msgs);
    58 
    5958                DEBUG(6,("gendb_search_v: %s %s -> %d\n",
    6059                         basedn?ldb_dn_get_linearized(basedn):"NULL",
     
    6261
    6362                ret = res->count;
    64                 *msgs = res->msgs;
     63                if (msgs != NULL) {
     64                        *msgs = talloc_steal(mem_ctx, res->msgs);
     65                }
    6566                talloc_free(res);
    6667        } else if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) {
    6768                ret = 0;
    68                 *msgs = NULL;
     69                if (msgs != NULL) *msgs = NULL;
    6970        } else {
    7071                DEBUG(4,("gendb_search_v: search failed: %s\n",
    7172                                        ldb_errstring(ldb)));
    7273                ret = -1;
     74                if (msgs != NULL) *msgs = NULL;
    7375        }
    7476
     
    7981
    8082/*
    81   search the LDB for the specified attributes - varargs variant
    82 */
     83 * search the LDB for the specified attributes - varargs variant
     84 */
    8385int gendb_search(struct ldb_context *ldb,
    8486                 TALLOC_CTX *mem_ctx,
     
    8688                 struct ldb_message ***res,
    8789                 const char * const *attrs,
    88                  const char *format, ...) 
     90                 const char *format, ...)
    8991{
    9092        va_list ap;
     
    99101
    100102/*
    101   search the LDB for a specified record (by DN)
    102 */
    103 
     103 * search the LDB for a specified record (by DN)
     104 */
    104105int gendb_search_dn(struct ldb_context *ldb,
    105106                 TALLOC_CTX *mem_ctx,
     
    111112}
    112113
    113 /*
    114   setup some initial ldif in a ldb
    115 */
    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 control
    136   return LDB_SUCCESS on success, or an ldb error code on error
    137 
    138   if the search returns 0 entries, return LDB_ERR_NO_SUCH_OBJECT
    139   if the search returns more than 1 entry, return LDB_ERR_CONSTRAINT_VIOLATION
    140 */
    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
    124#ifndef __LIB_UTIL_UTIL_LDB_H__
    225#define __LIB_UTIL_UTIL_LDB_H__
     
    2447                 struct ldb_message ***res,
    2548                 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);
    3649
    3750#endif /* __LIB_UTIL_UTIL_LDB_H__ */
  • vendor/current/lib/util/util_net.c

    r414 r740  
    2828#include "system/locale.h"
    2929#include "system/filesys.h"
     30#include "lib/util/util_net.h"
    3031#undef strcasecmp
    3132
     
    3637void zero_sockaddr(struct sockaddr_storage *pss)
    3738{
    38         memset(pss, '\0', sizeof(*pss));
     39        ZERO_STRUCTP(pss);
    3940        /* Ensure we're at least a valid sockaddr-storage. */
    4041        pss->ss_family = AF_INET;
     
    5051        struct addrinfo hints;
    5152
    52         memset(&hints, '\0', sizeof(hints));
     53        ZERO_STRUCT(hints);
     54
    5355        /* By default make sure it supports TCP. */
    5456        hints.ai_socktype = SOCK_STREAM;
    5557        hints.ai_flags = flags;
    5658
    57         /* Linux man page on getaddinfo() says port will be
    58            uninitialized when service string in NULL */
     59        /* Linux man page on getaddrinfo() says port will be
     60           uninitialized when service string is NULL */
    5961
    6062        ret = getaddrinfo(str, NULL,
     
    383385 * Check if a struct sockaddr has an unspecified address.
    384386 */
    385 bool is_zero_addr(const struct sockaddr *pss)
    386 {
    387 #if defined(HAVE_IPV6)
    388         if (pss->sa_family == AF_INET6) {
     387bool is_zero_addr(const struct sockaddr_storage *pss)
     388{
     389#if defined(HAVE_IPV6)
     390        if (pss->ss_family == AF_INET6) {
    389391                const struct in6_addr *pin6 =
    390392                        &((const struct sockaddr_in6 *)pss)->sin6_addr;
     
    392394        }
    393395#endif
    394         if (pss->sa_family == AF_INET) {
     396        if (pss->ss_family == AF_INET) {
    395397                const struct in_addr *pin = &((const struct sockaddr_in *)pss)->sin_addr;
    396398                return is_zero_ip_v4(*pin);
     
    539541
    540542
     543/****************************************************************************
     544 Get a port number in host byte order from a sockaddr_storage.
     545****************************************************************************/
     546
     547uint16_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
     570char *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
     590char *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
     602char *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
     638int 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
     669static 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
     694const 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  
    4444                                       int flags);
    4545
     46void 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
     53void 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 */
     59void 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
     72bool is_broadcast_addr(const struct sockaddr *pss);
     73bool is_loopback_ip_v4(struct in_addr ip);
     74bool is_loopback_addr(const struct sockaddr *pss);
     75bool is_zero_addr(const struct sockaddr_storage *pss);
     76void 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
     89bool is_address_any(const struct sockaddr *psa);
     90bool same_net(const struct sockaddr *ip1,
     91              const struct sockaddr *ip2,
     92              const struct sockaddr *mask);
     93bool sockaddr_equal(const struct sockaddr *ip1,
     94                    const struct sockaddr *ip2);
     95
     96bool is_address_any(const struct sockaddr *psa);
     97uint16_t get_sockaddr_port(const struct sockaddr_storage *pss);
     98char *print_sockaddr_len(char *dest,
     99                         size_t destlen,
     100                         const struct sockaddr *psa,
     101                         socklen_t psalen);
     102char *print_sockaddr(char *dest,
     103                        size_t destlen,
     104                        const struct sockaddr_storage *psa);
     105char *print_canonical_sockaddr(TALLOC_CTX *ctx,
     106                        const struct sockaddr_storage *pss);
     107const char *client_name(int fd);
     108int get_socket_port(int fd);
     109const char *client_socket_addr(int fd, char *addr, size_t addr_len);
     110
    46111#endif /* _SAMBA_UTIL_NET_H_ */
  • vendor/current/lib/util/util_pw.c

    r414 r740  
    44   Safe versions of getpw* calls
    55
     6   Copyright (C) Andrew Tridgell 1992-1998
     7   Copyright (C) Jeremy Allison  1998-2005
    68   Copyright (C) Andrew Bartlett 2002
     9   Copyright (C) Timur Bakeyev        2005
     10   Copyright (C) Bjoern Jacke    2006-2007
     11
    712   
    813   This program is free software; you can redistribute it and/or modify
     
    2126
    2227#include "includes.h"
     28#include "system/passwd.h"
     29#include "lib/util/util_pw.h"
    2330
    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
     35void sys_setpwent(void)
     36{
     37        setpwent();
     38}
     39
     40struct passwd *sys_getpwent(void)
     41{
     42        return getpwent();
     43}
     44
     45void sys_endpwent(void)
     46{
     47        endpwent();
     48}
     49
     50/**************************************************************************
     51 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
     52****************************************************************************/
     53
     54struct passwd *sys_getpwnam(const char *name)
     55{
     56        return getpwnam(name);
     57}
     58
     59struct passwd *sys_getpwuid(uid_t uid)
     60{
     61        return getpwuid(uid);
     62}
     63
     64struct group *sys_getgrnam(const char *name)
     65{
     66        return getgrnam(name);
     67}
     68
     69struct group *sys_getgrgid(gid_t gid)
     70{
     71        return getgrgid(gid);
     72}
     73
     74struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx,
     75                            const struct passwd *from)
    2676{
    2777        struct passwd *ret = talloc_zero(mem_ctx, struct passwd);
     
    4191}
    4292
    43 struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) 
     93struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
    4494{
    4595        struct passwd *temp;
     
    56106        }
    57107
    58         return alloc_copy_passwd(mem_ctx, temp);
     108        return tcopy_passwd(mem_ctx, temp);
    59109}
    60110
    61 struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid)
     111/****************************************************************************
     112 talloc'ed version of getpwuid.
     113****************************************************************************/
     114
     115struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid)
    62116{
    63117        struct passwd *temp;
     
    74128        }
    75129
    76         return alloc_copy_passwd(mem_ctx, temp);
     130        return tcopy_passwd(mem_ctx, temp);
    77131}
  • vendor/current/lib/util/util_str.c

    r414 r740  
    6565        if (len > maxlength) {
    6666                DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
    67                          (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));
     67                         (unsigned int)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));
    6868                len = maxlength;
    6969        }
     
    112112        return dest;
    113113}
    114 
    115 #ifdef VALGRIND
    116 size_t valgrind_strlen(const char *s)
    117 {
    118         size_t count;
    119         for(count = 0; *s++; count++)
    120                 ;
    121         return count;
    122 }
    123 #endif
    124 
    125114
    126115/**
  • vendor/current/lib/util/util_strlist.c

    r414 r740  
    2121#include "includes.h"
    2222#include "system/locale.h"
     23#include "lib/util/tsort.h"
    2324
    2425#undef strcasecmp
     
    121122/**
    122123 * build a null terminated list of strings from an argv-like input string
    123  * Entries are seperated by spaces and can be enclosed by quotes.
     124 * Entries are separated by spaces and can be enclosed by quotes.
    124125 * Does NOT support escaping
    125126 */
     
    183184 * join a list back to one string
    184185 */
    185 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator)
     186_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator)
    186187{
    187188        char *ret = NULL;
     
    194195
    195196        for (i = 1; list[i]; i++) {
    196                 ret = talloc_asprintf_append_buffer(ret, "%c%s", seperator, list[i]);
     197                ret = talloc_asprintf_append_buffer(ret, "%c%s", separator, list[i]);
    197198        }
    198199
     
    201202
    202203/** join a list back to one (shell-like) string; entries
    203  * seperated by spaces, using quotes where necessary */
     204 * separated by spaces, using quotes where necessary */
    204205_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep)
    205206{
     
    265266   Return true if all the elements of the list match exactly.
    266267 */
    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)
    268270{
    269271        int i;
     
    393395        list2 = (const char **)talloc_memdup(list, list,
    394396                                             sizeof(list[0])*(len+1));
    395         qsort(list2, len, sizeof(list2[0]), QSORT_CAST list_cmp);
     397        TYPESAFE_QSORT(list2, len, list_cmp);
    396398        list[0] = list2[0];
    397399        for (i=j=1;i<len;i++) {
     
    486488        return ret;
    487489}
     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  
    2121
    2222#include "includes.h"
    23 #include "tdb.h"
     23#include <tdb.h>
    2424#include "../lib/util/util_tdb.h"
    2525
     
    134134
    135135/****************************************************************************
    136  Store a int32_t value by an arbitary 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.
    137137 Input is int32_t in native byte order. Output in tdb is in little-endian.
    138138****************************************************************************/
     
    191191
    192192/****************************************************************************
    193  Store a uint32_t value by an arbitary 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.
    194194 Input is uint32_t in native byte order. Output in tdb is in little-endian.
    195195****************************************************************************/
  • 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
    122#ifndef _____LIB_UTIL_UTIL_TDB_H__
    223#define _____LIB_UTIL_UTIL_TDB_H__
    3 
    424
    525/***************************************************************
     
    4464
    4565/****************************************************************************
    46  Store a int32_t value by an arbitary 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.
    4767 Input is int32_t in native byte order. Output in tdb is in little-endian.
    4868****************************************************************************/
     
    6888
    6989/****************************************************************************
    70  Store a uint32_t value by an arbitary 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.
    7191 Input is uint32_t in native byte order. Output in tdb is in little-endian.
    7292****************************************************************************/
  • 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
    122#ifndef __LIB_UTIL_WRAP_XATTR_H__
    223#define __LIB_UTIL_WRAP_XATTR_H__
  • vendor/current/lib/zlib/contrib/ada/zlib-streams.ads

    r414 r740  
    3232   --  Flush the written data to the back stream,
    3333   --  all data placed to the compressor is flushing to the Back stream.
    34    --  Should not be used untill necessary, becouse it is decreasing
     34   --  Should not be used untill necessary, because it is decreasing
    3535   --  compression.
    3636
     
    9898      --  Buffer for Read operation.
    9999      --  We need to have this buffer in the record
    100       --  becouse not all read data from back stream
     100      --  because not all read data from back stream
    101101      --  could be processed during the read operation.
    102102
     
    104104      --  Buffer size for write operation.
    105105      --  We do not need to have this buffer
    106       --  in the record becouse all data could be
     106      --  in the record because all data could be
    107107      --  processed in the write operation.
    108108
  • vendor/current/lib/zlib/contrib/ada/zlib-thin.ads

    r414 r740  
    437437   pragma Import (C, inflateBackInit, "inflateBackInit_");
    438438
    439    --  I stopped binding the inflateBack routines, becouse realize that
     439   --  I stopped binding the inflateBack routines, because realize that
    440440   --  it does not support zlib and gzip headers for now, and have no
    441441   --  symmetric deflateBack routines.
  • vendor/current/lib/zlib/contrib/minizip/miniunz.c

    r414 r740  
    537537
    538538        strncpy(filename_try, zipfilename,MAXFILENAME-1);
    539         /* strncpy doesnt append the trailing NULL, of the string is too long. */
     539        /* strncpy doesn't append the trailing NULL, if the string is too long. */
    540540        filename_try[ MAXFILENAME ] = '\0';
    541541
  • vendor/current/lib/zlib/contrib/minizip/minizip.c

    r414 r740  
    7878
    7979    strncpy(name, f,MAXFILENAME-1);
    80     /* strncpy doesnt append the trailing NULL, of the string is too long. */
     80    /* strncpy doesn't append the trailing NULL, if the string is too long. */
    8181    name[ MAXFILENAME ] = '\0';
    8282
     
    254254        zipok = 1 ;
    255255        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
    256         /* strncpy doesnt append the trailing NULL, of the string is too long. */
     256        /* strncpy doesn't append the trailing NULL, if the string is too long. */
    257257        filename_try[ MAXFILENAME ] = '\0';
    258258
  • vendor/current/lib/zlib/contrib/minizip/unzip.c

    r414 r740  
    160160     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    161161   for end of file.
    162    IN assertion: the stream s has been sucessfully opened for reading.
     162   IN assertion: the stream s has been successfully opened for reading.
    163163*/
    164164
     
    296296/*
    297297   Compare two filename (fileName1,fileName2).
    298    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    299    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
     298   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
     299   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
    300300                                                                or strcasecmp)
    301    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
     301   If iCaseSensitivity = 0, case sensitivity is default of your operating system
    302302        (like 1 on Unix, 2 on Windows)
    303303
  • vendor/current/lib/zlib/contrib/minizip/unzip.h

    r414 r740  
    125125/*
    126126   Compare two filename (fileName1,fileName2).
    127    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    128    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
     127   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
     128   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
    129129                                or strcasecmp)
    130    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
     130   If iCaseSensitivity = 0, case sensitivity is default of your operating system
    131131    (like 1 on Unix, 2 on Windows)
    132132*/
  • vendor/current/lib/zlib/contrib/minizip/zip.c

    r414 r740  
    100100  uLong  avail_in_this_block;
    101101  uLong  filled_in_this_block;
    102   uLong  unused; /* for future use and alignement */
     102  uLong  unused; /* for future use and alignment */
    103103  unsigned char data[SIZEDATA_INDATABLOCK];
    104104} linkedlist_datablock_internal;
     
    118118
    119119    uLong pos_local_header;     /* offset of the local header of the file
    120                                      currenty writing */
     120                                     currently writing */
    121121    char* central_header;       /* central header data for the current file */
    122122    uLong size_centralheader;   /* size of the central header for cur file */
    123123    uLong flag;                 /* flag of the file currently writing */
    124124
    125     int  method;                /* compression method of file currenty wr.*/
     125    int  method;                /* compression method of file currently wr.*/
    126126    int  raw;                   /* 1 for directly writing raw data */
    127127    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
  • vendor/current/lib/zlib/contrib/puff/puff.c

    r414 r740  
    586586 *   the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
    587587 *   that length, and the symbols 16, 17, and 18 are run-length instructions.
    588  *   Each of 16, 17, and 18 are follwed by extra bits to define the length of
     588 *   Each of 16, 17, and 18 are followed by extra bits to define the length of
    589589 *   the run.  16 copies the last length 3 to 6 times.  17 represents 3 to 10
    590590 *   zero lengths, and 18 represents 11 to 138 zero lengths.  Unused symbols
  • vendor/current/lib/zlib/deflate.h

    r414 r740  
    189189
    190190                /* used by trees.c: */
    191     /* Didn't use ct_data typedef below to supress compiler warning */
     191    /* Didn't use ct_data typedef below to suppress compiler warning */
    192192    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
    193193    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
  • vendor/current/lib/zlib/examples/fitblk.c

    r414 r740  
    1818   nearly the requested output block size.  The first pass generates
    1919   enough deflate blocks to produce output to fill the requested
    20    output size plus a specfied excess amount (see the EXCESS define
     20   output size plus a specified excess amount (see the EXCESS define
    2121   below).  The last deflate block may go quite a bit past that, but
    2222   is discarded.  The second pass decompresses and recompresses just
  • vendor/current/lib/zlib/examples/gun.c

    r414 r740  
    4343   encountered in an input file, it is the last stream in that file.
    4444
    45    Like gunzip and uncompress, the file attributes of the orignal compressed
     45   Like gunzip and uncompress, the file attributes of the original compressed
    4646   file are maintained in the final uncompressed file, to the extent that the
    4747   user permissions allow it.
  • vendor/current/lib/zlib/gzio.c

    r414 r740  
    255255     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    256256   for end of file.
    257    IN assertion: the stream s has been sucessfully opened for reading.
     257   IN assertion: the stream s has been successfully opened for reading.
    258258*/
    259259local int get_byte(s)
     
    280280    to Z_DATA_ERROR if the magic header is present but the rest of the header
    281281    is incorrect.
    282     IN assertion: the stream s has already been created sucessfully;
     282    IN assertion: the stream s has already been created successfully;
    283283       s->stream.avail_in is zero for the first time, but may be non-zero
    284284       for concatenated .gz files.
  • vendor/current/lib/zlib/zlib.h

    r414 r740  
    886886
    887887     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
    888    the paramaters are invalid, Z_MEM_ERROR if the internal state could not
     888   the parameters are invalid, Z_MEM_ERROR if the internal state could not
    889889   be allocated, or Z_VERSION_ERROR if the version of the library does not
    890890   match the version of the header file.
Note: See TracChangeset for help on using the changeset viewer.