diff options
author | Gerald Carter <jerry@samba.org> | 2007-02-28 14:35:26 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2007-02-28 14:35:26 +0000 |
commit | 80236f0d60ce013134c1ed5422d148e541f70a4f (patch) | |
tree | f71326fa71c0323e6b5d87b75b289d0608480f87 /source/lib | |
parent | f05f5dce39b11e937fb19270b7bcc888582edf35 (diff) | |
download | samba-80236f0d60ce013134c1ed5422d148e541f70a4f.tar.gz samba-80236f0d60ce013134c1ed5422d148e541f70a4f.tar.xz samba-80236f0d60ce013134c1ed5422d148e541f70a4f.zip |
r21585: Start syncing the monster that will become 3.0.25pre1
Still todo:
* release notes
* few minor outstanding patches
* additional idmap man pages
Diffstat (limited to 'source/lib')
120 files changed, 20585 insertions, 7221 deletions
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c index d4e585f74f6..f4008457ac1 100644 --- a/source/lib/account_pol.c +++ b/source/lib/account_pol.c @@ -28,7 +28,6 @@ static TDB_CONTEXT *tdb; * ldap directly) - gd */ #define DATABASE_VERSION 3 -#define AP_LASTSET "LAST_CACHE_UPDATE" #define AP_TTL 60 @@ -84,28 +83,24 @@ static const struct ap_table account_policy_names[] = { {0, NULL, 0, "", NULL} }; -char *account_policy_names_list(void) -{ - char *nl, *p; - int i; - size_t len = 0; +void account_policy_names_list(const char ***names, int *num_names) +{ + const char **nl; + int i, count; - for (i=0; account_policy_names[i].string; i++) { - len += strlen(account_policy_names[i].string) + 1; + for (count=0; account_policy_names[count].string; count++) { } - len++; - nl = SMB_MALLOC(len); + nl = SMB_MALLOC_ARRAY(const char *, count); if (!nl) { - return NULL; + *num_names = 0; + return; } - p = nl; for (i=0; account_policy_names[i].string; i++) { - memcpy(p, account_policy_names[i].string, strlen(account_policy_names[i].string) + 1); - p[strlen(account_policy_names[i].string)] = '\n'; - p += strlen(account_policy_names[i].string) + 1; + nl[i] = account_policy_names[i].string; } - *p = '\0'; - return nl; + *num_names = count; + *names = nl; + return; } /**************************************************************************** @@ -169,50 +164,6 @@ int account_policy_name_to_fieldnum(const char *name) } /***************************************************************************** -Update LAST-Set counter inside the cache -*****************************************************************************/ - -static BOOL account_policy_cache_timestamp(uint32 *value, BOOL update, - const char *ap_name) -{ - pstring key; - uint32 val = 0; - time_t now; - - if (ap_name == NULL) - return False; - - slprintf(key, sizeof(key)-1, "%s/%s", ap_name, AP_LASTSET); - - if (!init_account_policy()) { - return False; - } - - if (!tdb_fetch_uint32(tdb, key, &val) && !update) { - DEBUG(10,("failed to get last set timestamp of cache\n")); - return False; - } - - *value = val; - - DEBUG(10, ("account policy cache lastset was: %s\n", http_timestring(val))); - - if (update) { - - now = time(NULL); - - if (!tdb_store_uint32(tdb, key, (uint32)now)) { - DEBUG(1, ("tdb_store_uint32 failed for %s\n", key)); - return False; - } - DEBUG(10, ("account policy cache lastset now: %s\n", http_timestring(now))); - *value = now; - } - - return True; -} - -/***************************************************************************** Get default value for account policy *****************************************************************************/ @@ -262,10 +213,13 @@ BOOL init_account_policy(void) return True; } - tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb) { - DEBUG(0,("Failed to open account policy database\n")); - return False; + tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); + if (!tdb) { /* the account policies files does not exist or open failed, try to create a new one */ + tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + if (!tdb) { + DEBUG(0,("Failed to open account policy database\n")); + return False; + } } /* handle a Samba upgrade */ @@ -311,7 +265,7 @@ Get an account policy (from tdb) BOOL account_policy_get(int field, uint32 *value) { - fstring name; + const char *name; uint32 regval; if (!init_account_policy()) { @@ -322,8 +276,8 @@ BOOL account_policy_get(int field, uint32 *value) *value = 0; } - fstrcpy(name, decode_account_policy_name(field)); - if (!*name) { + name = decode_account_policy_name(field); + if (name == NULL) { DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); return False; } @@ -348,14 +302,14 @@ Set an account policy (in tdb) BOOL account_policy_set(int field, uint32 value) { - fstring name; + const char *name; if (!init_account_policy()) { return False; } - fstrcpy(name, decode_account_policy_name(field)); - if (!*name) { + name = decode_account_policy_name(field); + if (name == NULL) { DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field)); return False; } @@ -376,8 +330,10 @@ Set an account policy in the cache BOOL cache_account_policy_set(int field, uint32 value) { - uint32 lastset; const char *policy_name = NULL; + char *cache_key = NULL; + char *cache_value = NULL; + BOOL ret = False; policy_name = decode_account_policy_name(field); if (policy_name == NULL) { @@ -385,94 +341,59 @@ BOOL cache_account_policy_set(int field, uint32 value) return False; } - DEBUG(10,("cache_account_policy_set: updating account pol cache\n")); - - if (!account_policy_set(field, value)) { - return False; - } - - if (!account_policy_cache_timestamp(&lastset, True, policy_name)) - { - DEBUG(10,("cache_account_policy_set: failed to get lastest cache update timestamp\n")); - return False; - } - - DEBUG(10,("cache_account_policy_set: cache valid until: %s\n", http_timestring(lastset+AP_TTL))); - - return True; -} - -/***************************************************************************** -Check whether account policies have been migrated to passdb -*****************************************************************************/ - -BOOL account_policy_migrated(BOOL init) -{ - pstring key; - uint32 val; - time_t now; - - slprintf(key, sizeof(key)-1, "AP_MIGRATED_TO_PASSDB"); - - if (!init_account_policy()) { - return False; - } - - if (init) { - now = time(NULL); - - if (!tdb_store_uint32(tdb, key, (uint32)now)) { - DEBUG(1, ("tdb_store_uint32 failed for %s\n", key)); - return False; - } - - return True; + if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) { + DEBUG(0, ("asprintf failed\n")); + goto done; } - if (!tdb_fetch_uint32(tdb, key, &val)) { - return False; + if (asprintf(&cache_value, "%lu\n", (unsigned long)value) < 0) { + DEBUG(0, ("asprintf failed\n")); + goto done; } - return True; -} - -/***************************************************************************** - Remove marker that informs that account policies have been migrated to passdb -*****************************************************************************/ + DEBUG(10,("cache_account_policy_set: updating account pol cache\n")); -BOOL remove_account_policy_migrated(void) -{ - if (!init_account_policy()) { - return False; - } + ret = gencache_set(cache_key, cache_value, time(NULL)+AP_TTL); - return tdb_delete_bystring(tdb, "AP_MIGRATED_TO_PASSDB"); + done: + SAFE_FREE(cache_key); + SAFE_FREE(cache_value); + return ret; } - /***************************************************************************** Get an account policy from the cache *****************************************************************************/ BOOL cache_account_policy_get(int field, uint32 *value) { - uint32 lastset; + const char *policy_name = NULL; + char *cache_key = NULL; + char *cache_value = NULL; + BOOL ret = False; - if (!account_policy_cache_timestamp(&lastset, False, - decode_account_policy_name(field))) - { - DEBUG(10,("cache_account_policy_get: failed to get latest cache update timestamp\n")); + policy_name = decode_account_policy_name(field); + if (policy_name == NULL) { + DEBUG(0,("cache_account_policy_set: no policy found\n")); return False; } - if ((lastset + AP_TTL) < (uint32)time(NULL) ) { - DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n")); - return False; - } + if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) { + DEBUG(0, ("asprintf failed\n")); + goto done; + } - return account_policy_get(field, value); -} + if (gencache_get(cache_key, &cache_value, NULL)) { + uint32 tmp = strtoul(cache_value, NULL, 10); + *value = tmp; + ret = True; + } + done: + SAFE_FREE(cache_key); + SAFE_FREE(cache_value); + return ret; +} /**************************************************************************** ****************************************************************************/ diff --git a/source/lib/adt_tree.c b/source/lib/adt_tree.c index 05a470bc49e..acd61ee4775 100644 --- a/source/lib/adt_tree.c +++ b/source/lib/adt_tree.c @@ -334,7 +334,7 @@ static void pathtree_print_children( TREE_NODE *node, int debug, const char *pat void* pathtree_find( SORTED_TREE *tree, char *key ) { - char *keystr, *base, *str, *p; + char *keystr, *base = NULL, *str = NULL, *p; TREE_NODE *current; void *result = NULL; @@ -383,7 +383,8 @@ static void pathtree_print_children( TREE_NODE *node, int debug, const char *pat trim_tree_keypath( p, &base, &str ); DEBUG(11,("pathtree_find: [loop] base => [%s], new_path => [%s]\n", - base, str)); + base ? base : "", + str ? str : "")); /* iterate to the next child */ diff --git a/source/lib/afs.c b/source/lib/afs.c index 8a304adcf0c..ea83fdebc25 100644 --- a/source/lib/afs.c +++ b/source/lib/afs.c @@ -211,6 +211,7 @@ char *afs_createtoken_str(const char *username, const char *cell) BOOL afs_login(connection_struct *conn) { + extern userdom_struct current_user_info; extern struct current_user current_user; DATA_BLOB ticket; pstring afs_username; @@ -222,7 +223,11 @@ BOOL afs_login(connection_struct *conn) struct ClearToken ct; pstrcpy(afs_username, lp_afs_username_map()); - standard_sub_conn(conn, afs_username, sizeof(afs_username)); + standard_sub_advanced(SNUM(conn), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + afs_username, sizeof(afs_username)); user_sid = ¤t_user.nt_user_token->user_sids[0]; pstring_sub(afs_username, "%s", sid_string_static(user_sid)); diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c index 097d746a638..3d02988a979 100644 --- a/source/lib/charcnv.c +++ b/source/lib/charcnv.c @@ -56,7 +56,8 @@ static const char *charset_name(charset_t ch) { const char *ret = NULL; - if (ch == CH_UCS2) ret = "UTF-16LE"; + if (ch == CH_UTF16LE) ret = "UTF-16LE"; + else if (ch == CH_UTF16BE) ret = "UTF-16BE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); @@ -132,11 +133,11 @@ void init_iconv(void) /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ - if (!conv_handles[CH_UNIX][CH_UCS2]) - conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII"); + if (!conv_handles[CH_UNIX][CH_UTF16LE]) + conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII"); - if (!conv_handles[CH_UCS2][CH_UNIX]) - conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2)); + if (!conv_handles[CH_UTF16LE][CH_UNIX]) + conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE)); for (c1=0;c1<NUM_CHARSETS;c1++) { for (c2=0;c2<NUM_CHARSETS;c2++) { @@ -156,10 +157,10 @@ void init_iconv(void) if (conv_handles[c1][c2] == (smb_iconv_t)-1) { DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n", charset_name((charset_t)c1), charset_name((charset_t)c2))); - if (c1 != CH_UCS2) { + if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) { n1 = "ASCII"; } - if (c2 != CH_UCS2) { + if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) { n2 = "ASCII"; } DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n", @@ -214,7 +215,7 @@ static size_t convert_string_internal(charset_t from, charset_t to, descriptor = conv_handles[from][to]; if (srclen == (size_t)-1) { - if (from == CH_UCS2) { + if (from == CH_UTF16LE || from == CH_UTF16BE) { srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2; } else { srclen = strlen((const char *)src)+1; @@ -286,8 +287,11 @@ static size_t convert_string_internal(charset_t from, charset_t to, if (o_len == 0 || i_len == 0) return destlen - o_len; - if (from == CH_UCS2 && to != CH_UCS2) { - /* Can't convert from ucs2 to multibyte. Replace with the default fail char. */ + if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) && + ((to != CH_UTF16LE)||(to != CH_UTF16BE))) { + /* Can't convert from utf16 any endian to multibyte. + Replace with the default fail char. + */ if (i_len < 2) return destlen - o_len; if (i_len >= 2) { @@ -306,8 +310,10 @@ static size_t convert_string_internal(charset_t from, charset_t to, /* Keep trying with the next char... */ goto again; - } else if (from != CH_UCS2 && to == CH_UCS2) { - /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */ + } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) { + /* Can't convert to UTF16LE - just widen by adding the + default fail char then zero. + */ if (o_len < 2) return destlen - o_len; @@ -326,7 +332,8 @@ static size_t convert_string_internal(charset_t from, charset_t to, /* Keep trying with the next char... */ goto again; - } else if (from != CH_UCS2 && to != CH_UCS2) { + } else if (from != CH_UTF16LE && from != CH_UTF16BE && + to != CH_UTF16LE && to != CH_UTF16BE) { /* Failed multibyte to multibyte. Just copy the default fail char and try again. */ outbuf[0] = lp_failed_convert_char(); @@ -384,7 +391,7 @@ size_t convert_string(charset_t from, charset_t to, if (srclen == 0) return 0; - if (from != CH_UCS2 && to != CH_UCS2) { + if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t slen = srclen; @@ -419,7 +426,7 @@ size_t convert_string(charset_t from, charset_t to, } } return retval; - } else if (from == CH_UCS2 && to != CH_UCS2) { + } else if (from == CH_UTF16LE && to != CH_UTF16LE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; @@ -455,7 +462,7 @@ size_t convert_string(charset_t from, charset_t to, } } return retval; - } else if (from != CH_UCS2 && to == CH_UCS2) { + } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; @@ -516,13 +523,14 @@ size_t convert_string(charset_t from, charset_t to, **/ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest, BOOL allow_bad_conv) + void const *src, size_t srclen, void *dst, BOOL allow_bad_conv) { size_t i_len, o_len, destlen = MAX(srclen, 512); size_t retval; const char *inbuf = (const char *)src; char *outbuf = NULL, *ob = NULL; smb_iconv_t descriptor; + void **dest = (void **)dst; *dest = NULL; @@ -628,8 +636,12 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, if (o_len == 0 || i_len == 0) goto out; - if (from == CH_UCS2 && to != CH_UCS2) { - /* Can't convert from ucs2 to multibyte. Just use the default fail char. */ + if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) && + ((to != CH_UTF16LE)||(to != CH_UTF16BE))) { + /* Can't convert from utf16 any endian to multibyte. + Replace with the default fail char. + */ + if (i_len < 2) goto out; @@ -649,8 +661,10 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, /* Keep trying with the next char... */ goto again; - } else if (from != CH_UCS2 && to == CH_UCS2) { - /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */ + } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) { + /* Can't convert to UTF16LE - just widen by adding the + default fail char then zero. + */ if (o_len < 2) goto out; @@ -669,9 +683,10 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, /* Keep trying with the next char... */ goto again; - } else if (from != CH_UCS2 && to != CH_UCS2) { + } else if (from != CH_UTF16LE && from != CH_UTF16BE && + to != CH_UTF16LE && to != CH_UTF16BE) { /* Failed multibyte to multibyte. Just copy the default fail char and - try again. */ + try again. */ outbuf[0] = lp_failed_convert_char(); inbuf++; @@ -702,9 +717,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, * * @returns Size in bytes of the converted string; or -1 in case of error. **/ -static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest, BOOL allow_bad_conv) +size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, + void const *src, size_t srclen, void *dst, + BOOL allow_bad_conv) { + void **dest = (void **)dst; size_t dest_len; *dest = NULL; @@ -730,7 +747,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) return srclen; } - size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True); + size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True); free(buffer); return size; } @@ -766,14 +783,14 @@ char *strdup_upper(const char *s) /* MB case. */ size_t size; wpstring buffer; - size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer), True); + size = convert_string(CH_UNIX, CH_UTF16LE, s, -1, buffer, sizeof(buffer), True); if (size == (size_t)-1) { return NULL; } strupper_w(buffer); - size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True); + size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True); if (size == (size_t)-1) { return NULL; } @@ -787,7 +804,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer = NULL; - size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen, + size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen, (void **)(void *)&buffer, True); if (size == (size_t)-1 || !buffer) { smb_panic("failed to create UCS2 buffer"); @@ -796,7 +813,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) SAFE_FREE(buffer); return srclen; } - size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True); + size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True); SAFE_FREE(buffer); return size; } @@ -904,7 +921,7 @@ size_t push_ascii_nstring(void *dest, const char *src) for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) { unsigned char mb[10]; /* Convert one smb_ucs2_t character at a time. */ - size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False); + size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False); if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) { memcpy((char *)dest + dest_len, mb, mb_len); dest_len += mb_len; @@ -944,9 +961,9 @@ size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, if (flags & STR_TERMINATE) { if (src_len == (size_t)-1) { - src_len = strlen(src) + 1; + src_len = strlen((const char *)src) + 1; } else { - size_t len = strnlen(src, src_len); + size_t len = strnlen((const char *)src, src_len); if (len < src_len) len++; src_len = len; @@ -1026,7 +1043,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ /* ucs2 is always a multiple of 2 bytes */ dest_len &= ~1; - ret = convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len, True); + ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True); if (ret == (size_t)-1) { return 0; } @@ -1034,9 +1051,13 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ len += ret; if (flags & STR_UPPER) { - smb_ucs2_t *dest_ucs2 = dest; + smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest; size_t i; - for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { + + /* We check for i < (ret / 2) below as the dest string isn't null + terminated if STR_TERMINATE isn't set. */ + + for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) { smb_ucs2_t v = toupper_w(dest_ucs2[i]); if (v != dest_ucs2[i]) { dest_ucs2[i] = v; @@ -1062,7 +1083,7 @@ size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True); } @@ -1080,7 +1101,7 @@ size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True); + return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True); } /** @@ -1178,7 +1199,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ if (flags & STR_TERMINATE) { /* src_len -1 is the default for null terminated strings. */ if (src_len != (size_t)-1) { - size_t len = strnlen_w(src, src_len/2); + size_t len = strnlen_w((const smb_ucs2_t *)src, + src_len/2); if (len < src_len/2) len++; src_len = len*2; @@ -1189,7 +1211,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ if (src_len != (size_t)-1) src_len &= ~1; - ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len, True); + ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True); if (ret == (size_t)-1) { return 0; } @@ -1227,7 +1249,7 @@ size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src) { size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); *dest = NULL; - return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True); + return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True); } /** @@ -1242,7 +1264,7 @@ size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src) { size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); *dest = NULL; - return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True); + return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True); } /** @@ -1370,33 +1392,85 @@ size_t align_string(const void *base_ptr, const char *p, int flags) return 0; } -/**************************************************************** - Calculate the size (in bytes) of the next multibyte character in - our internal character set. Note that p must be pointing to a - valid mb char, not within one. -****************************************************************/ +/* + Return the unicode codepoint for the next multi-byte CH_UNIX character + in the string. The unicode codepoint (codepoint_t) is an unsinged 32 bit value. + + Also return the number of bytes consumed (which tells the caller + how many bytes to skip to get to the next CH_UNIX character). + + Return INVALID_CODEPOINT if the next character cannot be converted. +*/ -size_t next_mb_char_size(const char *s) +codepoint_t next_codepoint(const char *str, size_t *size) { - size_t i; + /* It cannot occupy more than 4 bytes in UTF16 format */ + uint8_t buf[4]; + smb_iconv_t descriptor; + size_t ilen_orig; + size_t ilen; + size_t olen; + char *outbuf; + + if ((str[0] & 0x80) == 0) { + *size = 1; + return (codepoint_t)str[0]; + } - if (!(*s & 0x80)) - return 1; /* ascii. */ + /* We assume that no multi-byte character can take + more than 5 bytes. This is OK as we only + support codepoints up to 1M */ - conv_silent = True; - for ( i = 1; i <=4; i++ ) { - smb_ucs2_t uc; - if (convert_string(CH_UNIX, CH_UCS2, s, i, &uc, 2, False) == 2) { -#if 0 /* JRATEST */ - DEBUG(10,("next_mb_char_size: size %u at string %s\n", - (unsigned int)i, s)); -#endif - conv_silent = False; - return i; + ilen_orig = strnlen(str, 5); + ilen = ilen_orig; + + lazy_initialize_conv(); + + descriptor = conv_handles[CH_UNIX][CH_UTF16LE]; + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + *size = 1; + return INVALID_CODEPOINT; + } + + /* This looks a little strange, but it is needed to cope + with codepoints above 64k which are encoded as per RFC2781. */ + olen = 2; + outbuf = (char *)buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 2) { + /* We failed to convert to a 2 byte character. + See if we can convert to a 4 UTF16-LE byte char encoding. + */ + olen = 4; + outbuf = (char *)buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 4) { + /* We didn't convert any bytes */ + *size = 1; + return INVALID_CODEPOINT; } + olen = 4 - olen; + } else { + olen = 2 - olen; } - /* We're hosed - we don't know how big this is... */ - DEBUG(10,("next_mb_char_size: unknown size at string %s\n", s)); - conv_silent = False; - return 1; + + *size = ilen_orig - ilen; + + if (olen == 2) { + /* 2 byte, UTF16-LE encoded value. */ + return (codepoint_t)SVAL(buf, 0); + } + if (olen == 4) { + /* Decode a 4 byte UTF16-LE character manually. + See RFC2871 for the encoding machanism. + */ + codepoint_t w1 = SVAL(buf,0) & ~0xD800; + codepoint_t w2 = SVAL(buf,2) & ~0xDC00; + + return (codepoint_t)0x10000 + + (w1 << 10) + w2; + } + + /* no other length is valid */ + return INVALID_CODEPOINT; } diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c index ccd0d27f47b..c7eadc1acfb 100644 --- a/source/lib/data_blob.c +++ b/source/lib/data_blob.c @@ -47,9 +47,9 @@ DATA_BLOB data_blob(const void *p, size_t length) } if (p) { - ret.data = smb_xmemdup(p, length); + ret.data = (uint8 *)smb_xmemdup(p, length); } else { - ret.data = SMB_XMALLOC_ARRAY(unsigned char, length); + ret.data = SMB_XMALLOC_ARRAY(uint8, length); } ret.length = length; ret.free = free_data_blob; @@ -70,11 +70,11 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) } if (p) { - ret.data = TALLOC_MEMDUP(mem_ctx, p, length); + ret.data = (uint8 *)TALLOC_MEMDUP(mem_ctx, p, length); if (ret.data == NULL) smb_panic("data_blob_talloc: talloc_memdup failed.\n"); } else { - ret.data = TALLOC(mem_ctx, length); + ret.data = (uint8 *)TALLOC(mem_ctx, length); if (ret.data == NULL) smb_panic("data_blob_talloc: talloc failed.\n"); } @@ -102,7 +102,7 @@ void data_blob_free(DATA_BLOB *d) Clear a DATA_BLOB's contents *******************************************************************/ -static void data_blob_clear(DATA_BLOB *d) +void data_blob_clear(DATA_BLOB *d) { if (d->data) { memset(d->data, 0, d->length); @@ -118,3 +118,28 @@ void data_blob_clear_free(DATA_BLOB *d) data_blob_clear(d); data_blob_free(d); } + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +DATA_BLOB data_blob_string_const(const char *str) +{ + DATA_BLOB blob; + blob.data = CONST_DISCARD(uint8 *, str); + blob.length = strlen(str); + blob.free = NULL; + return blob; +} + +/** + * Create a new data blob from const data + */ +DATA_BLOB data_blob_const(const void *p, size_t length) +{ + DATA_BLOB blob; + blob.data = CONST_DISCARD(uint8 *, p); + blob.length = length; + blob.free = NULL; + return blob; +} diff --git a/source/lib/debug.c b/source/lib/debug.c index 2b6c42b8eb0..5f141661106 100644 --- a/source/lib/debug.c +++ b/source/lib/debug.c @@ -236,7 +236,7 @@ static char *debug_list_class_names_and_levels(void) } /* create single string list - add space for newline */ - b = buf = SMB_MALLOC(dim+1); + b = buf = (char *)SMB_MALLOC(dim+1); if (!buf) { err = True; goto done; @@ -320,7 +320,7 @@ int debug_add_class(const char *classname) new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1); if (!new_ptr) return -1; - DEBUGLEVEL_CLASS = new_ptr; + DEBUGLEVEL_CLASS = (int *)new_ptr; DEBUGLEVEL_CLASS[ndx] = 0; /* debug_level is the pointer used for the DEBUGLEVEL-thingy */ @@ -337,13 +337,13 @@ int debug_add_class(const char *classname) new_ptr = SMB_REALLOC_ARRAY(new_ptr, BOOL, debug_num_classes + 1); if (!new_ptr) return -1; - DEBUGLEVEL_CLASS_ISSET = new_ptr; + DEBUGLEVEL_CLASS_ISSET = (int *)new_ptr; DEBUGLEVEL_CLASS_ISSET[ndx] = False; new_ptr = SMB_REALLOC_ARRAY(classname_table, char *, debug_num_classes + 1); if (!new_ptr) return -1; - classname_table = new_ptr; + classname_table = (char **)new_ptr; classname_table[ndx] = SMB_STRDUP(classname); if (! classname_table[ndx]) @@ -472,9 +472,9 @@ BOOL debug_parse_levels(const char *params_str) ****************************************************************************/ static void debug_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { - const char *params_str = buf; + const char *params_str = (const char *)buf; /* Check, it's a proper string! */ if (params_str[len-1] != '\0') { @@ -509,7 +509,7 @@ void debug_message_send(pid_t pid, const char *params_str) ****************************************************************************/ static void debuglevel_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { char *message = debug_list_class_names_and_levels(); @@ -539,8 +539,8 @@ void debug_init(void) initialised = True; - message_register(MSG_DEBUG, debug_message); - message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message); + message_register(MSG_DEBUG, debug_message, NULL); + message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message, NULL); for(p = default_classname_table; *p; p++) { debug_add_class(*p); @@ -981,7 +981,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line ) /* Print it all out at once to prevent split syslog output. */ (void)Debug1( "[%s, %d%s] %s:%s(%d)\n", - timestring(lp_debug_hires_timestamp()), level, + current_timestring(lp_debug_hires_timestamp()), level, header_str, file, func, line ); } diff --git a/source/lib/display_sec.c b/source/lib/display_sec.c index 49a86c261ca..2b3542922c1 100644 --- a/source/lib/display_sec.c +++ b/source/lib/display_sec.c @@ -63,7 +63,7 @@ char *get_sec_mask_str(uint32 type) ****************************************************************************/ void display_sec_access(SEC_ACCESS *info) { - printf("\t\tPermissions: 0x%x: %s\n", info->mask, get_sec_mask_str(info->mask)); + printf("\t\tPermissions: 0x%x: %s\n", *info, get_sec_mask_str(*info)); } /**************************************************************************** @@ -92,7 +92,7 @@ void display_sec_ace(SEC_ACE *ace) break; } printf(" (%d) flags: %d\n", ace->type, ace->flags); - display_sec_access(&ace->info); + display_sec_access(&ace->access_mask); sid_to_string(sid_str, &ace->trustee); printf("\t\tSID: %s\n\n", sid_str); } @@ -110,7 +110,7 @@ void display_sec_acl(SEC_ACL *sec_acl) if (sec_acl->size != 0 && sec_acl->num_aces != 0) for (i = 0; i < sec_acl->num_aces; i++) - display_sec_ace(&sec_acl->ace[i]); + display_sec_ace(&sec_acl->aces[i]); } @@ -179,8 +179,8 @@ void display_sec_desc(SEC_DESC *sec) printf("\tOwner SID:\t%s\n", sid_str); } - if (sec->grp_sid) { - sid_to_string(sid_str, sec->grp_sid); + if (sec->group_sid) { + sid_to_string(sid_str, sec->group_sid); printf("\tParent SID:\t%s\n", sid_str); } } diff --git a/source/lib/dmallocmsg.c b/source/lib/dmallocmsg.c index 1b2308ecba6..fed7bf59c52 100644 --- a/source/lib/dmallocmsg.c +++ b/source/lib/dmallocmsg.c @@ -35,8 +35,10 @@ static unsigned long our_dm_mark = 0; * Respond to a POOL_USAGE message by sending back string form of memory * usage stats. **/ -static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED(src_pid), - void *UNUSED(buf), size_t UNUSED(len)) +static void msg_req_dmalloc_mark(int UNUSED(msg_type), + struct process_id UNUSED(src_pid), + void *UNUSED(buf), size_t UNUSED(len), + void *private_data) { #ifdef ENABLE_DMALLOC our_dm_mark = dmalloc_mark(); @@ -50,7 +52,8 @@ static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED( static void msg_req_dmalloc_log_changed(int UNUSED(msg_type), struct process_id UNUSED(src_pid), - void *UNUSED(buf), size_t UNUSED(len)) + void *UNUSED(buf), size_t UNUSED(len), + void *private_data) { #ifdef ENABLE_DMALLOC dmalloc_log_changed(our_dm_mark, True, True, True); @@ -66,7 +69,8 @@ static void msg_req_dmalloc_log_changed(int UNUSED(msg_type), **/ void register_dmalloc_msgs(void) { - message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark); - message_register(MSG_REQ_DMALLOC_LOG_CHANGED, msg_req_dmalloc_log_changed); + message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark, NULL); + message_register(MSG_REQ_DMALLOC_LOG_CHANGED, + msg_req_dmalloc_log_changed, NULL); DEBUG(2, ("Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED\n")); } diff --git a/source/lib/dprintf.c b/source/lib/dprintf.c index 8ed2fa5d8cd..2312c3db0cb 100644 --- a/source/lib/dprintf.c +++ b/source/lib/dprintf.c @@ -54,7 +54,7 @@ charset, but beware of it growing */ maxlen = ret*2; again: - p2 = SMB_MALLOC(maxlen); + p2 = (char *)SMB_MALLOC(maxlen); if (!p2) { SAFE_FREE(p); return -1; diff --git a/source/lib/dummysmbd.c b/source/lib/dummysmbd.c index 9b587224e3e..a291a5884d9 100644 --- a/source/lib/dummysmbd.c +++ b/source/lib/dummysmbd.c @@ -24,11 +24,6 @@ #include "includes.h" -void decrement_smbd_process_count( void ) -{ - return; -} - int find_service(fstring service) { return -1; @@ -38,3 +33,18 @@ BOOL conn_snum_used(int snum) { return False; } + +void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck) +{ +} + +void send_stat_cache_delete_message(const char *name) +{ +} + +NTSTATUS can_delete_directory(struct connection_struct *conn, + const char *dirname) +{ + return NT_STATUS_OK; +} + diff --git a/source/lib/events.c b/source/lib/events.c index 242c198511e..a00db77b6be 100644 --- a/source/lib/events.c +++ b/source/lib/events.c @@ -21,32 +21,93 @@ #include "includes.h" -static struct timed_event *timed_events; +struct timed_event { + struct timed_event *next, *prev; + struct event_context *event_ctx; + struct timeval when; + const char *event_name; + void (*handler)(struct event_context *event_ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data); + void *private_data; +}; -static int timed_event_destructor(void *p) +struct fd_event { + struct fd_event *prev, *next; + struct event_context *event_ctx; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + void (*handler)(struct event_context *event_ctx, + struct fd_event *event, + uint16 flags, + void *private_data); + void *private_data; +}; + +#define EVENT_FD_WRITEABLE(fde) \ + event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE) +#define EVENT_FD_READABLE(fde) \ + event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ) + +#define EVENT_FD_NOT_WRITEABLE(fde) \ + event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) +#define EVENT_FD_NOT_READABLE(fde) \ + event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ) + +struct event_context { + struct timed_event *timed_events; + struct fd_event *fd_events; +}; + +static int timed_event_destructor(struct timed_event *te) { - struct timed_event *te = talloc_get_type_abort(p, struct timed_event); DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, te->event_name)); - DLIST_REMOVE(timed_events, te); + DLIST_REMOVE(te->event_ctx->timed_events, te); return 0; } /**************************************************************************** + Add te by time. +****************************************************************************/ + +static void add_event_by_time(struct timed_event *te) +{ + struct event_context *ctx = te->event_ctx; + struct timed_event *last_te, *cur_te; + + /* Keep the list ordered by time. We must preserve this. */ + last_te = NULL; + for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) { + /* if the new event comes before the current one break */ + if (!timeval_is_zero(&cur_te->when) && + timeval_compare(&te->when, &cur_te->when) < 0) { + break; + } + last_te = cur_te; + } + + DLIST_ADD_AFTER(ctx->timed_events, te, last_te); +} + +/**************************************************************************** Schedule a function for future calling, cancel with TALLOC_FREE(). It's the responsibility of the handler to call TALLOC_FREE() on the event handed to it. ****************************************************************************/ -struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, +struct timed_event *event_add_timed(struct event_context *event_ctx, + TALLOC_CTX *mem_ctx, struct timeval when, const char *event_name, - void (*handler)(struct timed_event *te, + void (*handler)(struct event_context *event_ctx, + struct timed_event *te, const struct timeval *now, void *private_data), void *private_data) { - struct timed_event *te, *last_te, *cur_te; + struct timed_event *te; te = TALLOC_P(mem_ctx, struct timed_event); if (te == NULL) { @@ -54,23 +115,14 @@ struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, return NULL; } + te->event_ctx = event_ctx; te->when = when; te->event_name = event_name; te->handler = handler; te->private_data = private_data; - /* keep the list ordered */ - last_te = NULL; - for (cur_te = timed_events; cur_te; cur_te = cur_te->next) { - /* if the new event comes before the current one break */ - if (!timeval_is_zero(&cur_te->when) && - timeval_compare(&te->when, &cur_te->when) < 0) { - break; - } - last_te = cur_te; - } + add_event_by_time(te); - DLIST_ADD_AFTER(timed_events, te, last_te); talloc_set_destructor(te, timed_event_destructor); DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, @@ -78,44 +130,206 @@ struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, return te; } -void run_events(void) +static int fd_event_destructor(struct fd_event *fde) { - struct timeval now; + struct event_context *event_ctx = fde->event_ctx; - if (timed_events == NULL) { - /* No syscall if there are no events */ - DEBUG(11, ("run_events: No events\n")); - return; + DLIST_REMOVE(event_ctx->fd_events, fde); + return 0; +} + +struct fd_event *event_add_fd(struct event_context *event_ctx, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + void (*handler)(struct event_context *event_ctx, + struct fd_event *event, + uint16 flags, + void *private_data), + void *private_data) +{ + struct fd_event *fde; + + if (!(fde = TALLOC_P(mem_ctx, struct fd_event))) { + return NULL; } - GetTimeOfDay(&now); + fde->event_ctx = event_ctx; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->private_data = private_data; + + DLIST_ADD(event_ctx->fd_events, fde); - if (timeval_compare(&now, &timed_events->when) < 0) { - /* Nothing to do yet */ - DEBUG(11, ("run_events: Nothing to do\n")); + talloc_set_destructor(fde, fd_event_destructor); + return fde; +} + +void event_fd_set_writeable(struct fd_event *fde) +{ + fde->flags |= EVENT_FD_WRITE; +} + +void event_fd_set_not_writeable(struct fd_event *fde) +{ + fde->flags &= ~EVENT_FD_WRITE; +} + +void event_fd_set_readable(struct fd_event *fde) +{ + fde->flags |= EVENT_FD_READ; +} + +void event_fd_set_not_readable(struct fd_event *fde) +{ + fde->flags &= ~EVENT_FD_READ; +} + +void event_add_to_select_args(struct event_context *event_ctx, + const struct timeval *now, + fd_set *read_fds, fd_set *write_fds, + struct timeval *timeout, int *maxfd) +{ + struct fd_event *fde; + struct timeval diff; + + for (fde = event_ctx->fd_events; fde; fde = fde->next) { + if (fde->flags & EVENT_FD_READ) { + FD_SET(fde->fd, read_fds); + } + if (fde->flags & EVENT_FD_WRITE) { + FD_SET(fde->fd, write_fds); + } + + if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) + && (fde->fd > *maxfd)) { + *maxfd = fde->fd; + } + } + + if (event_ctx->timed_events == NULL) { return; } - DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name, - (unsigned long)timed_events)); + diff = timeval_until(now, &event_ctx->timed_events->when); + *timeout = timeval_min(timeout, &diff); +} + +BOOL run_events(struct event_context *event_ctx, + int selrtn, fd_set *read_fds, fd_set *write_fds) +{ + BOOL fired = False; + struct fd_event *fde, *next; + + /* Run all events that are pending, not just one (as we + did previously. */ + + while (event_ctx->timed_events) { + struct timeval now; + GetTimeOfDay(&now); + + if (timeval_compare( + &now, &event_ctx->timed_events->when) < 0) { + /* Nothing to do yet */ + DEBUG(11, ("run_events: Nothing to do\n")); + break; + } + + DEBUG(10, ("Running event \"%s\" %lx\n", + event_ctx->timed_events->event_name, + (unsigned long)event_ctx->timed_events)); + + event_ctx->timed_events->handler( + event_ctx, + event_ctx->timed_events, &now, + event_ctx->timed_events->private_data); + + fired = True; + } + + if (fired) { + /* + * We might have changed the socket status during the timed + * events, return to run select again. + */ + return True; + } + + if (selrtn == 0) { + /* + * No fd ready + */ + return fired; + } - timed_events->handler(timed_events, &now, timed_events->private_data); - return; + for (fde = event_ctx->fd_events; fde; fde = next) { + uint16 flags = 0; + + next = fde->next; + if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE; + + if (flags) { + fde->handler(event_ctx, fde, flags, fde->private_data); + fired = True; + } + } + + return fired; } -struct timeval *get_timed_events_timeout(struct timeval *to_ret) + +struct timeval *get_timed_events_timeout(struct event_context *event_ctx, + struct timeval *to_ret) { struct timeval now; - if (timed_events == NULL) { + if (event_ctx->timed_events == NULL) { return NULL; } now = timeval_current(); - *to_ret = timeval_until(&now, &timed_events->when); + *to_ret = timeval_until(&now, &event_ctx->timed_events->when); DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec, (int)to_ret->tv_usec)); return to_ret; } + +struct event_context *event_context_init(TALLOC_CTX *mem_ctx) +{ + return TALLOC_ZERO_P(NULL, struct event_context); +} + +int set_event_dispatch_time(struct event_context *event_ctx, + const char *event_name, struct timeval when) +{ + struct timed_event *te; + + for (te = event_ctx->timed_events; te; te = te->next) { + if (strcmp(event_name, te->event_name) == 0) { + DLIST_REMOVE(event_ctx->timed_events, te); + te->when = when; + add_event_by_time(te); + return 1; + } + } + return 0; +} + +/* Returns 1 if event was found and cancelled, 0 otherwise. */ + +int cancel_named_event(struct event_context *event_ctx, + const char *event_name) +{ + struct timed_event *te; + + for (te = event_ctx->timed_events; te; te = te->next) { + if (strcmp(event_name, te->event_name) == 0) { + TALLOC_FREE(te); + return 1; + } + } + return 0; +} diff --git a/source/lib/fault.c b/source/lib/fault.c index dc8c276d02c..b632a5c82fa 100644 --- a/source/lib/fault.c +++ b/source/lib/fault.c @@ -160,12 +160,13 @@ void dump_core_setup(const char *progname) exit(1); } +#if DUMP_CORE if (*corepath != '\0') { /* The chdir might fail if we dump core before we finish * processing the config file. */ if (chdir(corepath) != 0) { - DEBUG(0, ("unable to change to %s", corepath)); + DEBUG(0, ("unable to change to %s\n", corepath)); DEBUGADD(0, ("refusing to dump core\n")); exit(1); } @@ -182,5 +183,9 @@ void dump_core_setup(const char *progname) #endif abort(); + +#else /* DUMP_CORE */ + exit(1); +#endif /* DUMP_CORE */ } diff --git a/source/lib/gencache.c b/source/lib/gencache.c index 013eed8a00d..c58642553c0 100644 --- a/source/lib/gencache.c +++ b/source/lib/gencache.c @@ -130,9 +130,9 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) if (!valstr) return False; - keybuf.dptr = SMB_STRDUP(keystr); + keybuf.dptr = CONST_DISCARD(char *, keystr); keybuf.dsize = strlen(keystr)+1; - databuf.dptr = SMB_STRDUP(valstr); + databuf.dptr = valstr; databuf.dsize = strlen(valstr)+1; DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" " %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout), @@ -141,71 +141,9 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) ret = tdb_store(cache, keybuf, databuf, 0); SAFE_FREE(valstr); - SAFE_FREE(keybuf.dptr); - SAFE_FREE(databuf.dptr); - - return ret == 0; -} - - -/** - * Set existing entry to the cache file. - * - * @param keystr string that represents a key of this entry - * @param valstr text representation value being cached - * @param timeout time when the value is expired - * - * @retval true when entry is successfuly set - * @retval false on failure - **/ - -BOOL gencache_set_only(const char *keystr, const char *valstr, time_t timeout) -{ - int ret = -1; - TDB_DATA keybuf, databuf; - char *old_valstr, *datastr; - time_t old_timeout; - - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr && valstr); - - if (!gencache_init()) return False; - - if (cache_readonly) { - return False; - } - - /* - * Check whether entry exists in the cache - * Don't verify gencache_get exit code, since the entry may be expired - */ - gencache_get(keystr, &old_valstr, &old_timeout); - - if (!(old_valstr && old_timeout)) return False; - - DEBUG(10, ("Setting cache entry with key = %s; old value = %s and old timeout \ - = %s\n", keystr, old_valstr, ctime(&old_timeout))); - - asprintf(&datastr, CACHE_DATA_FMT, (int)timeout, valstr); - keybuf.dptr = SMB_STRDUP(keystr); - keybuf.dsize = strlen(keystr)+1; - databuf.dptr = SMB_STRDUP(datastr); - databuf.dsize = strlen(datastr)+1; - DEBUGADD(10, ("New value = %s, new timeout = %s (%d seconds %s)", valstr, - ctime(&timeout), (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - - ret = tdb_store(cache, keybuf, databuf, TDB_REPLACE); - - SAFE_FREE(datastr); - SAFE_FREE(old_valstr); - SAFE_FREE(keybuf.dptr); - SAFE_FREE(databuf.dptr); return ret == 0; } - /** * Delete one entry from the cache file. @@ -230,12 +168,11 @@ BOOL gencache_del(const char *keystr) return False; } - keybuf.dptr = SMB_STRDUP(keystr); + keybuf.dptr = CONST_DISCARD(char *, keystr); keybuf.dsize = strlen(keystr)+1; DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); ret = tdb_delete(cache, keybuf); - SAFE_FREE(keybuf.dptr); return ret == 0; } @@ -256,6 +193,8 @@ BOOL gencache_del(const char *keystr) BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) { TDB_DATA keybuf, databuf; + time_t t; + char *endptr; /* fail completely if get null pointers passed */ SMB_ASSERT(keystr); @@ -264,71 +203,55 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) return False; } - keybuf.dptr = SMB_STRDUP(keystr); + keybuf.dptr = CONST_DISCARD(char *, keystr); keybuf.dsize = strlen(keystr)+1; databuf = tdb_fetch(cache, keybuf); - SAFE_FREE(keybuf.dptr); - - if (databuf.dptr && databuf.dsize > TIMEOUT_LEN) { - char* entry_buf = SMB_STRNDUP(databuf.dptr, databuf.dsize); - char *v; - time_t t; - unsigned u; - int status; - char *fmt; - v = SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN); - if (!v) { - return False; - } + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", + keystr)); + return False; + } - SAFE_FREE(databuf.dptr); + t = strtol(databuf.dptr, &endptr, 10); - asprintf(&fmt, READ_CACHE_DATA_FMT_TEMPLATE, (unsigned int)databuf.dsize - TIMEOUT_LEN); - if (!fmt) { - SAFE_FREE(v); - return False; - } + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr)); + SAFE_FREE(databuf.dptr); + return False; + } - status = sscanf(entry_buf, fmt, &u, v); - SAFE_FREE(fmt); + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > time(NULL) ? "valid" : + "expired", keystr, endptr+1, ctime(&t))); - if ( status != 2 ) { - DEBUG(0, ("gencache_get: Invalid return %d from sscanf\n", status )); - } - t = u; - SAFE_FREE(entry_buf); + if (t <= time(NULL)) { - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > time(NULL) ? "valid" : - "expired", keystr, v, ctime(&t))); + /* We're expired, delete the entry */ + tdb_delete(cache, keybuf); - if (valstr) { - *valstr = v; - } else { - SAFE_FREE(v); - } + SAFE_FREE(databuf.dptr); + return False; + } - if (timeout) { - *timeout = t; + if (valstr) { + *valstr = SMB_STRDUP(endptr+1); + if (*valstr == NULL) { + SAFE_FREE(databuf.dptr); + DEBUG(0, ("strdup failed\n")); + return False; } - - return t > time(NULL); - - } - + } + SAFE_FREE(databuf.dptr); - if (valstr) { - *valstr = NULL; - } if (timeout) { - timeout = NULL; + *timeout = t; } - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", keystr)); - return False; -} + return True; +} + /** * Iterate through all entries which key matches to specified pattern @@ -389,7 +312,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time SAFE_FREE(databuf.dptr); - valstr = SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN); + valstr = (char *)SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN); if (!valstr) { SAFE_FREE(entry); SAFE_FREE(keystr); diff --git a/source/lib/getsmbpass.c b/source/lib/getsmbpass.c deleted file mode 100644 index bebddc69eb4..00000000000 --- a/source/lib/getsmbpass.c +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (C) 1992-1998 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ - -#include "includes.h" - -#ifdef REPLACE_GETPASS - -#ifdef SYSV_TERMIO - -/* SYSTEM V TERMIO HANDLING */ - -static struct termio t; - -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -#ifndef TCSAFLUSH -#define TCSAFLUSH 1 -#endif - -#ifndef TCSANOW -#define TCSANOW 0 -#endif - -static int tcgetattr(int fd, struct termio *t) -{ - return ioctl(fd, TCGETA, t); -} - -static int tcsetattr(int fd, int flags, struct termio *t) -{ - if(flags & TCSAFLUSH) - ioctl(fd, TCFLSH, TCIOFLUSH); - return ioctl(fd, TCSETS, t); -} - -#elif !defined(TCSAFLUSH) - -/* BSD TERMIO HANDLING */ - -static struct sgttyb t; - -#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) -#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) - -#define TCSAFLUSH 1 -#define TCSANOW 0 - -static int tcgetattr(int fd, struct sgttyb *t) -{ - return ioctl(fd, TIOCGETP, (char *)t); -} - -static int tcsetattr(int fd, int flags, struct sgttyb *t) -{ - return ioctl(fd, TIOCSETP, (char *)t); -} - -#else /* POSIX TERMIO HANDLING */ -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -static struct termios t; -#endif /* SYSV_TERMIO */ - -static SIG_ATOMIC_T gotintr; -static int in_fd = -1; - -/*************************************************************** - Signal function to tell us were ^C'ed. -****************************************************************/ - -static void gotintr_sig(void) -{ - gotintr = 1; - if (in_fd != -1) - close(in_fd); /* Safe way to force a return. */ - in_fd = -1; -} - -char *getsmbpass(const char *prompt) -{ - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST gotintr_sig); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) { - in = stdin; - out = stderr; - } else { - out = in; - } - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) { - if (ECHO_IS_ON(t)) { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); - } else { - echo_off = 0; - } - } else { - echo_off = 0; - } - - /* Write the prompt. */ - fputs(prompt, out); - fflush(out); - - /* Read the password. */ - buf[0] = 0; - if (!gotintr) { - in_fd = fileno(in); - fgets(buf, bufsize, in); - } - nread = strlen(buf); - if (nread) { - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - } - - /* Restore echoing. */ - if (echo_off) { - if (gotintr && in_fd == -1) - in = fopen ("/dev/tty", "w+"); - if (in != NULL) - tcsetattr (fileno (in), TCSANOW, &t); - } - - fprintf(out, "\n"); - fflush(out); - - if (in && in != stdin) /* We opened the terminal; now close it. */ - fclose(in); - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - - if (gotintr) { - printf("Interupted by signal.\n"); - fflush(stdout); - exit(1); - } - return buf; -} - -#else - void getsmbpasswd_dummy(void); - void getsmbpasswd_dummy(void) {;} -#endif diff --git a/source/lib/iconv.c b/source/lib/iconv.c index c96243633fb..6e040b77f17 100644 --- a/source/lib/iconv.c +++ b/source/lib/iconv.c @@ -128,6 +128,7 @@ static void lazy_initialize_iconv(void) } } +#ifdef HAVE_NATIVE_ICONV /* if there was an error then reset the internal state, this ensures that we don't have a shift state remaining for character sets like SJIS */ @@ -135,7 +136,6 @@ static size_t sys_iconv(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { -#ifdef HAVE_NATIVE_ICONV size_t ret = iconv((iconv_t)cd, (char **)inbuf, inbytesleft, outbuf, outbytesleft); @@ -145,11 +145,8 @@ static size_t sys_iconv(void *cd, errno = saved_errno; } return ret; -#else - errno = EINVAL; - return -1; -#endif } +#endif /** * This is a simple portable iconv() implementaion. diff --git a/source/lib/interface.c b/source/lib/interface.c index 2bd7d6ddbe0..9d0b966390f 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -187,7 +187,11 @@ void load_interfaces(void) total_probed = get_interfaces(ifaces, MAX_INTERFACES); if (total_probed > 0) { - probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); + probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed); + if (!probed_ifaces) { + DEBUG(0,("ERROR: memdup failed\n")); + exit(1); + } } /* if we don't have a interfaces line then use all broadcast capable diff --git a/source/lib/interfaces.c b/source/lib/interfaces.c index dc30bdce47a..839cab1286c 100644 --- a/source/lib/interfaces.c +++ b/source/lib/interfaces.c @@ -30,27 +30,21 @@ */ +#ifndef AUTOCONF_TEST +#include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> +#include <netdb.h> +#include <sys/ioctl.h> #include <netdb.h> #include <sys/ioctl.h> #include <sys/time.h> -#include <net/if.h> - -#ifdef AUTOCONF_TEST -struct iface_struct { - char name[16]; - struct in_addr ip; - struct in_addr netmask; -}; -#else -#include "config.h" -#include "interfaces.h" -#endif +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> #ifdef HAVE_SYS_TIME_H #include <sys/time.h> @@ -82,6 +76,12 @@ struct iface_struct { #define QSORT_CAST (int (*)(const void *, const void *)) #endif +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif + +#include "interfaces.h" + #if HAVE_IFACE_IFCONF /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 @@ -154,7 +154,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) return total; } -#elif HAVE_IFACE_IFREQ +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFCONF */ +#ifdef HAVE_IFACE_IFREQ #ifndef I_STR #include <sys/stropts.h> @@ -249,7 +251,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) return total; } -#elif HAVE_IFACE_AIX +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFREQ */ +#ifdef HAVE_IFACE_AIX /**************************************************************************** this one is for AIX (tested on 4.2) @@ -284,7 +288,7 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) i = ifc.ifc_len; while (i > 0 && total < max_interfaces) { - unsigned inc; + uint_t inc; inc = ifr->ifr_addr.sa_len; @@ -337,7 +341,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) return total; } -#else /* a dummy version */ +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_AIX */ +#ifndef _FOUND_IFACE_ANY static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) { return -1; @@ -356,10 +362,9 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) return r; } +int get_interfaces(struct iface_struct *ifaces, int max_interfaces); /* this wrapper is used to remove duplicates from the interface list generated above */ -int get_interfaces(struct iface_struct *ifaces, int max_interfaces); - int get_interfaces(struct iface_struct *ifaces, int max_interfaces) { int total, i, j; @@ -388,8 +393,6 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces) #ifdef AUTOCONF_TEST /* this is the autoconf driver to test get_interfaces() */ -#define MAX_INTERFACES 128 - int main() { struct iface_struct ifaces[MAX_INTERFACES]; diff --git a/source/lib/ldap_escape.c b/source/lib/ldap_escape.c index fcb787e9e85..26230884341 100644 --- a/source/lib/ldap_escape.c +++ b/source/lib/ldap_escape.c @@ -36,7 +36,7 @@ char *escape_ldap_string_alloc(const char *s) { size_t len = strlen(s)+1; - char *output = SMB_MALLOC(len); + char *output = (char *)SMB_MALLOC(len); const char *sub; int i = 0; char *p = output; @@ -68,7 +68,7 @@ char *escape_ldap_string_alloc(const char *s) if (sub) { len = len + 3; - output = SMB_REALLOC(output, len); + output = (char *)SMB_REALLOC(output, len); if (!output) { return NULL; } diff --git a/source/lib/messages.c b/source/lib/messages.c index dd6d4137d7b..e0bf86a46ce 100644 --- a/source/lib/messages.c +++ b/source/lib/messages.c @@ -66,14 +66,16 @@ struct message_rec { static struct dispatch_fns { struct dispatch_fns *next, *prev; int msg_type; - void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len); + void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len, + void *private_data); + void *private_data; } *dispatch_fns; /**************************************************************************** Free global objects. ****************************************************************************/ -void gfree_messsges(void) +void gfree_messages(void) { struct dispatch_fns *dfn, *next; @@ -102,9 +104,9 @@ static void sig_usr1(void) ****************************************************************************/ static void ping_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { - const char *msg = buf ? buf : "none"; + const char *msg = buf ? (const char *)buf : "none"; DEBUG(1,("INFO: Received PING message from PID %s [%s]\n", procid_str_static(&src), msg)); @@ -117,7 +119,10 @@ static void ping_message(int msg_type, struct process_id src, BOOL message_init(void) { - if (tdb) return True; + sec_init(); + + if (tdb) + return True; tdb = tdb_open_log(lock_path("messages.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, @@ -130,7 +135,7 @@ BOOL message_init(void) CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1); - message_register(MSG_PING, ping_message); + message_register(MSG_PING, ping_message, NULL); /* Register some debugging related messages */ @@ -161,9 +166,12 @@ static TDB_DATA message_key_pid(struct process_id pid) then delete its record in the database. ****************************************************************************/ -static BOOL message_notify(struct process_id procid) +static NTSTATUS message_notify(struct process_id procid) { pid_t pid = procid.pid; + int ret; + uid_t euid = geteuid(); + /* * Doing kill with a non-positive pid causes messages to be * sent to places we don't want. @@ -171,26 +179,52 @@ static BOOL message_notify(struct process_id procid) SMB_ASSERT(pid > 0); - if (kill(pid, SIGUSR1) == -1) { + if (euid != 0) { + become_root_uid_only(); + } + + ret = kill(pid, SIGUSR1); + + if (euid != 0) { + unbecome_root_uid_only(); + } + + if (ret == -1) { if (errno == ESRCH) { - DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); + DEBUG(2,("pid %d doesn't exist - deleting messages record\n", + (int)pid)); tdb_delete(tdb, message_key_pid(procid)); - } else { - DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); + + /* + * INVALID_HANDLE is the closest I can think of -- vl + */ + return NT_STATUS_INVALID_HANDLE; } - return False; + + DEBUG(2,("message to process %d failed - %s\n", (int)pid, + strerror(errno))); + + /* + * No call to map_nt_error_from_unix -- don't want to link in + * errormap.o into lots of utils. + */ + + if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER; + if (errno == EPERM) return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_UNSUCCESSFUL; } - return True; + + return NT_STATUS_OK; } /**************************************************************************** Send a message to a particular pid. ****************************************************************************/ -static BOOL message_send_pid_internal(struct process_id pid, int msg_type, - const void *buf, size_t len, - BOOL duplicates_allowed, - unsigned int timeout) +static NTSTATUS message_send_pid_internal(struct process_id pid, int msg_type, + const void *buf, size_t len, + BOOL duplicates_allowed, + unsigned int timeout) { TDB_DATA kbuf; TDB_DATA dbuf; @@ -219,9 +253,10 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type, kbuf = message_key_pid(pid); - dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec)); - if (!dbuf.dptr) - return False; + dbuf.dptr = (char *)SMB_MALLOC(len + sizeof(rec)); + if (!dbuf.dptr) { + return NT_STATUS_NO_MEMORY; + } memcpy(dbuf.dptr, &rec, sizeof(rec)); if (len > 0 && buf) @@ -236,13 +271,15 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type, /* lock the record for the destination */ if (timeout) { if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); - return False; + DEBUG(0,("message_send_pid_internal: failed to get " + "chainlock with timeout %ul.\n", timeout)); + return NT_STATUS_IO_TIMEOUT; } } else { if (tdb_chainlock(tdb, kbuf) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); - return False; + DEBUG(0,("message_send_pid_internal: failed to get " + "chainlock.\n")); + return NT_STATUS_LOCK_NOT_GRANTED; } } tdb_append(tdb, kbuf, dbuf); @@ -256,13 +293,15 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type, /* lock the record for the destination */ if (timeout) { if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); - return False; + DEBUG(0,("message_send_pid_internal: failed to get chainlock " + "with timeout %ul.\n", timeout)); + return NT_STATUS_IO_TIMEOUT; } } else { if (tdb_chainlock(tdb, kbuf) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); - return False; + DEBUG(0,("message_send_pid_internal: failed to get " + "chainlock.\n")); + return NT_STATUS_LOCK_NOT_GRANTED; } } @@ -291,10 +330,11 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type, if (!memcmp(ptr, &rec, sizeof(rec))) { if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { tdb_chainunlock(tdb, kbuf); - DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); + DEBUG(10,("message_send_pid_internal: discarding " + "duplicate message.\n")); SAFE_FREE(dbuf.dptr); SAFE_FREE(old_dbuf.dptr); - return True; + return NT_STATUS_OK; } } memcpy(&prec, ptr, sizeof(prec)); @@ -317,19 +357,23 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type, Send a message to a particular pid - no timeout. ****************************************************************************/ -BOOL message_send_pid(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed) +NTSTATUS message_send_pid(struct process_id pid, int msg_type, const void *buf, + size_t len, BOOL duplicates_allowed) { - return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0); + return message_send_pid_internal(pid, msg_type, buf, len, + duplicates_allowed, 0); } /**************************************************************************** Send a message to a particular pid, with timeout in seconds. ****************************************************************************/ -BOOL message_send_pid_with_timeout(struct process_id pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, unsigned int timeout) +NTSTATUS message_send_pid_with_timeout(struct process_id pid, int msg_type, + const void *buf, size_t len, + BOOL duplicates_allowed, unsigned int timeout) { - return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout); + return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, + timeout); } /**************************************************************************** @@ -441,8 +485,7 @@ static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, /**************************************************************************** Receive and dispatch any messages pending for this process. - Notice that all dispatch handlers for a particular msg_type get called, - so you can register multiple handlers for a message. + JRA changed Dec 13 2006. Only one message handler now permitted per type. *NOTE*: Dispatch functions must be able to cope with incoming messages on an *odd* byte boundary. ****************************************************************************/ @@ -454,7 +497,6 @@ void message_dispatch(void) char *buf; char *msgs_buf; size_t len, total_len; - struct dispatch_fns *dfn; int n_handled; if (!received_signal) @@ -468,19 +510,25 @@ void message_dispatch(void) return; for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { + struct dispatch_fns *dfn; + DEBUG(10,("message_dispatch: received msg_type=%d " "src_pid=%u\n", msg_type, (unsigned int) procid_to_pid(&src))); + n_handled = 0; for (dfn = dispatch_fns; dfn; dfn = dfn->next) { if (dfn->msg_type == msg_type) { DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type)); - dfn->fn(msg_type, src, len ? (void *)buf : NULL, len); + dfn->fn(msg_type, src, + len ? (void *)buf : NULL, len, + dfn->private_data); n_handled++; + break; } } if (!n_handled) { - DEBUG(5,("message_dispatch: warning: no handlers registed for " + DEBUG(5,("message_dispatch: warning: no handler registed for " "msg_type %d in pid %u\n", msg_type, (unsigned int)sys_getpid())); } @@ -489,17 +537,27 @@ void message_dispatch(void) } /**************************************************************************** - Register a dispatch function for a particular message type. + Register/replace a dispatch function for a particular message type. + JRA changed Dec 13 2006. Only one message handler now permitted per type. *NOTE*: Dispatch functions must be able to cope with incoming messages on an *odd* byte boundary. ****************************************************************************/ void message_register(int msg_type, void (*fn)(int msg_type, struct process_id pid, - void *buf, size_t len)) + void *buf, size_t len, + void *private_data), + void *private_data) { struct dispatch_fns *dfn; + for (dfn = dispatch_fns; dfn; dfn = dfn->next) { + if (dfn->msg_type == msg_type) { + dfn->fn = fn; + return; + } + } + dfn = SMB_MALLOC_P(struct dispatch_fns); if (dfn != NULL) { @@ -508,6 +566,7 @@ void message_register(int msg_type, dfn->msg_type = msg_type; dfn->fn = fn; + dfn->private_data = private_data; DLIST_ADD(dispatch_fns, dfn); } @@ -530,6 +589,7 @@ void message_deregister(int msg_type) if (dfn->msg_type == msg_type) { DLIST_REMOVE(dispatch_fns, dfn); SAFE_FREE(dfn); + return; } } } @@ -551,6 +611,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void { struct connections_data crec; struct msg_all *msg_all = (struct msg_all *)state; + NTSTATUS status; if (dbuf.dsize != sizeof(crec)) return 0; @@ -568,18 +629,17 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void /* If the msg send fails because the pid was not found (i.e. smbd died), * the msg has already been deleted from the messages.tdb.*/ - if (!message_send_pid(crec.pid, msg_all->msg_type, - msg_all->buf, msg_all->len, - msg_all->duplicates)) { + status = message_send_pid(crec.pid, msg_all->msg_type, + msg_all->buf, msg_all->len, + msg_all->duplicates); + + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { /* If the pid was not found delete the entry from connections.tdb */ - if (errno == ESRCH) { - DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", - procid_str_static(&crec.pid), - crec.cnum, crec.name)); - tdb_delete(the_tdb, kbuf); - } + DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", + procid_str_static(&crec.pid), crec.cnum, crec.name)); + tdb_delete(the_tdb, kbuf); } msg_all->n_sent++; return 0; @@ -643,4 +703,135 @@ void message_unblock(void) { BlockSignals(False, SIGUSR1); } + +/* + * Samba4 API wrapper around the Samba3 implementation. Yes, I know, we could + * import the whole Samba4 thing, but I want notify.c from Samba4 in first. + */ + +struct messaging_callback { + struct messaging_callback *prev, *next; + uint32 msg_type; + void (*fn)(struct messaging_context *msg, void *private_data, + uint32_t msg_type, + struct server_id server_id, DATA_BLOB *data); + void *private_data; +}; + +struct messaging_context { + struct server_id id; + struct messaging_callback *callbacks; +}; + +static int messaging_context_destructor(struct messaging_context *ctx) +{ + struct messaging_callback *cb; + + for (cb = ctx->callbacks; cb; cb = cb->next) { + /* + * We unconditionally remove all instances of our callback + * from the tdb basis. + */ + message_deregister(cb->msg_type); + } + return 0; +} + +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, + struct server_id server_id, + struct event_context *ev) +{ + struct messaging_context *ctx; + + if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) { + return NULL; + } + + ctx->id = server_id; + talloc_set_destructor(ctx, messaging_context_destructor); + return ctx; +} + +static void messaging_callback(int msg_type, struct process_id pid, + void *buf, size_t len, void *private_data) +{ + struct messaging_context *ctx = talloc_get_type_abort( + private_data, struct messaging_context); + struct messaging_callback *cb, *next; + + for (cb = ctx->callbacks; cb; cb = next) { + /* + * Allow a callback to remove itself + */ + next = cb->next; + + if (msg_type == cb->msg_type) { + DATA_BLOB blob; + struct server_id id; + + blob.data = (uint8 *)buf; + blob.length = len; + id.id = pid; + + cb->fn(ctx, cb->private_data, msg_type, id, &blob); + } + } +} + +/* + * Register a dispatch function for a particular message type. Allow multiple + * registrants +*/ +NTSTATUS messaging_register(struct messaging_context *ctx, void *private_data, + uint32_t msg_type, + void (*fn)(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data)) +{ + struct messaging_callback *cb; + + if (!(cb = talloc(ctx, struct messaging_callback))) { + return NT_STATUS_NO_MEMORY; + } + + cb->msg_type = msg_type; + cb->fn = fn; + cb->private_data = private_data; + + DLIST_ADD(ctx->callbacks, cb); + message_register(msg_type, messaging_callback, ctx); + return NT_STATUS_OK; +} + +/* + De-register the function for a particular message type. +*/ +void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type, + void *private_data) +{ + struct messaging_callback *cb, *next; + + for (cb = ctx->callbacks; cb; cb = next) { + next = cb->next; + if ((cb->msg_type == msg_type) + && (cb->private_data == private_data)) { + DLIST_REMOVE(ctx->callbacks, cb); + TALLOC_FREE(cb); + } + } +} + +/* + Send a message to a particular server +*/ +NTSTATUS messaging_send(struct messaging_context *msg, + struct server_id server, + uint32_t msg_type, DATA_BLOB *data) +{ + return message_send_pid_internal(server.id, msg_type, data->data, + data->length, True, 0); +} + /** @} **/ diff --git a/source/lib/pam_errors.c b/source/lib/pam_errors.c index 8a4c41d7df5..9d9a377a912 100644 --- a/source/lib/pam_errors.c +++ b/source/lib/pam_errors.c @@ -72,6 +72,13 @@ static const struct { {NT_STATUS_ACCOUNT_LOCKED_OUT, PAM_MAXTRIES}, {NT_STATUS_NO_MEMORY, PAM_BUF_ERR}, {NT_STATUS_PASSWORD_RESTRICTION, PAM_PERM_DENIED}, + {NT_STATUS_BACKUP_CONTROLLER, PAM_AUTHINFO_UNAVAIL}, + {NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND, PAM_AUTHINFO_UNAVAIL}, + {NT_STATUS_NO_LOGON_SERVERS, PAM_AUTHINFO_UNAVAIL}, + {NT_STATUS_INVALID_WORKSTATION, PAM_PERM_DENIED}, + {NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL}, + {NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL}, + {NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL}, {NT_STATUS_OK, PAM_SUCCESS} }; diff --git a/source/lib/popt_common.c b/source/lib/popt_common.c index d29e171be08..0c0ed86dd1f 100644 --- a/source/lib/popt_common.c +++ b/source/lib/popt_common.c @@ -123,7 +123,7 @@ static void popt_common_callback(poptContext con, } struct poptOption popt_common_connection[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback }, { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", "SOCKETOPTIONS" }, { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, @@ -134,7 +134,7 @@ struct poptOption popt_common_connection[] = { }; struct poptOption popt_common_samba[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_callback }, { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" }, @@ -143,7 +143,7 @@ struct poptOption popt_common_samba[] = { }; struct poptOption popt_common_version[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback }, { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, POPT_TABLEEND }; @@ -248,7 +248,7 @@ static void popt_dynconfig_callback(poptContext con, const struct poptOption popt_common_dynconfig[] = { - { NULL, '\0', POPT_ARG_CALLBACK, popt_dynconfig_callback }, + { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_dynconfig_callback }, { "sbindir", '\0' , POPT_ARG_STRING, NULL, DYN_SBINDIR, "Path to sbin directory", "SBINDIR" }, @@ -515,7 +515,7 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, diff --git a/source/lib/privileges.c b/source/lib/privileges.c index d19592e5826..c0f7857c95b 100644 --- a/source/lib/privileges.c +++ b/source/lib/privileges.c @@ -309,7 +309,8 @@ static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask ) check if the privilege is in the privilege list ****************************************************************************/ -static BOOL is_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check ) +static BOOL is_privilege_assigned( const SE_PRIV *privileges, + const SE_PRIV *check ) { SE_PRIV p1, p2; @@ -473,7 +474,7 @@ BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount) static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) { - PRIV_SID_LIST *priv = state; + PRIV_SID_LIST *priv = (PRIV_SID_LIST *)state; int prefixlen = strlen(PRIVPREFIX); DOM_SID sid; fstring sid_string; @@ -516,7 +517,9 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s return 0; } - add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count ); + if (!add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count )) { + return 0; + } return 0; } @@ -740,7 +743,7 @@ NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_l at a time here. *****************************************************************************/ -BOOL user_has_privileges(NT_USER_TOKEN *token, const SE_PRIV *privilege) +BOOL user_has_privileges(const NT_USER_TOKEN *token, const SE_PRIV *privilege) { if ( !token ) return False; diff --git a/source/lib/readline.c b/source/lib/readline.c index 1f599dc0a7f..24d16ea34fb 100644 --- a/source/lib/readline.c +++ b/source/lib/readline.c @@ -113,8 +113,10 @@ char *smb_readline(const char *prompt, void (*callback)(void), rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; } +#if HAVE_DECL_RL_EVENT_HOOK if (callback) rl_event_hook = (Function *)callback; +#endif ret = readline(prompt); if (ret && *ret) add_history(ret); @@ -154,7 +156,7 @@ history ****************************************************************************/ int cmd_history(void) { -#if defined(HAVE_LIBREADLINE) +#if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST) HIST_ENTRY **hlist; int i; diff --git a/source/lib/replace.c b/source/lib/replace.c deleted file mode 100644 index 19b37af9386..00000000000 --- a/source/lib/replace.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - Unix SMB/CIFS implementation. - replacement routines for broken systems - Copyright (C) Andrew Tridgell 1992-1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - void replace_dummy(void); - void replace_dummy(void) {} - -#ifndef HAVE_FTRUNCATE - /******************************************************************* -ftruncate for operating systems that don't have it -********************************************************************/ - int ftruncate(int f,SMB_OFF_T l) -{ -#ifdef HAVE_CHSIZE - return chsize(f,l); -#else - struct flock fl; - - fl.l_whence = 0; - fl.l_len = 0; - fl.l_start = l; - fl.l_type = F_WRLCK; - return fcntl(f, F_FREESP, &fl); -#endif -} -#endif /* HAVE_FTRUNCATE */ - -#ifndef HAVE_STRLCPY -/* like strncpy but does not 0 fill the buffer and always null - terminates. bufsize is the size of the destination buffer */ - size_t strlcpy(char *d, const char *s, size_t bufsize) -{ - size_t len = strlen(s); - size_t ret = len; - if (bufsize <= 0) return 0; - if (len >= bufsize) len = bufsize-1; - memcpy(d, s, len); - d[len] = 0; - return ret; -} -#endif - -#ifndef HAVE_STRLCAT -/* like strncat but does not 0 fill the buffer and always null - terminates. bufsize is the length of the buffer, which should - be one more than the maximum resulting string length */ - size_t strlcat(char *d, const char *s, size_t bufsize) -{ - size_t len1 = strlen(d); - size_t len2 = strlen(s); - size_t ret = len1 + len2; - - if (len1 >= bufsize) { - return 0; - } - if (len1+len2 >= bufsize) { - len2 = bufsize - (len1+1); - } - if (len2 > 0) { - memcpy(d+len1, s, len2); - d[len1+len2] = 0; - } - return ret; -} -#endif - -#ifndef HAVE_MKTIME -/******************************************************************* -a mktime() replacement for those who don't have it - contributed by -C.A. Lademann <cal@zls.com> -Corrections by richard.kettlewell@kewill.com -********************************************************************/ - -#define MINUTE 60 -#define HOUR 60*MINUTE -#define DAY 24*HOUR -#define YEAR 365*DAY - time_t mktime(struct tm *t) -{ - struct tm *u; - time_t epoch = 0; - int n; - int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - y, m, i; - - if(t->tm_year < 70) { - return((time_t)-1); - } - - n = t->tm_year + 1900 - 1; - epoch = (t->tm_year - 70) * YEAR + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; - - y = t->tm_year + 1900; - m = 0; - - for(i = 0; i < t->tm_mon; i++) { - epoch += mon [m] * DAY; - if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) { - epoch += DAY; - } - - if(++m > 11) { - m = 0; - y++; - } - } - - epoch += (t->tm_mday - 1) * DAY; - epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; - - if((u = localtime(&epoch)) != NULL) { - t->tm_sec = u->tm_sec; - t->tm_min = u->tm_min; - t->tm_hour = u->tm_hour; - t->tm_mday = u->tm_mday; - t->tm_mon = u->tm_mon; - t->tm_year = u->tm_year; - t->tm_wday = u->tm_wday; - t->tm_yday = u->tm_yday; - t->tm_isdst = u->tm_isdst; - } - - return(epoch); -} -#endif /* !HAVE_MKTIME */ - - - -#ifndef HAVE_RENAME -/* Rename a file. (from libiberty in GNU binutils) */ - int rename(const char *zfrom, const char *zto) -{ - if (link (zfrom, zto) < 0) { - if (errno != EEXIST) { - return -1; - } - if (unlink (zto) < 0 || link (zfrom, zto) < 0) { - return -1; - } - } - return unlink (zfrom); -} -#endif /* HAVE_RENAME */ - - -#ifndef HAVE_INNETGR -#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT) -/* - * Search for a match in a netgroup. This replaces it on broken systems. - */ - int innetgr(const char *group,const char *host,const char *user,const char *dom) -{ - char *hst, *usr, *dm; - - setnetgrent(group); - while (getnetgrent(&hst, &usr, &dm)) { - if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && - ((user == 0) || (usr == 0) || !strcmp(user, usr)) && - ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { - endnetgrent(); - return (1); - } - } - endnetgrent(); - return (0); -} -#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */ -#endif /* HAVE_INNETGR */ - - - -#ifndef HAVE_INITGROUPS -/**************************************************************************** - some systems don't have an initgroups call -****************************************************************************/ - int initgroups(char *name,gid_t id) -{ -#ifndef HAVE_SETGROUPS - static int done; - if (!done) { - DEBUG(1,("WARNING: running without setgroups\n")); - done=1; - } - /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ - return(0); -#else /* HAVE_SETGROUPS */ - gid_t *grouplst = NULL; - int max_gr = groups_max(); - int ret; - int i,j; - struct group *g; - char *gr; - - if((grouplst = SMB_MALLOC_ARRAY(gid_t, max_gr)) == NULL) { - DEBUG(0,("initgroups: malloc fail !\n")); - return -1; - } - - grouplst[0] = id; - i = 1; - while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { - if (g->gr_gid == id) - continue; - j = 0; - gr = g->gr_mem[0]; - while (gr && (*gr != (char)NULL)) { - if (strcmp(name,gr) == 0) { - grouplst[i] = g->gr_gid; - i++; - gr = (char *)NULL; - break; - } - gr = g->gr_mem[++j]; - } - } - endgrent(); - ret = sys_setgroups(i,grouplst); - SAFE_FREE(grouplst); - return ret; -#endif /* HAVE_SETGROUPS */ -} -#endif /* HAVE_INITGROUPS */ - - -#if (defined(SecureWare) && defined(SCO)) -/* This is needed due to needing the nap() function but we don't want - to include the Xenix libraries since that will break other things... - BTW: system call # 0x0c28 is the same as calling nap() */ - long nap(long milliseconds) { - return syscall(0x0c28, milliseconds); - } -#endif - - -#ifndef HAVE_MEMMOVE -/******************************************************************* -safely copies memory, ensuring no overlap problems. -this is only used if the machine does not have it's own memmove(). -this is not the fastest algorithm in town, but it will do for our -needs. -********************************************************************/ - void *memmove(void *dest,const void *src,int size) -{ - unsigned long d,s; - int i; - if (dest==src || !size) return(dest); - - d = (unsigned long)dest; - s = (unsigned long)src; - - if ((d >= (s+size)) || (s >= (d+size))) { - /* no overlap */ - memcpy(dest,src,size); - return(dest); - } - - if (d < s) { - /* we can forward copy */ - if (s-d >= sizeof(int) && - !(s%sizeof(int)) && - !(d%sizeof(int)) && - !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=0;i<size;i++) idest[i] = isrc[i]; - } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=0;i<size;i++) cdest[i] = csrc[i]; - } - } else { - /* must backward copy */ - if (d-s >= sizeof(int) && - !(s%sizeof(int)) && - !(d%sizeof(int)) && - !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=size-1;i>=0;i--) idest[i] = isrc[i]; - } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; - } - } - return(dest); -} -#endif /* HAVE_MEMMOVE */ - -#ifndef HAVE_STRDUP -/**************************************************************************** -duplicate a string -****************************************************************************/ - -#ifdef strdup -#undef strdup -#endif - - char *strdup(const char *s) -{ - size_t len; - char *ret; - - if (!s) return(NULL); - - len = strlen(s)+1; - ret = (char *)SMB_MALLOC(len); - if (!ret) return(NULL); - memcpy(ret,s,len); - return(ret); -} -#endif /* HAVE_STRDUP */ - -#ifdef REPLACE_INET_NTOA -char *rep_inet_ntoa(struct in_addr ip) -{ - unsigned char *p = (unsigned char *)&ip.s_addr; - static char buf[18]; - slprintf(buf, 17, "%d.%d.%d.%d", - (int)p[0], (int)p[1], (int)p[2], (int)p[3]); - return buf; -} -#endif /* REPLACE_INET_NTOA */ - -#ifndef HAVE_STRTOUL -#ifndef ULONG_MAX -#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ -#endif - -/* - * Convert a string to an unsigned long integer. - * Taken from libg++ - libiberty code. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ - unsigned long strtoul(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') { - neg = 1; - c = *s++; - } else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base); - for (acc = 0, any = 0;; c = *s++) { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper_ascii(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *) (any ? s - 1 : nptr); - return (acc); -} -#endif /* HAVE_STRTOUL */ - -#ifndef HAVE_SETLINEBUF - int setlinebuf(FILE *stream) -{ - return setvbuf(stream, (char *)NULL, _IOLBF, 0); -} -#endif /* HAVE_SETLINEBUF */ - -#ifndef HAVE_VSYSLOG -#ifdef HAVE_SYSLOG - void vsyslog (int facility_priority, const char *format, va_list arglist) -{ - char *msg = NULL; - vasprintf(&msg, format, arglist); - if (!msg) - return; - syslog(facility_priority, "%s", msg); - SAFE_FREE(msg); -} -#endif /* HAVE_SYSLOG */ -#endif /* HAVE_VSYSLOG */ diff --git a/source/lib/replace/.checker_innocent b/source/lib/replace/.checker_innocent new file mode 100644 index 00000000000..e6191765409 --- /dev/null +++ b/source/lib/replace/.checker_innocent @@ -0,0 +1,4 @@ +>>>MISTAKE21_create_files_6a9e68ada99a97cb +>>>MISTAKE21_os2_delete_9b2bfa7f38711d09 +>>>MISTAKE21_os2_delete_2fcc29aaa99a97cb +>>>SECURITY2_os2_delete_9b2bfa7f1c9396ca diff --git a/source/lib/replace/Makefile.in b/source/lib/replace/Makefile.in new file mode 100644 index 00000000000..10ba5b9415a --- /dev/null +++ b/source/lib/replace/Makefile.in @@ -0,0 +1,60 @@ +#!gmake +# +CC = @CC@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +includedir = @includedir@ +libdir = @libdir@ +VPATH = @libreplacedir@ +srcdir = @srcdir@ +builddir = @builddir@ +INSTALL = @INSTALL@ + +.PHONY: test + +CFLAGS=-I. -I@libreplacedir@ @CFLAGS@ + +OBJS = @LIBREPLACEOBJ@ + +all: showflags libreplace.a testsuite + +showflags: + @echo 'libreplace will be compiled with flags:' + @echo ' CC = $(CC)' + @echo ' CFLAGS = $(CFLAGS)' + @echo ' LIBS = $(LIBS)' + +install: all + mkdir -p $(libdir) + $(INSTALL) libreplace.a $(libdir) + +libreplace.a: $(OBJS) + ar -rcsv $@ $(OBJS) + +test: all + ./testsuite + +installcheck: install test + +TEST_OBJS = test/testsuite.o test/os2_delete.o + +testsuite: libreplace.a $(TEST_OBJS) + $(CC) -o testsuite $(TEST_OBJS) -L. -lreplace + +.c.o: + @echo Compiling $*.c + @mkdir -p `dirname $@` + @$(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o test/*.o *.a testsuite + rm -f testfile.dat + +distclean: clean + rm -f *~ */*~ + rm -f config.log config.status config.h config.cache + rm -f Makefile + +realdistclean: distclean + rm -f configure config.h.in diff --git a/source/lib/replace/README b/source/lib/replace/README new file mode 100644 index 00000000000..a313984c8ea --- /dev/null +++ b/source/lib/replace/README @@ -0,0 +1,88 @@ +This subsystem ensures that we can always use a certain core set of +functions and types, that are either provided by the OS or by replacement +functions / definitions in this subsystem. The aim is to try to stick +to POSIX functions in here as much as possible. Convenience functions +that are available on no platform at all belong in other subsystems +(such as LIBUTIL). + +The following functions are guaranteed: + +ftruncate +strlcpy +strlcat +mktime +rename +innetgr +initgroups +memmove +strdup +inet_ntoa +setlinebuf +vsyslog +timegm +setenv +strndup +strnlen +waitpid +seteuid +setegid +asprintf +snprintf +vasprintf +vsnprintf +opendir +readdir +telldir +seekdir +closedir +dlopen +dlclose +dlsym +dlerror +chroot +bzero +strerror +errno +mkdtemp +mkstemp (a secure one!) +pread +pwrite +getpass +readline (the library) +inet_ntoa +strtoll +strtoull +socketpair + +Types: +bool +socklen_t +uint_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +RTLD_LAZY +HOST_NAME_MAX +UINT16_MAX +UINT32_MAX +UINT64_MAX +CHAR_BIT + +Macros: +va_copy +__FUNCTION__ +__STRING +MIN +MAX +QSORT_CAST + +Prerequisites: +memset (for bzero) +syslog (for vsyslog) +setnetgrent, getnetgrent, endnetgrent (for innetgr) +mktemp (for mkstemp and mkdtemp) diff --git a/source/lib/replace/aclocal.m4 b/source/lib/replace/aclocal.m4 new file mode 100644 index 00000000000..5605e476bab --- /dev/null +++ b/source/lib/replace/aclocal.m4 @@ -0,0 +1 @@ +m4_include(libreplace.m4) diff --git a/source/lib/replace/autoconf-2.60.m4 b/source/lib/replace/autoconf-2.60.m4 new file mode 100644 index 00000000000..5360fff5d24 --- /dev/null +++ b/source/lib/replace/autoconf-2.60.m4 @@ -0,0 +1,197 @@ +# _AC_C_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST, +# ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE) +# -------------------------------------------------------------- +# Check whether the C compiler accepts features of STANDARD (e.g `c89', `c99') +# by trying to compile a program of TEST-PROLOGUE and TEST-BODY. If this fails, +# try again with each compiler option in the space-separated OPTION-LIST; if one +# helps, append it to CC. If eventually successful, run ACTION-IF-AVAILABLE, +# else ACTION-IF-UNAVAILABLE. +AC_DEFUN([_AC_C_STD_TRY], +[AC_MSG_CHECKING([for $CC option to accept ISO ]m4_translit($1, [c], [C])) +AC_CACHE_VAL(ac_cv_prog_cc_$1, +[ac_cv_prog_cc_$1=no +ac_save_CC=$CC +AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])]) +for ac_arg in '' $4 +do + CC="$ac_save_CC $ac_arg" + _AC_COMPILE_IFELSE([], [ac_cv_prog_cc_$1=$ac_arg]) + test "x$ac_cv_prog_cc_$1" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +])# AC_CACHE_VAL +case "x$ac_cv_prog_cc_$1" in + x) + AC_MSG_RESULT([none needed]) ;; + xno) + AC_MSG_RESULT([unsupported]) ;; + *) + CC="$CC $ac_cv_prog_cc_$1" + AC_MSG_RESULT([$ac_cv_prog_cc_$1]) ;; +esac +AS_IF([test "x$ac_cv_prog_cc_$1" != xno], [$5], [$6]) +])# _AC_C_STD_TRY + +# _AC_PROG_CC_C99 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ---------------------------------------------------------------- +# If the C compiler is not in ISO C99 mode by default, try to add an +# option to output variable CC to make it so. This macro tries +# various options that select ISO C99 on some system or another. It +# considers the compiler to be in ISO C99 mode if it handles mixed +# code and declarations, _Bool, inline and restrict. +AC_DEFUN([_AC_PROG_CC_C99], +[_AC_C_STD_TRY([c99], +[[#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict(ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy work. +static void +test_varargs(const char *format, ...) +{ + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg(args_copy, const char *); + break; + case 'd': // int + number = va_arg(args_copy, int); + break; + case 'f': // float + fnumber = (float) va_arg(args_copy, double); + break; + default: + break; + } + } + va_end(args_copy); + va_end(args); +} +]], +[[ + // Check bool and long long datatypes. + _Bool success = false; + long long int bignum = -1234567890LL; + unsigned long long int ubignum = 1234567890uLL; + + // Check restrict. + if (test_restrict("String literal") != 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs("s, d' f .", "string", 65, 34.234); + + // Check incomplete arrays work. + struct incomplete_array *ia = + malloc(sizeof(struct incomplete_array) + (sizeof(double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = (double) i * 1.234; + + // Check named initialisers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[43] = 543; + + // work around unused variable warnings + return bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'; +]], +dnl Try +dnl GCC -std=gnu99 (unused restrictive modes: -std=c99 -std=iso9899:1999) +dnl AIX -qlanglvl=extc99 (unused restrictive mode: -qlanglvl=stdc99) +dnl Intel ICC -c99 +dnl IRIX -c99 +dnl Solaris (unused because it causes the compiler to assume C99 semantics for +dnl library functions, and this is invalid before Solaris 10: -xc99) +dnl Tru64 -c99 +dnl with extended modes being tried first. +[[-std=gnu99 -c99 -qlanglvl=extc99]], [$1], [$2])[]dnl +])# _AC_PROG_CC_C99 + +# AC_PROG_CC_C99 +# -------------- +AC_DEFUN([AC_PROG_CC_C99], +[ AC_REQUIRE([AC_PROG_CC])dnl + _AC_PROG_CC_C99 +]) + +# AC_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS], +[ + AC_BEFORE([$0], [AC_COMPILE_IFELSE]) + AC_BEFORE([$0], [AC_RUN_IFELSE]) + + AC_REQUIRE([AC_GNU_SOURCE]) + AC_REQUIRE([AC_AIX]) + AC_REQUIRE([AC_MINIX]) + + AH_VERBATIM([__EXTENSIONS__], +[/* Enable extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif]) + AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__], + [ac_cv_safe_to_define___extensions__], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([ +# define __EXTENSIONS__ 1 + AC_INCLUDES_DEFAULT])], + [ac_cv_safe_to_define___extensions__=yes], + [ac_cv_safe_to_define___extensions__=no])]) + test $ac_cv_safe_to_define___extensions__ = yes && + AC_DEFINE([__EXTENSIONS__]) + AC_DEFINE([_POSIX_PTHREAD_SEMANTICS]) +]) diff --git a/source/lib/replace/autogen.sh b/source/lib/replace/autogen.sh new file mode 100755 index 00000000000..d46a4279f30 --- /dev/null +++ b/source/lib/replace/autogen.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f configure config.h.in + +autoheader || exit 1 +autoconf || exit 1 + +rm -rf autom4te.cache + +echo "Now run ./configure and then make." +exit 0 + diff --git a/source/lib/replace/config.guess b/source/lib/replace/config.guess new file mode 100755 index 00000000000..ad5281e66e9 --- /dev/null +++ b/source/lib/replace/config.guess @@ -0,0 +1,1466 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-08-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess +and + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/source/lib/replace/config.sub b/source/lib/replace/config.sub new file mode 100755 index 00000000000..1c366dfde9a --- /dev/null +++ b/source/lib/replace/config.sub @@ -0,0 +1,1579 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-07-08' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/source/lib/replace/configure.ac b/source/lib/replace/configure.ac new file mode 100644 index 00000000000..48fb7ce2594 --- /dev/null +++ b/source/lib/replace/configure.ac @@ -0,0 +1,22 @@ +AC_PREREQ(2.50) +AC_INIT(replace.c) +AC_CONFIG_SRCDIR([replace.c]) +AC_CONFIG_HEADER(config.h) + +AC_LIBREPLACE_ALL_CHECKS + +if test "$ac_cv_prog_gcc" = yes; then + CFLAGS="$CFLAGS -Wall" + CFLAGS="$CFLAGS -W" + CFLAGS="$CFLAGS -Wshadow" + CFLAGS="$CFLAGS -Wstrict-prototypes" + CFLAGS="$CFLAGS -Wpointer-arith" + CFLAGS="$CFLAGS -Wcast-qual" + CFLAGS="$CFLAGS -Wcast-align" + CFLAGS="$CFLAGS -Wwrite-strings" + CFLAGS="$CFLAGS -Werror-implicit-function-declaration" + CFLAGS="$CFLAGS -Wformat=2" + CFLAGS="$CFLAGS -Wno-format-y2k" +fi + +AC_OUTPUT(Makefile) diff --git a/source/lib/replace/dlfcn.c b/source/lib/replace/dlfcn.c new file mode 100644 index 00000000000..22f9f8bf79b --- /dev/null +++ b/source/lib/replace/dlfcn.c @@ -0,0 +1,54 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "replace.h" + +#ifndef HAVE_DLOPEN +void *rep_dlopen(const char *name, int flags) +{ + return NULL; +} +#endif + +#ifndef HAVE_DLSYM +void *rep_dlsym(void *handle, const char *symbol) +{ + return NULL; +} +#endif + +#ifndef HAVE_DLERROR +char *rep_dlerror(void) +{ + return "dynamic loading of objects not supported on this platform"; +} +#endif + +#ifndef HAVE_DLCLOSE +int rep_dlclose(void *handle) +{ + return 0; +} +#endif diff --git a/source/lib/replace/dlfcn.m4 b/source/lib/replace/dlfcn.m4 new file mode 100644 index 00000000000..2d5b2c5141a --- /dev/null +++ b/source/lib/replace/dlfcn.m4 @@ -0,0 +1,20 @@ +dnl dummies provided by dlfcn.c if not available +save_LIBS="$LIBS" +LIBS="" + +AC_SEARCH_LIBS(dlopen, dl) + +if test "$ac_cv_search_dlopen" != no; then + AC_CHECK_HEADERS(dlfcn.h) + + libreplace_cv_dlfcn=no + AC_CHECK_FUNCS([dlopen dlsym dlerror dlclose],[],[libreplace_cv_dlfcn=yes]) + + if test x"${libreplace_cv_dlfcn}" = x"yes";then + LIBREPLACEOBJ="${LIBREPLACEOBJ} dlfcn.o" + fi +fi + +LIBDL="$LIBS" +AC_SUBST(LIBDL) +LIBS="$save_LIBS" diff --git a/source/lib/replace/getpass.c b/source/lib/replace/getpass.c new file mode 100644 index 00000000000..2ccbf7b7336 --- /dev/null +++ b/source/lib/replace/getpass.c @@ -0,0 +1,212 @@ +/* Copyright (C) 1992-1998 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ + +#include "replace.h" + +#if defined(HAVE_TERMIOS_H) +/* POSIX terminal handling. */ +#include <termios.h> +#elif defined(HAVE_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <termio.h> +#elif defined(HAVE_SYS_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <sys/termio.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +/* + * Define additional missing types + */ +#ifndef HAVE_SIG_ATOMIC_T_TYPE +typedef int sig_atomic_t; +#endif + +#ifndef SIGCLD +#define SIGCLD SIGCHLD +#endif + +#ifndef SIGNAL_CAST +#define SIGNAL_CAST (RETSIGTYPE (*)(int)) +#endif + +#ifdef REPLACE_GETPASS + +#ifdef SYSV_TERMIO + +/* SYSTEM V TERMIO HANDLING */ + +static struct termio t; + +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +#ifndef TCSAFLUSH +#define TCSAFLUSH 1 +#endif + +#ifndef TCSANOW +#define TCSANOW 0 +#endif + +static int tcgetattr(int fd, struct termio *_t) +{ + return ioctl(fd, TCGETA, _t); +} + +static int tcsetattr(int fd, int flags, struct termio *_t) +{ + if(flags & TCSAFLUSH) + ioctl(fd, TCFLSH, TCIOFLUSH); + return ioctl(fd, TCSETS, _t); +} + +#elif !defined(TCSAFLUSH) + +/* BSD TERMIO HANDLING */ + +static struct sgttyb t; + +#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) +#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) + +#define TCSAFLUSH 1 +#define TCSANOW 0 + +static int tcgetattr(int fd, struct sgttyb *_t) +{ + return ioctl(fd, TIOCGETP, (char *)_t); +} + +static int tcsetattr(int fd, int flags, struct sgttyb *_t) +{ + return ioctl(fd, TIOCSETP, (char *)_t); +} + +#else /* POSIX TERMIO HANDLING */ +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +static struct termios t; +#endif /* SYSV_TERMIO */ + +static void catch_signal(int signum,void (*handler)(int )) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + memset(&act, 0, sizeof(act)); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + +char *getsmbpass(const char *prompt) +{ + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + catch_signal(SIGINT, SIGNAL_CAST SIG_IGN); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + if (ECHO_IS_ON(t)) + { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } + else + echo_off = 0; + } + else + echo_off = 0; + + /* Write the prompt. */ + fputs (prompt, out); + fflush (out); + + /* Read the password. */ + buf[0] = 0; + fgets(buf, bufsize, in); + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) + (void) tcsetattr (fileno (in), TCSANOW, &t); + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + /* Catch problematic signals */ + catch_signal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + return buf; +} + +#else + void getsmbpasswd_dummy(void); + void getsmbpasswd_dummy(void) {;} +#endif diff --git a/source/lib/replace/getpass.m4 b/source/lib/replace/getpass.m4 new file mode 100644 index 00000000000..20d04a63f65 --- /dev/null +++ b/source/lib/replace/getpass.m4 @@ -0,0 +1,17 @@ +AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I$libreplacedir/" +AC_TRY_COMPILE([ +#include "confdefs.h" +#define _LIBREPLACE_REPLACE_H +#define REPLACE_GETPASS 1 +#define main dont_declare_main +#include "$libreplacedir/getpass.c" +#undef main +],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no) +CPPFLAGS="$SAVE_CPPFLAGS" +]) +if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then + AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" +fi diff --git a/source/lib/replace/install-sh b/source/lib/replace/install-sh new file mode 100755 index 00000000000..58719246f04 --- /dev/null +++ b/source/lib/replace/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/source/lib/replace/libreplace.m4 b/source/lib/replace/libreplace.m4 new file mode 100644 index 00000000000..3328dea95e8 --- /dev/null +++ b/source/lib/replace/libreplace.m4 @@ -0,0 +1,355 @@ +AC_DEFUN_ONCE(AC_LIBREPLACE_LOCATION_CHECKS, +[ +echo "LIBREPLACE_LOCATION_CHECKS: START" + +dnl find the libreplace sources. This is meant to work both for +dnl libreplace standalone builds, and builds of packages using libreplace +libreplacedir="" +libreplacepaths="$srcdir $srcdir/lib/replace $srcdir/libreplace $srcdir/../libreplace $srcdir/../replace" +for d in $libreplacepaths; do + if test -f "$d/replace.c"; then + libreplacedir="$d" + AC_SUBST(libreplacedir) + break; + fi +done +if test x"$libreplacedir" = "x"; then + AC_MSG_ERROR([cannot find libreplace in $libreplacepaths]) +fi +LIBREPLACEOBJ="replace.o" +AC_SUBST(LIBREPLACEOBJ) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +echo "LIBREPLACE_LOCATION_CHECKS: END" +]) dnl end AC_LIBREPLACE_LOCATION_CHECKS + + +AC_DEFUN_ONCE(AC_LIBREPLACE_BROKEN_CHECKS, +[ +echo "LIBREPLACE_BROKEN_CHECKS: START" + +dnl find the libreplace sources. This is meant to work both for +dnl libreplace standalone builds, and builds of packages using libreplace +libreplacedir="" +for d in "$srcdir" "$srcdir/lib/replace" "$srcdir/libreplace" "$srcdir/../libreplace" "$srcdir/../replace"; do + if test -f "$d/replace.c"; then + libreplacedir="$d" + AC_SUBST(libreplacedir) + break; + fi +done +LIBREPLACEOBJ="replace.o" +AC_SUBST(LIBREPLACEOBJ) + +LIBREPLACEOBJ="${LIBREPLACEOBJ} snprintf.o" + +AC_TYPE_SIGNAL +AC_TYPE_UID_T +AC_TYPE_MODE_T +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_TYPE_PID_T +AC_STRUCT_ST_RDEV +AC_CHECK_TYPE(ino_t,unsigned) +AC_CHECK_TYPE(loff_t,off_t) +AC_CHECK_TYPE(offset_t,loff_t) + +AC_FUNC_MEMCMP + +AC_CHECK_FUNCS(pipe strftime srandom random srand rand usleep setbuffer lstat getpgrp) + +AC_CHECK_HEADERS(stdbool.h sys/select.h) +AC_CHECK_HEADERS(setjmp.h) + +AC_CHECK_TYPE(bool, +[AC_DEFINE(HAVE_BOOL, 1, [Whether the bool type is available])],, +[ +AC_INCLUDES_DEFAULT +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif] +) + +AC_CHECK_TYPE(_Bool, +[AC_DEFINE(HAVE__Bool, 1, [Whether the _Bool type is available])],, +[ +AC_INCLUDES_DEFAULT +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif] +) + +AC_CACHE_CHECK([for working mmap],samba_cv_HAVE_MMAP,[ +AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"], + samba_cv_HAVE_MMAP=yes,samba_cv_HAVE_MMAP=no,samba_cv_HAVE_MMAP=cross)]) +if test x"$samba_cv_HAVE_MMAP" = x"yes"; then + AC_DEFINE(HAVE_MMAP,1,[Whether mmap works]) +fi + + +AC_CHECK_HEADERS(sys/syslog.h syslog.h) +AC_CHECK_HEADERS(sys/time.h time.h) +AC_CHECK_HEADERS(stdarg.h vararg.h) +AC_CHECK_HEADERS(sys/socket.h netinet/in.h netdb.h arpa/inet.h) +AC_CHECK_HEADERS(netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h) +AC_CHECK_HEADERS(sys/sockio.h sys/un.h) + + +dnl we need to check that net/if.h really can be used, to cope with hpux +dnl where including it always fails +AC_CACHE_CHECK([for usable net/if.h],libreplace_cv_USABLE_NET_IF_H,[ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + AC_INCLUDES_DEFAULT + #if HAVE_SYS_SOCKET_H + # include <sys/socket.h> + #endif + #include <net/if.h> + int main(void) {return 0;}])], + [libreplace_cv_USABLE_NET_IF_H=yes], + [libreplace_cv_USABLE_NET_IF_H=no] + ) +]) +if test x"$libreplace_cv_USABLE_NET_IF_H" = x"yes";then + AC_DEFINE(HAVE_NET_IF_H, 1, usability of net/if.h) +fi + +AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ +AC_TRY_RUN([ +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <netinet/in.h> +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +main() { struct in_addr ip; ip.s_addr = 0x12345678; +if (strcmp(inet_ntoa(ip),"18.52.86.120") && + strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } +exit(1);}], + samba_cv_REPLACE_INET_NTOA=yes,samba_cv_REPLACE_INET_NTOA=no,samba_cv_REPLACE_INET_NTOA=cross)]) +if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then + AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) +fi + +dnl Provided by replace.c: +AC_TRY_COMPILE([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <sys/socket.h>], +[socklen_t foo;],, +[AC_DEFINE(socklen_t, int,[Socket length type])]) + +AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) +AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) +AC_CHECK_FUNCS(waitpid strlcpy strlcat innetgr initgroups memmove strdup) +AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp socketpair) +AC_HAVE_DECL(setresuid, [#include <unistd.h>]) +AC_HAVE_DECL(setresgid, [#include <unistd.h>]) +AC_HAVE_DECL(errno, [#include <errno.h>]) + +AC_CACHE_CHECK([for secure mkstemp],samba_cv_HAVE_SECURE_MKSTEMP,[ +AC_TRY_RUN([#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +main() { + struct stat st; + char tpl[20]="/tmp/test.XXXXXX"; + int fd = mkstemp(tpl); + if (fd == -1) exit(1); + unlink(tpl); + if (fstat(fd, &st) != 0) exit(1); + if ((st.st_mode & 0777) != 0600) exit(1); + exit(0); +}], +samba_cv_HAVE_SECURE_MKSTEMP=yes, +samba_cv_HAVE_SECURE_MKSTEMP=no, +samba_cv_HAVE_SECURE_MKSTEMP=cross)]) +if test x"$samba_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then + AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure]) +fi + +dnl Provided by snprintf.c: +AC_CHECK_HEADERS(stdio.h strings.h) +AC_CHECK_DECLS([snprintf, vsnprintf, asprintf, vasprintf]) +AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) + +AC_CACHE_CHECK([for C99 vsnprintf],samba_cv_HAVE_C99_VSNPRINTF,[ +AC_TRY_RUN([ +#include <sys/types.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +void foo(const char *format, ...) { + va_list ap; + int len; + char buf[20]; + long long l = 1234567890; + l *= 100; + + va_start(ap, format); + len = vsnprintf(buf, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) exit(2); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(3); + + if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(4); + if (snprintf(buf, 20, "%zu", 123456789) != 9 || strcmp(buf, "123456789") != 0) exit(5); + if (snprintf(buf, 20, "%2\$d %1\$d", 3, 4) != 3 || strcmp(buf, "4 3") != 0) exit(6); + if (snprintf(buf, 20, "%s", 0) < 3) exit(7); + + exit(0); +} +main() { foo("hello"); } +], +samba_cv_HAVE_C99_VSNPRINTF=yes,samba_cv_HAVE_C99_VSNPRINTF=no,samba_cv_HAVE_C99_VSNPRINTF=cross)]) +if test x"$samba_cv_HAVE_C99_VSNPRINTF" = x"yes"; then + AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Whether there is a C99 compliant vsnprintf]) +fi + + +dnl VA_COPY +AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[ +AC_TRY_LINK([#include <stdarg.h> +va_list ap1,ap2;], [va_copy(ap1,ap2);], +samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)]) +if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then + AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) +fi + +if test x"$samba_cv_HAVE_VA_COPY" != x"yes"; then +AC_CACHE_CHECK([for __va_copy],samba_cv_HAVE___VA_COPY,[ +AC_TRY_LINK([#include <stdarg.h> +va_list ap1,ap2;], [__va_copy(ap1,ap2);], +samba_cv_HAVE___VA_COPY=yes,samba_cv_HAVE___VA_COPY=no)]) +if test x"$samba_cv_HAVE___VA_COPY" = x"yes"; then + AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available]) +fi +fi + +dnl __FUNCTION__ macro +AC_CACHE_CHECK([for __FUNCTION__ macro],samba_cv_HAVE_FUNCTION_MACRO,[ +AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __FUNCTION__);], +samba_cv_HAVE_FUNCTION_MACRO=yes,samba_cv_HAVE_FUNCTION_MACRO=no)]) +if test x"$samba_cv_HAVE_FUNCTION_MACRO" = x"yes"; then + AC_DEFINE(HAVE_FUNCTION_MACRO,1,[Whether there is a __FUNCTION__ macro]) +else + dnl __func__ macro + AC_CACHE_CHECK([for __func__ macro],samba_cv_HAVE_func_MACRO,[ + AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);], + samba_cv_HAVE_func_MACRO=yes,samba_cv_HAVE_func_MACRO=no)]) + if test x"$samba_cv_HAVE_func_MACRO" = x"yes"; then + AC_DEFINE(HAVE_func_MACRO,1,[Whether there is a __func__ macro]) + fi +fi + +AC_CHECK_HEADERS([sys/param.h limits.h]) + +AC_CHECK_TYPE(comparison_fn_t, +[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])]) + +AC_CHECK_FUNCS(strnlen setenv) +AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) + +# this test disabled as we don't actually need __VA_ARGS__ yet +AC_TRY_CPP([ +#define eprintf(...) fprintf(stderr, __VA_ARGS__) +eprintf("bla", "bar"); +], AC_DEFINE(HAVE__VA_ARGS__MACRO, 1, [Whether the __VA_ARGS__ macro is available])) + +# Check prerequisites +AC_CHECK_FUNCS([memset printf syslog], [], + [ AC_MSG_ERROR([Required function not found])]) + +AC_CACHE_CHECK([for sig_atomic_t type],samba_cv_sig_atomic_t, [ + AC_TRY_COMPILE([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <signal.h>],[sig_atomic_t i = 0], + samba_cv_sig_atomic_t=yes,samba_cv_sig_atomic_t=no)]) +if test x"$samba_cv_sig_atomic_t" = x"yes"; then + AC_DEFINE(HAVE_SIG_ATOMIC_T_TYPE,1,[Whether we have the atomic_t variable type]) +fi + + +AC_CACHE_CHECK([for O_DIRECT flag to open(2)],samba_cv_HAVE_OPEN_O_DIRECT,[ +AC_TRY_COMPILE([ +#include <unistd.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif], +[int fd = open("/dev/null", O_DIRECT);], +samba_cv_HAVE_OPEN_O_DIRECT=yes,samba_cv_HAVE_OPEN_O_DIRECT=no)]) +if test x"$samba_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then + AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT]) +fi + + +AC_CACHE_CHECK([that the C compiler can precompile header files],samba_cv_precompiled_headers, [ + dnl Check whether the compiler can generate precompiled headers + touch conftest.h + if ${CC-cc} conftest.h 2> /dev/null && test -f conftest.h.gch; then + precompiled_headers=yes + else + precompiled_headers=no + fi]) +AC_SUBST(precompiled_headers) + + +dnl Check if the C compiler understands volatile (it should, being ANSI). +AC_CACHE_CHECK([that the C compiler understands volatile],samba_cv_volatile, [ + AC_TRY_COMPILE([#include <sys/types.h>],[volatile int i = 0], + samba_cv_volatile=yes,samba_cv_volatile=no)]) +if test x"$samba_cv_volatile" = x"yes"; then + AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile]) +fi + +m4_include(system/config.m4) + +m4_include(dlfcn.m4) +m4_include(getpass.m4) +m4_include(win32.m4) +m4_include(timegm.m4) +m4_include(repdir.m4) + +AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent memcpy],, + [AC_MSG_ERROR([Required function not found])]) + +echo "LIBREPLACE_BROKEN_CHECKS: END" +]) dnl end AC_LIBREPLACE_BROKEN_CHECKS + +AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_START, +[ +#LIBREPLACE_ALL_CHECKS: START" +]) +AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_END, +[ +#LIBREPLACE_ALL_CHECKS: END" +]) +m4_define(AC_LIBREPLACE_ALL_CHECKS, +[ +AC__LIBREPLACE_ALL_CHECKS_START +AC_LIBREPLACE_LOCATION_CHECKS +AC_LIBREPLACE_CC_CHECKS +AC_LIBREPLACE_BROKEN_CHECKS +AC__LIBREPLACE_ALL_CHECKS_END +]) + +m4_include(libreplace_cc.m4) +m4_include(libreplace_macros.m4) +m4_include(autoconf-2.60.m4) diff --git a/source/lib/replace/libreplace_cc.m4 b/source/lib/replace/libreplace_cc.m4 new file mode 100644 index 00000000000..74c53cad998 --- /dev/null +++ b/source/lib/replace/libreplace_cc.m4 @@ -0,0 +1,167 @@ + +AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_START, +[ +echo "LIBREPLACE_CC_CHECKS: START" +]) + +AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_END, +[ +echo "LIBREPLACE_CC_CHECKS: END" +]) + +dnl +dnl +dnl AC_LIBREPLACE_CC_CHECKS +dnl +dnl Note: we need to use m4_define instead of AC_DEFUN because +dnl of the ordering of tests +dnl +dnl +m4_define(AC_LIBREPLACE_CC_CHECKS, +[ +AC__LIBREPLACE_ONLY_CC_CHECKS_START + +dnl stop the C89 attempt by autoconf - if autoconf detects -Ae it will enable it +dnl which conflicts with C99 on HPUX +ac_cv_prog_cc_Ae=no + +savedCFLAGS=$CFLAGS +AC_PROG_CC +CFLAGS=$savedCFLAGS + +dnl don't try for C99 if we are using gcc, as otherwise we +dnl lose immediate structure constants +if test x"$GCC" != x"yes" ; then +AC_PROG_CC_C99 +fi + +if test x"$GCC" = x"yes" ; then + AC_MSG_CHECKING([for version of gcc]) + GCC_VERSION=`$CC -dumpversion` + AC_MSG_RESULT(${GCC_VERSION}) +fi +AC_USE_SYSTEM_EXTENSIONS +AC_C_BIGENDIAN +AC_C_INLINE +LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_WARN([c99 structure initializer are not supported])]) + +AC_PROG_INSTALL + +AC_ISC_POSIX +AC_EXTENSION_FLAG(_XOPEN_SOURCE_EXTENDED) +AC_EXTENSION_FLAG(_OSF_SOURCE) + +AC_SYS_LARGEFILE + +dnl Add #include for broken IRIX header files +case "$host_os" in + *irix6*) AC_ADD_INCLUDE(<standards.h>) + ;; + *hpux*) + # mmap on HPUX is completely broken... + AC_DEFINE(MMAP_BLACKLIST, 1, [Whether MMAP is broken]) + if test "`uname -r`" = "B.11.11"; then + AC_MSG_WARN([Enabling HPUX 11.11 header bug workaround]) + CFLAGS="$CFLAGS -D_LARGEFILE64_SUPPORT -D__LP64__ -DO_LARGEFILE=04000" + fi + if test "`uname -r`" = "B.11.23"; then + AC_MSG_WARN([Enabling HPUX 11.23 machine/sys/getppdp.h bug workaround]) + CFLAGS="$CFLAGS -D_MACHINE_SYS_GETPPDP_INCLUDED" + fi + ;; + *aix*) + AC_DEFINE(BROKEN_STRNDUP, 1, [Whether strndup is broken]) + AC_DEFINE(BROKEN_STRNLEN, 1, [Whether strnlen is broken]) + if test "${GCC}" != "yes"; then + ## for funky AIX compiler using strncpy() + CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000" + fi + ;; + # + # VOS may need to have POSIX support and System V compatibility enabled. + # + *vos*) + case "$CFLAGS" in + *-D_POSIX_C_SOURCE*);; + *) + CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112L" + AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Whether to enable POSIX support]) + ;; + esac + case "$CFLAGS" in + *-D_SYSV*|*-D_SVID_SOURCE*);; + *) + CFLAGS="$CFLAGS -D_SYSV" + AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility]) + ;; + esac + ;; +esac + + + +AC_CHECK_HEADERS([standards.h]) + +# Solaris needs HAVE_LONG_LONG defined +AC_CHECK_TYPES(long long) + +AC_CHECK_TYPE(uint_t, unsigned int) +AC_CHECK_TYPE(int8_t, char) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(int32_t, long) +AC_CHECK_TYPE(uint32_t, unsigned long) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint64_t, unsigned long long) + +AC_CHECK_TYPE(size_t, unsigned int) +AC_CHECK_TYPE(ssize_t, int) + +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(char) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long long) + +AC_CHECK_SIZEOF(off_t) +AC_CHECK_SIZEOF(size_t) +AC_CHECK_SIZEOF(ssize_t) + +AC_CHECK_TYPE(intptr_t, unsigned long long) +AC_CHECK_TYPE(ptrdiff_t, unsigned long long) + +if test x"$ac_cv_type_long_long" != x"yes";then + AC_MSG_ERROR([LIBREPLACE needs type 'long long']) +fi +if test $ac_cv_sizeof_long_long -lt 8;then + AC_MSG_ERROR([LIBREPLACE needs sizeof(long long) >= 8]) +fi + +############################################ +# check if the compiler can do immediate structures +AC_SUBST(libreplace_cv_immediate_structures) +AC_CACHE_CHECK([for immediate structures],libreplace_cv_immediate_structures,[ + AC_TRY_COMPILE([ + #include <stdio.h> + ],[ + typedef struct {unsigned x;} FOOBAR; + #define X_FOOBAR(x) ((FOOBAR) { x }) + #define FOO_ONE X_FOOBAR(1) + FOOBAR f = FOO_ONE; + static const struct { + FOOBAR y; + } f2[] = { + {FOO_ONE} + }; + ], + libreplace_cv_immediate_structures=yes, + libreplace_cv_immediate_structures=no, + libreplace_cv_immediate_structures=cross) +]) +if test x"$libreplace_cv_immediate_structures" = x"yes"; then + AC_DEFINE(HAVE_IMMEDIATE_STRUCTURES,1,[Whether the compiler supports immediate structures]) +fi + +AC__LIBREPLACE_ONLY_CC_CHECKS_END +]) dnl end AC_LIBREPLACE_CC_CHECKS diff --git a/source/lib/replace/libreplace_macros.m4 b/source/lib/replace/libreplace_macros.m4 new file mode 100644 index 00000000000..0669c10c2a0 --- /dev/null +++ b/source/lib/replace/libreplace_macros.m4 @@ -0,0 +1,308 @@ +# +# This is a collection of useful autoconf macros +# + +############################################ +# Check if the compiler handles c99 struct initialization, and if not try -AC99 and -c99 flags +# Usage: LIBREPLACE_C99_STRUCT_INIT(success-action,failure-action) +# changes CFLAGS to add -AC99 or -c99 if needed +AC_DEFUN([LIBREPLACE_C99_STRUCT_INIT], +[ +saved_CFLAGS="$CFLAGS"; +c99_init=no +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers) + CFLAGS="$saved_CFLAGS"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -AC99) + CFLAGS="$saved_CFLAGS -AC99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=extc99) + CFLAGS="$saved_CFLAGS -qlanglvl=extc99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=stdc99) + CFLAGS="$saved_CFLAGS -qlanglvl=stdc99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -c99) + CFLAGS="$saved_CFLAGS -c99" + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi + +if test "`uname`" = "HP-UX"; then + if test "$ac_cv_c_compiler_gnu" = no; then + # special override for broken HP-UX compiler - I can't find a way to test + # this properly (its a compiler bug) + CFLAGS="$CFLAGS -AC99"; + c99_init=yes; + fi +fi + +if test x"$c99_init" = x"yes"; then + saved_CFLAGS="" + $1 +else + CFLAGS="$saved_CFLAGS" + saved_CFLAGS="" + $2 +fi +]) + +dnl AC_PROG_CC_FLAG(flag) +AC_DEFUN(AC_PROG_CC_FLAG, +[AC_CACHE_CHECK(whether ${CC-cc} accepts -$1, ac_cv_prog_cc_$1, +[echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -$1 -c conftest.c 2>&1`"; then + ac_cv_prog_cc_$1=yes +else + ac_cv_prog_cc_$1=no +fi +rm -f conftest* +])]) + +AC_DEFUN([AC_EXTENSION_FLAG], +[ + cat >>confdefs.h <<\EOF +#ifndef $1 +# define $1 1 +#endif +EOF +AH_VERBATIM([$1], [#ifndef $1 +# define $1 1 +#endif]) +]) + + +dnl see if a declaration exists for a function or variable +dnl defines HAVE_function_DECL if it exists +dnl AC_HAVE_DECL(var, includes) +AC_DEFUN(AC_HAVE_DECL, +[ + AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[ + AC_TRY_COMPILE([$2],[int i = (int)$1], + ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)]) + if test x"$ac_cv_have_$1_decl" = x"yes"; then + AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available]) + fi +]) + + +# AC_CHECK_LIB_EXT(LIBRARY, [EXT_LIBS], [FUNCTION], +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [ADD-ACTION-IF-FOUND],[OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $3, not +# just for library $1. Separate tests with the same $1 and different $3s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$3]) +# is asking for trouble, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_ext_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB_EXT, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([AC_CHECK_LIB_EXT], +[ +AH_CHECK_LIB_EXT([$1]) +ac_check_lib_ext_save_LIBS=$LIBS +LIBS="-l$1 $$2 $7 $LIBS" +AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1])], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1''])])dnl + +m4_ifval([$3], + [ + AH_CHECK_FUNC_EXT([$3]) + AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1_$3])], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1''_$3])])dnl + AC_CACHE_CHECK([for $3 in -l$1], ac_Lib_func, + [AC_TRY_LINK_FUNC($3, + [AS_VAR_SET(ac_Lib_func, yes); + AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_func, no); + AS_VAR_SET(ac_Lib_ext, no)]) + ]) + AS_IF([test AS_VAR_GET(ac_Lib_func) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$3))])dnl + AS_VAR_POPDEF([ac_Lib_func])dnl + ],[ + AC_CACHE_CHECK([for -l$1], ac_Lib_ext, + [AC_TRY_LINK_FUNC([main], + [AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_ext, no)]) + ]) + ]) +LIBS=$ac_check_lib_ext_save_LIBS + +AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes], + [m4_default([$4], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1)) + case "$$2" in + *-l$1*) + ;; + *) + $2="-l$1 $$2" + ;; + esac]) + [$6] + ], + [$5])dnl +AS_VAR_POPDEF([ac_Lib_ext])dnl +])# AC_CHECK_LIB_EXT + +# AH_CHECK_LIB_EXT(LIBNAME) +# --------------------- +m4_define([AH_CHECK_LIB_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_LIB$1), + [Define to 1 if you have the `]$1[' library (-l]$1[).])]) + +dnl AC_SEARCH_LIBS_EXT(FUNCTION, SEARCH-LIBS, EXT_LIBS, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +dnl [OTHER-LIBRARIES]) +dnl -------------------------------------------------------- +dnl Search for a library defining FUNC, if it's not already available. +AC_DEFUN([AC_SEARCH_LIBS_EXT], +[AC_CACHE_CHECK([for library containing $1], [ac_cv_search_ext_$1], +[ +ac_func_search_ext_save_LIBS=$LIBS +ac_cv_search_ext_$1=no +AC_LINK_IFELSE([AC_LANG_CALL([], [$1])], + [ac_cv_search_ext_$1="none required"]) +if test "$ac_cv_search_ext_$1" = no; then + for ac_lib in $2; do + LIBS="-l$ac_lib $$3 $6 $ac_func_search_save_ext_LIBS" + AC_LINK_IFELSE([AC_LANG_CALL([], [$1])], + [ac_cv_search_ext_$1="-l$ac_lib" +break]) + done +fi +LIBS=$ac_func_search_ext_save_LIBS]) +AS_IF([test "$ac_cv_search_ext_$1" != no], + [test "$ac_cv_search_ext_$1" = "none required" || $3="$ac_cv_search_ext_$1 $$3" + $4], + [$5])dnl +]) + +dnl check for a function in a $LIBS and $OTHER_LIBS libraries variable. +dnl AC_CHECK_FUNC_EXT(func,OTHER_LIBS,IF-TRUE,IF-FALSE) +AC_DEFUN([AC_CHECK_FUNC_EXT], +[ + AH_CHECK_FUNC_EXT($1) + ac_check_func_ext_save_LIBS=$LIBS + LIBS="$2 $LIBS" + AS_VAR_PUSHDEF([ac_var], [ac_cv_func_ext_$1])dnl + AC_CACHE_CHECK([for $1], ac_var, + [AC_LINK_IFELSE([AC_LANG_FUNC_LINK_TRY([$1])], + [AS_VAR_SET(ac_var, yes)], + [AS_VAR_SET(ac_var, no)])]) + LIBS=$ac_check_func_ext_save_LIBS + AS_IF([test AS_VAR_GET(ac_var) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1])) $3], + [$4])dnl +AS_VAR_POPDEF([ac_var])dnl +])# AC_CHECK_FUNC + +# AH_CHECK_FUNC_EXT(FUNCNAME) +# --------------------- +m4_define([AH_CHECK_FUNC_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_$1), + [Define to 1 if you have the `]$1[' function.])]) + +dnl Define an AC_DEFINE with ifndef guard. +dnl AC_N_DEFINE(VARIABLE [, VALUE]) +define(AC_N_DEFINE, +[cat >> confdefs.h <<\EOF +[#ifndef] $1 +[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1) +[#endif] +EOF +]) + +dnl Add an #include +dnl AC_ADD_INCLUDE(VARIABLE) +define(AC_ADD_INCLUDE, +[cat >> confdefs.h <<\EOF +[#include] $1 +EOF +]) + +dnl remove an #include +dnl AC_REMOVE_INCLUDE(VARIABLE) +define(AC_REMOVE_INCLUDE, +[ +grep -v '[#include] $1' confdefs.h >confdefs.h.tmp +cat confdefs.h.tmp > confdefs.h +rm confdefs.h.tmp +]) + +dnl remove an #define +dnl AC_REMOVE_DEFINE(VARIABLE) +define(AC_REMOVE_DEFINE, +[ +grep -v '[#define] $1 ' confdefs.h |grep -v '[#define] $1[$]'>confdefs.h.tmp +cat confdefs.h.tmp > confdefs.h +rm confdefs.h.tmp +]) + +dnl AS_HELP_STRING is not available in autoconf 2.57, and AC_HELP_STRING is deprecated +dnl in autoconf 2.59, so define AS_HELP_STRING to be AC_HELP_STRING unless it is already +dnl defined. +m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) + +dnl check if the prototype in the header matches the given one +dnl AC_VERIFY_C_PROTOTYPE(prototype,functionbody,[IF-TRUE].[IF-FALSE],[extraheaders]) +AC_DEFUN(AC_VERIFY_C_PROTOTYPE, +[AC_CACHE_CHECK([for prototype $1], AS_TR_SH([ac_cv_c_prototype_$1]), + AC_COMPILE_IFELSE([ + AC_INCLUDES_DEFAULT + $5 + $1 + { + $2 + } + ],[ + AS_TR_SH([ac_cv_c_prototype_$1])=yes + ],[ + AS_TR_SH([ac_cv_c_prototype_$1])=no + ]) +) +AS_IF([test $AS_TR_SH([ac_cv_c_prototype_$1]) = yes],[$3],[$4]) +]) diff --git a/source/lib/replace/repdir.m4 b/source/lib/replace/repdir.m4 new file mode 100644 index 00000000000..f53a4c29745 --- /dev/null +++ b/source/lib/replace/repdir.m4 @@ -0,0 +1,78 @@ +AC_CACHE_CHECK([for broken readdir],libreplace_cv_READDIR_NEEDED,[ + AC_TRY_RUN([ +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_NEEDED=no], + [libreplace_cv_READDIR_NEEDED=yes], + [libreplace_cv_READDIR_NEEDED="assuming not"]) +]) + +# +# try to replace with getdirentries() if needed +# +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then +AC_CHECK_FUNCS(getdirentries) +AC_VERIFY_C_PROTOTYPE([long telldir(const DIR *dir)], + [ + return 0; + ],[ + AC_DEFINE(TELLDIR_TAKES_CONST_DIR, 1, [Whether telldir takes a const pointer]) + ],[],[ + #include <dirent.h> + ]) + +AC_VERIFY_C_PROTOTYPE([int seekdir(DIR *dir, long ofs)], + [ + return 0; + ],[ + AC_DEFINE(SEEKDIR_RETURNS_INT, 1, [Whether seekdir returns an int]) + ],[],[ + #include <dirent.h> + ]) +AC_CACHE_CHECK([for replacing readdir using getdirentries()],libreplace_cv_READDIR_GETDIRENTRIES,[ + AC_TRY_RUN([ +#define _LIBREPLACE_REPLACE_H +#include "$libreplacedir/repdir_getdirentries.c" +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_GETDIRENTRIES=yes], + [libreplace_cv_READDIR_GETDIRENTRIES=no]) +]) +fi +if test x"$libreplace_cv_READDIR_GETDIRENTRIES" = x"yes"; then + AC_DEFINE(REPLACE_READDIR,1,[replace readdir]) + AC_DEFINE(REPLACE_READDIR_GETDIRENTRIES,1,[replace readdir using getdirentries()]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} repdir_getdirentries.o" + libreplace_cv_READDIR_NEEDED=no +fi + +# +# try to replace with getdents() if needed +# +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then +AC_CHECK_FUNCS(getdents) +AC_CACHE_CHECK([for replacing readdir using getdents()],libreplace_cv_READDIR_GETDENTS,[ + AC_TRY_RUN([ +#define _LIBREPLACE_REPLACE_H +#error _donot_use_getdents_replacement_anymore +#include "$libreplacedir/repdir_getdents.c" +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_GETDENTS=yes], + [libreplace_cv_READDIR_GETDENTS=no]) +]) +fi +if test x"$libreplace_cv_READDIR_GETDENTS" = x"yes"; then + AC_DEFINE(REPLACE_READDIR,1,[replace readdir]) + AC_DEFINE(REPLACE_READDIR_GETDENTS,1,[replace readdir using getdents()]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} repdir_getdents.o" + libreplace_cv_READDIR_NEEDED=no +fi + +AC_MSG_CHECKING([a usable readdir()]) +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then + AC_MSG_RESULT(no) + AC_MSG_WARN([the provided readdir() is broken]) +else + AC_MSG_RESULT(yes) +fi diff --git a/source/lib/replace/repdir_getdents.c b/source/lib/replace/repdir_getdents.c new file mode 100644 index 00000000000..6b115c4c4fb --- /dev/null +++ b/source/lib/replace/repdir_getdents.c @@ -0,0 +1,167 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + a replacement for opendir/readdir/telldir/seekdir/closedir for BSD systems + + This is needed because the existing directory handling in FreeBSD + and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() + on files in a directory where telldir() has been used. On a block + boundary it will occasionally miss a file when seekdir() is used to + return to a position previously recorded with telldir(). + + This also fixes a severe performance and memory usage problem with + telldir() on BSD systems. Each call to telldir() in BSD adds an + entry to a linked list, and those entries are cleaned up on + closedir(). This means with a large directory closedir() can take an + arbitrary amount of time, causing network timeouts as millions of + telldir() entries are freed + + Note! This replacement code is not portable. It relies on getdents() + always leaving the file descriptor at a seek offset that is a + multiple of DIR_BUF_SIZE. If the code detects that this doesn't + happen then it will abort(). It also does not handle directories + with offsets larger than can be stored in a long, + + This code is available under other free software licenses as + well. Contact the author. +*/ + +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> + +#define DIR_BUF_BITS 9 +#define DIR_BUF_SIZE (1<<DIR_BUF_BITS) + +struct dir_buf { + int fd; + int nbytes, ofs; + off_t seekpos; + char buf[DIR_BUF_SIZE]; +}; + +DIR *opendir(const char *dname) +{ + struct dir_buf *d; + struct stat sb; + d = malloc(sizeof(*d)); + if (d == NULL) { + errno = ENOMEM; + return NULL; + } + d->fd = open(dname, O_RDONLY); + if (d->fd == -1) { + free(d); + return NULL; + } + if (fstat(d->fd, &sb) < 0) { + close(d->fd); + free(d); + return NULL; + } + if (!S_ISDIR(sb.st_mode)) { + close(d->fd); + free(d); + errno = ENOTDIR; + return NULL; + } + d->ofs = 0; + d->seekpos = 0; + d->nbytes = 0; + return (DIR *)d; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + struct dirent *de; + + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + } + if (d->ofs >= d->nbytes) { + return NULL; + } + de = (struct dirent *)&d->buf[d->ofs]; + d->ofs += de->d_reclen; + return de; +} + +long telldir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->ofs = 0; + d->nbytes = 0; + } + /* this relies on seekpos always being a multiple of + DIR_BUF_SIZE. Is that always true on BSD systems? */ + if (d->seekpos & (DIR_BUF_SIZE-1)) { + abort(); + } + return d->seekpos + d->ofs; +} + +void seekdir(DIR *dir, long ofs) +{ + struct dir_buf *d = (struct dir_buf *)dir; + d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { + if (readdir(dir) == NULL) break; + } +} + +void rewinddir(DIR *dir) +{ + seekdir(dir, 0); +} + +int closedir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + int r = close(d->fd); + if (r != 0) { + return r; + } + free(d); + return 0; +} + +#ifndef dirfd +/* darn, this is a macro on some systems. */ +int dirfd(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + return d->fd; +} +#endif diff --git a/source/lib/replace/repdir_getdirentries.c b/source/lib/replace/repdir_getdirentries.c new file mode 100644 index 00000000000..a6026dfb5d4 --- /dev/null +++ b/source/lib/replace/repdir_getdirentries.c @@ -0,0 +1,184 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + a replacement for opendir/readdir/telldir/seekdir/closedir for BSD + systems using getdirentries + + This is needed because the existing directory handling in FreeBSD + and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() + on files in a directory where telldir() has been used. On a block + boundary it will occasionally miss a file when seekdir() is used to + return to a position previously recorded with telldir(). + + This also fixes a severe performance and memory usage problem with + telldir() on BSD systems. Each call to telldir() in BSD adds an + entry to a linked list, and those entries are cleaned up on + closedir(). This means with a large directory closedir() can take an + arbitrary amount of time, causing network timeouts as millions of + telldir() entries are freed + + Note! This replacement code is not portable. It relies on + getdirentries() always leaving the file descriptor at a seek offset + that is a multiple of DIR_BUF_SIZE. If the code detects that this + doesn't happen then it will abort(). It also does not handle + directories with offsets larger than can be stored in a long, + + This code is available under other free software licenses as + well. Contact the author. +*/ + +#include "replace.h" +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> + +#define DIR_BUF_BITS 9 +#define DIR_BUF_SIZE (1<<DIR_BUF_BITS) + +struct dir_buf { + int fd; + int nbytes, ofs; + off_t seekpos; + char buf[DIR_BUF_SIZE]; +}; + +DIR *opendir(const char *dname) +{ + struct dir_buf *d; + struct stat sb; + d = malloc(sizeof(*d)); + if (d == NULL) { + errno = ENOMEM; + return NULL; + } + d->fd = open(dname, O_RDONLY); + if (d->fd == -1) { + free(d); + return NULL; + } + if (fstat(d->fd, &sb) < 0) { + close(d->fd); + free(d); + return NULL; + } + if (!S_ISDIR(sb.st_mode)) { + close(d->fd); + free(d); + errno = ENOTDIR; + return NULL; + } + d->ofs = 0; + d->seekpos = 0; + d->nbytes = 0; + return (DIR *)d; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + struct dirent *de; + + if (d->ofs >= d->nbytes) { + long pos; + d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos); + d->seekpos = pos; + d->ofs = 0; + } + if (d->ofs >= d->nbytes) { + return NULL; + } + de = (struct dirent *)&d->buf[d->ofs]; + d->ofs += de->d_reclen; + return de; +} + +#ifdef TELLDIR_TAKES_CONST_DIR +long telldir(const DIR *dir) +#else +long telldir(DIR *dir) +#endif +{ + struct dir_buf *d = (struct dir_buf *)dir; + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->ofs = 0; + d->nbytes = 0; + } + /* this relies on seekpos always being a multiple of + DIR_BUF_SIZE. Is that always true on BSD systems? */ + if (d->seekpos & (DIR_BUF_SIZE-1)) { + abort(); + } + return d->seekpos + d->ofs; +} + +#ifdef SEEKDIR_RETURNS_INT +int seekdir(DIR *dir, long ofs) +#else +void seekdir(DIR *dir, long ofs) +#endif +{ + struct dir_buf *d = (struct dir_buf *)dir; + long pos; + d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); + d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos); + d->ofs = 0; + while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { + if (readdir(dir) == NULL) break; + } +#ifdef SEEKDIR_RETURNS_INT + return -1; +#endif +} + +void rewinddir(DIR *dir) +{ + seekdir(dir, 0); +} + +int closedir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + int r = close(d->fd); + if (r != 0) { + return r; + } + free(d); + return 0; +} + +#ifndef dirfd +/* darn, this is a macro on some systems. */ +int dirfd(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + return d->fd; +} +#endif + + diff --git a/source/lib/replace/replace.c b/source/lib/replace/replace.c new file mode 100644 index 00000000000..9e6c75bd358 --- /dev/null +++ b/source/lib/replace/replace.c @@ -0,0 +1,613 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "replace.h" + +#include "system/filesys.h" +#include "system/time.h" +#include "system/passwd.h" +#include "system/syslog.h" +#include "system/network.h" +#include "system/locale.h" +#include "system/wait.h" + +void replace_dummy(void); +void replace_dummy(void) {} + +#ifndef HAVE_FTRUNCATE + /******************************************************************* +ftruncate for operating systems that don't have it +********************************************************************/ +int rep_ftruncate(int f, off_t l) +{ +#ifdef HAVE_CHSIZE + return chsize(f,l); +#elif defined(F_FREESP) + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = l; + fl.l_type = F_WRLCK; + return fcntl(f, F_FREESP, &fl); +#else +#error "you must have a ftruncate function" +#endif +} +#endif /* HAVE_FTRUNCATE */ + + +#ifndef HAVE_STRLCPY +/* like strncpy but does not 0 fill the buffer and always null + terminates. bufsize is the size of the destination buffer */ +size_t rep_strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + if (bufsize <= 0) return 0; + if (len >= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ +size_t rep_strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif + +#ifndef HAVE_MKTIME +/******************************************************************* +a mktime() replacement for those who don't have it - contributed by +C.A. Lademann <cal@zls.com> +Corrections by richard.kettlewell@kewill.com +********************************************************************/ + +#define MINUTE 60 +#define HOUR 60*MINUTE +#define DAY 24*HOUR +#define YEAR 365*DAY +time_t rep_mktime(struct tm *t) +{ + struct tm *u; + time_t epoch = 0; + int n; + int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + y, m, i; + + if(t->tm_year < 70) + return((time_t)-1); + + n = t->tm_year + 1900 - 1; + epoch = (t->tm_year - 70) * YEAR + + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; + + y = t->tm_year + 1900; + m = 0; + + for(i = 0; i < t->tm_mon; i++) { + epoch += mon [m] * DAY; + if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) + epoch += DAY; + + if(++m > 11) { + m = 0; + y++; + } + } + + epoch += (t->tm_mday - 1) * DAY; + epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; + + if((u = localtime(&epoch)) != NULL) { + t->tm_sec = u->tm_sec; + t->tm_min = u->tm_min; + t->tm_hour = u->tm_hour; + t->tm_mday = u->tm_mday; + t->tm_mon = u->tm_mon; + t->tm_year = u->tm_year; + t->tm_wday = u->tm_wday; + t->tm_yday = u->tm_yday; + t->tm_isdst = u->tm_isdst; + } + + return(epoch); +} +#endif /* !HAVE_MKTIME */ + + +#ifndef HAVE_INNETGR +#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT) +/* + * Search for a match in a netgroup. This replaces it on broken systems. + */ +int rep_innetgr(const char *group, const char *host, const char *user, + const char *dom) +{ + char *hst, *usr, *dm; + + setnetgrent(group); + while (getnetgrent(&hst, &usr, &dm)) { + if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && + ((user == 0) || (usr == 0) || !strcmp(user, usr)) && + ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { + endnetgrent(); + return (1); + } + } + endnetgrent(); + return (0); +} +#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */ +#endif /* HAVE_INNETGR */ + + + +#ifndef HAVE_INITGROUPS +/**************************************************************************** + some systems don't have an initgroups call +****************************************************************************/ +int rep_initgroups(char *name, gid_t id) +{ +#ifndef HAVE_SETGROUPS + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ + errno = ENOSYS; + return -1; +#else /* HAVE_SETGROUPS */ + +#include <grp.h> + + gid_t *grouplst = NULL; + int max_gr = 32; + int ret; + int i,j; + struct group *g; + char *gr; + + if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) { + errno = ENOMEM; + return -1; + } + + grouplst[0] = id; + i = 1; + while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { + if (g->gr_gid == id) + continue; + j = 0; + gr = g->gr_mem[0]; + while (gr && (*gr != (char)NULL)) { + if (strcmp(name,gr) == 0) { + grouplst[i] = g->gr_gid; + i++; + gr = (char *)NULL; + break; + } + gr = g->gr_mem[++j]; + } + } + endgrent(); + ret = setgroups(i, grouplst); + free(grouplst); + return ret; +#endif /* HAVE_SETGROUPS */ +} +#endif /* HAVE_INITGROUPS */ + + +#if (defined(SecureWare) && defined(SCO)) +/* This is needed due to needing the nap() function but we don't want + to include the Xenix libraries since that will break other things... + BTW: system call # 0x0c28 is the same as calling nap() */ +long nap(long milliseconds) { + return syscall(0x0c28, milliseconds); + } +#endif + + +#ifndef HAVE_MEMMOVE +/******************************************************************* +safely copies memory, ensuring no overlap problems. +this is only used if the machine does not have it's own memmove(). +this is not the fastest algorithm in town, but it will do for our +needs. +********************************************************************/ +void *rep_memmove(void *dest,const void *src,int size) +{ + unsigned long d,s; + int i; + if (dest==src || !size) return(dest); + + d = (unsigned long)dest; + s = (unsigned long)src; + + if ((d >= (s+size)) || (s >= (d+size))) { + /* no overlap */ + memcpy(dest,src,size); + return(dest); + } + + if (d < s) { + /* we can forward copy */ + if (s-d >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=0;i<size;i++) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=0;i<size;i++) cdest[i] = csrc[i]; + } + } else { + /* must backward copy */ + if (d-s >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + } + } + return(dest); +} +#endif /* HAVE_MEMMOVE */ + +#ifndef HAVE_STRDUP +/**************************************************************************** +duplicate a string +****************************************************************************/ +char *rep_strdup(const char *s) +{ + size_t len; + char *ret; + + if (!s) return(NULL); + + len = strlen(s)+1; + ret = (char *)malloc(len); + if (!ret) return(NULL); + memcpy(ret,s,len); + return(ret); +} +#endif /* HAVE_STRDUP */ + +#ifndef WITH_PTHREADS +/* REWRITE: not thread safe */ +#ifdef REPLACE_INET_NTOA +char *rep_inet_ntoa(struct in_addr ip) +{ + uint8_t *p = (uint8_t *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} +#endif /* REPLACE_INET_NTOA */ +#endif + +#ifndef HAVE_SETLINEBUF +void rep_setlinebuf(FILE *stream) +{ + setvbuf(stream, (char *)NULL, _IOLBF, 0); +} +#endif /* HAVE_SETLINEBUF */ + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) +{ + char *msg = NULL; + vasprintf(&msg, format, arglist); + if (!msg) + return; + syslog(facility_priority, "%s", msg); + free(msg); +} +#endif /* HAVE_SYSLOG */ +#endif /* HAVE_VSYSLOG */ + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + size_t rep_strnlen(const char *s, size_t max) +{ + size_t len; + + for (len = 0; len < max; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} +#endif + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ +char *rep_strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#ifndef HAVE_WAITPID +int rep_waitpid(pid_t pid,int *status,int options) +{ + return wait4(pid, status, options, NULL); +} +#endif + +#ifndef HAVE_SETEUID +int rep_seteuid(uid_t euid) +{ +#ifdef HAVE_SETRESUID + return setresuid(-1, euid, -1); +#else +# error "You need a seteuid function" +#endif +} +#endif + +#ifndef HAVE_SETEGID +int rep_setegid(gid_t egid) +{ +#ifdef HAVE_SETRESGID + return setresgid(-1, egid, -1); +#else +# error "You need a setegid function" +#endif +} +#endif + +/******************************************************************* +os/2 also doesn't have chroot +********************************************************************/ +#ifndef HAVE_CHROOT +int rep_chroot(const char *dname) +{ + errno = ENOSYS; + return -1; +} +#endif + +/***************************************************************** + Possibly replace mkstemp if it is broken. +*****************************************************************/ + +#ifndef HAVE_SECURE_MKSTEMP +int rep_mkstemp(char *template) +{ + /* have a reasonable go at emulating it. Hope that + the system mktemp() isn't completly hopeless */ + char *p = mktemp(template); + if (!p) + return -1; + return open(p, O_CREAT|O_EXCL|O_RDWR, 0600); +} +#endif + +#ifndef HAVE_MKDTEMP +char *rep_mkdtemp(char *template) +{ + char *dname; + + if ((dname = mktemp(template))) { + if (mkdir(dname, 0700) >= 0) { + return dname; + } + } + + return NULL; +} +#endif + +#ifndef HAVE_PREAD +ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return read(__fd, __buf, __nbytes); +} +#endif + +#ifndef HAVE_PWRITE +ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return write(__fd, __buf, __nbytes); +} +#endif + +#ifndef HAVE_STRCASESTR +char *rep_strcasestr(const char *haystack, const char *needle) +{ + const char *s; + size_t nlen = strlen(needle); + for (s=haystack;*s;s++) { + if (toupper(*needle) == toupper(*s) && + strncasecmp(s, needle, nlen) == 0) { + return (char *)((intptr_t)s); + } + } + return NULL; +} +#endif + +#ifndef HAVE_STRTOK_R +/* based on GLIBC version, copyright Free Software Foundation */ +char *rep_strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) s = *save_ptr; + + s += strspn(s, delim); + if (*s == '\0') { + *save_ptr = s; + return NULL; + } + + token = s; + s = strpbrk(token, delim); + if (s == NULL) { + *save_ptr = token + strlen(token); + } else { + *s = '\0'; + *save_ptr = s + 1; + } + + return token; +} +#endif + +#ifndef HAVE_STRTOLL +long long int rep_strtoll(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOQ + return strtoq(str, endptr, base); +#elif defined(HAVE___STRTOLL) + return __strtoll(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (long long int) strtol(str, endptr, base); +#else +# error "You need a strtoll function" +#endif +} +#endif + + +#ifndef HAVE_STRTOULL +unsigned long long int rep_strtoull(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOUQ + return strtouq(str, endptr, base); +#elif defined(HAVE___STRTOULL) + return __strtoull(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (unsigned long long int) strtoul(str, endptr, base); +#else +# error "You need a strtoull function" +#endif +} +#endif + +#ifndef HAVE_SETENV +int rep_setenv(const char *name, const char *value, int overwrite) +{ + char *p; + size_t l1, l2; + int ret; + + if (!overwrite && getenv(name)) { + return 0; + } + + l1 = strlen(name); + l2 = strlen(value); + + p = malloc(l1+l2+2); + if (p == NULL) { + return -1; + } + memcpy(p, name, l1); + p[l1] = '='; + memcpy(p+l1+1, value, l2); + p[l1+l2+1] = 0; + + ret = putenv(p); + if (ret != 0) { + free(p); + } + + return ret; +} +#endif + +#ifndef HAVE_SOCKETPAIR +int rep_socketpair(int d, int type, int protocol, int sv[2]) +{ + if (d != AF_UNIX) { + errno = EAFNOSUPPORT; + return -1; + } + + if (protocol != 0) { + errno = EPROTONOSUPPORT; + return -1; + } + + if (type != SOCK_STREAM) { + errno = EOPNOTSUPP; + return -1; + } + + return pipe(sv); +} +#endif diff --git a/source/lib/replace/replace.h b/source/lib/replace/replace.h new file mode 100644 index 00000000000..d75394aa1fc --- /dev/null +++ b/source/lib/replace/replace.h @@ -0,0 +1,408 @@ +/* + Unix SMB/CIFS implementation. + + macros to go along with the lib/replace/ portability layer code + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _LIBREPLACE_REPLACE_H +#define _LIBREPLACE_REPLACE_H + +#ifndef NO_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STANDARDS_H +#include <standards.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> + +#if defined(_MSC_VER) || defined(__MINGW32__) +#include "win32_replace.h" +#endif + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +/* force off HAVE_INTTYPES_H so that roken doesn't try to include both, + which causes a warning storm on irix */ +#undef HAVE_INTTYPES_H +#elif HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif + +#ifndef HAVE_STRERROR +extern char *sys_errlist[]; +#define strerror(i) sys_errlist[i] +#endif + +#ifndef HAVE_ERRNO_DECL +extern int errno; +#endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +char *rep_strdup(const char *s); +#endif + +#ifndef HAVE_MEMMOVE +#define memmove rep_memmove +void *rep_memmove(void *dest,const void *src,int size); +#endif + +#if !defined(HAVE_MKTIME) || !defined(HAVE_TIMEGM) +#include "system/time.h" +#endif + +#ifndef HAVE_MKTIME +#define mktime rep_mktime +time_t rep_mktime(struct tm *t); +#endif + +#ifndef HAVE_TIMEGM +struct tm; +#define timegm rep_timegm +time_t rep_timegm(struct tm *tm); +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy rep_strlcpy +size_t rep_strlcpy(char *d, const char *s, size_t bufsize); +#endif + +#ifndef HAVE_STRLCAT +#define strlcat rep_strlcat +size_t rep_strlcat(char *d, const char *s, size_t bufsize); +#endif + +#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP)) +#undef HAVE_STRNDUP +#define strndup rep_strndup +char *rep_strndup(const char *s, size_t n); +#endif + +#if (defined(BROKEN_STRNLEN) || !defined(HAVE_STRNLEN)) +#undef HAVE_STRNLEN +#define strnlen rep_strnlen +size_t rep_strnlen(const char *s, size_t n); +#endif + +#ifndef HAVE_SETENV +#define setenv rep_setenv +int rep_setenv(const char *name, const char *value, int overwrite); +#endif + +#ifndef HAVE_SETEUID +#define seteuid rep_seteuid +int rep_seteuid(uid_t); +#endif + +#ifndef HAVE_SETEGID +#define setegid rep_setegid +int rep_setegid(gid_t); +#endif + +#ifndef HAVE_SETLINEBUF +#define setlinebuf rep_setlinebuf +void rep_setlinebuf(FILE *); +#endif + +#ifndef HAVE_STRCASESTR +#define strcasestr rep_strcasestr +char *rep_strcasestr(const char *haystack, const char *needle); +#endif + +#ifndef HAVE_STRTOK_R +#define strtok_r rep_strtok_r +char *rep_strtok_r(char *s, const char *delim, char **save_ptr); +#endif + +#ifndef HAVE_STRTOLL +#define strtoll rep_strtoll +long long int rep_strtoll(const char *str, char **endptr, int base); +#endif + +#ifndef HAVE_STRTOULL +#define strtoull rep_strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base); +#endif + +#ifndef HAVE_FTRUNCATE +#define ftruncate rep_ftruncate +int rep_ftruncate(int,off_t); +#endif + +#ifndef HAVE_INITGROUPS +#define ftruncate rep_ftruncate +int rep_initgroups(char *name, gid_t id); +#endif + +#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET) +#define bzero(a,b) memset((a),'\0',(b)) +#endif + +#ifndef HAVE_DLERROR +#define dlerror rep_dlerror +char *rep_dlerror(void); +#endif + +#ifndef HAVE_DLOPEN +#define dlopen rep_dlopen +void *rep_dlopen(const char *name, int flags); +#endif + +#ifndef HAVE_DLSYM +#define dlsym rep_dlsym +void *rep_dlsym(void *handle, const char *symbol); +#endif + +#ifndef HAVE_DLCLOSE +#define dlclose rep_dlclose +int rep_dlclose(void *handle); +#endif + +#ifndef HAVE_SOCKETPAIR +#define socketpair rep_socketpair +int rep_socketpair(int d, int type, int protocol, int sv[2]); +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef HAVE_VASPRINTF +#define vasprintf rep_vasprintf +int rep_vasprintf(char **ptr, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define snprintf rep_snprintf +int rep_snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); +#endif + +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vsnprintf rep_vsnprintf +int rep_vsnprintf(char *,size_t ,const char *, va_list ap) PRINTF_ATTRIBUTE(3,0); +#endif + +#ifndef HAVE_ASPRINTF +#define asprintf rep_asprintf +int rep_asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +#define vsyslog rep_vsyslog +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) PRINTF_ATTRIBUTE(2,0); +#endif +#endif + +/* we used to use these fns, but now we have good replacements + for snprintf and vsnprintf */ +#define slprintf snprintf + + +#ifndef HAVE_VA_COPY +#undef va_copy +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +#ifndef HAVE_VOLATILE +#define volatile +#endif + +#ifndef HAVE_COMPARISON_FN_T +typedef int (*comparison_fn_t)(const void *, const void *); +#endif + +/* Load header file for dynamic linking stuff */ +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + +#ifndef HAVE_SECURE_MKSTEMP +#define mkstemp(path) rep_mkstemp(path) +int rep_mkstemp(char *temp); +#endif + +#ifndef HAVE_MKDTEMP +#define mkdtemp rep_mkdtemp +char *rep_mkdtemp(char *template); +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +/* The extra casts work around common compiler bugs. */ +#define _TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. + It is necessary at least when t == time_t. */ +#define _TYPE_MINIMUM(t) ((t) (_TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) +#define _TYPE_MAXIMUM(t) ((t) (~ (t) 0 - _TYPE_MINIMUM (t))) + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 64 +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX ((uint64_t)-1) +#endif + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifndef INT32_MAX +#define INT32_MAX _TYPE_MAXIMUM(int32_t) +#endif + +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif + +#if !defined(HAVE_BOOL) +#ifdef HAVE__Bool +#define bool _Bool +#else +typedef int bool; +#endif +#endif + +/* + * to prevent <rpcsvc/yp_prot.h> from doing a redefine of 'bool' + * + * IRIX, HPUX, MacOS 10 and Solaris need BOOL_DEFINED + * Tru64 needs _BOOL_EXISTS + * AIX needs _BOOL,_TRUE,_FALSE + */ +#ifndef BOOL_DEFINED +#define BOOL_DEFINED +#endif +#ifndef _BOOL_EXISTS +#define _BOOL_EXISTS +#endif +#ifndef _BOOL +#define _BOOL +#endif + +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined +#endif + +#ifndef true +#define true (1) +#endif +#ifndef false +#define false (0) +#endif + +#ifndef _TRUE +#define _TRUE true +#endif +#ifndef _FALSE +#define _FALSE false +#endif + +#ifndef HAVE_FUNCTION_MACRO +#ifdef HAVE_func_MACRO +#define __FUNCTION__ __func__ +#else +#define __FUNCTION__ ("") +#endif +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#if MMAP_BLACKLIST +#undef HAVE_MMAP +#endif + +#endif /* _LIBREPLACE_REPLACE_H */ diff --git a/source/lib/replace/samba.m4 b/source/lib/replace/samba.m4 new file mode 100644 index 00000000000..3769c7f50e9 --- /dev/null +++ b/source/lib/replace/samba.m4 @@ -0,0 +1,23 @@ +AC_LIBREPLACE_BROKEN_CHECKS + +SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL}]) +SMB_ENABLE(LIBREPLACE_EXT) + +LIBREPLACE_DIR=`echo ${libreplacedir} |sed -e 's/^\.\///g'` + +LIBREPLACE_OBJS="" +for obj in ${LIBREPLACEOBJ}; do + LIBREPLACE_OBJS="${LIBREPLACE_OBJS} ${LIBREPLACE_DIR}/${obj}" +done + +SMB_SUBSYSTEM(LIBREPLACE, + [${LIBREPLACE_OBJS}], + [LIBREPLACE_EXT], + [-Ilib/replace]) + +LIBREPLACE_HOSTCC_OBJS=`echo ${LIBREPLACE_OBJS} |sed -e 's/\.o/\.ho/g'` + +SMB_SUBSYSTEM(LIBREPLACE_HOSTCC, + [${LIBREPLACE_HOSTCC_OBJS}], + [], + [-Ilib/replace]) diff --git a/source/lib/snprintf.c b/source/lib/replace/snprintf.c index 8ff76ab1165..9f8a7657e52 100644 --- a/source/lib/snprintf.c +++ b/source/lib/replace/snprintf.c @@ -103,11 +103,8 @@ * **************************************************************/ -#ifndef NO_CONFIG_H -#include "config.h" -#else -#define NULL 0 -#endif +#include "replace.h" +#include "system/locale.h" #ifdef TEST_SNPRINTF /* need math library headers for testing */ @@ -121,22 +118,6 @@ # include <math.h> #endif /* TEST_SNPRINTF */ -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif -#ifdef HAVE_CTYPE_H -#include <ctype.h> -#endif -#include <sys/types.h> -#include <stdarg.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) /* only include stdio.h if we are not re-defining snprintf or vsnprintf */ #include <stdio.h> @@ -145,6 +126,9 @@ void dummy_snprintf(void) {} #endif /* HAVE_SNPRINTF, etc */ +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + #ifdef HAVE_LONG_DOUBLE #define LDOUBLE long double #else @@ -197,6 +181,7 @@ #define DP_C_LONG 3 #define DP_C_LDOUBLE 4 #define DP_C_LLONG 5 +#define DP_C_SIZET 6 /* Chunk types */ #define CNK_FMT_STR 0 @@ -216,9 +201,6 @@ #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) #endif -/* yes this really must be a ||. Don't muck with this (tridge) */ -#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) - struct pr_chunk { int type; /* chunk type */ int num; /* parameter number */ @@ -242,7 +224,7 @@ struct pr_chunk_x { int num; }; -static size_t dopr(char *buffer, size_t maxlen, const char *format, +static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max); @@ -255,7 +237,7 @@ static struct pr_chunk *new_chunk(void); static int add_cnk_list_entry(struct pr_chunk_x **list, int max_num, struct pr_chunk *chunk); -static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) { char ch; int state; @@ -269,7 +251,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args struct pr_chunk *cnk = NULL; struct pr_chunk_x *clist = NULL; int max_pos; - size_t ret = -1; + int ret = -1; VA_COPY(args, args_in); @@ -467,6 +449,10 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args cnk->cflags = DP_C_LDOUBLE; ch = *format++; break; + case 'z': + cnk->cflags = DP_C_SIZET; + ch = *format++; + break; default: break; } @@ -575,6 +561,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args cnk->value = va_arg (args, long int); else if (cnk->cflags == DP_C_LLONG) cnk->value = va_arg (args, LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = va_arg (args, ssize_t); else cnk->value = va_arg (args, int); @@ -592,6 +580,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args cnk->value = (unsigned long int)va_arg (args, unsigned long int); else if (cnk->cflags == DP_C_LLONG) cnk->value = (LLONG)va_arg (args, unsigned LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = (size_t)va_arg (args, size_t); else cnk->value = (unsigned int)va_arg (args, unsigned int); @@ -644,6 +634,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args cnk->pnum = va_arg (args, long int *); else if (cnk->cflags == DP_C_LLONG) cnk->pnum = va_arg (args, LLONG *); + else if (cnk->cflags == DP_C_SIZET) + cnk->pnum = va_arg (args, ssize_t *); else cnk->pnum = va_arg (args, int *); @@ -725,6 +717,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args *((long int *)(cnk->pnum)) = (long int)currlen; else if (cnk->cflags == DP_C_LLONG) *((LLONG *)(cnk->pnum)) = (LLONG)currlen; + else if (cnk->cflags == DP_C_SIZET) + *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen; else *((int *)(cnk->pnum)) = (int)currlen; break; @@ -748,6 +742,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args ret = currlen; done: + va_end(args); + while (chunks) { cnk = chunks->next; free(chunks); @@ -920,7 +916,7 @@ static LLONG ROUND(LDOUBLE value) static double my_modf(double x0, double *iptr) { int i; - LLONG l; + LLONG l=0; double x = x0; double f = 1.0; @@ -1190,11 +1186,10 @@ static int add_cnk_list_entry(struct pr_chunk_x **list, return max; } - int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args) + int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { return dopr(str, count, fmt, args); } -#define vsnprintf smb_vsnprintf #endif /* yes this really must be a ||. Don't muck with this (tridge) @@ -1204,7 +1199,7 @@ static int add_cnk_list_entry(struct pr_chunk_x **list, * that doesn't work properly according to the autoconf test. */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) -int smb_snprintf(char *str,size_t count,const char *fmt,...) + int snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; @@ -1214,7 +1209,48 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) va_end(ap); return ret; } -#define snprintf smb_snprintf +#endif + +#ifndef HAVE_C99_VSNPRINTF + int printf(const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stdout); + } + free(s); + + return ret; +} +#endif + +#ifndef HAVE_C99_VSNPRINTF + int fprintf(FILE *stream, const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stream); + } + free(s); + + return ret; +} #endif #endif @@ -1226,16 +1262,16 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) va_list ap2; VA_COPY(ap2, ap); - ret = vsnprintf(NULL, 0, format, ap2); + va_end(ap2); if (ret <= 0) return ret; (*ptr) = (char *)malloc(ret+1); if (!*ptr) return -1; VA_COPY(ap2, ap); - ret = vsnprintf(*ptr, ret+1, format, ap2); + va_end(ap2); return ret; } @@ -1260,6 +1296,7 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) #ifdef TEST_SNPRINTF int sprintf(char *str,const char *fmt,...); + int printf(const char *fmt,...); int main (void) { @@ -1329,15 +1366,20 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) int fail = 0; int num = 0; int l1, l2; + char *ss_fmt[] = { + "%zd", + "%zu", + NULL + }; + size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0}; printf ("Testing snprintf format codes against system sprintf...\n"); for (x = 0; fp_fmt[x] ; x++) { for (y = 0; fp_nums[y] != 0 ; y++) { buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); - l2 = sprintf(buf1, fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); + l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]); buf1[1023] = buf2[1023] = '\0'; if (strcmp (buf1, buf2) || (l1 != l2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", @@ -1351,9 +1393,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) for (x = 0; int_fmt[x] ; x++) { for (y = 0; int_nums[y] != 0 ; y++) { buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); - l2 = sprintf(buf1, int_fmt[x], int_nums[y]); - sprintf (buf2, int_fmt[x], int_nums[y]); + l1 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + l2 = sprintf (buf2, int_fmt[x], int_nums[y]); buf1[1023] = buf2[1023] = '\0'; if (strcmp (buf1, buf2) || (l1 != l2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", @@ -1367,9 +1408,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) for (x = 0; str_fmt[x] ; x++) { for (y = 0; str_vals[y] != 0 ; y++) { buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); - l2 = sprintf(buf1, str_fmt[x], str_vals[y]); - sprintf (buf2, str_fmt[x], str_vals[y]); + l1 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + l2 = sprintf (buf2, str_fmt[x], str_vals[y]); buf1[1023] = buf2[1023] = '\0'; if (strcmp (buf1, buf2) || (l1 != l2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", @@ -1384,9 +1424,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) for (x = 0; ll_fmt[x] ; x++) { for (y = 0; ll_nums[y] != 0 ; y++) { buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, ll_fmt[x], ll_nums[y]); - l2 = sprintf(buf1, ll_fmt[x], ll_nums[y]); - sprintf (buf2, ll_fmt[x], ll_nums[y]); + l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]); + l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]); buf1[1023] = buf2[1023] = '\0'; if (strcmp (buf1, buf2) || (l1 != l2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", @@ -1433,6 +1472,21 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); fail++; } + + for (x = 0; ss_fmt[x] ; x++) { + for (y = 0; ss_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x], ss_nums[y]); + l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + ss_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } #if 0 buf1[0] = buf2[0] = '\0'; l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890); diff --git a/source/lib/replace/system/README b/source/lib/replace/system/README new file mode 100644 index 00000000000..69a2b80b56c --- /dev/null +++ b/source/lib/replace/system/README @@ -0,0 +1,4 @@ +This directory contains wrappers around logical groups of system +include files. The idea is to avoid #ifdef blocks in the main code, +and instead put all the necessary conditional includes in subsystem +specific header files in this directory. diff --git a/source/lib/replace/system/aio.h b/source/lib/replace/system/aio.h new file mode 100644 index 00000000000..45154ccb27a --- /dev/null +++ b/source/lib/replace/system/aio.h @@ -0,0 +1,29 @@ +#ifndef _system_aio_h +#define _system_aio_h +/* + Unix SMB/CIFS implementation. + + AIO system include wrappers + + Copyright (C) Andrew Tridgell 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_LIBAIO_H +#include <libaio.h> +#endif + +#endif diff --git a/source/lib/replace/system/capability.h b/source/lib/replace/system/capability.h new file mode 100644 index 00000000000..6ed8ae8de02 --- /dev/null +++ b/source/lib/replace/system/capability.h @@ -0,0 +1,41 @@ +#ifndef _system_capability_h +#define _system_capability_h +/* + Unix SMB/CIFS implementation. + + capability system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_SYS_CAPABILITY_H + +#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) +#define _I386_STATFS_H +#define BROKEN_REDHAT_7_STATFS_WORKAROUND +#endif + +#include <sys/capability.h> + +#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND +#undef _I386_STATFS_H +#undef BROKEN_REDHAT_7_STATFS_WORKAROUND +#endif + +#endif + +#endif diff --git a/source/lib/replace/system/config.m4 b/source/lib/replace/system/config.m4 new file mode 100644 index 00000000000..4d66317a5ee --- /dev/null +++ b/source/lib/replace/system/config.m4 @@ -0,0 +1,31 @@ +# filesys +AC_HEADER_DIRENT +AC_CHECK_HEADERS(fcntl.h sys/fcntl.h sys/acl.h sys/resource.h sys/ioctl.h sys/mode.h sys/filio.h sys/fs/s5param.h sys/filsys.h ) + +# select +AC_CHECK_HEADERS(sys/select.h) + +# time +AC_CHECK_HEADERS(sys/time.h utime.h) +AC_HEADER_TIME + +# wait +AC_HEADER_SYS_WAIT + +# capability +AC_CHECK_HEADERS(sys/capability.h) + +# passwd +AC_CHECK_HEADERS(grp.h sys/id.h compat.h shadow.h sys/priv.h pwd.h sys/security.h) + +# locale +AC_CHECK_HEADERS(ctype.h locale.h) + +# glob +AC_CHECK_HEADERS(fnmatch.h) + +# shmem +AC_CHECK_HEADERS(sys/ipc.h sys/mman.h sys/shm.h ) + +# terminal +AC_CHECK_HEADERS(termios.h termio.h sys/termio.h ) diff --git a/source/lib/replace/system/dir.h b/source/lib/replace/system/dir.h new file mode 100644 index 00000000000..64e413c9079 --- /dev/null +++ b/source/lib/replace/system/dir.h @@ -0,0 +1,64 @@ +#ifndef _system_dir_h +#define _system_dir_h +/* + Unix SMB/CIFS implementation. + + directory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#ifndef HAVE_MKDIR_MODE +#define mkdir(dir, mode) mkdir(dir) +#endif + +/* Test whether a file name is the "." or ".." directory entries. + * These really should be inline functions. + */ +#ifndef ISDOT +#define ISDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '\0' \ + ) +#endif + +#ifndef ISDOTDOT +#define ISDOTDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '.' && \ + *(((const char *)(path)) + 2) == '\0' \ + ) +#endif + +#endif diff --git a/source/lib/replace/system/filesys.h b/source/lib/replace/system/filesys.h new file mode 100644 index 00000000000..1e48f7ab404 --- /dev/null +++ b/source/lib/replace/system/filesys.h @@ -0,0 +1,170 @@ +#ifndef _system_filesys_h +#define _system_filesys_h +/* + Unix SMB/CIFS implementation. + + filesystem system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <unistd.h> +#include <sys/stat.h> + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif + +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif + +#ifdef HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif + +#ifdef HAVE_SYS_FS_S5PARAM_H +#include <sys/fs/s5param.h> +#endif + +#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY) +#include <sys/filsys.h> +#endif + +#ifdef HAVE_SYS_STATFS_H +# include <sys/statfs.h> +#endif + +#ifdef HAVE_DUSTAT_H +#include <sys/dustat.h> +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include <sys/statvfs.h> +#endif + +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +#include <sys/file.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#else +#ifdef HAVE_SYS_FCNTL_H +#include <sys/fcntl.h> +#endif +#endif + +#ifdef HAVE_SYS_MODE_H +/* apparently AIX needs this for S_ISLNK */ +#ifndef S_ISLNK +#include <sys/mode.h> +#endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +/* + * Veritas File System. Often in addition to native. + * Quotas different. + */ +#if defined(HAVE_SYS_FS_VX_QUOTA_H) +#define VXFS_QUOTA +#endif + +#if HAVE_SYS_ATTRIBUTES_H +#include <sys/attributes.h> +#endif + +/* mutually exclusive (SuSE 8.2) */ +#if HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#elif HAVE_SYS_XATTR_H +#include <sys/xattr.h> +#endif + + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +/* Some POSIX definitions for those without */ + +#ifndef S_IFDIR +#define S_IFDIR 0x4000 +#endif +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR) +#endif +#ifndef S_IRWXU +#define S_IRWXU 00700 /* read, write, execute: owner */ +#endif +#ifndef S_IRUSR +#define S_IRUSR 00400 /* read permission: owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 00200 /* write permission: owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 00100 /* execute permission: owner */ +#endif +#ifndef S_IRWXG +#define S_IRWXG 00070 /* read, write, execute: group */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 00040 /* read permission: group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 00020 /* write permission: group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 00010 /* execute permission: group */ +#endif +#ifndef S_IRWXO +#define S_IRWXO 00007 /* read, write, execute: other */ +#endif +#ifndef S_IROTH +#define S_IROTH 00004 /* read permission: other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 00002 /* write permission: other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 00001 /* execute permission: other */ +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#endif diff --git a/source/lib/replace/system/glob.h b/source/lib/replace/system/glob.h new file mode 100644 index 00000000000..0e51f397c69 --- /dev/null +++ b/source/lib/replace/system/glob.h @@ -0,0 +1,33 @@ +#ifndef _system_glob_h +#define _system_glob_h +/* + Unix SMB/CIFS implementation. + + glob system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif + +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif + +#endif diff --git a/source/lib/replace/system/iconv.h b/source/lib/replace/system/iconv.h new file mode 100644 index 00000000000..abc2d6f4e1b --- /dev/null +++ b/source/lib/replace/system/iconv.h @@ -0,0 +1,53 @@ +#ifndef _system_iconv_h +#define _system_iconv_h +/* + Unix SMB/CIFS implementation. + + iconv memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(HAVE_ICONV) && defined(HAVE_ICONV_H) +#define HAVE_ICONV +#endif + +#if !defined(HAVE_GICONV) && defined(HAVE_GICONV_H) +#define HAVE_GICONV +#endif + +#if !defined(HAVE_BICONV) && defined(HAVE_BICONV_H) +#define HAVE_BICONV +#endif + +#ifdef HAVE_NATIVE_ICONV +#if defined(HAVE_ICONV) +#include <iconv.h> +#elif defined(HAVE_GICONV) +#include <giconv.h> +#elif defined(HAVE_BICONV) +#include <biconv.h> +#endif +#endif /* HAVE_NATIVE_ICONV */ + +/* needed for some systems without iconv. Doesn't really matter + what error code we use */ +#ifndef EILSEQ +#define EILSEQ EIO +#endif + +#endif diff --git a/source/lib/replace/system/kerberos.h b/source/lib/replace/system/kerberos.h new file mode 100644 index 00000000000..1617b96aad1 --- /dev/null +++ b/source/lib/replace/system/kerberos.h @@ -0,0 +1,132 @@ +#ifndef _system_kerberos_h +#define _system_kerberos_h + +/* + Unix SMB/CIFS implementation. + + kerberos system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_KRB5 +/* Whether the krb5_address struct has a addrtype property */ +/* #undef HAVE_ADDRTYPE_IN_KRB5_ADDRESS */ +/* Whether the krb5_address struct has a addr_type property */ +#define HAVE_ADDR_TYPE_IN_KRB5_ADDRESS 1 +/* Define to 1 if you have the `gsskrb5_extract_authz_data_from_sec_context' */ +#define HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT 1 +/* Define to 1 if you have the `gsskrb5_get_initiator_subkey' function. */ +#define HAVE_GSSKRB5_GET_INITIATOR_SUBKEY 1 +/* Define to 1 if you have the `gsskrb5_register_acceptor_identity' function. */ +#define HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY 1 +/* Define to 1 if you have the `gss_krb5_ccache_name' function. */ +#define HAVE_GSS_KRB5_CCACHE_NAME 1 +/* Define to 1 if you have the `krb5_addlog_func' function. */ +#define HAVE_KRB5_ADDLOG_FUNC 1 +/* Define to 1 if you have the `krb5_auth_con_setkey' function. */ +#define HAVE_KRB5_AUTH_CON_SETKEY 1 +/* Define to 1 if you have the `krb5_auth_con_setuseruserkey' function. */ +/* #undef HAVE_KRB5_AUTH_CON_SETUSERUSERKEY */ +/* Define to 1 if you have the `krb5_c_enctype_compare' function. */ +#define HAVE_KRB5_C_ENCTYPE_COMPARE 1 +/* Define to 1 if you have the `krb5_c_verify_checksum' function. */ +#define HAVE_KRB5_C_VERIFY_CHECKSUM 1 +/* Whether the type krb5_encrypt_block exists */ +/* #undef HAVE_KRB5_ENCRYPT_BLOCK */ +/* Define to 1 if you have the `krb5_encrypt_data' function. */ +/* #undef HAVE_KRB5_ENCRYPT_DATA */ +/* Define to 1 if you have the `krb5_enctypes_compatible_keys' function. */ +#define HAVE_KRB5_ENCTYPES_COMPATIBLE_KEYS 1 +/* Define to 1 if you have the `krb5_free_data_contents' function. */ +#define HAVE_KRB5_FREE_DATA_CONTENTS 1 +/* Define to 1 if you have the `krb5_free_error_string' function. */ +#define HAVE_KRB5_FREE_ERROR_STRING 1 +/* Define to 1 if you have the `krb5_free_keytab_entry_contents' function. */ +/* #undef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS */ +/* Define to 1 if you have the `krb5_free_ktypes' function. */ +/* #undef HAVE_KRB5_FREE_KTYPES */ +/* Define to 1 if you have the `krb5_free_unparsed_name' function. */ +/* #undef HAVE_KRB5_FREE_UNPARSED_NAME */ +/* Define to 1 if you have the `krb5_get_default_in_tkt_etypes' function. */ +#define HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES 1 +/* Define to 1 if you have the `krb5_get_error_string' function. */ +#define HAVE_KRB5_GET_ERROR_STRING 1 +/* Define to 1 if you have the `krb5_get_permitted_enctypes' function. */ +/* #undef HAVE_KRB5_GET_PERMITTED_ENCTYPES */ +/* Define to 1 if you have the `krb5_get_pw_salt' function. */ +#define HAVE_KRB5_GET_PW_SALT 1 +/* Define to 1 if you have the <krb5.h> header file. */ +#define HAVE_KRB5_H 1 +/* Define to 1 if you have the `krb5_initlog' function. */ +#define HAVE_KRB5_INITLOG 1 +/* Define to 1 if you have the `krb5_kdc_default_config' function. */ +#define HAVE_KRB5_KDC_DEFAULT_CONFIG 1 +/* Whether the krb5_creds struct has a keyblock property */ +/* #undef HAVE_KRB5_KEYBLOCK_IN_CREDS */ +/* Whether the krb5_keyblock struct has a keyvalue property */ +#define HAVE_KRB5_KEYBLOCK_KEYVALUE 1 +/* Whether krb5_keytab_entry has key member */ +/* #undef HAVE_KRB5_KEYTAB_ENTRY_KEY */ +/* Whether krb5_keytab_entry has keyblock member */ +#define HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK 1 +/* Define to 1 if you have the `krb5_krbhst_get_addrinfo' function. */ +#define HAVE_KRB5_KRBHST_GET_ADDRINFO 1 +/* Define to 1 if you have the `krb5_kt_compare' function. */ +#define HAVE_KRB5_KT_COMPARE 1 +/* Define to 1 if you have the `krb5_kt_free_entry' function. */ +#define HAVE_KRB5_KT_FREE_ENTRY 1 +/* Whether the type krb5_log_facility exists */ +#define HAVE_KRB5_LOG_FACILITY 1 +/* Define to 1 if you have the `krb5_mk_req_extended' function. */ +#define HAVE_KRB5_MK_REQ_EXTENDED 1 +/* Define to 1 if you have the `krb5_principal2salt' function. */ +/* #undef HAVE_KRB5_PRINCIPAL2SALT */ +/* Define to 1 if you have the `krb5_principal_get_comp_string' function. */ +#define HAVE_KRB5_PRINCIPAL_GET_COMP_STRING 1 +/* Whether krb5_princ_component is available */ +/* #undef HAVE_KRB5_PRINC_COMPONENT */ +/* Whether the krb5_creds struct has a session property */ +#define HAVE_KRB5_SESSION_IN_CREDS 1 +/* Define to 1 if you have the `krb5_set_default_in_tkt_etypes' function. */ +#define HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES 1 +/* Define to 1 if you have the `krb5_set_default_tgs_ktypes' function. */ +/* #undef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES */ +/* Define to 1 if you have the `krb5_set_real_time' function. */ +#define HAVE_KRB5_SET_REAL_TIME 1 +/* Define to 1 if you have the `krb5_set_warn_dest' function. */ +#define HAVE_KRB5_SET_WARN_DEST 1 +/* Define to 1 if you have the `krb5_string_to_key' function. */ +#define HAVE_KRB5_STRING_TO_KEY 1 +/* Define to 1 if you have the `krb5_string_to_key_salt' function. */ +#define HAVE_KRB5_STRING_TO_KEY_SALT 1 +/* Define to 1 if you have the `krb5_ticket_get_authorization_data_type' */ +#define HAVE_KRB5_TICKET_GET_AUTHORIZATION_DATA_TYPE 1 +/* Whether the krb5_ticket struct has a enc_part2 property */ +/* #undef HAVE_KRB5_TKT_ENC_PART2 */ +/* Define to 1 if you have the `krb5_use_enctype' function. */ +/* #undef HAVE_KRB5_USE_ENCTYPE */ +/* Define to 1 if you have the `krb5_verify_checksum' function. */ +#define HAVE_KRB5_VERIFY_CHECKSUM 1 +/* Whether krb5_princ_realm returns krb5_realm or krb5_data */ +#define KRB5_PRINC_REALM_RETURNS_REALM 1 + +#include "heimdal/lib/krb5/krb5.h" +#include "heimdal/lib/com_err/com_err.h" +#endif + +#endif diff --git a/source/lib/replace/system/locale.h b/source/lib/replace/system/locale.h new file mode 100644 index 00000000000..82b179dc5b8 --- /dev/null +++ b/source/lib/replace/system/locale.h @@ -0,0 +1,34 @@ +#ifndef _system_locale_h +#define _system_locale_h + +/* + Unix SMB/CIFS implementation. + + locale include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_CTYPE_H +#include <ctype.h> +#endif + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif + +#endif diff --git a/source/lib/replace/system/network.h b/source/lib/replace/system/network.h new file mode 100644 index 00000000000..5e648dcd156 --- /dev/null +++ b/source/lib/replace/system/network.h @@ -0,0 +1,113 @@ +#ifndef _system_network_h +#define _system_network_h +/* + Unix SMB/CIFS implementation. + + networking system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifdef HAVE_UNIXSOCKET +#include <sys/un.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +/* + * The next three defines are needed to access the IPTOS_* options + * on some systems. + */ + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif + +#ifdef HAVE_NETINET_IN_IP_H +#include <netinet/in_ip.h> +#endif + +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef SOCKET_WRAPPER +#ifndef SOCKET_WRAPPER_NOT_REPLACE +#define SOCKET_WRAPPER_REPLACE +#endif +#include "lib/socket_wrapper/socket_wrapper.h" +#endif + +#ifdef REPLACE_INET_NTOA +char *rep_inet_ntoa(struct in_addr ip); +#define inet_ntoa rep_inet_ntoa +#endif + +/* + * glibc on linux doesn't seem to have MSG_WAITALL + * defined. I think the kernel has it though.. + */ +#ifndef MSG_WAITALL +#define MSG_WAITALL 0 +#endif + +/* + * Some older systems seem not to have MAXHOSTNAMELEN + * defined. + */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 254 +#endif + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7f000001 +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#endif diff --git a/source/lib/replace/system/passwd.h b/source/lib/replace/system/passwd.h new file mode 100644 index 00000000000..21f31f0388c --- /dev/null +++ b/source/lib/replace/system/passwd.h @@ -0,0 +1,91 @@ +#ifndef _system_passwd_h +#define _system_passwd_h + +/* + Unix SMB/CIFS implementation. + + passwd system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif +#ifdef HAVE_SYS_PRIV_H +#include <sys/priv.h> +#endif +#ifdef HAVE_SYS_ID_H +#include <sys/id.h> +#endif + +#ifdef HAVE_CRYPT_H +#include <crypt.h> +#endif + +#ifdef HAVE_SHADOW_H +#include <shadow.h> +#endif + +#ifdef HAVE_SYS_SECURITY_H +#include <sys/security.h> +#include <prot.h> +#define PASSWORD_LENGTH 16 +#endif /* HAVE_SYS_SECURITY_H */ + +#ifdef HAVE_GETPWANAM +#include <sys/label.h> +#include <sys/audit.h> +#include <pwdadj.h> +#endif + +#ifdef HAVE_COMPAT_H +#include <compat.h> +#endif + +#ifdef REPLACE_GETPASS +#define getpass(prompt) getsmbpass((prompt)) +#endif + +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 32 /* Guess... */ +#endif + +/* what is the longest significant password available on your system? + Knowing this speeds up password searches a lot */ +#ifndef PASSWORD_LENGTH +#define PASSWORD_LENGTH 8 +#endif + +#if defined(HAVE_PUTPRPWNAM) && defined(AUTH_CLEARTEXT_SEG_CHARS) +#define OSF1_ENH_SEC 1 +#endif + +#ifndef ALLOW_CHANGE_PASSWORD +#if (defined(HAVE_TERMIOS_H) && defined(HAVE_DUP2) && defined(HAVE_SETSID)) +#define ALLOW_CHANGE_PASSWORD 1 +#endif +#endif + +#if defined(HAVE_CRYPT16) && defined(HAVE_GETAUTHUID) +#define ULTRIX_AUTH 1 +#endif + +#endif diff --git a/source/lib/replace/system/printing.h b/source/lib/replace/system/printing.h new file mode 100644 index 00000000000..489ccb1da8c --- /dev/null +++ b/source/lib/replace/system/printing.h @@ -0,0 +1,46 @@ +#ifndef _system_printing_h +#define _system_printing_h + +/* + Unix SMB/CIFS implementation. + + printing system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef AIX +#define DEFAULT_PRINTING PRINT_AIX +#define PRINTCAP_NAME "/etc/qconfig" +#endif + +#ifdef HPUX +#define DEFAULT_PRINTING PRINT_HPUX +#endif + +#ifdef QNX +#define DEFAULT_PRINTING PRINT_QNX +#endif + +#ifndef DEFAULT_PRINTING +#define DEFAULT_PRINTING PRINT_BSD +#endif +#ifndef PRINTCAP_NAME +#define PRINTCAP_NAME "/etc/printcap" +#endif + +#endif diff --git a/source/lib/replace/system/readline.h b/source/lib/replace/system/readline.h new file mode 100644 index 00000000000..4a64ef13766 --- /dev/null +++ b/source/lib/replace/system/readline.h @@ -0,0 +1,48 @@ +#ifndef _system_readline_h +#define _system_readline_h +/* + Unix SMB/CIFS implementation. + + readline wrappers + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_LIBREADLINE +# ifdef HAVE_READLINE_READLINE_H +# include <readline/readline.h> +# ifdef HAVE_READLINE_HISTORY_H +# include <readline/history.h> +# endif +# else +# ifdef HAVE_READLINE_H +# include <readline.h> +# ifdef HAVE_HISTORY_H +# include <history.h> +# endif +# else +# undef HAVE_LIBREADLINE +# endif +# endif +#endif + +#ifdef HAVE_NEW_LIBREADLINE +# define RL_COMPLETION_CAST (rl_completion_func_t *) +#else +/* This type is missing from libreadline<4.0 (approximately) */ +# define RL_COMPLETION_CAST +#endif /* HAVE_NEW_LIBREADLINE */ + +#endif diff --git a/source/lib/replace/system/select.h b/source/lib/replace/system/select.h new file mode 100644 index 00000000000..20346259c27 --- /dev/null +++ b/source/lib/replace/system/select.h @@ -0,0 +1,33 @@ +#ifndef _system_select_h +#define _system_select_h +/* + Unix SMB/CIFS implementation. + + select system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifndef SELECT_CAST +#define SELECT_CAST +#endif + +#endif diff --git a/source/lib/replace/system/shmem.h b/source/lib/replace/system/shmem.h new file mode 100644 index 00000000000..26fa7c8d433 --- /dev/null +++ b/source/lib/replace/system/shmem.h @@ -0,0 +1,55 @@ +#ifndef _system_shmem_h +#define _system_shmem_h +/* + Unix SMB/CIFS implementation. + + shared memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if defined(HAVE_SYS_IPC_H) +#include <sys/ipc.h> +#endif /* HAVE_SYS_IPC_H */ + +#if defined(HAVE_SYS_SHM_H) +#include <sys/shm.h> +#endif /* HAVE_SYS_SHM_H */ + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +/* NetBSD doesn't have these */ +#ifndef SHM_R +#define SHM_R 0400 +#endif + +#ifndef SHM_W +#define SHM_W 0200 +#endif + + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#endif diff --git a/source/lib/replace/system/syslog.h b/source/lib/replace/system/syslog.h new file mode 100644 index 00000000000..e123830a709 --- /dev/null +++ b/source/lib/replace/system/syslog.h @@ -0,0 +1,66 @@ +#ifndef _system_syslog_h +#define _system_syslog_h +/* + Unix SMB/CIFS implementation. + + syslog system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#else +#ifdef HAVE_SYS_SYSLOG_H +#include <sys/syslog.h> +#endif +#endif + +/* For sys_adminlog(). */ +#ifndef LOG_EMERG +#define LOG_EMERG 0 /* system is unusable */ +#endif + +#ifndef LOG_ALERT +#define LOG_ALERT 1 /* action must be taken immediately */ +#endif + +#ifndef LOG_CRIT +#define LOG_CRIT 2 /* critical conditions */ +#endif + +#ifndef LOG_ERR +#define LOG_ERR 3 /* error conditions */ +#endif + +#ifndef LOG_WARNING +#define LOG_WARNING 4 /* warning conditions */ +#endif + +#ifndef LOG_NOTICE +#define LOG_NOTICE 5 /* normal but significant condition */ +#endif + +#ifndef LOG_INFO +#define LOG_INFO 6 /* informational */ +#endif + +#ifndef LOG_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +#endif + +#endif diff --git a/source/lib/replace/system/terminal.h b/source/lib/replace/system/terminal.h new file mode 100644 index 00000000000..94d6b5cc98d --- /dev/null +++ b/source/lib/replace/system/terminal.h @@ -0,0 +1,42 @@ +#ifndef _system_terminal_h +#define _system_terminal_h +/* + Unix SMB/CIFS implementation. + + terminal system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SUNOS4 +/* on SUNOS4 termios.h conflicts with sys/ioctl.h */ +#undef HAVE_TERMIOS_H +#endif + + +#if defined(HAVE_TERMIOS_H) +/* POSIX terminal handling. */ +#include <termios.h> +#elif defined(HAVE_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <termio.h> +#elif defined(HAVE_SYS_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <sys/termio.h> +#endif + +#endif diff --git a/source/lib/replace/system/time.h b/source/lib/replace/system/time.h new file mode 100644 index 00000000000..e7c88f133d4 --- /dev/null +++ b/source/lib/replace/system/time.h @@ -0,0 +1,40 @@ +#ifndef _system_time_h +#define _system_time_h +/* + Unix SMB/CIFS implementation. + + time system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#else +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#else +#include <time.h> +#endif +#endif + +#ifdef HAVE_UTIME_H +#include <utime.h> +#endif + +#endif diff --git a/source/lib/replace1.c b/source/lib/replace/system/wait.h index e1be56eb128..3855f7ae724 100644 --- a/source/lib/replace1.c +++ b/source/lib/replace/system/wait.h @@ -1,7 +1,11 @@ +#ifndef _system_wait_h +#define _system_wait_h /* Unix SMB/CIFS implementation. - replacement routines for broken systems - Copyright (C) Andrew Tridgell 1992-1998 + + waitpid system include wrappers + + Copyright (C) Andrew Tridgell 2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,25 +22,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif - void replace1_dummy(void); - void replace1_dummy(void) {} +#include <signal.h> -#ifndef HAVE_SETENV - int setenv(const char *name, const char *value, int overwrite) -{ - char *p = NULL; - int ret = -1; +#ifndef SIGCLD +#define SIGCLD SIGCHLD +#endif - asprintf(&p, "%s=%s", name, value); +#ifndef SIGNAL_CAST +#define SIGNAL_CAST (RETSIGTYPE (*)(int)) +#endif - if (overwrite || getenv(name)) { - if (p) ret = putenv(p); - } else { - ret = 0; - } +#ifdef HAVE_SETJMP_H +#include <setjmp.h> +#endif - return ret; -} #endif diff --git a/source/lib/replace/test/os2_delete.c b/source/lib/replace/test/os2_delete.c new file mode 100644 index 00000000000..c8abfccff9b --- /dev/null +++ b/source/lib/replace/test/os2_delete.c @@ -0,0 +1,115 @@ +/* + test readdir/unlink pattern that OS/2 uses + tridge@samba.org July 2005 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> + +#define NUM_FILES 700 +#define READDIR_SIZE 100 +#define DELETE_SIZE 4 + +#define TESTDIR "test.dir" + +static int test_readdir_os2_delete_ret; + +#define FAILED(d) (printf("failure: readdir [\nFailed for %s - %d = %s\n]\n", d, errno, strerror(errno)), test_readdir_os2_delete_ret = 1, 1) + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +static void cleanup(void) +{ + /* I'm a lazy bastard */ + system("rm -rf " TESTDIR); + mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir"); +} + +static void create_files(void) +{ + int i; + for (i=0;i<NUM_FILES;i++) { + char fname[40]; + sprintf(fname, TESTDIR "/test%u.txt", i); + close(open(fname, O_CREAT|O_RDWR, 0600)) == 0 || FAILED("close"); + } +} + +static int os2_delete(DIR *d) +{ + off_t offsets[READDIR_SIZE]; + int i, j; + struct dirent *de; + char names[READDIR_SIZE][30]; + + /* scan, remembering offsets */ + for (i=0, de=readdir(d); + de && i < READDIR_SIZE; + de=readdir(d), i++) { + offsets[i] = telldir(d); + strcpy(names[i], de->d_name); + } + + if (i == 0) { + return 0; + } + + /* delete the first few */ + for (j=0; j<MIN(i, DELETE_SIZE); j++) { + char fname[40]; + sprintf(fname, TESTDIR "/%s", names[j]); + unlink(fname) == 0 || FAILED("unlink"); + } + + /* seek to just after the deletion */ + seekdir(d, offsets[j-1]); + + /* return number deleted */ + return j; +} + +int test_readdir_os2_delete(void) +{ + int total_deleted = 0; + DIR *d; + struct dirent *de; + + test_readdir_os2_delete_ret = 0; + + cleanup(); + create_files(); + + d = opendir(TESTDIR "/test0.txt"); + if (d != NULL) FAILED("opendir() on file succeed"); + if (errno != ENOTDIR) FAILED("opendir() on file didn't give ENOTDIR"); + + d = opendir(TESTDIR); + + /* skip past . and .. */ + de = readdir(d); + strcmp(de->d_name, ".") == 0 || FAILED("match ."); + de = readdir(d); + strcmp(de->d_name, "..") == 0 || FAILED("match .."); + + while (1) { + int n = os2_delete(d); + if (n == 0) break; + total_deleted += n; + } + closedir(d); + + fprintf(stderr, "Deleted %d files of %d\n", total_deleted, NUM_FILES); + + rmdir(TESTDIR) == 0 || FAILED("rmdir"); + + return test_readdir_os2_delete_ret; +} diff --git a/source/lib/replace/test/shared_mmap.c b/source/lib/replace/test/shared_mmap.c new file mode 100644 index 00000000000..50dad8d6964 --- /dev/null +++ b/source/lib/replace/test/shared_mmap.c @@ -0,0 +1,68 @@ +/* this tests whether we can use a shared writeable mmap on a file - + as needed for the mmap variant of FAST_SHARE_MODES */ + +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define DATA "conftest.mmap" + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +main() +{ + int *buf; + int i; + int fd = open(DATA,O_RDWR|O_CREAT|O_TRUNC,0666); + int count=7; + + if (fd == -1) exit(1); + + for (i=0;i<10000;i++) { + write(fd,&i,sizeof(i)); + } + + close(fd); + + if (fork() == 0) { + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + while (count-- && buf[9124] != 55732) sleep(1); + + if (count <= 0) exit(1); + + buf[1763] = 7268; + exit(0); + } + + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + if (buf == (int *)-1) exit(1); + + buf[9124] = 55732; + + while (count-- && buf[1763] != 7268) sleep(1); + + unlink(DATA); + + if (count > 0) exit(0); + exit(1); +} diff --git a/source/lib/replace/test/testsuite.c b/source/lib/replace/test/testsuite.c new file mode 100644 index 00000000000..effbdb13ef0 --- /dev/null +++ b/source/lib/replace/test/testsuite.c @@ -0,0 +1,481 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "replace.h" + +/* + we include all the system/ include files here so that libreplace tests + them in the build farm +*/ +#include "system/capability.h" +#include "system/dir.h" +#include "system/filesys.h" +#include "system/glob.h" +#include "system/iconv.h" +#include "system/locale.h" +#include "system/network.h" +#include "system/passwd.h" +#include "system/printing.h" +#include "system/readline.h" +#include "system/select.h" +#include "system/shmem.h" +#include "system/syslog.h" +#include "system/terminal.h" +#include "system/time.h" +#include "system/wait.h" +#include "system/aio.h" + +#define TESTFILE "testfile.dat" + +/* + test ftruncate() function + */ +static int test_ftruncate(void) +{ + struct stat st; + int fd; + const int size = 1234; + printf("test: ftruncate\n"); + unlink(TESTFILE); + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: ftruncate [\n" + "creating '%s' failed - %s\n]\n", TESTFILE, strerror(errno)); + return false; + } + if (ftruncate(fd, size) != 0) { + printf("failure: ftruncate [\n%s\n]\n", strerror(errno)); + return false; + } + if (fstat(fd, &st) != 0) { + printf("failure: ftruncate [\nfstat failed - %s\n]\n", strerror(errno)); + return false; + } + if (st.st_size != size) { + printf("failure: ftruncate [\ngave wrong size %d - expected %d\n]\n", + (int)st.st_size, size); + return false; + } + unlink(TESTFILE); + printf("success: ftruncate\n"); + return true; +} + +/* + test strlcpy() function. + see http://www.gratisoft.us/todd/papers/strlcpy.html + */ +static int test_strlcpy(void) +{ + char buf[4]; + const struct { + const char *src; + size_t result; + } tests[] = { + { "abc", 3 }, + { "abcdef", 6 }, + { "abcd", 4 }, + { "", 0 }, + { NULL, 0 } + }; + int i; + printf("test: strlcpy\n"); + for (i=0;tests[i].src;i++) { + if (strlcpy(buf, tests[i].src, sizeof(buf)) != tests[i].result) { + printf("failure: strlcpy [\ntest %d failed\n]\n", i); + return false; + } + } + printf("success: strlcpy\n"); + return true; +} + +static int test_strlcat(void) +{ + /* FIXME */ + return true; +} + +static int test_mktime(void) +{ + /* FIXME */ + return true; +} + +static int test_innetgr(void) +{ + /* FIXME */ + return true; +} + +static int test_initgroups(void) +{ + /* FIXME */ + return true; +} + +static int test_memmove(void) +{ + /* FIXME */ + return true; +} + +static int test_strdup(void) +{ + /* FIXME */ + return true; +} + +static int test_setlinebuf(void) +{ + printf("test: setlinebuf\n"); + setlinebuf(stdout); + printf("success: setlinebuf\n"); + return true; +} + +static int test_vsyslog(void) +{ + /* FIXME */ + return true; +} + +static int test_timegm(void) +{ + /* FIXME */ + return true; +} + +static int test_setenv(void) +{ + /* FIXME */ + return true; +} + +static int test_strndup(void) +{ + /* FIXME */ + return true; +} + +static int test_strnlen(void) +{ + /* FIXME */ + return true; +} + +static int test_waitpid(void) +{ + /* FIXME */ + return true; +} + +static int test_seteuid(void) +{ + /* FIXME */ + return true; +} + +static int test_setegid(void) +{ + /* FIXME */ + return true; +} + +static int test_asprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_snprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_vasprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_vsnprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_opendir(void) +{ + /* FIXME */ + return true; +} + +extern int test_readdir_os2_delete(void); + +static int test_readdir(void) +{ + printf("test: readdir\n"); + if (test_readdir_os2_delete() != 0) { + return false; + } + printf("success: readdir\n"); + return true; +} + +static int test_telldir(void) +{ + /* FIXME */ + return true; +} + +static int test_seekdir(void) +{ + /* FIXME */ + return true; +} + +static int test_dlopen(void) +{ + /* FIXME: test dlopen, dlsym, dlclose, dlerror */ + return true; +} + + +static int test_chroot(void) +{ + /* FIXME: chroot() */ + return true; +} + +static int test_bzero(void) +{ + /* FIXME: bzero */ + return true; +} + +static int test_strerror(void) +{ + /* FIXME */ + return true; +} + +static int test_errno(void) +{ + /* FIXME */ + return true; +} + +static int test_mkdtemp(void) +{ + /* FIXME */ + return true; +} + +static int test_mkstemp(void) +{ + /* FIXME */ + return true; +} + +static int test_pread(void) +{ + /* FIXME */ + return true; +} + +static int test_pwrite(void) +{ + /* FIXME */ + return true; +} + +static int test_getpass(void) +{ + /* FIXME */ + return true; +} + +static int test_inet_ntoa(void) +{ + /* FIXME */ + return true; +} + +static int test_strtoll(void) +{ + /* FIXME */ + return true; +} + +static int test_strtoull(void) +{ + /* FIXME */ + return true; +} + +/* +FIXME: +Types: +bool +socklen_t +uint_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +*/ + +static int test_va_copy(void) +{ + /* FIXME */ + return true; +} + +static int test_FUNCTION(void) +{ + /* FIXME: test __FUNCTION__ macro */ + return true; +} + +static int test_MIN(void) +{ + /* FIXME */ + return true; +} + +static int test_MAX(void) +{ + /* FIXME */ + return true; +} + +static int test_socketpair(void) +{ + int sock[2]; + char buf[20]; + + printf("test: socketpair\n"); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == -1) { + printf("failure: socketpair [\n" + "socketpair() failed\n" + "]\n"); + return false; + } + + if (write(sock[1], "automatisch", 12) == -1) { + printf("failure: socketpair [\n" + "write() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (read(sock[0], buf, 12) == -1) { + printf("failure: socketpair [\n" + "read() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (strcmp(buf, "automatisch") != 0) { + printf("failure: socketpair [\n" + "expected: automatisch, got: %s\n" + "]\n", buf); + return false; + } + + printf("success: socketpair\n"); + + return true; +} + +struct torture_context; +bool torture_local_replace(struct torture_context *ctx) +{ + bool ret = true; + ret &= test_ftruncate(); + ret &= test_strlcpy(); + ret &= test_strlcat(); + ret &= test_mktime(); + ret &= test_innetgr(); + ret &= test_initgroups(); + ret &= test_memmove(); + ret &= test_strdup(); + ret &= test_setlinebuf(); + ret &= test_vsyslog(); + ret &= test_timegm(); + ret &= test_setenv(); + ret &= test_strndup(); + ret &= test_strnlen(); + ret &= test_waitpid(); + ret &= test_seteuid(); + ret &= test_setegid(); + ret &= test_asprintf(); + ret &= test_snprintf(); + ret &= test_vasprintf(); + ret &= test_vsnprintf(); + ret &= test_opendir(); + ret &= test_readdir(); + ret &= test_telldir(); + ret &= test_seekdir(); + ret &= test_dlopen(); + ret &= test_chroot(); + ret &= test_bzero(); + ret &= test_strerror(); + ret &= test_errno(); + ret &= test_mkdtemp(); + ret &= test_mkstemp(); + ret &= test_pread(); + ret &= test_pwrite(); + ret &= test_getpass(); + ret &= test_inet_ntoa(); + ret &= test_strtoll(); + ret &= test_strtoll(); + ret &= test_strtoull(); + ret &= test_va_copy(); + ret &= test_FUNCTION(); + ret &= test_MIN(); + ret &= test_MAX(); + ret &= test_socketpair(); + + return ret; +} + +#if _SAMBA_BUILD_<4 +int main(void) +{ + bool ret = torture_local_replace(NULL); + if (ret) + return 0; + return -1; +} +#endif diff --git a/source/lib/timegm.c b/source/lib/replace/timegm.c index dcc710b1ece..395c684e117 100644 --- a/source/lib/timegm.c +++ b/source/lib/replace/timegm.c @@ -35,9 +35,8 @@ adapted for Samba4 by Andrew Tridgell */ -#include "includes.h" - -#ifndef HAVE_TIMEGM +#include "replace.h" +#include "system/time.h" static int is_leap(unsigned y) { @@ -45,14 +44,14 @@ static int is_leap(unsigned y) return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); } -time_t timegm(struct tm *tm) +time_t rep_timegm(struct tm *tm) { static const unsigned ndays[2][12] ={ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; time_t res = 0; unsigned i; - + if (tm->tm_mon > 12 || tm->tm_mon < 0 || tm->tm_mday > 31 || @@ -62,7 +61,7 @@ time_t timegm(struct tm *tm) /* invalid tm structure */ return 0; } - + for (i = 70; i < tm->tm_year; ++i) res += is_leap(i) ? 366 : 365; @@ -77,5 +76,3 @@ time_t timegm(struct tm *tm) res += tm->tm_sec; return res; } - -#endif /* HAVE_TIMEGM */ diff --git a/source/lib/replace/timegm.m4 b/source/lib/replace/timegm.m4 new file mode 100644 index 00000000000..59f3ae05211 --- /dev/null +++ b/source/lib/replace/timegm.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(timegm,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} timegm.o"]) diff --git a/source/lib/replace/win32.m4 b/source/lib/replace/win32.m4 new file mode 100644 index 00000000000..9ac84cdf2ad --- /dev/null +++ b/source/lib/replace/win32.m4 @@ -0,0 +1,20 @@ +AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) + +####################################### +# Check for mkdir mode +AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, + AC_TRY_COMPILE([ + #include <stdio.h> + #ifdef HAVE_DIRECT_H + #include <direct.h> + #endif],[ + mkdir("foo",0777); + return 0; + ], + ac_mkdir_has_mode="yes", + ac_mkdir_has_mode="no") ) + +if test "$ac_mkdir_has_mode" = "yes" +then + AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) +fi diff --git a/source/lib/replace/win32_replace.h b/source/lib/replace/win32_replace.h new file mode 100644 index 00000000000..9901e72f6ef --- /dev/null +++ b/source/lib/replace/win32_replace.h @@ -0,0 +1,159 @@ +#ifndef _WIN32_REPLACE_H +#define _WIN32_REPLACE_H + +#ifdef HAVE_WINSOCK2_H +#include <winsock2.h> +#endif + +#ifdef HAVE_WS2TCPIP_H +#include <ws2tcpip.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif + +/* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */ + +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define ECONNREFUSED WSAECONNREFUSED +#define EINPROGRESS WSAEINPROGRESS +#define EMSGSIZE WSAEMSGSIZE +#define ENOBUFS WSAENOBUFS +#define ENOTSOCK WSAENOTSOCK +#define ENETUNREACH WSAENETUNREACH +#define ENOPROTOOPT WSAENOPROTOOPT +#define ENOTCONN WSAENOTCONN +#define ENOTSUP 134 + +/* We undefine the following constants due to conflicts with the w32api headers + * and the Windows Platform SDK/DDK. + */ + +#undef interface + +#undef ERROR_INVALID_PARAMETER +#undef ERROR_INSUFFICIENT_BUFFER +#undef ERROR_INVALID_DATATYPE + +#undef FILE_GENERIC_READ +#undef FILE_GENERIC_WRITE +#undef FILE_GENERIC_EXECUTE +#undef FILE_ATTRIBUTE_READONLY +#undef FILE_ATTRIBUTE_HIDDEN +#undef FILE_ATTRIBUTE_SYSTEM +#undef FILE_ATTRIBUTE_DIRECTORY +#undef FILE_ATTRIBUTE_ARCHIVE +#undef FILE_ATTRIBUTE_DEVICE +#undef FILE_ATTRIBUTE_NORMAL +#undef FILE_ATTRIBUTE_TEMPORARY +#undef FILE_ATTRIBUTE_REPARSE_POINT +#undef FILE_ATTRIBUTE_COMPRESSED +#undef FILE_ATTRIBUTE_OFFLINE +#undef FILE_ATTRIBUTE_ENCRYPTED +#undef FILE_FLAG_WRITE_THROUGH +#undef FILE_FLAG_NO_BUFFERING +#undef FILE_FLAG_RANDOM_ACCESS +#undef FILE_FLAG_SEQUENTIAL_SCAN +#undef FILE_FLAG_DELETE_ON_CLOSE +#undef FILE_FLAG_BACKUP_SEMANTICS +#undef FILE_FLAG_POSIX_SEMANTICS +#undef FILE_TYPE_DISK +#undef FILE_TYPE_UNKNOWN +#undef FILE_CASE_SENSITIVE_SEARCH +#undef FILE_CASE_PRESERVED_NAMES +#undef FILE_UNICODE_ON_DISK +#undef FILE_PERSISTENT_ACLS +#undef FILE_FILE_COMPRESSION +#undef FILE_VOLUME_QUOTAS +#undef FILE_VOLUME_IS_COMPRESSED +#undef FILE_NOTIFY_CHANGE_FILE_NAME +#undef FILE_NOTIFY_CHANGE_DIR_NAME +#undef FILE_NOTIFY_CHANGE_ATTRIBUTES +#undef FILE_NOTIFY_CHANGE_SIZE +#undef FILE_NOTIFY_CHANGE_LAST_WRITE +#undef FILE_NOTIFY_CHANGE_LAST_ACCESS +#undef FILE_NOTIFY_CHANGE_CREATION +#undef FILE_NOTIFY_CHANGE_EA +#undef FILE_NOTIFY_CHANGE_SECURITY +#undef FILE_NOTIFY_CHANGE_STREAM_NAME +#undef FILE_NOTIFY_CHANGE_STREAM_SIZE +#undef FILE_NOTIFY_CHANGE_STREAM_WRITE +#undef FILE_NOTIFY_CHANGE_NAME + +#undef PRINTER_ATTRIBUTE_QUEUED +#undef PRINTER_ATTRIBUTE_DIRECT +#undef PRINTER_ATTRIBUTE_DEFAULT +#undef PRINTER_ATTRIBUTE_SHARED +#undef PRINTER_ATTRIBUTE_NETWORK +#undef PRINTER_ATTRIBUTE_HIDDEN +#undef PRINTER_ATTRIBUTE_LOCAL +#undef PRINTER_ATTRIBUTE_ENABLE_DEVQ +#undef PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS +#undef PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST +#undef PRINTER_ATTRIBUTE_WORK_OFFLINE +#undef PRINTER_ATTRIBUTE_ENABLE_BIDI +#undef PRINTER_ATTRIBUTE_RAW_ONLY +#undef PRINTER_ATTRIBUTE_PUBLISHED +#undef PRINTER_ENUM_DEFAULT +#undef PRINTER_ENUM_LOCAL +#undef PRINTER_ENUM_CONNECTIONS +#undef PRINTER_ENUM_FAVORITE +#undef PRINTER_ENUM_NAME +#undef PRINTER_ENUM_REMOTE +#undef PRINTER_ENUM_SHARED +#undef PRINTER_ENUM_NETWORK +#undef PRINTER_ENUM_EXPAND +#undef PRINTER_ENUM_CONTAINER +#undef PRINTER_ENUM_ICON1 +#undef PRINTER_ENUM_ICON2 +#undef PRINTER_ENUM_ICON3 +#undef PRINTER_ENUM_ICON4 +#undef PRINTER_ENUM_ICON5 +#undef PRINTER_ENUM_ICON6 +#undef PRINTER_ENUM_ICON7 +#undef PRINTER_ENUM_ICON8 +#undef PRINTER_STATUS_PAUSED +#undef PRINTER_STATUS_ERROR +#undef PRINTER_STATUS_PENDING_DELETION +#undef PRINTER_STATUS_PAPER_JAM +#undef PRINTER_STATUS_PAPER_OUT +#undef PRINTER_STATUS_MANUAL_FEED +#undef PRINTER_STATUS_PAPER_PROBLEM +#undef PRINTER_STATUS_OFFLINE +#undef PRINTER_STATUS_IO_ACTIVE +#undef PRINTER_STATUS_BUSY +#undef PRINTER_STATUS_PRINTING +#undef PRINTER_STATUS_OUTPUT_BIN_FULL +#undef PRINTER_STATUS_NOT_AVAILABLE +#undef PRINTER_STATUS_WAITING +#undef PRINTER_STATUS_PROCESSING +#undef PRINTER_STATUS_INITIALIZING +#undef PRINTER_STATUS_WARMING_UP +#undef PRINTER_STATUS_TONER_LOW +#undef PRINTER_STATUS_NO_TONER +#undef PRINTER_STATUS_PAGE_PUNT +#undef PRINTER_STATUS_USER_INTERVENTION +#undef PRINTER_STATUS_OUT_OF_MEMORY +#undef PRINTER_STATUS_DOOR_OPEN +#undef PRINTER_STATUS_SERVER_UNKNOWN +#undef PRINTER_STATUS_POWER_SAVE + +#undef DWORD +#undef HKEY_CLASSES_ROOT +#undef HKEY_CURRENT_USER +#undef HKEY_LOCAL_MACHINE +#undef HKEY_USERS +#undef HKEY_PERFORMANCE_DATA +#undef HKEY_CURRENT_CONFIG +#undef HKEY_DYN_DATA +#undef REG_DWORD +#undef REG_QWORD + +#undef SERVICE_STATE_ALL + +#undef SE_GROUP_MANDATORY +#undef SE_GROUP_ENABLED_BY_DEFAULT +#undef SE_GROUP_ENABLED + +#endif /* _WIN32_REPLACE_H */ diff --git a/source/lib/secace.c b/source/lib/secace.c index f1d4d99cc16..ab7ad811a0a 100644 --- a/source/lib/secace.c +++ b/source/lib/secace.c @@ -46,10 +46,10 @@ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) ace_dest->type = ace_src->type; ace_dest->flags = ace_src->flags; ace_dest->size = ace_src->size; - ace_dest->info.mask = ace_src->info.mask; + ace_dest->access_mask = ace_src->access_mask; ace_dest->obj_flags = ace_src->obj_flags; - memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct uuid)); - memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct uuid)); + memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct GUID)); + memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct GUID)); sid_copy(&ace_dest->trustee, &ace_src->trustee); } @@ -62,7 +62,7 @@ void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, u t->type = type; t->flags = flag; t->size = sid_size(sid) + 8; - t->info = mask; + t->access_mask = mask; ZERO_STRUCTP(&t->trustee); sid_copy(&t->trustee, sid); @@ -89,7 +89,7 @@ NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsign (*pp_new)[i].type = 0; (*pp_new)[i].flags = 0; (*pp_new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); - (*pp_new)[i].info.mask = mask; + (*pp_new)[i].access_mask = mask; sid_copy(&(*pp_new)[i].trustee, sid); return NT_STATUS_OK; } @@ -106,7 +106,7 @@ NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask) for (i = 0; i < num; i ++) { if (sid_compare(&ace[i].trustee, sid) == 0) { - ace[i].info.mask = mask; + ace[i].access_mask = mask; return NT_STATUS_OK; } } @@ -160,7 +160,7 @@ BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) /* Check top level stuff */ if (s1->type != s2->type || s1->flags != s2->flags || - s1->info.mask != s2->info.mask) { + s1->access_mask != s2->access_mask) { return False; } diff --git a/source/lib/secacl.c b/source/lib/secacl.c index e213e0d9a0c..4e2178c195e 100644 --- a/source/lib/secacl.c +++ b/source/lib/secacl.c @@ -46,13 +46,13 @@ SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *a positive number. */ if ((num_aces) && - ((dst->ace = TALLOC_ARRAY(ctx, SEC_ACE, num_aces)) + ((dst->aces = TALLOC_ARRAY(ctx, SEC_ACE, num_aces)) == NULL)) { return NULL; } for (i = 0; i < num_aces; i++) { - dst->ace[i] = ace_list[i]; /* Structure copy. */ + dst->aces[i] = ace_list[i]; /* Structure copy. */ dst->size += ace_list[i].size; } @@ -68,7 +68,7 @@ SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) if(src == NULL) return NULL; - return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); + return make_sec_acl(ctx, src->revision, src->num_aces, src->aces); } /******************************************************************* @@ -105,7 +105,7 @@ BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) BOOL found = False; for (j = 0; j < s2->num_aces; j++) { - if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { + if (sec_ace_equal(&s1->aces[i], &s2->aces[j])) { found = True; break; } diff --git a/source/lib/secdesc.c b/source/lib/secdesc.c index f8873277cf8..16dde0da111 100644 --- a/source/lib/secdesc.c +++ b/source/lib/secdesc.c @@ -49,8 +49,8 @@ size_t sec_desc_size(SEC_DESC *psd) if (psd->owner_sid != NULL) offset += sid_size(psd->owner_sid); - if (psd->grp_sid != NULL) - offset += sid_size(psd->grp_sid); + if (psd->group_sid != NULL) + offset += sid_size(psd->group_sid); if (psd->sacl != NULL) offset += psd->sacl->size; @@ -104,11 +104,11 @@ BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) return False; } - if (!sid_equal(s1->grp_sid, s2->grp_sid)) { + if (!sid_equal(s1->group_sid, s2->group_sid)) { fstring str1, str2; - sid_to_string(str1, s1->grp_sid); - sid_to_string(str2, s2->grp_sid); + sid_to_string(str1, s1->group_sid); + sid_to_string(str2, s2->group_sid); DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", str1, str2)); @@ -157,8 +157,8 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : old_sdb->sec->owner_sid; - group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : - old_sdb->sec->grp_sid; + group_sid = new_sdb->sec->group_sid ? new_sdb->sec->group_sid : + old_sdb->sec->group_sid; secdesc_type = new_sdb->sec->type; @@ -192,7 +192,7 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU ********************************************************************/ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, - const DOM_SID *owner_sid, const DOM_SID *grp_sid, + const DOM_SID *owner_sid, const DOM_SID *group_sid, SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) { SEC_DESC *dst; @@ -219,7 +219,7 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) goto error_exit; - if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) + if(group_sid && ((dst->group_sid = sid_dup_talloc(ctx,group_sid)) == NULL)) goto error_exit; if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) @@ -248,9 +248,9 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, offset += sid_size(dst->owner_sid); } - if (dst->grp_sid != NULL) { + if (dst->group_sid != NULL) { dst->off_grp_sid = offset; - offset += sid_size(dst->grp_sid); + offset += sid_size(dst->group_sid); } *sd_size = (size_t)offset; @@ -274,7 +274,7 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) return NULL; return make_sec_desc( ctx, src->revision, src->type, - src->owner_sid, src->grp_sid, src->sacl, + src->owner_sid, src->group_sid, src->sacl, src->dacl, &dummy); } @@ -282,11 +282,11 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) Creates a SEC_DESC structure with typical defaults. ********************************************************************/ -SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid, +SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *group_sid, SEC_ACL *dacl, size_t *sd_size) { return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - owner_sid, grp_sid, NULL, dacl, sd_size); + owner_sid, group_sid, NULL, dacl, sd_size); } /******************************************************************* @@ -341,7 +341,7 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 *sd_size = 0; - status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); + status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask); if (!NT_STATUS_IS_OK(status)) return status; @@ -350,7 +350,7 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 return NT_STATUS_UNSUCCESSFUL; if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + psd[0]->group_sid, psd[0]->sacl, dacl, sd_size))) return NT_STATUS_UNSUCCESSFUL; *psd = sd; @@ -369,7 +369,7 @@ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER; - status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); + status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask); if (!NT_STATUS_IS_OK(status)) return status; @@ -393,7 +393,7 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size = 0; - status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); + status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid); if (!NT_STATUS_IS_OK(status)) return status; @@ -402,7 +402,7 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t return NT_STATUS_UNSUCCESSFUL; if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + psd[0]->group_sid, psd[0]->sacl, dacl, sd_size))) return NT_STATUS_UNSUCCESSFUL; *psd = sd; @@ -434,7 +434,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, return NULL; for (i = 0; i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *ace = &the_acl->aces[i]; SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; uint8 new_flags = 0; BOOL inherit = False; @@ -490,17 +490,17 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, if (!inherit) continue; - init_sec_access(&new_ace->info, ace->info.mask); + init_sec_access(&new_ace->access_mask, ace->access_mask); init_sec_ace(new_ace, &ace->trustee, ace->type, - new_ace->info, new_flags); + new_ace->access_mask, new_flags); sid_to_string(sid_str, &ace->trustee); DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, - ace->type, ace->flags, ace->info.mask, + ace->type, ace->flags, ace->access_mask, sid_str, new_ace->type, new_ace->flags, - new_ace->info.mask)); + new_ace->access_mask)); new_ace_list_ndx++; } @@ -515,7 +515,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, parent_ctr->owner_sid, - parent_ctr->grp_sid, + parent_ctr->group_sid, parent_ctr->sacl, new_dacl, &size); @@ -530,7 +530,5 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, void init_sec_access(SEC_ACCESS *t, uint32 mask) { - t->mask = mask; + *t = mask; } - - diff --git a/source/lib/sharesec.c b/source/lib/sharesec.c index 8105d5c37a6..e3216aa4594 100644 --- a/source/lib/sharesec.c +++ b/source/lib/sharesec.c @@ -108,7 +108,8 @@ SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def Pull a security descriptor from the share tdb. ********************************************************************/ -SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize) +SEC_DESC *get_share_security( TALLOC_CTX *ctx, const char *servicename, + size_t *psize) { prs_struct ps; fstring key; @@ -122,12 +123,13 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize) /* Fetch security descriptor from tdb */ - slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum)); + slprintf(key, sizeof(key)-1, "SECDESC/%s", servicename); if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 || !sec_io_desc("get_share_security", &psd, &ps, 1)) { - DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) )); + DEBUG(4, ("get_share_security: using default secdesc for %s\n", + servicename)); return get_share_security_default(ctx, psize, GENERIC_ALL_ACCESS); } @@ -143,7 +145,7 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize) Store a security descriptor in the share db. ********************************************************************/ -BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd) +BOOL set_share_security(const char *share_name, SEC_DESC *psd) { prs_struct ps; TALLOC_CTX *mem_ctx = NULL; @@ -186,24 +188,56 @@ out: Delete a security descriptor. ********************************************************************/ -BOOL delete_share_security(int snum) +BOOL delete_share_security(const struct share_params *params) { TDB_DATA kbuf; fstring key; - slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum)); + slprintf(key, sizeof(key)-1, "SECDESC/%s", + lp_servicename(params->service)); kbuf.dptr = key; kbuf.dsize = strlen(key)+1; - if (tdb_delete(share_tdb, kbuf) != 0) { + if (tdb_trans_delete(share_tdb, kbuf) != 0) { DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n", - lp_servicename(snum) )); + lp_servicename(params->service) )); return False; } return True; } +/******************************************************************* + Can this user access with share with the required permissions ? +********************************************************************/ + +BOOL share_access_check(const NT_USER_TOKEN *token, const char *sharename, + uint32 desired_access) +{ + uint32 granted; + NTSTATUS status; + TALLOC_CTX *mem_ctx = NULL; + SEC_DESC *psd = NULL; + size_t sd_size; + BOOL ret = True; + + if (!(mem_ctx = talloc_init("share_access_check"))) { + return False; + } + + psd = get_share_security(mem_ctx, sharename, &sd_size); + + if (!psd) { + TALLOC_FREE(mem_ctx); + return True; + } + + ret = se_access_check(psd, token, desired_access, &granted, &status); + + talloc_destroy(mem_ctx); + return ret; +} + /*************************************************************************** Parse the contents of an acl string from a usershare file. ***************************************************************************/ diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index a63e1c1bcc3..c102c2185f5 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -340,8 +340,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { return result; } - static int ldapmsg_destructor(void *p) { - LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *); + static int ldapmsg_destructor(LDAPMessage **result) { ldap_msgfree(*result); return 0; } @@ -361,9 +360,8 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { talloc_set_destructor(handle, ldapmsg_destructor); } - static int ldapmod_destructor(void *p) { - LDAPMod ***result = talloc_get_type_abort(p, LDAPMod **); - ldap_mods_free(*result, True); + static int ldapmod_destructor(LDAPMod ***mod) { + ldap_mods_free(*mod, True); return 0; } @@ -574,7 +572,6 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) { struct smbldap_state *tmp_ldap_state; struct smbldap_state_lookup *t; - struct smbldap_state_lookup *tmp; if ((tmp_ldap_state = smbldap_find_state(ld))) { SMB_ASSERT(tmp_ldap_state == smbldap_state); @@ -584,7 +581,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) t = SMB_XMALLOC_P(struct smbldap_state_lookup); ZERO_STRUCTP(t); - DLIST_ADD_END(smbldap_state_lookup_list, t, tmp); + DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *); t->ld = ld; t->smbldap_state = smbldap_state; } @@ -806,20 +803,27 @@ static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, if (freeit) { SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); + if (*credp) { + memset(*credp, '\0', strlen(*credp)); + } SAFE_FREE(*credp); } else { DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); + ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]")); - *whop = SMB_STRDUP(ldap_state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = SMB_STRDUP(ldap_state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; + if (ldap_state->anonymous) { + *whop = NULL; + *credp = NULL; + } else { + *whop = SMB_STRDUP(ldap_state->bind_dn); + if (!*whop) { + return LDAP_NO_MEMORY; + } + *credp = SMB_STRDUP(ldap_state->bind_secret); + if (!*credp) { + SAFE_FREE(*whop); + return LDAP_NO_MEMORY; + } } *methodp = LDAP_AUTH_SIMPLE; } @@ -841,12 +845,13 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct, ber_tag_t request, ber_int_t msgid, void *arg) { - struct smbldap_state *ldap_state = arg; + struct smbldap_state *ldap_state = + (struct smbldap_state *)arg; int rc; int version; DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n", - url, ldap_state->bind_dn)); + url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]")); /* call START_TLS again (ldaps:// is handled by the OpenLDAP library * itself) before rebinding to another LDAP server to avoid to expose @@ -927,24 +932,22 @@ static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct) { int rc; - char *ldap_dn; - char *ldap_secret; int version; - /* get the password */ - if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } + if (!ldap_state->anonymous && !ldap_state->bind_dn) { - ldap_state->bind_dn = ldap_dn; - ldap_state->bind_secret = ldap_secret; + /* get the default dn and password only if they are not set already */ + if (!fetch_ldap_pw(&ldap_state->bind_dn, &ldap_state->bind_secret)) { + DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); + return LDAP_INVALID_CREDENTIALS; + } + } /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite (OpenLDAP) doesnt' seem to support it */ DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", - ldap_state->uri, ldap_dn)); + ldap_state->uri, ldap_state->bind_dn)); #ifdef HAVE_LDAP_SET_REBIND_PROC #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) @@ -964,7 +967,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ #endif - rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); + rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; @@ -973,7 +976,8 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ DEBUG(ldap_state->num_failures ? 2 : 0, ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n", ldap_state->uri, - ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc), + ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]", + ldap_err2string(rc), ld_error ? ld_error : "(unknown)")); SAFE_FREE(ld_error); ldap_state->num_failures++; @@ -1080,8 +1084,6 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state) DEBUG(5,("The connection to the LDAP server was closed\n")); /* maybe free the results here --metze */ - - return NT_STATUS_OK; } @@ -1230,12 +1232,23 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, sizelimit, res); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; + int ld_errno; + + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_NUMBER, &ld_errno); + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(10,("Failed search for base: %s, error: %s " - "(%s)\n", base, ldap_err2string(rc), - ld_error ? ld_error : "unknown")); + DEBUG(10, ("Failed search for base: %s, error: %d (%s) " + "(%s)\n", base, ld_errno, + ldap_err2string(rc), + ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); + + if (ld_errno == LDAP_SERVER_DOWN) { + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + } } } @@ -1289,7 +1302,7 @@ int smbldap_search_paged(struct smbldap_state *ldap_state, /* construct cookie */ if (*cookie != NULL) { ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie); - ber_bvfree(*cookie); /* don't need it from last time */ + ber_bvfree((struct berval *)*cookie); /* don't need it from last time */ *cookie = NULL; } else { ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0); @@ -1370,12 +1383,23 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; + int ld_errno; + + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_NUMBER, &ld_errno); + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(10,("Failed to modify dn: %s, error: %s " - "(%s)\n", dn, ldap_err2string(rc), - ld_error ? ld_error : "unknown")); + DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) " + "(%s)\n", dn, ld_errno, + ldap_err2string(rc), + ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); + + if (ld_errno == LDAP_SERVER_DOWN) { + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + } } } @@ -1402,12 +1426,23 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; + int ld_errno; + + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_NUMBER, &ld_errno); + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(10,("Failed to add dn: %s, error: %s " - "(%s)\n", dn, ldap_err2string(rc), - ld_error ? ld_error : "unknown")); + DEBUG(10, ("Failed to add dn: %s, error: %d (%s) " + "(%s)\n", dn, ld_errno, + ldap_err2string(rc), + ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); + + if (ld_errno == LDAP_SERVER_DOWN) { + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + } } } @@ -1434,12 +1469,23 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; + int ld_errno; + + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_NUMBER, &ld_errno); + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(10,("Failed to delete dn: %s, error: %s " - "(%s)\n", dn, ldap_err2string(rc), - ld_error ? ld_error : "unknown")); + DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) " + "(%s)\n", dn, ld_errno, + ldap_err2string(rc), + ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); + + if (ld_errno == LDAP_SERVER_DOWN) { + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + } } } @@ -1465,12 +1511,23 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, clientctrls, retoidp, retdatap); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; + int ld_errno; + + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_NUMBER, &ld_errno); + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(10,("Extended operation failed with error: %s " - "(%s)\n", ldap_err2string(rc), - ld_error ? ld_error : "unknown")); + DEBUG(10, ("Extended operation failed with error: " + "%d (%s) (%s)\n", ld_errno, + ldap_err2string(rc), + ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); + + if (ld_errno == LDAP_SERVER_DOWN) { + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + } } } @@ -1703,3 +1760,24 @@ BOOL smbldap_has_naming_context(LDAP *ld, const char *naming_context) const char *attrs[] = { "namingContexts", NULL }; return smbldap_check_root_dse(ld, attrs, naming_context); } + +BOOL smbldap_set_creds(struct smbldap_state *ldap_state, BOOL anon, const char *dn, const char *secret) +{ + ldap_state->anonymous = anon; + + /* free any previously set credential */ + + SAFE_FREE(ldap_state->bind_dn); + if (ldap_state->bind_secret) { + /* make sure secrets are zeroed out of memory */ + memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret)); + SAFE_FREE(ldap_state->bind_secret); + } + + if ( ! anon) { + ldap_state->bind_dn = SMB_STRDUP(dn); + ldap_state->bind_secret = SMB_STRDUP(secret); + } + + return True; +} diff --git a/source/lib/socket_wrapper.c b/source/lib/socket_wrapper.c deleted file mode 100644 index e9c1404d113..00000000000 --- a/source/lib/socket_wrapper.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - Socket wrapper library. Passes all socket communication over - unix domain sockets if the environment variable SOCKET_WRAPPER_DIR - is set. - Copyright (C) Jelmer Vernooij 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#ifdef _PUBLIC_ -#undef _PUBLIC_ -#endif -#define _PUBLIC_ - -#ifdef SOCKET_WRAPPER_REPLACE -#undef accept -#undef connect -#undef bind -#undef getpeername -#undef getsockname -#undef getsockopt -#undef setsockopt -#undef recvfrom -#undef sendto -#undef socket -#undef close -#endif - -/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support - * for now */ -#define REWRITE_CALLS - -#ifdef REWRITE_CALLS -#define real_accept accept -#define real_connect connect -#define real_bind bind -#define real_getpeername getpeername -#define real_getsockname getsockname -#define real_getsockopt getsockopt -#define real_setsockopt setsockopt -#define real_recvfrom recvfrom -#define real_sendto sendto -#define real_socket socket -#define real_close close -#endif - -#undef malloc -#undef calloc -#undef strdup -/* we need to use a very terse format here as IRIX 6.4 silently - truncates names to 16 chars, so if we use a longer name then we - can't tell which port a packet came from with recvfrom() - - with this format we have 8 chars left for the directory name -*/ -#define SOCKET_FORMAT "%c%02X%04X" -#define SOCKET_TYPE_CHAR_TCP 'T' -#define SOCKET_TYPE_CHAR_UDP 'U' - -static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) -{ - struct sockaddr *ret = (struct sockaddr *)malloc(len); - memcpy(ret, data, len); - return ret; -} - -struct socket_info -{ - int fd; - - int domain; - int type; - int protocol; - int bound; - int bcast; - - char *path; - char *tmp_path; - - struct sockaddr *myname; - socklen_t myname_len; - - struct sockaddr *peername; - socklen_t peername_len; - - struct socket_info *prev, *next; -}; - -static struct socket_info *sockets = NULL; - - -static const char *socket_wrapper_dir(void) -{ - const char *s = getenv("SOCKET_WRAPPER_DIR"); - if (s == NULL) { - return NULL; - } - if (strncmp(s, "./", 2) == 0) { - s += 2; - } - return s; -} - -static unsigned int socket_wrapper_default_iface(void) -{ - const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE"); - if (s) { - unsigned int iface; - if (sscanf(s, "%u", &iface) == 1) { - if (iface >= 1 && iface <= 0xFF) { - return iface; - } - } - } - - return 1;/* 127.0.0.1 */ -} - -static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) -{ - unsigned int iface; - unsigned int prt; - const char *p; - char type; - - if ((*len) < sizeof(struct sockaddr_in)) { - return 0; - } - - p = strrchr(un->sun_path, '/'); - if (p) p++; else p = un->sun_path; - - if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) { - errno = EINVAL; - return -1; - } - - if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) { - errno = EINVAL; - return -1; - } - - if (iface == 0 || iface > 0xFF) { - errno = EINVAL; - return -1; - } - - if (prt > 0xFFFF) { - errno = EINVAL; - return -1; - } - - in->sin_family = AF_INET; - in->sin_addr.s_addr = htonl((127<<24) | iface); - in->sin_port = htons(prt); - - *len = sizeof(struct sockaddr_in); - return 0; -} - -static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, - int *bcast) -{ - char u_type = '\0'; - char b_type = '\0'; - char a_type = '\0'; - char type = '\0'; - unsigned int addr= ntohl(in->sin_addr.s_addr); - unsigned int prt = ntohs(in->sin_port); - unsigned int iface; - int is_bcast = 0; - - if (bcast) *bcast = 0; - - if (prt == 0) { - errno = EINVAL; - return -1; - } - - switch (si->type) { - case SOCK_STREAM: - u_type = SOCKET_TYPE_CHAR_TCP; - break; - case SOCK_DGRAM: - u_type = SOCKET_TYPE_CHAR_UDP; - a_type = SOCKET_TYPE_CHAR_UDP; - b_type = SOCKET_TYPE_CHAR_UDP; - break; - } - - if (a_type && addr == 0xFFFFFFFF) { - /* 255.255.255.255 only udp */ - is_bcast = 2; - type = a_type; - iface = socket_wrapper_default_iface(); - } else if (b_type && addr == 0x7FFFFFFF) { - /* 127.255.255.255 only udp */ - is_bcast = 1; - type = b_type; - iface = socket_wrapper_default_iface(); - } else if ((addr & 0xFFFFFF00) == 0x7F000000) { - /* 127.0.0.X */ - is_bcast = 0; - type = u_type; - iface = (addr & 0x000000FF); - } else { - errno = ENETUNREACH; - return -1; - } - - if (bcast) *bcast = is_bcast; - - if (is_bcast) { - snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", - socket_wrapper_dir()); - /* the caller need to do more processing */ - return 0; - } - - snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, - socket_wrapper_dir(), type, iface, prt); - - return 0; -} - -static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, - int *bcast) -{ - char u_type = '\0'; - char d_type = '\0'; - char b_type = '\0'; - char a_type = '\0'; - char type = '\0'; - unsigned int addr= ntohl(in->sin_addr.s_addr); - unsigned int prt = ntohs(in->sin_port); - unsigned int iface; - struct stat st; - int is_bcast = 0; - - if (bcast) *bcast = 0; - - switch (si->type) { - case SOCK_STREAM: - u_type = SOCKET_TYPE_CHAR_TCP; - d_type = SOCKET_TYPE_CHAR_TCP; - break; - case SOCK_DGRAM: - u_type = SOCKET_TYPE_CHAR_UDP; - d_type = SOCKET_TYPE_CHAR_UDP; - a_type = SOCKET_TYPE_CHAR_UDP; - b_type = SOCKET_TYPE_CHAR_UDP; - break; - } - - if (addr == 0) { - /* 0.0.0.0 */ - is_bcast = 0; - type = d_type; - iface = socket_wrapper_default_iface(); - } else if (a_type && addr == 0xFFFFFFFF) { - /* 255.255.255.255 only udp */ - is_bcast = 2; - type = a_type; - iface = socket_wrapper_default_iface(); - } else if (b_type && addr == 0x7FFFFFFF) { - /* 127.255.255.255 only udp */ - is_bcast = 1; - type = b_type; - iface = socket_wrapper_default_iface(); - } else if ((addr & 0xFFFFFF00) == 0x7F000000) { - /* 127.0.0.X */ - is_bcast = 0; - type = u_type; - iface = (addr & 0x000000FF); - } else { - errno = EADDRNOTAVAIL; - return -1; - } - - if (bcast) *bcast = is_bcast; - - if (prt == 0) { - /* handle auto-allocation of ephemeral ports */ - for (prt = 5001; prt < 10000; prt++) { - snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, - socket_wrapper_dir(), type, iface, prt); - if (stat(un->sun_path, &st) == 0) continue; - - ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); - return 0; - } - errno = ENFILE; - return -1; - } - - snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, - socket_wrapper_dir(), type, iface, prt); - return 0; -} - -static struct socket_info *find_socket_info(int fd) -{ - struct socket_info *i; - for (i = sockets; i; i = i->next) { - if (i->fd == fd) - return i; - } - - return NULL; -} - -static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, - struct sockaddr_un *out_addr, int alloc_sock, int *bcast) -{ - if (!out_addr) - return 0; - - out_addr->sun_family = AF_UNIX; - - switch (in_addr->sa_family) { - case AF_INET: - switch (si->type) { - case SOCK_STREAM: - case SOCK_DGRAM: - break; - default: - errno = ESOCKTNOSUPPORT; - return -1; - } - if (alloc_sock) { - return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast); - } else { - return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast); - } - case AF_UNIX: - memcpy(out_addr, in_addr, sizeof(*out_addr)); - return 0; - default: - break; - } - - errno = EAFNOSUPPORT; - return -1; -} - -static int sockaddr_convert_from_un(const struct socket_info *si, - const struct sockaddr_un *in_addr, - socklen_t un_addrlen, - int family, - struct sockaddr *out_addr, - socklen_t *_out_addrlen) -{ - socklen_t out_addrlen; - - if (out_addr == NULL || _out_addrlen == NULL) - return 0; - - if (un_addrlen == 0) { - *_out_addrlen = 0; - return 0; - } - - out_addrlen = *_out_addrlen; - if (out_addrlen > un_addrlen) { - out_addrlen = un_addrlen; - } - - switch (family) { - case AF_INET: - switch (si->type) { - case SOCK_STREAM: - case SOCK_DGRAM: - break; - default: - errno = ESOCKTNOSUPPORT; - return -1; - } - return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen); - case AF_UNIX: - memcpy(out_addr, in_addr, out_addrlen); - *_out_addrlen = out_addrlen; - return 0; - default: - break; - } - - errno = EAFNOSUPPORT; - return -1; -} - -_PUBLIC_ int swrap_socket(int domain, int type, int protocol) -{ - struct socket_info *si; - int fd; - - if (!socket_wrapper_dir()) { - return real_socket(domain, type, protocol); - } - - fd = real_socket(AF_UNIX, type, 0); - - if (fd == -1) return -1; - - si = calloc(1, sizeof(struct socket_info)); - - si->domain = domain; - si->type = type; - si->protocol = protocol; - si->fd = fd; - - DLIST_ADD(sockets, si); - - return si->fd; -} - -_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - struct socket_info *parent_si, *child_si; - int fd; - struct sockaddr_un un_addr; - socklen_t un_addrlen = sizeof(un_addr); - struct sockaddr_un un_my_addr; - socklen_t un_my_addrlen = sizeof(un_my_addr); - struct sockaddr my_addr; - socklen_t my_addrlen = sizeof(my_addr); - int ret; - - parent_si = find_socket_info(s); - if (!parent_si) { - return real_accept(s, addr, addrlen); - } - - memset(&un_addr, 0, sizeof(un_addr)); - memset(&un_my_addr, 0, sizeof(un_my_addr)); - memset(&my_addr, 0, sizeof(my_addr)); - - ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret == -1) return ret; - - fd = ret; - - ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, - parent_si->domain, addr, addrlen); - if (ret == -1) return ret; - - child_si = malloc(sizeof(struct socket_info)); - memset(child_si, 0, sizeof(*child_si)); - - child_si->fd = fd; - child_si->domain = parent_si->domain; - child_si->type = parent_si->type; - child_si->protocol = parent_si->protocol; - child_si->bound = 1; - - ret = real_getsockname(fd, &un_my_addr, &un_my_addrlen); - if (ret == -1) return ret; - - ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, - child_si->domain, &my_addr, &my_addrlen); - if (ret == -1) return ret; - - child_si->myname_len = my_addrlen; - child_si->myname = sockaddr_dup(&my_addr, my_addrlen); - - child_si->peername_len = *addrlen; - child_si->peername = sockaddr_dup(addr, *addrlen); - - DLIST_ADD(sockets, child_si); - - return fd; -} - -/* using sendto() or connect() on an unbound socket would give the - recipient no way to reply, as unlike UDP and TCP, a unix domain - socket can't auto-assign emphemeral port numbers, so we need to - assign it here */ -static int swrap_auto_bind(struct socket_info *si) -{ - struct sockaddr_un un_addr; - struct sockaddr_in in; - int i; - char type; - int ret; - struct stat st; - - un_addr.sun_family = AF_UNIX; - - switch (si->type) { - case SOCK_STREAM: - type = SOCKET_TYPE_CHAR_TCP; - break; - case SOCK_DGRAM: - type = SOCKET_TYPE_CHAR_UDP; - break; - default: - errno = ESOCKTNOSUPPORT; - return -1; - } - - for (i=0;i<1000;i++) { - snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), - "%s/"SOCKET_FORMAT, socket_wrapper_dir(), - type, socket_wrapper_default_iface(), i + 10000); - if (stat(un_addr.sun_path, &st) == 0) continue; - - ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); - if (ret == -1) return ret; - - si->tmp_path = strdup(un_addr.sun_path); - si->bound = 1; - break; - } - if (i == 1000) { - errno = ENFILE; - return -1; - } - - memset(&in, 0, sizeof(in)); - in.sin_family = AF_INET; - in.sin_port = htons(i); - in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface()); - - si->myname_len = sizeof(in); - si->myname = sockaddr_dup(&in, si->myname_len); - si->bound = 1; - return 0; -} - - -_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) -{ - int ret; - struct sockaddr_un un_addr; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_connect(s, serv_addr, addrlen); - } - - if (si->bound == 0 && si->domain != AF_UNIX) { - ret = swrap_auto_bind(si); - if (ret == -1) return -1; - } - - ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); - if (ret == -1) return -1; - - ret = real_connect(s, (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); - - /* to give better errors */ - if (serv_addr->sa_family == AF_INET) { - if (ret == -1 && errno == ENOENT) { - errno = EHOSTUNREACH; - } - } - - if (ret == 0) { - si->peername_len = addrlen; - si->peername = sockaddr_dup(serv_addr, addrlen); - } - - return ret; -} - -_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) -{ - int ret; - struct sockaddr_un un_addr; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_bind(s, myaddr, addrlen); - } - - si->myname_len = addrlen; - si->myname = sockaddr_dup(myaddr, addrlen); - - ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast); - if (ret == -1) return -1; - - unlink(un_addr.sun_path); - - ret = real_bind(s, (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); - - if (ret == 0) { - si->bound = 1; - } - - return ret; -} - -_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getpeername(s, name, addrlen); - } - - if (!si->peername) - { - errno = ENOTCONN; - return -1; - } - - memcpy(name, si->peername, si->peername_len); - *addrlen = si->peername_len; - - return 0; -} - -_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getsockname(s, name, addrlen); - } - - memcpy(name, si->myname, si->myname_len); - *addrlen = si->myname_len; - - return 0; -} - -_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getsockopt(s, level, optname, optval, optlen); - } - - if (level == SOL_SOCKET) { - return real_getsockopt(s, level, optname, optval, optlen); - } - - switch (si->domain) { - case AF_UNIX: - return real_getsockopt(s, level, optname, optval, optlen); - default: - errno = ENOPROTOOPT; - return -1; - } -} - -_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_setsockopt(s, level, optname, optval, optlen); - } - - if (level == SOL_SOCKET) { - return real_setsockopt(s, level, optname, optval, optlen); - } - - switch (si->domain) { - case AF_UNIX: - return real_setsockopt(s, level, optname, optval, optlen); - case AF_INET: - /* Silence some warnings */ -#ifdef TCP_NODELAY - if (optname == TCP_NODELAY) - return 0; -#endif - default: - errno = ENOPROTOOPT; - return -1; - } -} - -_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) -{ - struct sockaddr_un un_addr; - socklen_t un_addrlen = sizeof(un_addr); - int ret; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_recvfrom(s, buf, len, flags, from, fromlen); - } - - /* irix 6.4 forgets to null terminate the sun_path string :-( */ - memset(&un_addr, 0, sizeof(un_addr)); - ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret == -1) - return ret; - - if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, - si->domain, from, fromlen) == -1) { - return -1; - } - - return ret; -} - - -_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) -{ - struct sockaddr_un un_addr; - int ret; - struct socket_info *si = find_socket_info(s); - int bcast = 0; - - if (!si) { - return real_sendto(s, buf, len, flags, to, tolen); - } - - if (si->bound == 0 && si->domain != AF_UNIX) { - ret = swrap_auto_bind(si); - if (ret == -1) return -1; - } - - ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast); - if (ret == -1) return -1; - - if (bcast) { - struct stat st; - unsigned int iface; - unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); - char type; - - type = SOCKET_TYPE_CHAR_UDP; - - for(iface=0; iface <= 0xFF; iface++) { - snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, - socket_wrapper_dir(), type, iface, prt); - if (stat(un_addr.sun_path, &st) != 0) continue; - - /* ignore the any errors in broadcast sends */ - real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); - } - return len; - } - - ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); - - /* to give better errors */ - if (to->sa_family == AF_INET) { - if (ret == -1 && errno == ENOENT) { - errno = EHOSTUNREACH; - } - } - - return ret; -} - -_PUBLIC_ int swrap_close(int fd) -{ - struct socket_info *si = find_socket_info(fd); - - if (si) { - DLIST_REMOVE(sockets, si); - - free(si->path); - free(si->myname); - free(si->peername); - if (si->tmp_path) { - unlink(si->tmp_path); - free(si->tmp_path); - } - free(si); - } - - return real_close(fd); -} diff --git a/source/lib/socket_wrapper/config.m4 b/source/lib/socket_wrapper/config.m4 new file mode 100644 index 00000000000..42212abc7fc --- /dev/null +++ b/source/lib/socket_wrapper/config.m4 @@ -0,0 +1,22 @@ +AC_ARG_ENABLE(socket-wrapper, +[ --enable-socket-wrapper Turn on socket wrapper library (default=no)]) + +DEFAULT_TEST_TARGET=test-noswrap +HAVE_SOCKET_WRAPPER=no + +if eval "test x$developer = xyes"; then + enable_socket_wrapper=yes +fi + +if eval "test x$enable_socket_wrapper = xyes"; then + AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library]) + DEFAULT_TEST_TARGET=test-swrap + HAVE_SOCKET_WRAPPER=yes + + # this is only used for samba3 + SOCKET_WRAPPER_OBJS="lib/socket_wrapper/socket_wrapper.o" +fi + +AC_SUBST(DEFAULT_TEST_TARGET) +AC_SUBST(HAVE_SOCKET_WRAPPER) +AC_SUBST(SOCKET_WRAPPER_OBJS) diff --git a/source/lib/socket_wrapper/socket_wrapper.c b/source/lib/socket_wrapper/socket_wrapper.c new file mode 100644 index 00000000000..3a72c5a74a0 --- /dev/null +++ b/source/lib/socket_wrapper/socket_wrapper.c @@ -0,0 +1,1596 @@ +/* + * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org> + * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + Socket wrapper library. Passes all socket communication over + unix domain sockets if the environment variable SOCKET_WRAPPER_DIR + is set. +*/ + +#ifdef _SAMBA_BUILD_ + +#define SOCKET_WRAPPER_NOT_REPLACE +#include "includes.h" +#include "system/network.h" +#include "system/filesys.h" + +#ifdef malloc +#undef malloc +#endif +#ifdef calloc +#undef calloc +#endif +#ifdef strdup +#undef strdup +#endif + +#else /* _SAMBA_BUILD_ */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#define _PUBLIC_ + +#endif + +#define SWRAP_DLIST_ADD(list,item) do { \ + if (!(list)) { \ + (item)->prev = NULL; \ + (item)->next = NULL; \ + (list) = (item); \ + } else { \ + (item)->prev = NULL; \ + (item)->next = (list); \ + (list)->prev = (item); \ + (list) = (item); \ + } \ +} while (0) + +#define SWRAP_DLIST_REMOVE(list,item) do { \ + if ((list) == (item)) { \ + (list) = (item)->next; \ + if (list) { \ + (list)->prev = NULL; \ + } \ + } else { \ + if ((item)->prev) { \ + (item)->prev->next = (item)->next; \ + } \ + if ((item)->next) { \ + (item)->next->prev = (item)->prev; \ + } \ + } \ + (item)->prev = NULL; \ + (item)->next = NULL; \ +} while (0) + +/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support + * for now */ +#define REWRITE_CALLS + +#ifdef REWRITE_CALLS +#define real_accept accept +#define real_connect connect +#define real_bind bind +#define real_listen listen +#define real_getpeername getpeername +#define real_getsockname getsockname +#define real_getsockopt getsockopt +#define real_setsockopt setsockopt +#define real_recvfrom recvfrom +#define real_sendto sendto +#define real_ioctl ioctl +#define real_recv recv +#define real_send send +#define real_socket socket +#define real_close close +#endif + +#ifdef HAVE_GETTIMEOFDAY_TZ +#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL) +#else +#define swrapGetTimeOfDay(tval) gettimeofday(tval) +#endif + +/* we need to use a very terse format here as IRIX 6.4 silently + truncates names to 16 chars, so if we use a longer name then we + can't tell which port a packet came from with recvfrom() + + with this format we have 8 chars left for the directory name +*/ +#define SOCKET_FORMAT "%c%02X%04X" +#define SOCKET_TYPE_CHAR_TCP 'T' +#define SOCKET_TYPE_CHAR_UDP 'U' + +#define MAX_WRAPPED_INTERFACES 16 + +static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) +{ + struct sockaddr *ret = (struct sockaddr *)malloc(len); + memcpy(ret, data, len); + return ret; +} + +struct socket_info +{ + int fd; + + int family; + int type; + int protocol; + int bound; + int bcast; + int is_server; + + char *path; + char *tmp_path; + + struct sockaddr *myname; + socklen_t myname_len; + + struct sockaddr *peername; + socklen_t peername_len; + + struct { + unsigned long pck_snd; + unsigned long pck_rcv; + } io; + + struct socket_info *prev, *next; +}; + +static struct socket_info *sockets; + + +static const char *socket_wrapper_dir(void) +{ + const char *s = getenv("SOCKET_WRAPPER_DIR"); + if (s == NULL) { + return NULL; + } + if (strncmp(s, "./", 2) == 0) { + s += 2; + } + return s; +} + +static unsigned int socket_wrapper_default_iface(void) +{ + const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE"); + if (s) { + unsigned int iface; + if (sscanf(s, "%u", &iface) == 1) { + if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) { + return iface; + } + } + } + + return 1;/* 127.0.0.1 */ +} + +static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) +{ + unsigned int iface; + unsigned int prt; + const char *p; + char type; + + if ((*len) < sizeof(struct sockaddr_in)) { + return 0; + } + + p = strrchr(un->sun_path, '/'); + if (p) p++; else p = un->sun_path; + + if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) { + errno = EINVAL; + return -1; + } + + if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) { + errno = EINVAL; + return -1; + } + + if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) { + errno = EINVAL; + return -1; + } + + if (prt > 0xFFFF) { + errno = EINVAL; + return -1; + } + + in->sin_family = AF_INET; + in->sin_addr.s_addr = htonl((127<<24) | iface); + in->sin_port = htons(prt); + + *len = sizeof(struct sockaddr_in); + return 0; +} + +static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, + int *bcast) +{ + char u_type = '\0'; + char b_type = '\0'; + char a_type = '\0'; + char type = '\0'; + unsigned int addr= ntohl(in->sin_addr.s_addr); + unsigned int prt = ntohs(in->sin_port); + unsigned int iface; + int is_bcast = 0; + + if (bcast) *bcast = 0; + + if (prt == 0) { + errno = EINVAL; + return -1; + } + + switch (si->type) { + case SOCK_STREAM: + u_type = SOCKET_TYPE_CHAR_TCP; + break; + case SOCK_DGRAM: + u_type = SOCKET_TYPE_CHAR_UDP; + a_type = SOCKET_TYPE_CHAR_UDP; + b_type = SOCKET_TYPE_CHAR_UDP; + break; + } + + if (a_type && addr == 0xFFFFFFFF) { + /* 255.255.255.255 only udp */ + is_bcast = 2; + type = a_type; + iface = socket_wrapper_default_iface(); + } else if (b_type && addr == 0x7FFFFFFF) { + /* 127.255.255.255 only udp */ + is_bcast = 1; + type = b_type; + iface = socket_wrapper_default_iface(); + } else if ((addr & 0xFFFFFF00) == 0x7F000000) { + /* 127.0.0.X */ + is_bcast = 0; + type = u_type; + iface = (addr & 0x000000FF); + } else { + errno = ENETUNREACH; + return -1; + } + + if (bcast) *bcast = is_bcast; + + if (is_bcast) { + snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", + socket_wrapper_dir()); + /* the caller need to do more processing */ + return 0; + } + + snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, + socket_wrapper_dir(), type, iface, prt); + + return 0; +} + +static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, + int *bcast) +{ + char u_type = '\0'; + char d_type = '\0'; + char b_type = '\0'; + char a_type = '\0'; + char type = '\0'; + unsigned int addr= ntohl(in->sin_addr.s_addr); + unsigned int prt = ntohs(in->sin_port); + unsigned int iface; + struct stat st; + int is_bcast = 0; + + if (bcast) *bcast = 0; + + switch (si->type) { + case SOCK_STREAM: + u_type = SOCKET_TYPE_CHAR_TCP; + d_type = SOCKET_TYPE_CHAR_TCP; + break; + case SOCK_DGRAM: + u_type = SOCKET_TYPE_CHAR_UDP; + d_type = SOCKET_TYPE_CHAR_UDP; + a_type = SOCKET_TYPE_CHAR_UDP; + b_type = SOCKET_TYPE_CHAR_UDP; + break; + } + + if (addr == 0) { + /* 0.0.0.0 */ + is_bcast = 0; + type = d_type; + iface = socket_wrapper_default_iface(); + } else if (a_type && addr == 0xFFFFFFFF) { + /* 255.255.255.255 only udp */ + is_bcast = 2; + type = a_type; + iface = socket_wrapper_default_iface(); + } else if (b_type && addr == 0x7FFFFFFF) { + /* 127.255.255.255 only udp */ + is_bcast = 1; + type = b_type; + iface = socket_wrapper_default_iface(); + } else if ((addr & 0xFFFFFF00) == 0x7F000000) { + /* 127.0.0.X */ + is_bcast = 0; + type = u_type; + iface = (addr & 0x000000FF); + } else { + errno = EADDRNOTAVAIL; + return -1; + } + + if (bcast) *bcast = is_bcast; + + if (prt == 0) { + /* handle auto-allocation of ephemeral ports */ + for (prt = 5001; prt < 10000; prt++) { + snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, + socket_wrapper_dir(), type, iface, prt); + if (stat(un->sun_path, &st) == 0) continue; + + ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); + return 0; + } + errno = ENFILE; + return -1; + } + + snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, + socket_wrapper_dir(), type, iface, prt); + return 0; +} + +static struct socket_info *find_socket_info(int fd) +{ + struct socket_info *i; + for (i = sockets; i; i = i->next) { + if (i->fd == fd) + return i; + } + + return NULL; +} + +static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, + struct sockaddr_un *out_addr, int alloc_sock, int *bcast) +{ + if (!out_addr) + return 0; + + out_addr->sun_family = AF_UNIX; + + switch (in_addr->sa_family) { + case AF_INET: + switch (si->type) { + case SOCK_STREAM: + case SOCK_DGRAM: + break; + default: + errno = ESOCKTNOSUPPORT; + return -1; + } + if (alloc_sock) { + return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast); + } else { + return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast); + } + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +static int sockaddr_convert_from_un(const struct socket_info *si, + const struct sockaddr_un *in_addr, + socklen_t un_addrlen, + int family, + struct sockaddr *out_addr, + socklen_t *_out_addrlen) +{ + socklen_t out_addrlen; + + if (out_addr == NULL || _out_addrlen == NULL) + return 0; + + if (un_addrlen == 0) { + *_out_addrlen = 0; + return 0; + } + + out_addrlen = *_out_addrlen; + if (out_addrlen > un_addrlen) { + out_addrlen = un_addrlen; + } + + switch (family) { + case AF_INET: + switch (si->type) { + case SOCK_STREAM: + case SOCK_DGRAM: + break; + default: + errno = ESOCKTNOSUPPORT; + return -1; + } + return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen); + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +enum swrap_packet_type { + SWRAP_CONNECT_SEND, + SWRAP_CONNECT_UNREACH, + SWRAP_CONNECT_RECV, + SWRAP_CONNECT_ACK, + SWRAP_ACCEPT_SEND, + SWRAP_ACCEPT_RECV, + SWRAP_ACCEPT_ACK, + SWRAP_RECVFROM, + SWRAP_SENDTO, + SWRAP_SENDTO_UNREACH, + SWRAP_PENDING_RST, + SWRAP_RECV, + SWRAP_RECV_RST, + SWRAP_SEND, + SWRAP_SEND_RST, + SWRAP_CLOSE_SEND, + SWRAP_CLOSE_RECV, + SWRAP_CLOSE_ACK +}; + +struct swrap_file_hdr { + unsigned long magic; + unsigned short version_major; + unsigned short version_minor; + long timezone; + unsigned long sigfigs; + unsigned long frame_max_len; +#define SWRAP_FRAME_LENGTH_MAX 0xFFFF + unsigned long link_type; +}; +#define SWRAP_FILE_HDR_SIZE 24 + +struct swrap_packet { + struct { + unsigned long seconds; + unsigned long micro_seconds; + unsigned long recorded_length; + unsigned long full_length; + } frame; +#define SWRAP_PACKET__FRAME_SIZE 16 + + struct { + struct { + unsigned char ver_hdrlen; + unsigned char tos; + unsigned short packet_length; + unsigned short identification; + unsigned char flags; + unsigned char fragment; + unsigned char ttl; + unsigned char protocol; + unsigned short hdr_checksum; + unsigned long src_addr; + unsigned long dest_addr; + } hdr; +#define SWRAP_PACKET__IP_HDR_SIZE 20 + + union { + struct { + unsigned short source_port; + unsigned short dest_port; + unsigned long seq_num; + unsigned long ack_num; + unsigned char hdr_length; + unsigned char control; + unsigned short window; + unsigned short checksum; + unsigned short urg; + } tcp; +#define SWRAP_PACKET__IP_P_TCP_SIZE 20 + struct { + unsigned short source_port; + unsigned short dest_port; + unsigned short length; + unsigned short checksum; + } udp; +#define SWRAP_PACKET__IP_P_UDP_SIZE 8 + struct { + unsigned char type; + unsigned char code; + unsigned short checksum; + unsigned long unused; + } icmp; +#define SWRAP_PACKET__IP_P_ICMP_SIZE 8 + } p; + } ip; +}; +#define SWRAP_PACKET_SIZE 56 + +static const char *socket_wrapper_pcap_file(void) +{ + static int initialized = 0; + static const char *s = NULL; + static const struct swrap_file_hdr h; + static const struct swrap_packet p; + + if (initialized == 1) { + return s; + } + initialized = 1; + + /* + * TODO: don't use the structs use plain buffer offsets + * and PUSH_U8(), PUSH_U16() and PUSH_U32() + * + * for now make sure we disable PCAP support + * if the struct has alignment! + */ + if (sizeof(h) != SWRAP_FILE_HDR_SIZE) { + return NULL; + } + if (sizeof(p) != SWRAP_PACKET_SIZE) { + return NULL; + } + if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) { + return NULL; + } + if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) { + return NULL; + } + if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) { + return NULL; + } + if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) { + return NULL; + } + if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) { + return NULL; + } + + s = getenv("SOCKET_WRAPPER_PCAP_FILE"); + if (s == NULL) { + return NULL; + } + if (strncmp(s, "./", 2) == 0) { + s += 2; + } + return s; +} + +static struct swrap_packet *swrap_packet_init(struct timeval *tval, + const struct sockaddr_in *src_addr, + const struct sockaddr_in *dest_addr, + int socket_type, + const unsigned char *payload, + size_t payload_len, + unsigned long tcp_seq, + unsigned long tcp_ack, + unsigned char tcp_ctl, + int unreachable, + size_t *_packet_len) +{ + struct swrap_packet *ret; + struct swrap_packet *packet; + size_t packet_len; + size_t alloc_len; + size_t nonwire_len = sizeof(packet->frame); + size_t wire_hdr_len = 0; + size_t wire_len = 0; + size_t icmp_hdr_len = 0; + size_t icmp_truncate_len = 0; + unsigned char protocol = 0, icmp_protocol = 0; + unsigned short src_port = src_addr->sin_port; + unsigned short dest_port = dest_addr->sin_port; + + switch (socket_type) { + case SOCK_STREAM: + protocol = 0x06; /* TCP */ + wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp); + wire_len = wire_hdr_len + payload_len; + break; + + case SOCK_DGRAM: + protocol = 0x11; /* UDP */ + wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp); + wire_len = wire_hdr_len + payload_len; + break; + } + + if (unreachable) { + icmp_protocol = protocol; + protocol = 0x01; /* ICMP */ + if (wire_len > 64 ) { + icmp_truncate_len = wire_len - 64; + } + icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp); + wire_hdr_len += icmp_hdr_len; + wire_len += icmp_hdr_len; + } + + packet_len = nonwire_len + wire_len; + alloc_len = packet_len; + if (alloc_len < sizeof(struct swrap_packet)) { + alloc_len = sizeof(struct swrap_packet); + } + ret = (struct swrap_packet *)malloc(alloc_len); + if (!ret) return NULL; + + packet = ret; + + packet->frame.seconds = tval->tv_sec; + packet->frame.micro_seconds = tval->tv_usec; + packet->frame.recorded_length = wire_len - icmp_truncate_len; + packet->frame.full_length = wire_len - icmp_truncate_len; + + packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ + packet->ip.hdr.tos = 0x00; + packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len); + packet->ip.hdr.identification = htons(0xFFFF); + packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ + packet->ip.hdr.fragment = htons(0x0000); + packet->ip.hdr.ttl = 0xFF; + packet->ip.hdr.protocol = protocol; + packet->ip.hdr.hdr_checksum = htons(0x0000); + packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr; + packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr; + + if (unreachable) { + packet->ip.p.icmp.type = 0x03; /* destination unreachable */ + packet->ip.p.icmp.code = 0x01; /* host unreachable */ + packet->ip.p.icmp.checksum = htons(0x0000); + packet->ip.p.icmp.unused = htonl(0x00000000); + + /* set the ip header in the ICMP payload */ + packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len); + packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ + packet->ip.hdr.tos = 0x00; + packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len); + packet->ip.hdr.identification = htons(0xFFFF); + packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ + packet->ip.hdr.fragment = htons(0x0000); + packet->ip.hdr.ttl = 0xFF; + packet->ip.hdr.protocol = icmp_protocol; + packet->ip.hdr.hdr_checksum = htons(0x0000); + packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr; + packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr; + + src_port = dest_addr->sin_port; + dest_port = src_addr->sin_port; + } + + switch (socket_type) { + case SOCK_STREAM: + packet->ip.p.tcp.source_port = src_port; + packet->ip.p.tcp.dest_port = dest_port; + packet->ip.p.tcp.seq_num = htonl(tcp_seq); + packet->ip.p.tcp.ack_num = htonl(tcp_ack); + packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */ + packet->ip.p.tcp.control = tcp_ctl; + packet->ip.p.tcp.window = htons(0x7FFF); + packet->ip.p.tcp.checksum = htons(0x0000); + packet->ip.p.tcp.urg = htons(0x0000); + + break; + + case SOCK_DGRAM: + packet->ip.p.udp.source_port = src_addr->sin_port; + packet->ip.p.udp.dest_port = dest_addr->sin_port; + packet->ip.p.udp.length = htons(8 + payload_len); + packet->ip.p.udp.checksum = htons(0x0000); + + break; + } + + if (payload && payload_len > 0) { + unsigned char *p = (unsigned char *)ret; + p += nonwire_len; + p += wire_hdr_len; + memcpy(p, payload, payload_len); + } + + *_packet_len = packet_len - icmp_truncate_len; + return ret; +} + +static int swrap_get_pcap_fd(const char *fname) +{ + static int fd = -1; + + if (fd != -1) return fd; + + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644); + if (fd != -1) { + struct swrap_file_hdr file_hdr; + file_hdr.magic = 0xA1B2C3D4; + file_hdr.version_major = 0x0002; + file_hdr.version_minor = 0x0004; + file_hdr.timezone = 0x00000000; + file_hdr.sigfigs = 0x00000000; + file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX; + file_hdr.link_type = 0x0065; /* 101 RAW IP */ + + write(fd, &file_hdr, sizeof(file_hdr)); + return fd; + } + + fd = open(fname, O_WRONLY|O_APPEND, 0644); + + return fd; +} + +static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr, + enum swrap_packet_type type, + const void *buf, size_t len) +{ + const struct sockaddr_in *src_addr; + const struct sockaddr_in *dest_addr; + const char *file_name; + unsigned long tcp_seq = 0; + unsigned long tcp_ack = 0; + unsigned char tcp_ctl = 0; + int unreachable = 0; + struct timeval tv; + struct swrap_packet *packet; + size_t packet_len = 0; + int fd; + + file_name = socket_wrapper_pcap_file(); + if (!file_name) { + return; + } + + if (si->family != AF_INET) { + return; + } + + switch (type) { + case SWRAP_CONNECT_SEND: + if (si->type != SOCK_STREAM) return; + + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x02; /* SYN */ + + si->io.pck_snd += 1; + + break; + + case SWRAP_CONNECT_RECV: + if (si->type != SOCK_STREAM) return; + + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x12; /** SYN,ACK */ + + si->io.pck_rcv += 1; + + break; + + case SWRAP_CONNECT_UNREACH: + if (si->type != SOCK_STREAM) return; + + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + /* Unreachable: resend the data of SWRAP_CONNECT_SEND */ + tcp_seq = si->io.pck_snd - 1; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x02; /* SYN */ + unreachable = 1; + + break; + + case SWRAP_CONNECT_ACK: + if (si->type != SOCK_STREAM) return; + + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x10; /* ACK */ + + break; + + case SWRAP_ACCEPT_SEND: + if (si->type != SOCK_STREAM) return; + + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x02; /* SYN */ + + si->io.pck_rcv += 1; + + break; + + case SWRAP_ACCEPT_RECV: + if (si->type != SOCK_STREAM) return; + + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x12; /* SYN,ACK */ + + si->io.pck_snd += 1; + + break; + + case SWRAP_ACCEPT_ACK: + if (si->type != SOCK_STREAM) return; + + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x10; /* ACK */ + + break; + + case SWRAP_SEND: + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)si->peername; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x18; /* PSH,ACK */ + + si->io.pck_snd += len; + + break; + + case SWRAP_SEND_RST: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)si->peername; + + if (si->type == SOCK_DGRAM) { + swrap_dump_packet(si, si->peername, + SWRAP_SENDTO_UNREACH, + buf, len); + return; + } + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x14; /** RST,ACK */ + + break; + + case SWRAP_PENDING_RST: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)si->peername; + + if (si->type == SOCK_DGRAM) { + return; + } + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x14; /* RST,ACK */ + + break; + + case SWRAP_RECV: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)si->peername; + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x18; /* PSH,ACK */ + + si->io.pck_rcv += len; + + break; + + case SWRAP_RECV_RST: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)si->peername; + + if (si->type == SOCK_DGRAM) { + return; + } + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x14; /* RST,ACK */ + + break; + + case SWRAP_SENDTO: + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)addr; + + si->io.pck_snd += len; + + break; + + case SWRAP_SENDTO_UNREACH: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + unreachable = 1; + + break; + + case SWRAP_RECVFROM: + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)addr; + + si->io.pck_rcv += len; + + break; + + case SWRAP_CLOSE_SEND: + if (si->type != SOCK_STREAM) return; + + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)si->peername; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x11; /* FIN, ACK */ + + si->io.pck_snd += 1; + + break; + + case SWRAP_CLOSE_RECV: + if (si->type != SOCK_STREAM) return; + + dest_addr = (const struct sockaddr_in *)si->myname; + src_addr = (const struct sockaddr_in *)si->peername; + + tcp_seq = si->io.pck_rcv; + tcp_ack = si->io.pck_snd; + tcp_ctl = 0x11; /* FIN,ACK */ + + si->io.pck_rcv += 1; + + break; + + case SWRAP_CLOSE_ACK: + if (si->type != SOCK_STREAM) return; + + src_addr = (const struct sockaddr_in *)si->myname; + dest_addr = (const struct sockaddr_in *)si->peername; + + tcp_seq = si->io.pck_snd; + tcp_ack = si->io.pck_rcv; + tcp_ctl = 0x10; /* ACK */ + + break; + default: + return; + } + + swrapGetTimeOfDay(&tv); + + packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type, + (const unsigned char *)buf, len, + tcp_seq, tcp_ack, tcp_ctl, unreachable, + &packet_len); + if (!packet) { + return; + } + + fd = swrap_get_pcap_fd(file_name); + if (fd != -1) { + write(fd, packet, packet_len); + } + + free(packet); +} + +_PUBLIC_ int swrap_socket(int family, int type, int protocol) +{ + struct socket_info *si; + int fd; + + if (!socket_wrapper_dir()) { + return real_socket(family, type, protocol); + } + + switch (family) { + case AF_INET: + break; + case AF_UNIX: + return real_socket(family, type, protocol); + default: + errno = EAFNOSUPPORT; + return -1; + } + + switch (type) { + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + errno = EPROTONOSUPPORT; + return -1; + } + + switch (protocol) { + case 0: + break; + default: + errno = EPROTONOSUPPORT; + return -1; + } + + fd = real_socket(AF_UNIX, type, 0); + + if (fd == -1) return -1; + + si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); + + si->family = family; + si->type = type; + si->protocol = protocol; + si->fd = fd; + + SWRAP_DLIST_ADD(sockets, si); + + return si->fd; +} + +_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct socket_info *parent_si, *child_si; + int fd; + struct sockaddr_un un_addr; + socklen_t un_addrlen = sizeof(un_addr); + struct sockaddr_un un_my_addr; + socklen_t un_my_addrlen = sizeof(un_my_addr); + struct sockaddr my_addr; + socklen_t my_addrlen = sizeof(my_addr); + int ret; + + parent_si = find_socket_info(s); + if (!parent_si) { + return real_accept(s, addr, addrlen); + } + + memset(&un_addr, 0, sizeof(un_addr)); + memset(&un_my_addr, 0, sizeof(un_my_addr)); + memset(&my_addr, 0, sizeof(my_addr)); + + ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret == -1) return ret; + + fd = ret; + + ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, + parent_si->family, addr, addrlen); + if (ret == -1) { + close(fd); + return ret; + } + + child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); + memset(child_si, 0, sizeof(*child_si)); + + child_si->fd = fd; + child_si->family = parent_si->family; + child_si->type = parent_si->type; + child_si->protocol = parent_si->protocol; + child_si->bound = 1; + child_si->is_server = 1; + + ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); + if (ret == -1) { + free(child_si); + close(fd); + return ret; + } + + ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, + child_si->family, &my_addr, &my_addrlen); + if (ret == -1) { + free(child_si); + close(fd); + return ret; + } + + child_si->myname_len = my_addrlen; + child_si->myname = sockaddr_dup(&my_addr, my_addrlen); + + child_si->peername_len = *addrlen; + child_si->peername = sockaddr_dup(addr, *addrlen); + + SWRAP_DLIST_ADD(sockets, child_si); + + swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0); + swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0); + swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0); + + return fd; +} + +static int autobind_start_init; +static int autobind_start; + +/* using sendto() or connect() on an unbound socket would give the + recipient no way to reply, as unlike UDP and TCP, a unix domain + socket can't auto-assign emphemeral port numbers, so we need to + assign it here */ +static int swrap_auto_bind(struct socket_info *si) +{ + struct sockaddr_un un_addr; + struct sockaddr_in in; + int i; + char type; + int ret; + int port; + struct stat st; + + if (autobind_start_init != 1) { + autobind_start_init = 1; + autobind_start = getpid(); + autobind_start %= 50000; + autobind_start += 10000; + } + + un_addr.sun_family = AF_UNIX; + + switch (si->type) { + case SOCK_STREAM: + type = SOCKET_TYPE_CHAR_TCP; + break; + case SOCK_DGRAM: + type = SOCKET_TYPE_CHAR_UDP; + break; + default: + errno = ESOCKTNOSUPPORT; + return -1; + } + + if (autobind_start > 60000) { + autobind_start = 10000; + } + + for (i=0;i<1000;i++) { + port = autobind_start + i; + snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), + "%s/"SOCKET_FORMAT, socket_wrapper_dir(), + type, socket_wrapper_default_iface(), port); + if (stat(un_addr.sun_path, &st) == 0) continue; + + ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); + if (ret == -1) return ret; + + si->tmp_path = strdup(un_addr.sun_path); + si->bound = 1; + autobind_start = port + 1; + break; + } + if (i == 1000) { + errno = ENFILE; + return -1; + } + + memset(&in, 0, sizeof(in)); + in.sin_family = AF_INET; + in.sin_port = htons(port); + in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface()); + + si->myname_len = sizeof(in); + si->myname = sockaddr_dup(&in, si->myname_len); + return 0; +} + + +_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_connect(s, serv_addr, addrlen); + } + + if (si->bound == 0) { + ret = swrap_auto_bind(si); + if (ret == -1) return -1; + } + + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); + if (ret == -1) return -1; + + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); + + ret = real_connect(s, (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + /* to give better errors */ + if (ret == -1 && errno == ENOENT) { + errno = EHOSTUNREACH; + } + + if (ret == 0) { + si->peername_len = addrlen; + si->peername = sockaddr_dup(serv_addr, addrlen); + + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0); + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0); + } else { + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0); + } + + return ret; +} + +_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_bind(s, myaddr, addrlen); + } + + si->myname_len = addrlen; + si->myname = sockaddr_dup(myaddr, addrlen); + + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast); + if (ret == -1) return -1; + + unlink(un_addr.sun_path); + + ret = real_bind(s, (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + if (ret == 0) { + si->bound = 1; + } + + return ret; +} + +_PUBLIC_ int swrap_listen(int s, int backlog) +{ + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_listen(s, backlog); + } + + ret = real_listen(s, backlog); + + return ret; +} + +_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getpeername(s, name, addrlen); + } + + if (!si->peername) + { + errno = ENOTCONN; + return -1; + } + + memcpy(name, si->peername, si->peername_len); + *addrlen = si->peername_len; + + return 0; +} + +_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getsockname(s, name, addrlen); + } + + memcpy(name, si->myname, si->myname_len); + *addrlen = si->myname_len; + + return 0; +} + +_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getsockopt(s, level, optname, optval, optlen); + } + + if (level == SOL_SOCKET) { + return real_getsockopt(s, level, optname, optval, optlen); + } + + errno = ENOPROTOOPT; + return -1; +} + +_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_setsockopt(s, level, optname, optval, optlen); + } + + if (level == SOL_SOCKET) { + return real_setsockopt(s, level, optname, optval, optlen); + } + + switch (si->family) { + case AF_INET: + return 0; + default: + errno = ENOPROTOOPT; + return -1; + } +} + +_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) +{ + struct sockaddr_un un_addr; + socklen_t un_addrlen = sizeof(un_addr); + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_recvfrom(s, buf, len, flags, from, fromlen); + } + + /* irix 6.4 forgets to null terminate the sun_path string :-( */ + memset(&un_addr, 0, sizeof(un_addr)); + ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret == -1) + return ret; + + if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, + si->family, from, fromlen) == -1) { + return -1; + } + + swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret); + + return ret; +} + + +_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +{ + struct sockaddr_un un_addr; + int ret; + struct socket_info *si = find_socket_info(s); + int bcast = 0; + + if (!si) { + return real_sendto(s, buf, len, flags, to, tolen); + } + + if (si->bound == 0) { + ret = swrap_auto_bind(si); + if (ret == -1) return -1; + } + + ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast); + if (ret == -1) return -1; + + if (bcast) { + struct stat st; + unsigned int iface; + unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); + char type; + + type = SOCKET_TYPE_CHAR_UDP; + + for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { + snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, + socket_wrapper_dir(), type, iface, prt); + if (stat(un_addr.sun_path, &st) != 0) continue; + + /* ignore the any errors in broadcast sends */ + real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); + } + + swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); + + return len; + } + + ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); + + /* to give better errors */ + if (ret == -1 && errno == ENOENT) { + errno = EHOSTUNREACH; + } + + if (ret == -1) { + swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); + swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len); + } else { + swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret); + } + + return ret; +} + +_PUBLIC_ int swrap_ioctl(int s, int r, void *p) +{ + int ret; + struct socket_info *si = find_socket_info(s); + int value; + + if (!si) { + return real_ioctl(s, r, p); + } + + ret = real_ioctl(s, r, p); + + switch (r) { + case FIONREAD: + value = *((int *)p); + if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { + swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); + } else if (value == 0) { /* END OF FILE */ + swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); + } + break; + } + + return ret; +} + +_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags) +{ + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_recv(s, buf, len, flags); + } + + ret = real_recv(s, buf, len, flags); + if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { + swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); + } else if (ret == 0) { /* END OF FILE */ + swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); + } else { + swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret); + } + + return ret; +} + + +_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) +{ + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_send(s, buf, len, flags); + } + + ret = real_send(s, buf, len, flags); + + if (ret == -1) { + swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); + swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); + } else { + swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); + } + + return ret; +} + +_PUBLIC_ int swrap_close(int fd) +{ + struct socket_info *si = find_socket_info(fd); + int ret; + + if (!si) { + return real_close(fd); + } + + SWRAP_DLIST_REMOVE(sockets, si); + + if (si->myname && si->peername) { + swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0); + } + + ret = real_close(fd); + + if (si->myname && si->peername) { + swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0); + swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0); + } + + if (si->path) free(si->path); + if (si->myname) free(si->myname); + if (si->peername) free(si->peername); + if (si->tmp_path) { + unlink(si->tmp_path); + free(si->tmp_path); + } + free(si); + + return ret; +} diff --git a/source/lib/socket_wrapper/socket_wrapper.h b/source/lib/socket_wrapper/socket_wrapper.h new file mode 100644 index 00000000000..1d8dac17632 --- /dev/null +++ b/source/lib/socket_wrapper/socket_wrapper.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org> + * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef __SOCKET_WRAPPER_H__ +#define __SOCKET_WRAPPER_H__ + +int swrap_socket(int family, int type, int protocol); +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen); +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen); +int swrap_listen(int s, int backlog); +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); +int swrap_ioctl(int s, int req, void *ptr); +ssize_t swrap_recv(int s, void *buf, size_t len, int flags); +ssize_t swrap_send(int s, const void *buf, size_t len, int flags); +int swrap_close(int); + +#ifdef SOCKET_WRAPPER_REPLACE + +#ifdef accept +#undef accept +#endif +#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen) + +#ifdef connect +#undef connect +#endif +#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen) + +#ifdef bind +#undef bind +#endif +#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen) + +#ifdef listen +#undef listen +#endif +#define listen(s,blog) swrap_listen(s,blog) + +#ifdef getpeername +#undef getpeername +#endif +#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen) + +#ifdef getsockname +#undef getsockname +#endif +#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen) + +#ifdef getsockopt +#undef getsockopt +#endif +#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen) + +#ifdef setsockopt +#undef setsockopt +#endif +#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen) + +#ifdef recvfrom +#undef recvfrom +#endif +#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen) + +#ifdef sendto +#undef sendto +#endif +#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen) + +#ifdef ioctl +#undef ioctl +#endif +#define ioctl(s,req,ptr) swrap_ioctl(s,req,ptr) + +#ifdef recv +#undef recv +#endif +#define recv(s,buf,len,flags) swrap_recv(s,buf,len,flags) + +#ifdef send +#undef send +#endif +#define send(s,buf,len,flags) swrap_send(s,buf,len,flags) + +#ifdef socket +#undef socket +#endif +#define socket(domain,type,protocol) swrap_socket(domain,type,protocol) + +#ifdef close +#undef close +#endif +#define close(s) swrap_close(s) +#endif + +#endif /* __SOCKET_WRAPPER_H__ */ diff --git a/source/lib/substitute.c b/source/lib/substitute.c index ff9deb8a5f0..4c81bd8444e 100644 --- a/source/lib/substitute.c +++ b/source/lib/substitute.c @@ -415,11 +415,12 @@ static const char *automount_server(const char *user_name) don't allow expansions. ****************************************************************************/ -void standard_sub_basic(const char *smb_name, char *str, size_t len) +void standard_sub_basic(const char *smb_name, const char *domain_name, + char *str, size_t len) { char *s; - if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) { + if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) { strncpy( str, s, len ); } @@ -432,11 +433,12 @@ void standard_sub_basic(const char *smb_name, char *str, size_t len) This function will return an allocated string that have to be freed. ****************************************************************************/ -char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str) +char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, + const char *domain_name, const char *str) { char *a, *t; - if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) { + if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) { return NULL; } t = talloc_strdup(mem_ctx, a); @@ -447,7 +449,8 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *st /**************************************************************************** ****************************************************************************/ -char *alloc_sub_basic(const char *smb_name, const char *str) +char *alloc_sub_basic(const char *smb_name, const char *domain_name, + const char *str) { char *b, *p, *s, *r, *a_string; fstring pidstr; @@ -463,7 +466,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) a_string = SMB_STRDUP(str); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); + DEBUG(0, ("alloc_sub_basic: Out of memory!\n")); return NULL; } @@ -490,7 +493,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) } break; case 'D' : - r = strdup_upper(current_user_info.domain); + r = strdup_upper(domain_name); if (r == NULL) { goto error; } @@ -522,7 +525,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) a_string = realloc_string_sub(a_string, "%R", remote_proto); break; case 'T' : - a_string = realloc_string_sub(a_string, "%T", timestring(False)); + a_string = realloc_string_sub(a_string, "%T", current_timestring(False)); break; case 'a' : a_string = realloc_string_sub(a_string, "%a", remote_arch); @@ -580,32 +583,20 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, uid_t uid, gid_t gid) { - char *a, *t; - a = alloc_sub_specified(input_string, username, domain, uid, gid); - if (!a) { + char *a_string; + char *ret_string = NULL; + char *b, *p, *s; + TALLOC_CTX *tmp_ctx; + + if (!(tmp_ctx = talloc_new(mem_ctx))) { + DEBUG(0, ("talloc_new failed\n")); return NULL; } - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; -} - -/**************************************************************************** -****************************************************************************/ - -char *alloc_sub_specified(const char *input_string, - const char *username, - const char *domain, - uid_t uid, - gid_t gid) -{ - char *a_string, *ret_string; - char *b, *p, *s; - a_string = SMB_STRDUP(input_string); + a_string = talloc_strdup(tmp_ctx, input_string); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); - return NULL; + DEBUG(0, ("talloc_sub_specified: Out of memory!\n")); + goto done; } for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { @@ -614,30 +605,42 @@ char *alloc_sub_specified(const char *input_string, switch (*(p+1)) { case 'U' : - a_string = realloc_string_sub(a_string, "%U", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%U", username); break; case 'u' : - a_string = realloc_string_sub(a_string, "%u", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%u", username); break; case 'G' : if (gid != -1) { - a_string = realloc_string_sub(a_string, "%G", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%G", + gidtoname(gid)); } else { - a_string = realloc_string_sub(a_string, "%G", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, + "%G", "NO_GROUP"); } break; case 'g' : if (gid != -1) { - a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", + gidtoname(gid)); } else { - a_string = realloc_string_sub(a_string, "%g", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", "NO_GROUP"); } break; case 'D' : - a_string = realloc_string_sub(a_string, "%D", domain); + a_string = talloc_string_sub(tmp_ctx, a_string, + "%D", domain); break; case 'N' : - a_string = realloc_string_sub(a_string, "%N", automount_server(username)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%N", + automount_server(username)); break; default: break; @@ -645,42 +648,27 @@ char *alloc_sub_specified(const char *input_string, p++; if (a_string == NULL) { - return NULL; + goto done; } } - ret_string = alloc_sub_basic(username, a_string); - SAFE_FREE(a_string); - return ret_string; -} + /* Watch out, using "mem_ctx" here, so all intermediate stuff goes + * away with the TALLOC_FREE(tmp_ctx) further down. */ -/**************************************************************************** -****************************************************************************/ + ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string); -char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, - int snum, - const char *user, - const char *connectpath, - gid_t gid, - const char *smb_name, - const char *str) -{ - char *a, *t; - a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str); - if (!a) { - return NULL; - } - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; + done: + TALLOC_FREE(tmp_ctx); + return ret_string; } /**************************************************************************** ****************************************************************************/ -char *alloc_sub_advanced(int snum, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, const char *str) +static char *alloc_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + const char *str) { char *a_string, *ret_string; char *b, *p, *s, *h; @@ -707,7 +695,7 @@ char *alloc_sub_advanced(int snum, const char *user, a_string = realloc_string_sub(a_string, "%P", connectpath); break; case 'S': - a_string = realloc_string_sub(a_string, "%S", lp_servicename(snum)); + a_string = realloc_string_sub(a_string, "%S", servicename); break; case 'g': a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); @@ -724,7 +712,8 @@ char *alloc_sub_advanced(int snum, const char *user, * "path =" string in [homes] and so needs the * service name, not the username. */ case 'p': - a_string = realloc_string_sub(a_string, "%p", automount_path(lp_servicename(snum))); + a_string = realloc_string_sub(a_string, "%p", + automount_path(servicename)); break; default: @@ -737,70 +726,64 @@ char *alloc_sub_advanced(int snum, const char *user, } } - ret_string = alloc_sub_basic(smb_name, a_string); + ret_string = alloc_sub_basic(smb_name, domain_name, a_string); SAFE_FREE(a_string); return ret_string; } -/**************************************************************************** - Do some standard substitutions in a string. -****************************************************************************/ +/* + * This obviously is inefficient and needs to be merged into + * alloc_sub_advanced... + */ -void standard_sub_conn(connection_struct *conn, char *str, size_t len) +char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, + const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + const char *str) { - char *s; - - s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, smb_user_name, str); + char *a, *t; - if ( s ) { - strncpy( str, s, len ); - SAFE_FREE( s ); + if (!(a = alloc_sub_advanced(servicename, user, connectpath, gid, + smb_name, domain_name, str))) { + return NULL; } + t = talloc_strdup(mem_ctx, a); + SAFE_FREE(a); + return t; } -/**************************************************************************** -****************************************************************************/ -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str) +void standard_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + char *str, size_t len) { - return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, - conn->connectpath, conn->gid, - smb_user_name, str); -} - -/**************************************************************************** -****************************************************************************/ + char *s; + + s = alloc_sub_advanced(servicename, user, connectpath, + gid, smb_name, domain_name, str); -char *alloc_sub_conn(connection_struct *conn, const char *str) -{ - return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, smb_user_name, str); + if ( s ) { + strncpy( str, s, len ); + SAFE_FREE( s ); + } } /**************************************************************************** - Like standard_sub but by snum. -****************************************************************************/ + * Do some standard substitutions in a string. + * ****************************************************************************/ -void standard_sub_snum(int snum, char *str, size_t len) +void standard_sub_conn(connection_struct *conn, char *str, size_t len) { - static uid_t cached_uid = -1; - static fstring cached_user; char *s; - - /* calling uidtoname() on every substitute would be too expensive, so - we cache the result here as nearly every call is for the same uid */ - - if (cached_uid != current_user.ut.uid) { - fstrcpy(cached_user, uidtoname(current_user.ut.uid)); - cached_uid = current_user.ut.uid; - } - s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid, - smb_user_name, str); + s = alloc_sub_advanced(lp_servicename(SNUM(conn)), conn->user, conn->connectpath, + conn->gid, smb_user_name, "", str); if ( s ) { strncpy( str, s, len ); SAFE_FREE( s ); } } + diff --git a/source/lib/sysacls.c b/source/lib/sysacls.c index 36baf96016c..d31c1870c34 100644 --- a/source/lib/sysacls.c +++ b/source/lib/sysacls.c @@ -2,6 +2,8 @@ Unix SMB/CIFS implementation. Samba system utilities for ACL support. Copyright (C) Jeremy Allison 2000. + Copyright (C) Volker Lendecke 2006 + Copyright (C) Michael Adam 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,337 +26,6 @@ #define DBGC_CLASS DBGC_ACLS /* - This file wraps all differing system ACL interfaces into a consistent - one based on the POSIX interface. It also returns the correct errors - for older UNIX systems that don't support ACLs. - - The interfaces that each ACL implementation must support are as follows : - - int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) - int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) - int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p - void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) - SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) - SMB_ACL_T sys_acl_get_fd(int fd) - int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset); - int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) - SMB_ACL_T sys_acl_init( int count) - int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) - int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) - int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) - int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) - int sys_acl_valid( SMB_ACL_T theacl ) - int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) - int sys_acl_set_fd( int fd, SMB_ACL_T theacl) - int sys_acl_delete_def_file(const char *path) - - This next one is not POSIX complient - but we *have* to have it ! - More POSIX braindamage. - - int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) - - The generic POSIX free is the following call. We split this into - several different free functions as we may need to add tag info - to structures when emulating the POSIX interface. - - int sys_acl_free( void *obj_p) - - The calls we actually use are : - - int sys_acl_free_text(char *text) - free acl_to_text - int sys_acl_free_acl(SMB_ACL_T posix_acl) - int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype) - -*/ - -#if defined(HAVE_POSIX_ACLS) - -/* Identity mapping - easy. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return acl_get_entry( the_acl, entry_id, entry_p); -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file( path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - return acl_clear_perms(permset); -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return acl_add_perm(permset, perm); -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ -#if defined(HAVE_ACL_GET_PERM_NP) - /* - * Required for TrustedBSD-based ACL implementations where - * non-POSIX.1e functions are denoted by a _np (non-portable) - * suffix. - */ - return acl_get_perm_np(permset, perm); -#else - return acl_get_perm(permset, perm); -#endif -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return acl_create_entry(pacl, pentry); -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - return acl_valid(theacl); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file(name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file(name); -} - -int sys_acl_free_text(char *text) -{ - return acl_free(text); -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free(qual); -} - -#elif defined(HAVE_TRU64_ACLS) -/* - * The interface to DEC/Compaq Tru64 UNIX ACLs - * is based on Draft 13 of the POSIX spec which is - * slightly different from the Draft 16 interface. - * - * Also, some of the permset manipulation functions - * such as acl_clear_perm() and acl_add_perm() appear - * to be broken on Tru64 so we have to manipulate - * the permission bits in the permset directly. - */ -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_ENTRY_T entry; - - if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) { - return -1; - } - - errno = 0; - if ((entry = acl_get_entry(the_acl)) != NULL) { - *entry_p = entry; - return 1; - } - - return errno ? -1 : 0; -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file((char *)path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd, ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - *permset = 0; /* acl_clear_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) { - errno = EINVAL; - return -1; - } - - *permset |= perm; /* acl_add_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return *permset & perm; /* Tru64 doesn't have acl_get_perm() */ -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - SMB_ACL_ENTRY_T entry; - - if ((entry = acl_create_entry(pacl)) == NULL) { - return -1; - } - - *pentry = entry; - return 0; -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - acl_entry_t entry; - - return acl_valid(theacl, &entry); -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file((char *)name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file((char *)name); -} - -int sys_acl_free_text(char *text) -{ - /* - * (void) cast and explicit return 0 are for DEC UNIX - * which just #defines acl_free_text() to be free() - */ - (void) acl_free_text(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free_qualifier(qual, tagtype); -} - -#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) - -/* - * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX. - * Modified by Toomas Soome <tsoome@ut.ee> for Solaris. - */ - -/* * Note that while this code implements sufficient functionality * to support the sys_acl_* interfaces it does not provide all * of the semantics of the POSIX ACL interfaces. @@ -369,19 +40,6 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) * sys_acl_set_fd() */ -/* - * The only difference between Solaris and UnixWare / OpenUNIX is - * that the #defines for the ACL operations have different names - */ -#if defined(HAVE_UNIXWARE_ACLS) - -#define SETACL ACL_SET -#define GETACL ACL_GET -#define GETACLCNT ACL_CNT - -#endif - - int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) { if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { @@ -428,148 +86,16 @@ int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) { - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; -} - -/* - * There is no way of knowing what size the ACL returned by - * GETACL will be unless you first call GETACLCNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use GETACLCNT to find out the actual - * size, reallocate the ACL buffer, and then call GETACL again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * GETACLCNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * GETACLCNT and the call to GETACL. - */ - while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) { - return NULL; + if (entry_d->a_type == SMB_ACL_USER) { + return &entry_d->uid; } - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } + if (entry_d->a_type == SMB_ACL_GROUP) { + return &entry_d->gid; } - if (count < 0) { - sys_acl_free_acl(acl_d); + errno = EINVAL; return NULL; - } - - /* - * calculate the number of access ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - - acl_d->count = naccess; - - return acl_d; } int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) @@ -585,15 +111,15 @@ int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) && perm != SMB_ACL_EXECUTE) { errno = EINVAL; return -1; - } - + } + if (permset_d == NULL) { errno = EINVAL; return -1; } *permset_d |= perm; - + return 0; } @@ -615,19 +141,18 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) */ len = 0; maxlen = 20 * acl_d->count; - if ((text = SMB_MALLOC(maxlen)) == NULL) { + if ((text = (char *)SMB_MALLOC(maxlen)) == NULL) { errno = ENOMEM; return NULL; } for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; + struct smb_acl_entry *ap = &acl_d->acl[i]; struct group *gr; char tagbuf[12]; char idbuf[12]; - char *tag; - char *id = ""; + const char *tag; + const char *id = ""; char perms[4]; int nbytes; @@ -639,27 +164,24 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) */ default: slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); + ap->a_type); tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; break; - + case SMB_ACL_USER: - id = uidtoname(ap->a_id); + id = uidtoname(ap->uid); case SMB_ACL_USER_OBJ: tag = "user"; break; case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { + if ((gr = getgrgid(ap->gid)) == NULL) { slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); + (long)ap->gid); id = idbuf; } else { id = gr->gr_name; - } + } case SMB_ACL_GROUP_OBJ: tag = "group"; break; @@ -690,11 +212,11 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) */ if ((len + nbytes) > maxlen) { maxlen += nbytes + 20 * (acl_d->count - i); - if ((text = SMB_REALLOC(text, maxlen)) == NULL) { - errno = ENOMEM; + if ((text = (char *)SMB_REALLOC(text, maxlen)) == NULL) { + errno = ENOMEM; return NULL; - } } + } slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); len += nbytes - 1; @@ -721,11 +243,13 @@ SMB_ACL_T sys_acl_init(int count) * acl[] array, this actually allocates an ACL with room * for (count+1) entries */ - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) { + if ((a = (struct smb_acl_t *)SMB_MALLOC( + sizeof(struct smb_acl_t) + + count * sizeof(struct smb_acl_entry))) == NULL) { errno = ENOMEM; return NULL; } - + a->size = count + 1; a->count = 0; a->next = -1; @@ -733,7 +257,6 @@ SMB_ACL_T sys_acl_init(int count) return a; } - int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) { SMB_ACL_T acl_d; @@ -750,8 +273,9 @@ int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) } entry_d = &acl_d->acl[acl_d->count++]; - entry_d->a_type = 0; - entry_d->a_id = -1; + entry_d->a_type = SMB_ACL_TAG_INVALID; + entry_d->uid = -1; + entry_d->gid = -1; entry_d->a_perm = 0; *entry_p = entry_d; @@ -772,184 +296,36 @@ int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) default: errno = EINVAL; return -1; - } + } return 0; } int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) { - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; + if (entry_d->a_type == SMB_ACL_USER) { + entry_d->uid = *((uid_t *)qual_p); + return 0; + } + if (entry_d->a_type == SMB_ACL_GROUP) { + entry_d->gid = *((gid_t *)qual_p); + return 0; } - entry_d->a_id = *((id_t *)qual_p); - - return 0; + errno = EINVAL; + return -1; } int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) { if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* - * sort the ACL and check it for validity - * - * if it's a minimal ACL with only 4 entries then we - * need to recalculate the mask permissions to make - * sure that they are the same as the GROUP_OBJ - * permissions as required by the UnixWare acl() system call. - * - * (note: since POSIX allows minimal ACLs which only contain - * 3 entries - ie there is no mask entry - we should, in theory, - * check for this and add a mask entry if necessary - however - * we "know" that the caller of this interface always specifies - * a mask so, in practice "this never happens" (tm) - if it *does* - * happen aclsort() will fail and return an error and someone will - * have to fix it ...) - */ - -static int acl_sort(SMB_ACL_T acl_d) -{ - int fixmask = (acl_d->count <= 4); - - if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) { errno = EINVAL; return -1; } - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, SETACL, acl_count, acl_p); - - SAFE_FREE(acl_buf); - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - if (acl_sort(acl_d) != 0) { - return -1; - } - - return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]); -} -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, SETACL, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; + entry_d->a_perm = *permset_d; + + return 0; } int sys_acl_free_text(char *text) @@ -969,2231 +345,261 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) return 0; } -#elif defined(HAVE_HPUX_ACLS) -#include <dl.h> - -/* - * Based on the Solaris/SCO code - with modifications. - */ - -/* - * Note that while this code implements sufficient functionality - * to support the sys_acl_* interfaces it does not provide all - * of the semantics of the POSIX ACL interfaces. - * - * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned - * from a call to sys_acl_get_entry() should not be assumed to be - * valid after calling any of the following functions, which may - * reorder the entries in the ACL. - * - * sys_acl_valid() - * sys_acl_set_file() - * sys_acl_set_fd() - */ - -/* This checks if the POSIX ACL system call is defined */ -/* which basically corresponds to whether JFS 3.3 or */ -/* higher is installed. If acl() was called when it */ -/* isn't defined, it causes the process to core dump */ -/* so it is important to check this and avoid acl() */ -/* calls if it isn't there. */ - -static BOOL hpux_acl_call_presence(void) -{ - - shl_t handle = NULL; - void *value; - int ret_val=0; - static BOOL already_checked=0; - - if(already_checked) - return True; - - - ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); - - if(ret_val != 0) { - DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n", - ret_val, errno, strerror(errno))); - DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); - return False; - } - - DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n")); - - already_checked = True; - return True; -} - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->count) { - return 0; - } - - *entry_p = &acl_d->acl[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->a_type; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = &entry_d->a_perm; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) +int sys_acl_valid(SMB_ACL_T acl_d) { - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; + errno = EINVAL; + return -1; } /* - * There is no way of knowing what size the ACL returned by - * ACL_GET will be unless you first call ACL_CNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use ACL_CNT to find out the actual - * size, reallocate the ACL buffer, and then call ACL_GET again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - return NULL; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * ACL_CNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * ACL_CNT and the call to ACL_GET. - */ - while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - *permset_d = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - *permset_d |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return *permset_d & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - int i; - int len, maxlen; - char *text; - - /* - * use an initial estimate of 20 bytes per ACL entry - * when allocating memory for the text representation - * of the ACL - */ - len = 0; - maxlen = 20 * acl_d->count; - if ((text = SMB_MALLOC(maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - - for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; - struct group *gr; - char tagbuf[12]; - char idbuf[12]; - char *tag; - char *id = ""; - char perms[4]; - int nbytes; - - switch (ap->a_type) { - /* - * for debugging purposes it's probably more - * useful to dump unknown tag types rather - * than just returning an error - */ - default: - slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); - tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - break; - - case SMB_ACL_USER: - id = uidtoname(ap->a_id); - case SMB_ACL_USER_OBJ: - tag = "user"; - break; - - case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - } else { - id = gr->gr_name; - } - case SMB_ACL_GROUP_OBJ: - tag = "group"; - break; - - case SMB_ACL_OTHER: - tag = "other"; - break; - - case SMB_ACL_MASK: - tag = "mask"; - break; - - } - - perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; - perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; - perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; - perms[3] = '\0'; - - /* <tag> : <qualifier> : rwx \n \0 */ - nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; - - /* - * If this entry would overflow the buffer - * allocate enough additional memory for this - * entry and an estimate of another 20 bytes - * for each entry still to be processed - */ - if ((len + nbytes) > maxlen) { - maxlen += nbytes + 20 * (acl_d->count - i); - if ((text = SMB_REALLOC(text, maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - } - - slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); - len += nbytes - 1; - } - - if (len_p) - *len_p = len; - - return text; -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - /* - * note that since the definition of the structure pointed - * to by the SMB_ACL_T includes the first element of the - * acl[] array, this actually allocates an ACL with room - * for (count+1) entries - */ - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->size = count + 1; - a->count = 0; - a->next = -1; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->count >= acl_d->size) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->acl[acl_d->count++]; - entry_d->a_type = 0; - entry_d->a_id = -1; - entry_d->a_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->a_type = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->a_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* Structure to capture the count for each type of ACE. */ - -struct hpux_acl_types { - int n_user; - int n_def_user; - int n_user_obj; - int n_def_user_obj; - - int n_group; - int n_def_group; - int n_group_obj; - int n_def_group_obj; - - int n_other; - int n_other_obj; - int n_def_other_obj; - - int n_class_obj; - int n_def_class_obj; - - int n_illegal_obj; -}; - -/* count_obj: - * Counts the different number of objects in a given array of ACL - * structures. - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL strucutres. - * aclp - Array of ACL structures. - * acl_type_count - Pointer to acl_types structure. Should already be - * allocated. - * Output: - * - * acl_type_count - This structure is filled up with counts of various - * acl types. - */ - -static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count) -{ - int i; - - memset(acl_type_count, 0, sizeof(struct hpux_acl_types)); - - for(i=0;i<acl_count;i++) { - switch(aclp[i].a_type) { - case USER: - acl_type_count->n_user++; - break; - case USER_OBJ: - acl_type_count->n_user_obj++; - break; - case DEF_USER_OBJ: - acl_type_count->n_def_user_obj++; - break; - case GROUP: - acl_type_count->n_group++; - break; - case GROUP_OBJ: - acl_type_count->n_group_obj++; - break; - case DEF_GROUP_OBJ: - acl_type_count->n_def_group_obj++; - break; - case OTHER_OBJ: - acl_type_count->n_other_obj++; - break; - case DEF_OTHER_OBJ: - acl_type_count->n_def_other_obj++; - break; - case CLASS_OBJ: - acl_type_count->n_class_obj++; - break; - case DEF_CLASS_OBJ: - acl_type_count->n_def_class_obj++; - break; - case DEF_USER: - acl_type_count->n_def_user++; - break; - case DEF_GROUP: - acl_type_count->n_def_group++; - break; - default: - acl_type_count->n_illegal_obj++; - break; - } - } -} - -/* swap_acl_entries: Swaps two ACL entries. - * - * Inputs: aclp0, aclp1 - ACL entries to be swapped. + * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and + * sys_acl_delete_def_file are to be redirected to the default + * statically-bound acl vfs module, but they are replacable. */ - -static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1) -{ - struct acl temp_acl; - - temp_acl.a_type = aclp0->a_type; - temp_acl.a_id = aclp0->a_id; - temp_acl.a_perm = aclp0->a_perm; - - aclp0->a_type = aclp1->a_type; - aclp0->a_id = aclp1->a_id; - aclp0->a_perm = aclp1->a_perm; - - aclp1->a_type = temp_acl.a_type; - aclp1->a_id = temp_acl.a_id; - aclp1->a_perm = temp_acl.a_perm; -} - -/* prohibited_duplicate_type - * Identifies if given ACL type can have duplicate entries or - * not. - * - * Inputs: acl_type - ACL Type. - * - * Outputs: - * - * Return.. - * - * True - If the ACL type matches any of the prohibited types. - * False - If the ACL type doesn't match any of the prohibited types. - */ - -static BOOL hpux_prohibited_duplicate_type(int acl_type) -{ - switch(acl_type) { - case USER: - case GROUP: - case DEF_USER: - case DEF_GROUP: - return True; - default: - return False; - } -} - -/* get_needed_class_perm - * Returns the permissions of a ACL structure only if the ACL - * type matches one of the pre-determined types for computing - * CLASS_OBJ permissions. - * - * Inputs: aclp - Pointer to ACL structure. - */ - -static int hpux_get_needed_class_perm(struct acl *aclp) -{ - switch(aclp->a_type) { - case USER: - case GROUP_OBJ: - case GROUP: - case DEF_USER_OBJ: - case DEF_USER: - case DEF_GROUP_OBJ: - case DEF_GROUP: - case DEF_CLASS_OBJ: - case DEF_OTHER_OBJ: - return aclp->a_perm; - default: - return 0; - } -} - -/* acl_sort for HPUX. - * Sorts the array of ACL structures as per the description in - * aclsort man page. Refer to aclsort man page for more details - * - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL structures. - * calclass - If this is not zero, then we compute the CLASS_OBJ - * permissions. - * aclp - Array of ACL structures. - * - * Outputs: - * - * aclp - Sorted array of ACL structures. - * - * Outputs: - * - * Returns 0 for success -1 for failure. Prints a message to the Samba - * debug log in case of failure. - */ - -static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp) -{ -#if !defined(HAVE_HPUX_ACLSORT) - /* - * The aclsort() system call is availabe on the latest HPUX General - * Patch Bundles. So for HPUX, we developed our version of acl_sort - * function. Because, we don't want to update to a new - * HPUX GR bundle just for aclsort() call. - */ - - struct hpux_acl_types acl_obj_count; - int n_class_obj_perm = 0; - int i, j; - if(!acl_count) { - DEBUG(10,("Zero acl count passed. Returning Success\n")); - return 0; - } - - if(aclp == NULL) { - DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n")); - return -1; - } - - /* Count different types of ACLs in the ACLs array */ - - hpux_count_obj(acl_count, aclp, &acl_obj_count); - - /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, - * CLASS_OBJ and OTHER_OBJ - */ - - if( (acl_obj_count.n_user_obj != 1) || - (acl_obj_count.n_group_obj != 1) || - (acl_obj_count.n_class_obj != 1) || - (acl_obj_count.n_other_obj != 1) - ) { - DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \ -USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n")); - return -1; - } - - /* If any of the default objects are present, there should be only - * one of them each. - */ - - if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) || - (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) { - DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \ -or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n")); - return -1; - } - - /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl - * structures. - * - * Sorting crieteria - First sort by ACL type. If there are multiple entries of - * same ACL type, sort by ACL id. - * - * I am using the trival kind of sorting method here because, performance isn't - * really effected by the ACLs feature. More over there aren't going to be more - * than 17 entries on HPUX. - */ - - for(i=0; i<acl_count;i++) { - for (j=i+1; j<acl_count; j++) { - if( aclp[i].a_type > aclp[j].a_type ) { - /* ACL entries out of order, swap them */ - - hpux_swap_acl_entries((aclp+i), (aclp+j)); - - } else if ( aclp[i].a_type == aclp[j].a_type ) { - - /* ACL entries of same type, sort by id */ - - if(aclp[i].a_id > aclp[j].a_id) { - hpux_swap_acl_entries((aclp+i), (aclp+j)); - } else if (aclp[i].a_id == aclp[j].a_id) { - /* We have a duplicate entry. */ - if(hpux_prohibited_duplicate_type(aclp[i].a_type)) { - DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n", - aclp[i].a_type, aclp[i].a_id)); - return -1; - } - } - - } - } - } - - /* set the class obj permissions to the computed one. */ - if(calclass) { - int n_class_obj_index = -1; - - for(i=0;i<acl_count;i++) { - n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i)); - - if(aclp[i].a_type == CLASS_OBJ) - n_class_obj_index = i; - } - aclp[n_class_obj_index].a_perm = n_class_obj_perm; - } - - return 0; -#else - return aclsort(acl_count, calclass, aclp); -#endif -} - -/* - * sort the ACL and check it for validity - * - * if it's a minimal ACL with only 4 entries then we - * need to recalculate the mask permissions to make - * sure that they are the same as the GROUP_OBJ - * permissions as required by the UnixWare acl() system call. - * - * (note: since POSIX allows minimal ACLs which only contain - * 3 entries - ie there is no mask entry - we should, in theory, - * check for this and add a mask entry if necessary - however - * we "know" that the caller of this interface always specifies - * a mask so, in practice "this never happens" (tm) - if it *does* - * happen aclsort() will fail and return an error and someone will - * have to fix it ...) - */ - -static int acl_sort(SMB_ACL_T acl_d) -{ - int fixmask = (acl_d->count <= 4); - - if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) { - errno = EINVAL; - return -1; - } - return 0; -} +#if defined(HAVE_POSIX_ACLS) -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - errno=ENOSYS; - return -1; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, ACL_SET, acl_count, acl_p); - - if (acl_buf) { - free(acl_buf); - } - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d); -} - -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, ACL_SET, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; -} - -int sys_acl_free_text(char *text) -{ - free(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T acl_d) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - free(acl_d); - return 0; + return posixacl_sys_acl_get_file(handle, path_p, type); } - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return 0; -} - -#elif defined(HAVE_IRIX_ACLS) - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->aclp->acl_cnt) { - return 0; - } - - *entry_p = &acl_d->aclp->acl_entry[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->ae_tag; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = entry_d; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) -{ - if (entry_d->ae_tag != SMB_ACL_USER - && entry_d->ae_tag != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->ae_id; -} - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T a; - - if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_file(path_p, type)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T a; - - if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_fd(fd)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - permset_d->ae_perm = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - permset_d->ae_perm |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return permset_d->ae_perm & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - return acl_to_text(acl_d->aclp, len_p); -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->next = -1; - a->freeaclp = False; - a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *)); - a->aclp->acl_cnt = 0; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++]; - entry_d->ae_tag = 0; - entry_d->ae_id = 0; - entry_d->ae_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->ae_tag = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->ae_tag != SMB_ACL_GROUP - && entry_d->ae_tag != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->ae_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->ae_perm = permset_d->ae_perm; - - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_valid(acl_d->aclp); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - return acl_set_file(name, type, acl_d->aclp); -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - return acl_set_fd(fd, acl_d->aclp); -} - -int sys_acl_delete_def_file(const char *name) + +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - return acl_delete_def_file(name); + return posixacl_sys_acl_get_fd(handle, fsp, fd); } - -int sys_acl_free_text(char *text) + +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - return acl_free(text); + return posixacl_sys_acl_set_file(handle, name, type, acl_d); } - -int sys_acl_free_acl(SMB_ACL_T acl_d) + +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - if (acl_d->freeaclp) { - acl_free(acl_d->aclp); - } - acl_free(acl_d); - return 0; + return posixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - return 0; + return posixacl_sys_acl_delete_def_file(handle, path); } #elif defined(HAVE_AIX_ACLS) -/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ - -int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - struct acl_entry_link *link; - struct new_acl_entry *entry; - int keep_going; - - DEBUG(10,("This is the count: %d\n",theacl->count)); - - /* Check if count was previously set to -1. * - * If it was, that means we reached the end * - * of the acl last time. */ - if(theacl->count == -1) - return(0); - - link = theacl; - /* To get to the next acl, traverse linked list until index * - * of acl matches the count we are keeping. This count is * - * incremented each time we return an acl entry. */ - - for(keep_going = 0; keep_going < theacl->count; keep_going++) - link = link->nextp; - - entry = *entry_p = link->entryp; - - DEBUG(10,("*entry_p is %d\n",entry_p)); - DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access)); - - /* Increment count */ - theacl->count++; - if(link->nextp == NULL) - theacl->count = -1; - - return(1); + return aixacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - /* Initialize tag type */ - - *tag_type_p = -1; - DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type)); - - /* Depending on what type of entry we have, * - * return tag type. */ - switch(entry_d->ace_id->id_type) { - case ACEID_USER: - *tag_type_p = SMB_ACL_USER; - break; - case ACEID_GROUP: - *tag_type_p = SMB_ACL_GROUP; - break; - - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - *tag_type_p = entry_d->ace_id->id_type; - break; - - default: - return(-1); - } - - return(0); + return aixacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - DEBUG(10,("Starting AIX sys_acl_get_permset\n")); - *permset_p = &entry_d->ace_access; - DEBUG(10,("**permset_p is %d\n",**permset_p)); - if(!(**permset_p & S_IXUSR) && - !(**permset_p & S_IWUSR) && - !(**permset_p & S_IRUSR) && - (**permset_p != 0)) - return(-1); - - DEBUG(10,("Ending AIX sys_acl_get_permset\n")); - return(0); + return aixacl_sys_acl_set_file(handle, name, type, acl_d); } -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - return(entry_d->ace_id->id_data); + return aixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* AIX has no DEFAULT */ - if ( type == SMB_ACL_TYPE_DEFAULT ) - return NULL; - - /* Get the acl using statacl */ - - DEBUG(10,("Entering sys_acl_get_file\n")); - DEBUG(10,("path_p is %s\n",path_p)); - - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = statacl((char *)path_p,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("statacl returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - acl_entry = file_acl->acl_ext; - - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL) - return(NULL); - - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); - - return(acl_entry_link_head); + return aixacl_sys_acl_delete_def_file(handle, path); } -SMB_ACL_T sys_acl_get_fd(int fd) -{ - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* Get the acl using fstatacl */ - - DEBUG(10,("Entering sys_acl_get_fd\n")); - DEBUG(10,("fd is %d\n",fd)); - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = fstatacl(fd,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - - acl_entry = file_acl->acl_ext; - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL){ - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0){ - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); +#elif defined(HAVE_TRU64_ACLS) - return(acl_entry_link_head); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - *permset = *permset & ~0777; - return(0); + return tru64acl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - if((perm != 0) && - (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0) - return(-1); - - *permset |= perm; - DEBUG(10,("This is the permset now: %d\n",*permset)); - return(0); + return tru64acl_sys_acl_get_fd(handle, fsp, fd); } -char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - return(NULL); + return tru64acl_sys_acl_set_file(handle, name, type, acl_d); } -SMB_ACL_T sys_acl_init( int count) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - struct acl_entry_link *theacl = NULL; - - DEBUG(10,("Entering sys_acl_init\n")); - - theacl = SMB_MALLOC_P(struct acl_entry_link); - if(theacl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_init is %d\n",errno)); - return(NULL); - } - - theacl->count = 0; - theacl->nextp = NULL; - theacl->prevp = NULL; - theacl->entryp = NULL; - DEBUG(10,("Exiting sys_acl_init\n")); - return(theacl); + return tru64acl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - struct acl_entry_link *theacl; - struct acl_entry_link *acl_entryp; - struct acl_entry_link *temp_entry; - int counting; - - DEBUG(10,("Entering the sys_acl_create_entry\n")); - - theacl = acl_entryp = *pacl; - - /* Get to the end of the acl before adding entry */ - - for(counting=0; counting < theacl->count; counting++){ - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - temp_entry = acl_entryp; - acl_entryp = acl_entryp->nextp; - } - - if(theacl->count != 0){ - temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - acl_entryp->prevp = temp_entry; - DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp)); - } - - *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(*pentry == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - memset(*pentry,0,sizeof(struct new_acl_entry)); - acl_entryp->entryp->ace_len = sizeof(struct acl_entry); - acl_entryp->entryp->ace_type = ACC_PERMIT; - acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id); - acl_entryp->nextp = NULL; - theacl->count++; - DEBUG(10,("Exiting sys_acl_create_entry\n")); - return(0); + return tru64acl_sys_acl_delete_def_file(handle, path); } -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - DEBUG(10,("Starting AIX sys_acl_set_tag_type\n")); - entry->ace_id->id_type = tagtype; - DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type)); - DEBUG(10,("Ending AIX sys_acl_set_tag_type\n")); -} +#elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS) -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - DEBUG(10,("Starting AIX sys_acl_set_qualifier\n")); - memcpy(entry->ace_id->id_data,qual,sizeof(uid_t)); - DEBUG(10,("Ending AIX sys_acl_set_qualifier\n")); - return(0); + return solarisacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - DEBUG(10,("Starting AIX sys_acl_set_permset\n")); - if(!(*permset & S_IXUSR) && - !(*permset & S_IWUSR) && - !(*permset & S_IRUSR) && - (*permset != 0)) - return(-1); - - entry->ace_access = *permset; - DEBUG(10,("entry->ace_access = %d\n",entry->ace_access)); - DEBUG(10,("Ending AIX sys_acl_set_permset\n")); - return(0); + return solarisacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_valid( SMB_ACL_T theacl ) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - int user_obj = 0; - int group_obj = 0; - int other_obj = 0; - struct acl_entry_link *acl_entry; - - for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) { - user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ); - group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ); - other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER); - } - - DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj)); - - if(user_obj != 1 || group_obj != 1 || other_obj != 1) - return(-1); - - return(0); + return solarisacl_sys_acl_set_file(handle, name, type, acl_d); } -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint ace_access; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_file\n")); - DEBUG(10,("File name is %s\n",name)); - - /* AIX has no default ACL */ - if(acltype == SMB_ACL_TYPE_DEFAULT) - return(0); - - acl_length = BUFSIZ; - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = chacl(name,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting the sys_acl_set_file\n")); - return(rc); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_fd\n")); - acl_length = BUFSIZ; - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id_type is %d\n",id_type)); - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = fchacl(fd,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting sys_acl_set_fd\n")); - return(rc); + return solarisacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_delete_def_file(const char *name) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - /* AIX has no default ACL */ - return 0; + return solarisacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return(*permset & perm); -} +#elif defined(HAVE_HPUX_ACLS) -int sys_acl_free_text(char *text) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - return(0); + return hpuxacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_free_acl(SMB_ACL_T posix_acl) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - struct acl_entry_link *acl_entry_link; - - for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) { - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - } - - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - SAFE_FREE(acl_entry_link->entryp); - SAFE_FREE(acl_entry_link); - - return(0); + return hpuxacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - return(0); + return hpuxacl_sys_acl_set_file(handle, name, type, acl_d); } -#else /* No ACLs. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - errno = ENOSYS; - return -1; + return hpuxacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - errno = ENOSYS; - return -1; + return hpuxacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - errno = ENOSYS; - return -1; -} +#elif defined(HAVE_IRIX_ACLS) -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - errno = ENOSYS; - return NULL; + return irixacl_sys_acl_get_file(handle, path_p, type); } -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - errno = ENOSYS; - return (SMB_ACL_T)NULL; + return irixacl_sys_acl_get_fd(handle, fsp, fd); } -SMB_ACL_T sys_acl_get_fd(int fd) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - errno = ENOSYS; - return (SMB_ACL_T)NULL; + return irixacl_sys_acl_set_file(handle, name, type, acl_d); } -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - errno = ENOSYS; - return -1; + return irixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - errno = ENOSYS; - return -1; + return irixacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - errno = ENOSYS; - return (permset & perm) ? 1 : 0; -} +#else /* No ACLs. */ -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { +#ifdef ENOTSUP + errno = ENOTSUP; +#else errno = ENOSYS; +#endif return NULL; } -int sys_acl_free_text(char *text) -{ - errno = ENOSYS; - return -1; -} - -SMB_ACL_T sys_acl_init( int count) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { +#ifdef ENOTSUP + errno = ENOTSUP; +#else errno = ENOSYS; +#endif return NULL; } -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_delete_def_file(const char *name) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { +#ifdef ENOTSUP + errno = ENOTSUP; +#else errno = ENOSYS; +#endif return -1; } -int sys_acl_free_acl(SMB_ACL_T the_acl) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { +#ifdef ENOTSUP + errno = ENOTSUP; +#else errno = ENOSYS; +#endif return -1; } -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { +#ifdef ENOTSUP + errno = ENOTSUP; +#else errno = ENOSYS; +#endif return -1; } -#endif /* No ACLs. */ +#endif /************************************************************************ Deliberately outside the ACL defines. Return 1 if this is a "no acls" diff --git a/source/lib/sysquotas_linux.c b/source/lib/sysquotas_linux.c index 761562b402e..9c0d0056f6d 100644 --- a/source/lib/sysquotas_linux.c +++ b/source/lib/sysquotas_linux.c @@ -526,9 +526,9 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt case SMB_USER_FS_QUOTA_TYPE: id.uid = getuid(); - if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) { - if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) { - ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp); + if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) { + if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) { + ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp); } } @@ -541,9 +541,9 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt case SMB_GROUP_FS_QUOTA_TYPE: id.gid = getgid(); - if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) { - if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) { - ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp); + if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) { + if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) { + ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp); } } diff --git a/source/lib/system.c b/source/lib/system.c index 2e5f42307bd..20b31113ecd 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -44,6 +44,27 @@ /******************************************************************* + A wrapper for memalign +********************************************************************/ + +void* sys_memalign( size_t align, size_t size ) +{ +#if defined(HAVE_MEMALIGN) + return memalign( align, size ); +#elif defined(HAVE_POSIX_MEMALIGN) + char *p = NULL; + int ret = posix_memalign( &p, align, size ); + if ( ret == 0 ) + return p; + + return NULL; +#else + DEBUG(0,("memalign functionalaity not available on this platform!\n")); + return NULL; +#endif +} + +/******************************************************************* A wrapper for usleep in case we don't have one. ********************************************************************/ @@ -105,7 +126,6 @@ ssize_t sys_write(int fd, const void *buf, size_t count) return ret; } - /******************************************************************* A pread wrapper that will deal with EINTR and 64-bit file offsets. ********************************************************************/ @@ -175,6 +195,20 @@ ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct } /******************************************************************* +A recv wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_recv(int fd, void *buf, size_t count, int flags) +{ + ssize_t ret; + + do { + ret = recv(fd, buf, count, flags); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* A recvfrom wrapper that will deal with EINTR. ********************************************************************/ @@ -366,6 +400,31 @@ FILE *sys_fopen(const char *path, const char *type) #endif } + +/******************************************************************* + A flock() wrapper that will perform the kernel flock. +********************************************************************/ + +void kernel_flock(int fd, uint32 share_mode) +{ +#if HAVE_KERNEL_SHARE_MODES + int kernel_mode = 0; + if (share_mode == FILE_SHARE_WRITE) { + kernel_mode = LOCK_MAND|LOCK_WRITE; + } else if (share_mode == FILE_SHARE_READ) { + kernel_mode = LOCK_MAND|LOCK_READ; + } else if (share_mode == FILE_SHARE_NONE) { + kernel_mode = LOCK_MAND; + } + if (kernel_mode) { + flock(fd, kernel_mode); + } +#endif + ; +} + + + /******************************************************************* An opendir wrapper that will deal with 64 bit filesizes. ********************************************************************/ @@ -922,6 +981,82 @@ void sys_endpwent(void) Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid() ****************************************************************************/ +#ifdef ENABLE_BUILD_FARM_HACKS + +/* + * In the build farm we want to be able to join machines to the domain. As we + * don't have root access, we need to bypass direct access to /etc/passwd + * after a user has been created via samr. Fake those users. + */ + +static struct passwd *fake_pwd; +static int num_fake_pwd; + +struct passwd *sys_getpwnam(const char *name) +{ + int i; + + for (i=0; i<num_fake_pwd; i++) { + if (strcmp(fake_pwd[i].pw_name, name) == 0) { + DEBUG(10, ("Returning fake user %s\n", name)); + return &fake_pwd[i]; + } + } + + return getpwnam(name); +} + +struct passwd *sys_getpwuid(uid_t uid) +{ + int i; + + for (i=0; i<num_fake_pwd; i++) { + if (fake_pwd[i].pw_uid == uid) { + DEBUG(10, ("Returning fake user %s\n", + fake_pwd[i].pw_name)); + return &fake_pwd[i]; + } + } + + return getpwuid(uid); +} + +void faked_create_user(const char *name) +{ + int i; + uid_t uid; + struct passwd new_pwd; + + for (i=0; i<10; i++) { + generate_random_buffer((unsigned char *)&uid, + sizeof(uid)); + if (getpwuid(uid) == NULL) { + break; + } + } + + if (i==10) { + /* Weird. No free uid found... */ + return; + } + + new_pwd.pw_name = SMB_STRDUP(name); + new_pwd.pw_passwd = SMB_STRDUP("x"); + new_pwd.pw_uid = uid; + new_pwd.pw_gid = 100; + new_pwd.pw_gecos = SMB_STRDUP("faked user"); + new_pwd.pw_dir = SMB_STRDUP("/nodir"); + new_pwd.pw_shell = SMB_STRDUP("/bin/false"); + + ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd, + &num_fake_pwd); + + DEBUG(10, ("Added fake user %s, have %d fake users\n", + name, num_fake_pwd)); +} + +#else + struct passwd *sys_getpwnam(const char *name) { return getpwnam(name); @@ -932,6 +1067,8 @@ struct passwd *sys_getpwuid(uid_t uid) return getpwuid(uid); } +#endif + struct group *sys_getgrnam(const char *name) { return getgrnam(name); @@ -1417,7 +1554,12 @@ int sys_dup2(int oldfd, int newfd) ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size) { #if defined(HAVE_GETXATTR) +#ifndef XATTR_ADD_OPT return getxattr(path, name, value, size); +#else + int options = 0; + return getxattr(path, name, value, size, 0, options); +#endif #elif defined(HAVE_GETEA) return getea(path, name, value, size); #elif defined(HAVE_EXTATTR_GET_FILE) @@ -1462,6 +1604,9 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s { #if defined(HAVE_LGETXATTR) return lgetxattr(path, name, value, size); +#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return getxattr(path, name, value, size, 0, options); #elif defined(HAVE_LGETEA) return lgetea(path, name, value, size); #elif defined(HAVE_EXTATTR_GET_LINK) @@ -1501,7 +1646,12 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) { #if defined(HAVE_FGETXATTR) +#ifndef XATTR_ADD_OPT return fgetxattr(filedes, name, value, size); +#else + int options = 0; + return fgetxattr(filedes, name, value, size, 0, options); +#endif #elif defined(HAVE_FGETEA) return fgetea(filedes, name, value, size); #elif defined(HAVE_EXTATTR_GET_FD) @@ -1702,7 +1852,12 @@ static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t ssize_t sys_listxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LISTXATTR) +#ifndef XATTR_ADD_OPT return listxattr(path, list, size); +#else + int options = 0; + return listxattr(path, list, size, options); +#endif #elif defined(HAVE_LISTEA) return listea(path, list, size); #elif defined(HAVE_EXTATTR_LIST_FILE) @@ -1721,6 +1876,9 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LLISTXATTR) return llistxattr(path, list, size); +#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return listxattr(path, list, size, options); #elif defined(HAVE_LLISTEA) return llistea(path, list, size); #elif defined(HAVE_EXTATTR_LIST_LINK) @@ -1738,7 +1896,12 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size) ssize_t sys_flistxattr (int filedes, char *list, size_t size) { #if defined(HAVE_FLISTXATTR) +#ifndef XATTR_ADD_OPT return flistxattr(filedes, list, size); +#else + int options = 0; + return flistxattr(filedes, list, size, options); +#endif #elif defined(HAVE_FLISTEA) return flistea(filedes, list, size); #elif defined(HAVE_EXTATTR_LIST_FD) @@ -1756,7 +1919,12 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size) int sys_removexattr (const char *path, const char *name) { #if defined(HAVE_REMOVEXATTR) +#ifndef XATTR_ADD_OPT return removexattr(path, name); +#else + int options = 0; + return removexattr(path, name, options); +#endif #elif defined(HAVE_REMOVEEA) return removeea(path, name); #elif defined(HAVE_EXTATTR_DELETE_FILE) @@ -1783,6 +1951,9 @@ int sys_lremovexattr (const char *path, const char *name) { #if defined(HAVE_LREMOVEXATTR) return lremovexattr(path, name); +#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return removexattr(path, name, options); #elif defined(HAVE_LREMOVEEA) return lremoveea(path, name); #elif defined(HAVE_EXTATTR_DELETE_LINK) @@ -1808,7 +1979,12 @@ int sys_lremovexattr (const char *path, const char *name) int sys_fremovexattr (int filedes, const char *name) { #if defined(HAVE_FREMOVEXATTR) +#ifndef XATTR_ADD_OPT return fremovexattr(filedes, name); +#else + int options = 0; + return fremovexattr(filedes, name, options); +#endif #elif defined(HAVE_FREMOVEEA) return fremoveea(filedes, name); #elif defined(HAVE_EXTATTR_DELETE_FD) @@ -1839,7 +2015,12 @@ int sys_fremovexattr (int filedes, const char *name) int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) { #if defined(HAVE_SETXATTR) +#ifndef XATTR_ADD_OPT return setxattr(path, name, value, size, flags); +#else + int options = 0; + return setxattr(path, name, value, size, 0, options); +#endif #elif defined(HAVE_SETEA) return setea(path, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_FILE) @@ -1888,6 +2069,9 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t { #if defined(HAVE_LSETXATTR) return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return setxattr(path, name, value, size, 0, options); #elif defined(LSETEA) return lsetea(path, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_LINK) @@ -1936,7 +2120,12 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) { #if defined(HAVE_FSETXATTR) +#ifndef XATTR_ADD_OPT return fsetxattr(filedes, name, value, size, flags); +#else + int options = 0; + return fsetxattr(filedes, name, value, size, 0, options); +#endif #elif defined(HAVE_FSETEA) return fsetea(filedes, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_FD) @@ -2164,3 +2353,28 @@ int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct return -1; } #endif /* WITH_AIO */ + +int sys_getpeereid( int s, uid_t *uid) +{ +#if defined(HAVE_PEERCRED) + struct ucred cred; + socklen_t cred_len = sizeof(struct ucred); + int ret; + + ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); + if (ret != 0) { + return -1; + } + + if (cred_len != sizeof(struct ucred)) { + errno = EINVAL; + return -1; + } + + *uid = cred.uid; + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} diff --git a/source/lib/system_smbd.c b/source/lib/system_smbd.c index fc506c901db..509b2bbcb1e 100644 --- a/source/lib/system_smbd.c +++ b/source/lib/system_smbd.c @@ -181,11 +181,18 @@ BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user, groups = NULL; /* Add in primary group first */ - add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp); + if (!add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp)) { + SAFE_FREE(temp_groups); + return False; + } - for (i=0; i<max_grp; i++) - add_gid_to_array_unique(mem_ctx, temp_groups[i], - &groups, &ngrp); + for (i=0; i<max_grp; i++) { + if (!add_gid_to_array_unique(mem_ctx, temp_groups[i], + &groups, &ngrp)) { + SAFE_FREE(temp_groups); + return False; + } + } *p_ngroups = ngrp; *ret_groups = groups; diff --git a/source/lib/talloc/Makefile.in b/source/lib/talloc/Makefile.in new file mode 100644 index 00000000000..14e81156921 --- /dev/null +++ b/source/lib/talloc/Makefile.in @@ -0,0 +1,71 @@ +#!gmake +# +prefix = @prefix@ +datarootdir = @datarootdir@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +mandir = @mandir@ +VPATH = @srcdir@:@libreplacedir@ +srcdir = @srcdir@ +builddir = @builddir@ +XSLTPROC = @XSLTPROC@ +INSTALLCMD = @INSTALL@ +CC = @CC@ +CFLAGS = @CFLAGS@ -DHAVE_CONFIG_H= -I. -I@srcdir@ -I@libreplacedir@ +EXTRA_TARGETS = @DOC_TARGET@ + +.SUFFIXES: .c .o .3 .3.xml .xml .html + +LIBOBJ = @TALLOCOBJ@ @LIBREPLACEOBJ@ + +all: showflags libtalloc.a testsuite $(EXTRA_TARGETS) + +showflags: + @echo 'talloc will be compiled with flags:' + @echo ' CFLAGS = $(CFLAGS)' + @echo ' LIBS = $(LIBS)' + +testsuite: $(LIBOBJ) testsuite.o + $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) + +libtalloc.a: $(LIBOBJ) + ar -rv $@ $(LIBOBJ) + @-ranlib $@ + +install: all + ${INSTALLCMD} -d ${libdir} + ${INSTALLCMD} -m 755 libtalloc.a $(libdir) + ${INSTALLCMD} -d ${includedir} + ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(includedir) + ${INSTALLCMD} -m 644 talloc.pc $(libdir)/pkgconfig + if [ -f talloc.3 ];then ${INSTALLCMD} -d ${mandir}/man3; fi + if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(mandir)/man3; fi + +doc: talloc.3 talloc.3.html + +.3.xml.3: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +.xml.html: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< + +clean: + rm -f *~ $(LIBOBJ) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html + +test: testsuite + ./testsuite + +gcov: + gcov talloc.c + +installcheck: + $(MAKE) test + +distclean: clean + rm -f *~ */*~ + rm -f Makefile + rm -f config.log config.status config.h config.cache + +realdistclean: distclean + rm -f configure config.h.in diff --git a/source/lib/talloc/aclocal.m4 b/source/lib/talloc/aclocal.m4 new file mode 100644 index 00000000000..5605e476bab --- /dev/null +++ b/source/lib/talloc/aclocal.m4 @@ -0,0 +1 @@ +m4_include(libreplace.m4) diff --git a/source/lib/talloc/autogen.sh b/source/lib/talloc/autogen.sh new file mode 100755 index 00000000000..bf84eeee19a --- /dev/null +++ b/source/lib/talloc/autogen.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f configure config.h.in + +IPATHS="-I libreplace -I lib/replace -I ../libreplace -I ../replace" +autoconf $IPATHS || exit 1 +autoheader $IPATHS || exit 1 + +rm -rf autom4te.cache + +echo "Now run ./configure and then make." +exit 0 + diff --git a/source/lib/talloc/config.guess b/source/lib/talloc/config.guess new file mode 100755 index 00000000000..ad5281e66e9 --- /dev/null +++ b/source/lib/talloc/config.guess @@ -0,0 +1,1466 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-08-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess +and + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/source/lib/talloc/config.mk b/source/lib/talloc/config.mk new file mode 100644 index 00000000000..0b06687dabd --- /dev/null +++ b/source/lib/talloc/config.mk @@ -0,0 +1,18 @@ +################################################ +# Start LIBRARY LIBTALLOC +[LIBRARY::LIBTALLOC] +VERSION = 0.0.1 +SO_VERSION = 0 +OBJ_FILES = talloc.o +MANPAGE = talloc.3 +CFLAGS = -Ilib/talloc +PUBLIC_HEADERS = talloc.h +DESCRIPTION = A hierarchical pool based memory system with destructors +# +# End LIBRARY LIBTALLOC +################################################ + +[BINARY::TALLOC] +OBJ_FILES = testsuite.o +PRIVATE_DEPENDENCIES = LIBTALLOC +INSTALLDIR = TORTUREDIR/LOCAL diff --git a/source/lib/talloc/config.sub b/source/lib/talloc/config.sub new file mode 100755 index 00000000000..1c366dfde9a --- /dev/null +++ b/source/lib/talloc/config.sub @@ -0,0 +1,1579 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-07-08' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/source/lib/talloc/configure.ac b/source/lib/talloc/configure.ac new file mode 100644 index 00000000000..51e7256bf88 --- /dev/null +++ b/source/lib/talloc/configure.ac @@ -0,0 +1,18 @@ +AC_PREREQ(2.50) +AC_INIT(talloc.h) +AC_CONFIG_SRCDIR([talloc.c]) +AC_SUBST(datarootdir) +AC_CONFIG_HEADER(config.h) + +AC_LIBREPLACE_ALL_CHECKS + +m4_include(libtalloc.m4) + +AC_PATH_PROG(XSLTPROC,xsltproc) +DOC_TARGET="" +if test -n "$XSLTPROC"; then + DOC_TARGET=doc +fi +AC_SUBST(DOC_TARGET) + +AC_OUTPUT(Makefile talloc.pc) diff --git a/source/lib/talloc/install-sh b/source/lib/talloc/install-sh new file mode 100755 index 00000000000..58719246f04 --- /dev/null +++ b/source/lib/talloc/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/source/lib/talloc/libtalloc.m4 b/source/lib/talloc/libtalloc.m4 new file mode 100644 index 00000000000..4a0ee3c8fc5 --- /dev/null +++ b/source/lib/talloc/libtalloc.m4 @@ -0,0 +1,27 @@ +dnl find the talloc sources. This is meant to work both for +dnl talloc standalone builds, and builds of packages using talloc +tallocdir="" +tallocpaths="$srcdir $srcdir/lib/talloc $srcdir/talloc $srcdir/../talloc" +for d in $tallocpaths; do + if test -f "$d/talloc.c"; then + tallocdir="$d" + AC_SUBST(tallocdir) + break; + fi +done +if test x"$tallocdir" = "x"; then + AC_MSG_ERROR([cannot find talloc source in $tallocpaths]) +fi +TALLOCOBJ="talloc.o" +AC_SUBST(TALLOCOBJ) + +AC_CHECK_SIZEOF(size_t,cross) +AC_CHECK_SIZEOF(void *,cross) + +if test $ac_cv_sizeof_size_t -lt $ac_cv_sizeof_void_p; then + AC_WARN([size_t cannot represent the amount of used memory of a process]) + AC_WARN([please report this to <samba-technical@samba.org>]) + AC_WARN([sizeof(size_t) = $ac_cv_sizeof_size_t]) + AC_WARN([sizeof(void *) = $ac_cv_sizeof_void_p]) + AC_ERROR([sizeof(size_t) < sizeof(void *)]) +fi diff --git a/source/lib/talloc/talloc.3.xml b/source/lib/talloc/talloc.3.xml new file mode 100644 index 00000000000..2400fef2dc5 --- /dev/null +++ b/source/lib/talloc/talloc.3.xml @@ -0,0 +1,718 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> +<refentry> + <refmeta> + <refentrytitle>talloc</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + <refnamediv> + <refname>talloc</refname> +<refpurpose>hierarchical reference counted memory pool system with destructors</refpurpose> + </refnamediv> + <refsynopsisdiv> +<synopsis>#include <talloc/talloc.h></synopsis> + </refsynopsisdiv> + <refsect1><title>DESCRIPTION</title> + <para> + If you are used to talloc from Samba3 then please read this + carefully, as talloc has changed a lot. + </para> + <para> + The new talloc is a hierarchical, reference counted memory pool + system with destructors. Quite a mouthful really, but not too bad + once you get used to it. + </para> + <para> + Perhaps the biggest change from Samba3 is that there is no + distinction between a "talloc context" and a "talloc pointer". Any + pointer returned from talloc() is itself a valid talloc context. + This means you can do this: + </para> + <programlisting> + struct foo *X = talloc(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + </programlisting> + <para> + and the pointer <literal role="code">X->name</literal> + would be a "child" of the talloc context <literal + role="code">X</literal> which is itself a child of + <literal role="code">mem_ctx</literal>. So if you do + <literal role="code">talloc_free(mem_ctx)</literal> then + it is all destroyed, whereas if you do <literal + role="code">talloc_free(X)</literal> then just <literal + role="code">X</literal> and <literal + role="code">X->name</literal> are destroyed, and if + you do <literal + role="code">talloc_free(X->name)</literal> then just + the name element of <literal role="code">X</literal> is + destroyed. + </para> + <para> + If you think about this, then what this effectively gives you is an + n-ary tree, where you can free any part of the tree with + talloc_free(). + </para> + <para> + If you find this confusing, then I suggest you run the <literal + role="code">testsuite</literal> program to watch talloc + in action. You may also like to add your own tests to <literal + role="code">testsuite.c</literal> to clarify how some + particular situation is handled. + </para> + </refsect1> + <refsect1><title>TALLOC API</title> + <para> + The following is a complete guide to the talloc API. Read it all at + least twice. + </para> + <refsect2><title>(type *)talloc(const void *ctx, type);</title> + <para> + The talloc() macro is the core of the talloc library. It takes a + memory <emphasis role="italic">ctx</emphasis> and a <emphasis + role="italic">type</emphasis>, and returns a pointer to a new + area of memory of the given <emphasis + role="italic">type</emphasis>. + </para> + <para> + The returned pointer is itself a talloc context, so you can use + it as the <emphasis role="italic">ctx</emphasis> argument to more + calls to talloc() if you wish. + </para> + <para> + The returned pointer is a "child" of the supplied context. This + means that if you talloc_free() the <emphasis + role="italic">ctx</emphasis> then the new child disappears as + well. Alternatively you can free just the child. + </para> + <para> + The <emphasis role="italic">ctx</emphasis> argument to talloc() + can be NULL, in which case a new top level context is created. + </para> + </refsect2> + <refsect2><title>void *talloc_size(const void *ctx, size_t size);</title> + <para> + The function talloc_size() should be used when you don't have a + convenient type to pass to talloc(). Unlike talloc(), it is not + type safe (as it returns a void *), so you are on your own for + type checking. + </para> + </refsect2> + <refsect2><title>(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);</title> + <para> + The talloc_ptrtype() macro should be used when you have a pointer and + want to allocate memory to point at with this pointer. When compiling + with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() + and talloc_get_name() will return the current location in the source file. + and not the type. + </para> + </refsect2> + <refsect2><title>int talloc_free(void *ptr);</title> + <para> + The talloc_free() function frees a piece of talloc memory, and + all its children. You can call talloc_free() on any pointer + returned by talloc(). + </para> + <para> + The return value of talloc_free() indicates success or failure, + with 0 returned for success and -1 for failure. The only + possible failure condition is if <emphasis + role="italic">ptr</emphasis> had a destructor attached to it and + the destructor returned -1. See <link + linkend="talloc_set_destructor"><quote>talloc_set_destructor()</quote></link> + for details on destructors. + </para> + <para> + If this pointer has an additional parent when talloc_free() is + called then the memory is not actually released, but instead the + most recently established parent is destroyed. See <link + linkend="talloc_reference"><quote>talloc_reference()</quote></link> + for details on establishing additional parents. + </para> + <para> + For more control on which parent is removed, see <link + linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>. + </para> + <para> + talloc_free() operates recursively on its children. + </para> + </refsect2> + <refsect2 id="talloc_reference"><title>void *talloc_reference(const void *ctx, const void *ptr);</title> + <para> + The talloc_reference() function makes <emphasis + role="italic">ctx</emphasis> an additional parent of <emphasis + role="italic">ptr</emphasis>. + </para> + <para> + The return value of talloc_reference() is always the original + pointer <emphasis role="italic">ptr</emphasis>, unless talloc ran + out of memory in creating the reference in which case it will + return NULL (each additional reference consumes around 48 bytes + of memory on intel x86 platforms). + </para> + <para> + If <emphasis role="italic">ptr</emphasis> is NULL, then the + function is a no-op, and simply returns NULL. + </para> + <para> + After creating a reference you can free it in one of the + following ways: + </para> + <para> + <itemizedlist> + <listitem> + <para> + you can talloc_free() any parent of the original pointer. + That will reduce the number of parents of this pointer by 1, + and will cause this pointer to be freed if it runs out of + parents. + </para> + </listitem> + <listitem> + <para> + you can talloc_free() the pointer itself. That will destroy + the most recently established parent to the pointer and leave + the pointer as a child of its current parent. + </para> + </listitem> + </itemizedlist> + </para> + <para> + For more control on which parent to remove, see <link + linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>. + </para> + </refsect2> + <refsect2 id="talloc_unlink"><title>int talloc_unlink(const void *ctx, const void *ptr);</title> + <para> + The talloc_unlink() function removes a specific parent from + <emphasis role="italic">ptr</emphasis>. The <emphasis + role="italic">ctx</emphasis> passed must either be a context used + in talloc_reference() with this pointer, or must be a direct + parent of ptr. + </para> + <para> + Note that if the parent has already been removed using + talloc_free() then this function will fail and will return -1. + Likewise, if <emphasis role="italic">ptr</emphasis> is NULL, then + the function will make no modifications and return -1. + </para> + <para> + Usually you can just use talloc_free() instead of + talloc_unlink(), but sometimes it is useful to have the + additional control on which parent is removed. + </para> + </refsect2> + <refsect2 id="talloc_set_destructor"><title>void talloc_set_destructor(const void *ptr, int (*destructor)(void *));</title> + <para> + The function talloc_set_destructor() sets the <emphasis + role="italic">destructor</emphasis> for the pointer <emphasis + role="italic">ptr</emphasis>. A <emphasis + role="italic">destructor</emphasis> is a function that is called + when the memory used by a pointer is about to be released. The + destructor receives <emphasis role="italic">ptr</emphasis> as an + argument, and should return 0 for success and -1 for failure. + </para> + <para> + The <emphasis role="italic">destructor</emphasis> can do anything + it wants to, including freeing other pieces of memory. A common + use for destructors is to clean up operating system resources + (such as open file descriptors) contained in the structure the + destructor is placed on. + </para> + <para> + You can only place one destructor on a pointer. If you need more + than one destructor then you can create a zero-length child of + the pointer and place an additional destructor on that. + </para> + <para> + To remove a destructor call talloc_set_destructor() with NULL for + the destructor. + </para> + <para> + If your destructor attempts to talloc_free() the pointer that it + is the destructor for then talloc_free() will return -1 and the + free will be ignored. This would be a pointless operation + anyway, as the destructor is only called when the memory is just + about to go away. + </para> + </refsect2> + <refsect2><title>int talloc_increase_ref_count(const void *<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_increase_ref_count(<emphasis + role="italic">ptr</emphasis>) function is exactly equivalent to: + </para> + <programlisting>talloc_reference(NULL, ptr);</programlisting> + <para> + You can use either syntax, depending on which you think is + clearer in your code. + </para> + <para> + It returns 0 on success and -1 on failure. + </para> + </refsect2> + <refsect2><title>size_t talloc_reference_count(const void *<emphasis role="italic">ptr</emphasis>);</title> + <para> + Return the number of references to the pointer. + </para> + </refsect2> + <refsect2 id="talloc_set_name"><title>void talloc_set_name(const void *ptr, const char *fmt, ...);</title> + <para> + Each talloc pointer has a "name". The name is used principally + for debugging purposes, although it is also possible to set and + get the name on a pointer in as a way of "marking" pointers in + your code. + </para> + <para> + The main use for names on pointer is for "talloc reports". See + <link + linkend="talloc_report"><quote>talloc_report_depth_cb()</quote></link>, + <link + linkend="talloc_report"><quote>talloc_report_depth_file()</quote></link>, + <link + linkend="talloc_report"><quote>talloc_report()</quote></link> + <link + linkend="talloc_report"><quote>talloc_report()</quote></link> + and <link + linkend="talloc_report_full"><quote>talloc_report_full()</quote></link> + for details. Also see <link + linkend="talloc_enable_leak_report"><quote>talloc_enable_leak_report()</quote></link> + and <link + linkend="talloc_enable_leak_report_full"><quote>talloc_enable_leak_report_full()</quote></link>. + </para> + <para> + The talloc_set_name() function allocates memory as a child of the + pointer. It is logically equivalent to: + </para> + <programlisting>talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));</programlisting> + <para> + Note that multiple calls to talloc_set_name() will allocate more + memory without releasing the name. All of the memory is released + when the ptr is freed using talloc_free(). + </para> + </refsect2> + <refsect2><title>void talloc_set_name_const(const void *<emphasis role="italic">ptr</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title> + <para> + The function talloc_set_name_const() is just like + talloc_set_name(), but it takes a string constant, and is much + faster. It is extensively used by the "auto naming" macros, such + as talloc_p(). + </para> + <para> + This function does not allocate any memory. It just copies the + supplied pointer into the internal representation of the talloc + ptr. This means you must not pass a <emphasis + role="italic">name</emphasis> pointer to memory that will + disappear before <emphasis role="italic">ptr</emphasis> is freed + with talloc_free(). + </para> + </refsect2> + <refsect2><title>void *talloc_named(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title> + <para> + The talloc_named() function creates a named talloc pointer. It + is equivalent to: + </para> + <programlisting>ptr = talloc_size(ctx, size); +talloc_set_name(ptr, fmt, ....);</programlisting> + </refsect2> + <refsect2><title>void *talloc_named_const(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title> + <para> + This is equivalent to: + </para> + <programlisting>ptr = talloc_size(ctx, size); +talloc_set_name_const(ptr, name);</programlisting> + </refsect2> + <refsect2><title>const char *talloc_get_name(const void *<emphasis role="italic">ptr</emphasis>);</title> + <para> + This returns the current name for the given talloc pointer, + <emphasis role="italic">ptr</emphasis>. See <link + linkend="talloc_set_name"><quote>talloc_set_name()</quote></link> + for details. + </para> + </refsect2> + <refsect2><title>void *talloc_init(const char *<emphasis role="italic">fmt</emphasis>, ...);</title> + <para> + This function creates a zero length named talloc context as a top + level context. It is equivalent to: + </para> + <programlisting>talloc_named(NULL, 0, fmt, ...);</programlisting> + </refsect2> + <refsect2><title>void *talloc_new(void *<emphasis role="italic">ctx</emphasis>);</title> + <para> + This is a utility macro that creates a new memory context hanging + off an exiting context, automatically naming it "talloc_new: + __location__" where __location__ is the source line it is called + from. It is particularly useful for creating a new temporary + working context. + </para> + </refsect2> + <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_realloc(const void *<emphasis role="italic">ctx</emphasis>, void *<emphasis role="italic">ptr</emphasis>, <emphasis role="italic">type</emphasis>, <emphasis role="italic">count</emphasis>);</title> + <para> + The talloc_realloc() macro changes the size of a talloc pointer. + It has the following equivalences: + </para> + <programlisting>talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); +talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);</programlisting> + <para> + The <emphasis role="italic">ctx</emphasis> argument is only used + if <emphasis role="italic">ptr</emphasis> is not NULL, otherwise + it is ignored. + </para> + <para> + talloc_realloc() returns the new pointer, or NULL on failure. + The call will fail either due to a lack of memory, or because the + pointer has more than one parent (see <link + linkend="talloc_reference"><quote>talloc_reference()</quote></link>). + </para> + </refsect2> + <refsect2><title>void *talloc_realloc_size(const void *ctx, void *ptr, size_t size);</title> + <para> + the talloc_realloc_size() function is useful when the type is not + known so the type-safe talloc_realloc() cannot be used. + </para> + </refsect2> + <refsect2><title>TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_steal() function changes the parent context of a + talloc pointer. It is typically used when the context that the + pointer is currently a child of is going to be freed and you wish + to keep the memory for a longer time. + </para> + <para> + The talloc_steal() function returns the pointer that you pass it. + It does not have any failure modes. + </para> + <para> + NOTE: It is possible to produce loops in the parent/child + relationship if you are not careful with talloc_steal(). No + guarantees are provided as to your sanity or the safety of your + data if you do this. + </para> + </refsect2> + <refsect2><title>TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE **<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_move() function is a wrapper around + talloc_steal() which zeros the source pointer after the + move. This avoids a potential source of bugs where a + programmer leaves a pointer in two structures, and uses the + pointer from the old structure after it has been moved to a + new one. + </para> + </refsect2> + <refsect2><title>size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_total_size() function returns the total size in bytes + used by this pointer and all child pointers. Mostly useful for + debugging. + </para> + <para> + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + </para> + </refsect2> + <refsect2><title>size_t talloc_total_blocks(const void *<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_total_blocks() function returns the total memory block + count used by this pointer and all child pointers. Mostly useful + for debugging. + </para> + <para> + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + </para> + </refsect2> + <refsect2 id="talloc_report"><title>void talloc_report(const void *ptr, FILE *f);</title> + <para> + The talloc_report() function prints a summary report of all + memory used by <emphasis role="italic">ptr</emphasis>. One line + of report is printed for each immediate child of ptr, showing the + total memory and number of blocks used by that child. + </para> + <para> + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + </para> + </refsect2> + <refsect2 id="talloc_report_full"><title>void talloc_report_full(const void *<emphasis role="italic">ptr</emphasis>, FILE *<emphasis role="italic">f</emphasis>);</title> + <para> + This provides a more detailed report than talloc_report(). It + will recursively print the entire tree of memory referenced by + the pointer. References in the tree are shown by giving the name + of the pointer that is referenced. + </para> + <para> + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + </para> + </refsect2> + <refsect2 id="talloc_report_depth_cb"> + <funcsynopsis><funcprototype> + <funcdef>void <function>talloc_report_depth_cb</function></funcdef> + <paramdef><parameter>const void *ptr</parameter></paramdef> + <paramdef><parameter>int depth</parameter></paramdef> + <paramdef><parameter>int max_depth</parameter></paramdef> + <paramdef><parameter>void (*callback)(const void *ptr, int depth, int max_depth, int is_ref, void *priv)</parameter></paramdef> + <paramdef><parameter>void *priv</parameter></paramdef> + </funcprototype></funcsynopsis> + <para> + This provides a more flexible reports than talloc_report(). It + will recursively call the callback for the entire tree of memory + referenced by the pointer. References in the tree are passed with + <emphasis role="italic">is_ref = 1</emphasis> and the pointer that is referenced. + </para> + <para> + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + </para> + <para> + The recursion is stopped when depth >= max_depth. + max_depth = -1 means only stop at leaf nodes. + </para> + </refsect2> + <refsect2 id="talloc_report_depth_file"> + <funcsynopsis><funcprototype> + <funcdef>void <function>talloc_report_depth_file</function></funcdef> + <paramdef><parameter>const void *ptr</parameter></paramdef> + <paramdef><parameter>int depth</parameter></paramdef> + <paramdef><parameter>int max_depth</parameter></paramdef> + <paramdef><parameter>FILE *f</parameter></paramdef> + </funcprototype></funcsynopsis> + <para> + This provides a more flexible reports than talloc_report(). It + will let you specify the depth and max_depth. + </para> + </refsect2> + <refsect2 id="talloc_enable_leak_report"><title>void talloc_enable_leak_report(void);</title> + <para> + This enables calling of talloc_report(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report command line option. + </para> + <para> + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + </para> + <para> + Here is a typical talloc report: + </para> + <screen format="linespecific">talloc report on 'null_context' (total 267 bytes in 15 blocks) +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(UTF8,CP850) contains 42 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(CP850,UTF8) contains 42 bytes in 2 blocks +iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks +iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + </screen> + </refsect2> + <refsect2 id="talloc_enable_leak_report_full"><title>void talloc_enable_leak_report_full(void);</title> + <para> + This enables calling of talloc_report_full(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report-full command line option. + </para> + <para> + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + </para> + <para> + Here is a typical full report: + </para> + <screen format="linespecific">full talloc report on 'root' (total 18 bytes in 8 blocks) +p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + </screen> + </refsect2> + <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_zero(const void *<emphasis role="italic">ctx</emphasis>, <emphasis role="italic">type</emphasis>);</title> + <para> + The talloc_zero() macro is equivalent to: + </para> + <programlisting>ptr = talloc(ctx, type); +if (ptr) memset(ptr, 0, sizeof(type));</programlisting> + </refsect2> + <refsect2><title>void *talloc_zero_size(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>)</title> + <para> + The talloc_zero_size() function is useful when you don't have a + known type. + </para> + </refsect2> + <refsect2><title>void *talloc_memdup(const void *<emphasis role="italic">ctx</emphasis>, const void *<emphasis role="italic">p</emphasis>, size_t size);</title> + <para> + The talloc_memdup() function is equivalent to: + </para> + <programlisting>ptr = talloc_size(ctx, size); +if (ptr) memcpy(ptr, p, size);</programlisting> + </refsect2> + <refsect2><title>char *talloc_strdup(const void *<emphasis role="italic">ctx</emphasis>, const char *<emphasis role="italic">p</emphasis>);</title> + <para> + The talloc_strdup() function is equivalent to: + </para> + <programlisting>ptr = talloc_size(ctx, strlen(p)+1); +if (ptr) memcpy(ptr, p, strlen(p)+1);</programlisting> + <para> + This function sets the name of the new pointer to the passed + string. This is equivalent to: + </para> + <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> + </refsect2> + <refsect2><title>char *talloc_strndup(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">p</emphasis>, size_t <emphasis role="italic">n</emphasis>);</title> + <para> + The talloc_strndup() function is the talloc equivalent of the C + library function strndup(3). + </para> + <para> + This function sets the name of the new pointer to the passed + string. This is equivalent to: + </para> + <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> + </refsect2> + <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> + <para> + The talloc_vasprintf() function is the talloc equivalent of the C + library function vasprintf(3). + </para> + </refsect2> + <refsect2><title>char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title> + <para> + The talloc_asprintf() function is the talloc equivalent of the C + library function asprintf(3). + </para> + <para> + This function sets the name of the new pointer to the passed + string. This is equivalent to: + </para> + <programlisting>talloc_set_name_const(ptr, ptr)</programlisting> + </refsect2> + <refsect2><title>char *talloc_asprintf_append(char *s, const char *fmt, ...);</title> + <para> + The talloc_asprintf_append() function appends the given formatted + string to the given string. + </para> + </refsect2> + <refsect2><title>(type *)talloc_array(const void *ctx, type, uint_t count);</title> + <para> + The talloc_array() macro is equivalent to: + </para> + <programlisting>(type *)talloc_size(ctx, sizeof(type) * count);</programlisting> + <para> + except that it provides integer overflow protection for the + multiply, returning NULL if the multiply overflows. + </para> + </refsect2> + <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, uint_t count);</title> + <para> + The talloc_array_size() function is useful when the type is not + known. It operates in the same way as talloc_array(), but takes a + size instead of a type. + </para> + </refsect2> + <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);</title> + <para> + The talloc_ptrtype() macro should be used when you have a pointer to an array + and want to allocate memory of an array to point at with this pointer. When compiling + with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() + and talloc_get_name() will return the current location in the source file. + and not the type. + </para> + </refsect2> + <refsect2><title>void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size)</title> + <para> + This is a non-macro version of talloc_realloc(), which is useful + as libraries sometimes want a realloc function pointer. A + realloc(3) implementation encapsulates the functionality of + malloc(3), free(3) and realloc(3) in one call, which is why it is + useful to be able to pass around a single function pointer. + </para> + </refsect2> + <refsect2><title>void *talloc_autofree_context(void);</title> + <para> + This is a handy utility function that returns a talloc context + which will be automatically freed on program exit. This can be + used to reduce the noise in memory leak reports. + </para> + </refsect2> + <refsect2><title>void *talloc_check_name(const void *ptr, const char *name);</title> + <para> + This function checks if a pointer has the specified <emphasis + role="italic">name</emphasis>. If it does then the pointer is + returned. It it doesn't then NULL is returned. + </para> + </refsect2> + <refsect2><title>(type *)talloc_get_type(const void *ptr, type);</title> + <para> + This macro allows you to do type checking on talloc pointers. It + is particularly useful for void* private pointers. It is + equivalent to this: + </para> + <programlisting>(type *)talloc_check_name(ptr, #type)</programlisting> + </refsect2> + <refsect2><title>talloc_set_type(const void *ptr, type);</title> + <para> + This macro allows you to force the name of a pointer to be a + particular <emphasis>type</emphasis>. This can be + used in conjunction with talloc_get_type() to do type checking on + void* pointers. + </para> + <para> + It is equivalent to this: + </para> + <programlisting>talloc_set_name_const(ptr, #type)</programlisting> + </refsect2> + </refsect1> + <refsect1><title>PERFORMANCE</title> + <para> + All the additional features of talloc(3) over malloc(3) do come at a + price. We have a simple performance test in Samba4 that measures + talloc() versus malloc() performance, and it seems that talloc() is + about 10% slower than malloc() on my x86 Debian Linux box. For + Samba, the great reduction in code complexity that we get by using + talloc makes this worthwhile, especially as the total overhead of + talloc/malloc in Samba is already quite small. + </para> + </refsect1> + <refsect1><title>SEE ALSO</title> + <para> + malloc(3), strndup(3), vasprintf(3), asprintf(3), + <ulink url="http://talloc.samba.org/"/> + </para> + </refsect1> + <refsect1><title>COPYRIGHT/LICENSE</title> + <para> + Copyright (C) Andrew Tridgell 2004 + </para> + <para> + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at + your option) any later version. + </para> + <para> + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + </para> + <para> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + </para> + </refsect1> +</refentry> diff --git a/source/lib/talloc.c b/source/lib/talloc/talloc.c index 51087ef9791..028b44a8c72 100644 --- a/source/lib/talloc.c +++ b/source/lib/talloc/talloc.c @@ -1,4 +1,4 @@ -/* +/* Samba Unix SMB/CIFS implementation. Samba trivial allocation library - new interface @@ -6,11 +6,12 @@ NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 - + Copyright (C) Stefan Metzmacher 2006 + ** NOTE! The following LGPL license applies to the talloc ** library. This does NOT imply that all of Samba is released ** under the LGPL - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -31,8 +32,9 @@ */ #ifdef _SAMBA_BUILD_ +#include "version.h" +#if (SAMBA_VERSION_MAJOR<4) #include "includes.h" -#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file * we trust ourselves... */ #ifdef malloc @@ -41,17 +43,14 @@ #ifdef realloc #undef realloc #endif -#endif -#else -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <stdint.h> +#define _TALLOC_SAMBA3 +#endif /* (SAMBA_VERSION_MAJOR<4) */ +#endif /* _SAMBA_BUILD_ */ + +#ifndef _TALLOC_SAMBA3 +#include "replace.h" #include "talloc.h" -/* assume a modern system */ -#define HAVE_VA_COPY -#endif +#endif /* not _TALLOC_SAMBA3 */ /* use this to force every realloc to change the pointer, to stress test code that might not cope */ @@ -78,13 +77,23 @@ #endif #endif +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) x +#define unlikely(x) x +#endif + /* this null_context is only used if talloc_enable_leak_report() or talloc_enable_leak_report_full() is called, otherwise it remains NULL */ -static const void *null_context; -static void *cleanup_context; - +static void *null_context; +static void *autofree_context; struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; @@ -108,15 +117,16 @@ struct talloc_chunk { #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) /* panic if we get a bad magic value */ -static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - const char *pp = ptr; + const char *pp = (const char *)ptr; struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); - if ((tc->flags & ~0xF) != TALLOC_MAGIC) { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - if (tc->flags & TALLOC_FLAG_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { + if (tc->flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } else { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } } return tc; } @@ -152,10 +162,17 @@ do { \ /* return the parent chunk of a pointer */ -static struct talloc_chunk *talloc_parent_chunk(const void *ptr) +static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) { - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); while (tc->prev) tc=tc->prev; + return tc->parent; } @@ -165,23 +182,32 @@ void *talloc_parent(const void *ptr) return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } +/* + find parents name +*/ +const char *talloc_parent_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? tc->name : NULL; +} + /* Allocate a bit of memory as a child of an existing pointer */ -void *_talloc(const void *context, size_t size) +static inline void *__talloc(const void *context, size_t size) { struct talloc_chunk *tc; - if (context == NULL) { + if (unlikely(context == NULL)) { context = null_context; } - if (size >= MAX_TALLOC_SIZE) { + if (unlikely(size >= MAX_TALLOC_SIZE)) { return NULL; } - tc = malloc(TC_HDR_SIZE+size); - if (tc == NULL) return NULL; + tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); + if (unlikely(tc == NULL)) return NULL; tc->size = size; tc->flags = TALLOC_MAGIC; @@ -190,16 +216,19 @@ void *_talloc(const void *context, size_t size) tc->name = NULL; tc->refs = NULL; - if (context) { + if (likely(context)) { struct talloc_chunk *parent = talloc_chunk_from_ptr(context); - tc->parent = parent; - if (parent->child) { parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; } - - _TLIST_ADD(parent->child, tc); + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; } else { tc->next = tc->prev = tc->parent = NULL; } @@ -207,14 +236,13 @@ void *_talloc(const void *context, size_t size) return TC_PTR_FROM_CHUNK(tc); } - /* setup a destructor to be called on free of a pointer the destructor should return 0 on success, or -1 on failure. if the destructor fails then the free is failed, and the memory can be continued to be used */ -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->destructor = destructor; @@ -223,28 +251,54 @@ void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) /* increase the reference count on a piece of memory. */ -void talloc_increase_ref_count(const void *ptr) +int talloc_increase_ref_count(const void *ptr) { - talloc_reference(null_context, ptr); + if (unlikely(!talloc_reference(null_context, ptr))) { + return -1; + } + return 0; } /* helper for talloc_reference() + + this is referenced by a function pointer and should not be inline */ -static int talloc_reference_destructor(void *ptr) +static int talloc_reference_destructor(struct talloc_reference_handle *handle) { - struct talloc_reference_handle *handle = ptr; - struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); - struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); - if (tc1->destructor != (talloc_destructor_t)-1) { - tc1->destructor = NULL; - } - _TLIST_REMOVE(tc2->refs, handle); - talloc_free(handle); + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); return 0; } /* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +static inline void *_talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _talloc_set_name_const(ptr, name); + + return ptr; +} + +/* make a secondary reference to a pointer, hanging off the given context. the pointer remains valid until both the original caller and this given context are freed. @@ -253,16 +307,17 @@ static int talloc_reference_destructor(void *ptr) same underlying data, and you want to be able to free the two instances separately, and in either order */ -void *talloc_reference(const void *context, const void *ptr) +void *_talloc_reference(const void *context, const void *ptr) { struct talloc_chunk *tc; struct talloc_reference_handle *handle; - if (ptr == NULL) return NULL; + if (unlikely(ptr == NULL)) return NULL; tc = talloc_chunk_from_ptr(ptr); - handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); - - if (handle == NULL) return NULL; + handle = (struct talloc_reference_handle *)_talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); + if (unlikely(handle == NULL)) return NULL; /* note that we hang the destructor off the handle, not the main context as that allows the caller to still setup their @@ -273,17 +328,163 @@ void *talloc_reference(const void *context, const void *ptr) return handle->ptr; } + +/* + internal talloc_free call +*/ +static inline int _talloc_free(void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs)) { + int is_child; + /* check this is a reference from a child or grantchild + * back to it's parent or grantparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free(tc->refs); + if (is_child) { + return _talloc_free(ptr); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + if (unlikely(tc->destructor)) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free(child) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + talloc_steal(new_parent, child); + } + } + + tc->flags |= TALLOC_FLAG_FREE; + free(tc); + return 0; +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +void *_talloc_steal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + + + /* remove a secondary reference to a pointer. This undo's what talloc_reference() has done. The context and pointer arguments must match those given to a talloc_reference() */ -static int talloc_unreference(const void *context, const void *ptr) +static inline int talloc_unreference(const void *context, const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *h; - if (context == NULL) { + if (unlikely(context == NULL)) { context = null_context; } @@ -299,10 +500,7 @@ static int talloc_unreference(const void *context, const void *ptr) return -1; } - talloc_set_destructor(h, NULL); - _TLIST_REMOVE(tc->refs, h); - talloc_free(h); - return 0; + return _talloc_free(h); } /* @@ -339,7 +537,7 @@ int talloc_unlink(const void *context, void *ptr) tc_p = talloc_chunk_from_ptr(ptr); if (tc_p->refs == NULL) { - return talloc_free(ptr); + return _talloc_free(ptr); } new_p = talloc_parent_chunk(tc_p->refs); @@ -361,37 +559,31 @@ int talloc_unlink(const void *context, void *ptr) /* add a name to an existing pointer - va_list version */ -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = talloc_vasprintf(ptr, fmt, ap); - if (tc->name) { - talloc_set_name_const(tc->name, ".name"); + if (likely(tc->name)) { + _talloc_set_name_const(tc->name, ".name"); } + return tc->name; } /* add a name to an existing pointer */ -void talloc_set_name(const void *ptr, const char *fmt, ...) +const char *talloc_set_name(const void *ptr, const char *fmt, ...) { + const char *name; va_list ap; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); + return name; } -/* - more efficient way to add a name to a pointer - the name must point to a - true string constant -*/ -void talloc_set_name_const(const void *ptr, const char *name) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = name; -} /* create a named talloc pointer. Any talloc pointer can be named, and @@ -402,33 +594,20 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) { va_list ap; void *ptr; + const char *name; - ptr = _talloc(context, size); - if (ptr == NULL) return NULL; + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) return NULL; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); - return ptr; -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named_const(const void *context, size_t size, const char *name) -{ - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) { + if (unlikely(name == NULL)) { + _talloc_free(ptr); return NULL; } - talloc_set_name_const(ptr, name); - return ptr; } @@ -438,10 +617,10 @@ void *talloc_named_const(const void *context, size_t size, const char *name) const char *talloc_get_name(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - if (tc->name == TALLOC_MAGIC_REFERENCE) { + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { return ".reference"; } - if (tc->name) { + if (likely(tc->name)) { return tc->name; } return "UNNAMED"; @@ -455,9 +634,9 @@ const char *talloc_get_name(const void *ptr) void *talloc_check_name(const void *ptr, const char *name) { const char *pname; - if (ptr == NULL) return NULL; + if (unlikely(ptr == NULL)) return NULL; pname = talloc_get_name(ptr); - if (pname == name || strcmp(pname, name) == 0) { + if (likely(pname == name || strcmp(pname, name) == 0)) { return discard_const_p(void, ptr); } return NULL; @@ -471,16 +650,27 @@ void *talloc_init(const char *fmt, ...) { va_list ap; void *ptr; + const char *name; + /* + * samba3 expects talloc_report_depth_cb(NULL, ...) + * reports all talloc'ed memory, so we need to enable + * null_tracking + */ talloc_enable_null_tracking(); - ptr = _talloc(NULL, 0); - if (ptr == NULL) return NULL; + ptr = __talloc(NULL, 0); + if (unlikely(ptr == NULL)) return NULL; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); + if (unlikely(name == NULL)) { + _talloc_free(ptr); + return NULL; + } + return ptr; } @@ -493,7 +683,7 @@ void talloc_free_children(void *ptr) { struct talloc_chunk *tc; - if (ptr == NULL) { + if (unlikely(ptr == NULL)) { return; } @@ -507,11 +697,11 @@ void talloc_free_children(void *ptr) final choice is the null context. */ void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; - if (tc->child->refs) { + if (unlikely(tc->child->refs)) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); if (p) new_parent = TC_PTR_FROM_CHUNK(p); } - if (talloc_free(child) == -1) { + if (unlikely(_talloc_free(child) == -1)) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); if (p) new_parent = TC_PTR_FROM_CHUNK(p); @@ -522,6 +712,32 @@ void talloc_free_children(void *ptr) } /* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + return __talloc(context, size); +} + +/* + externally callable talloc_set_name_const() +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + _talloc_set_name_const(ptr, name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* free a talloc pointer. This also frees all child pointers of this pointer recursively @@ -531,61 +747,7 @@ void talloc_free_children(void *ptr) */ int talloc_free(void *ptr) { - struct talloc_chunk *tc; - - if (ptr == NULL) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->refs) { - int is_child; - struct talloc_reference_handle *handle = tc->refs; - is_child = talloc_is_parent(handle, handle->ptr); - talloc_reference_destructor(tc->refs); - if (is_child) { - return talloc_free(ptr); - } - return -1; - } - - if (tc->flags & TALLOC_FLAG_LOOP) { - /* we have a free loop - stop looping */ - return 0; - } - - if (tc->destructor) { - talloc_destructor_t d = tc->destructor; - if (d == (talloc_destructor_t)-1) { - return -1; - } - tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { - tc->destructor = d; - return -1; - } - tc->destructor = NULL; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - talloc_free_children(ptr); - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->flags |= TALLOC_FLAG_FREE; - - free(tc); - return 0; + return _talloc_free(ptr); } @@ -600,24 +762,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n void *new_ptr; /* size zero is equivalent to free() */ - if (size == 0) { - talloc_free(ptr); + if (unlikely(size == 0)) { + _talloc_free(ptr); return NULL; } - if (size >= MAX_TALLOC_SIZE) { + if (unlikely(size >= MAX_TALLOC_SIZE)) { return NULL; } - /* realloc(NULL) is equavalent to malloc() */ + /* realloc(NULL) is equivalent to malloc() */ if (ptr == NULL) { - return talloc_named_const(context, size, name); + return _talloc_named_const(context, size, name); } tc = talloc_chunk_from_ptr(ptr); /* don't allow realloc on referenced pointers */ - if (tc->refs) { + if (unlikely(tc->refs)) { return NULL; } @@ -633,18 +795,18 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n #else new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif - if (!new_ptr) { + if (unlikely(!new_ptr)) { tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } - tc = new_ptr; + tc = (struct talloc_chunk *)new_ptr; tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { - tc->parent->child = new_ptr; + tc->parent->child = tc; } if (tc->child) { - tc->child->parent = new_ptr; + tc->child->parent = tc; } if (tc->prev) { @@ -655,76 +817,31 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } tc->size = size; - talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); return TC_PTR_FROM_CHUNK(tc); } -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred. - passing NULL as ptr will always return NULL with no side effects. +/* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL */ -void *talloc_steal(const void *new_ctx, const void *ptr) +void *_talloc_move(const void *new_ctx, const void *_pptr) { - struct talloc_chunk *tc, *new_tc; - - if (!ptr) { - return NULL; - } - - if (new_ctx == NULL) { - new_ctx = null_context; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (new_ctx == NULL) { - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = tc->next = tc->prev = NULL; - return discard_const_p(void, ptr); - } - - new_tc = talloc_chunk_from_ptr(new_ctx); - - if (tc == new_tc || tc->parent == new_tc) { - return discard_const_p(void, ptr); - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = new_tc; - if (new_tc->child) new_tc->child->parent = NULL; - _TLIST_ADD(new_tc->child, tc); - - return discard_const_p(void, ptr); + const void **pptr = discard_const_p(const void *,_pptr); + void *ret = _talloc_steal(new_ctx, *pptr); + (*pptr) = NULL; + return ret; } /* return the total size of a talloc pool (subtree) */ -off_t talloc_total_size(const void *ptr) +size_t talloc_total_size(const void *ptr) { - off_t total = 0; + size_t total = 0; struct talloc_chunk *c, *tc; - + if (ptr == NULL) { ptr = null_context; } @@ -753,9 +870,9 @@ off_t talloc_total_size(const void *ptr) /* return the total number of blocks in a talloc pool (subtree) */ -off_t talloc_total_blocks(const void *ptr) +size_t talloc_total_blocks(const void *ptr) { - off_t total = 0; + size_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); if (tc->flags & TALLOC_FLAG_LOOP) { @@ -777,11 +894,11 @@ off_t talloc_total_blocks(const void *ptr) /* return the number of external references to a pointer */ -static int talloc_reference_count(const void *ptr) +size_t talloc_reference_count(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *h; - int ret = 0; + size_t ret = 0; for (h=tc->refs;h;h=h->next) { ret++; @@ -792,80 +909,110 @@ static int talloc_reference_count(const void *ptr) /* report on memory usage by all children of a pointer, giving a full tree view */ -void talloc_report_depth(const void *ptr, FILE *f, int depth) +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) { - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); if (tc->flags & TALLOC_FLAG_LOOP) { return; } - tc->flags |= TALLOC_FLAG_LOOP; + callback(ptr, depth, max_depth, 0, private_data); + if (max_depth >= 0 && depth >= max_depth) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); - const char *name2 = talloc_get_name(handle->ptr); - fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); } else { - const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), - talloc_reference_count(TC_PTR_FROM_CHUNK(c))); - talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); } } tc->flags &= ~TALLOC_FLAG_LOOP; } -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_full(const void *ptr, FILE *f) +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) { - if (ptr == NULL) { - ptr = null_context; + const char *name = talloc_get_name(ptr); + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; } - if (ptr == NULL) return; - fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", + depth*4, "", + name, (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); + (unsigned long)talloc_total_blocks(ptr), + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif +} - talloc_report_depth(ptr, f, 1); +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); fflush(f); } /* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + +/* report on memory usage by all children of a pointer */ void talloc_report(const void *ptr, FILE *f) { - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); - } - fflush(f); + talloc_report_depth_file(ptr, 0, 1, f); } /* @@ -889,92 +1036,23 @@ static void talloc_report_null_full(void) } /* - free allocated global memory -*/ - -void talloc_nc_free(void) -{ - if ( null_context ) - talloc_free( (void*)null_context ); -} - -/* enable tracking of the NULL context */ void talloc_enable_null_tracking(void) { if (null_context == NULL) { - null_context = talloc_named_const(NULL, 0, "null_context"); - } -} - -#ifdef _SAMBA_BUILD_ -/* Ugly calls to Samba-specific sprintf_append... JRA. */ - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth) -{ - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - if (tc->flags & TALLOC_FLAG_LOOP) { - return; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - for (c=tc->child;c;c=c->next) { - if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); - const char *name2 = talloc_get_name(handle->ptr); - - sprintf_append(NULL, pps, plen, pbuflen, - "%*sreference to: %s\n", depth*4, "", name2); - - } else { - const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); - - sprintf_append(NULL, pps, plen, pbuflen, - "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), - talloc_reference_count(TC_PTR_FROM_CHUNK(c))); - - talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1); - } + null_context = _talloc_named_const(NULL, 0, "null_context"); } - tc->flags &= ~TALLOC_FLAG_LOOP; } /* - report on memory usage by all children of a pointer + disable tracking of the NULL context */ -char *talloc_describe_all(void) +void talloc_disable_null_tracking(void) { - ssize_t len = 0; - size_t buflen = 512; - char *s = NULL; - - if (null_context == NULL) { - return NULL; - } - - sprintf_append(NULL, &s, &len, &buflen, - "full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(null_context), - (unsigned long)talloc_total_size(null_context), - (unsigned long)talloc_total_blocks(null_context)); - - if (!s) { - return NULL; - } - talloc_report_depth_str(null_context, &s, &len, &buflen, 1); - return s; + _talloc_free(null_context); + null_context = NULL; } -#endif /* enable leak reporting on exit @@ -999,7 +1077,7 @@ void talloc_enable_leak_report_full(void) */ void *_talloc_zero(const void *ctx, size_t size, const char *name) { - void *p = talloc_named_const(ctx, size, name); + void *p = _talloc_named_const(ctx, size, name); if (p) { memset(p, '\0', size); @@ -1014,9 +1092,9 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name) */ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) { - void *newp = talloc_named_const(t, size, name); + void *newp = _talloc_named_const(t, size, name); - if (newp) { + if (likely(newp)) { memcpy(newp, p, size); } @@ -1032,9 +1110,9 @@ char *talloc_strdup(const void *t, const char *p) if (!p) { return NULL; } - ret = talloc_memdup(t, p, strlen(p) + 1); - if (ret) { - talloc_set_name_const(ret, ret); + ret = (char *)talloc_memdup(t, p, strlen(p) + 1); + if (likely(ret)) { + _talloc_set_name_const(ret, ret); } return ret; } @@ -1073,21 +1151,19 @@ char *talloc_strndup(const void *t, const char *p, size_t n) for (len=0; len<n && p[len]; len++) ; - ret = _talloc(t, len + 1); + ret = (char *)__talloc(t, len + 1); if (!ret) { return NULL; } memcpy(ret, p, len); ret[len] = 0; - talloc_set_name_const(ret, ret); + _talloc_set_name_const(ret, ret); return ret; } -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) va_copy(dest, src) -#elif defined(HAVE___VA_COPY) -#define VA_COPY(dest, src) __va_copy(dest, src) +#ifndef HAVE_VA_COPY +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) #else -#define VA_COPY(dest, src) (dest) = (src) +#define va_copy(dest, src) (dest) = (src) #endif #endif @@ -1098,18 +1174,20 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) va_list ap2; char c; - VA_COPY(ap2, ap); - /* this call looks strange, but it makes it work on older solaris boxes */ - if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) { + va_copy(ap2, ap); + len = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + if (len < 0) { return NULL; } - ret = _talloc(t, len+1); + ret = (char *)__talloc(t, len+1); if (ret) { - VA_COPY(ap2, ap); + va_copy(ap2, ap); vsnprintf(ret, len+1, fmt, ap2); - talloc_set_name_const(ret, ret); + va_end(ap2); + _talloc_set_name_const(ret, ret); } return ret; @@ -1137,14 +1215,12 @@ char *talloc_asprintf(const void *t, const char *fmt, ...) * and return @p s, which may have moved. Good for gradually * accumulating output into a string buffer. **/ - -static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { struct talloc_chunk *tc; int len, s_len; va_list ap2; + char c; if (s == NULL) { return talloc_vasprintf(NULL, fmt, ap); @@ -1152,10 +1228,13 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) tc = talloc_chunk_from_ptr(s); - VA_COPY(ap2, ap); - s_len = tc->size - 1; - if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) { + + va_copy(ap2, ap); + len = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + + if (len <= 0) { /* Either the vsnprintf failed or the format resulted in * no characters being formatted. In the former case, we * ought to return NULL, in the latter we ought to return @@ -1168,10 +1247,10 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) s = talloc_realloc(NULL, s, char, s_len + len+1); if (!s) return NULL; - VA_COPY(ap2, ap); - + va_copy(ap2, ap); vsnprintf(s+s_len, len+1, fmt, ap2); - talloc_set_name_const(s, s); + va_end(ap2); + _talloc_set_name_const(s, s); return s; } @@ -1199,7 +1278,7 @@ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - return talloc_named_const(ctx, el_size * count, name); + return _talloc_named_const(ctx, el_size * count, name); } /* @@ -1236,10 +1315,15 @@ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) } +static int talloc_autofree_destructor(void *ptr) +{ + autofree_context = NULL; + return 0; +} + static void talloc_autofree(void) { - talloc_free(cleanup_context); - cleanup_context = NULL; + _talloc_free(autofree_context); } /* @@ -1248,11 +1332,12 @@ static void talloc_autofree(void) */ void *talloc_autofree_context(void) { - if (cleanup_context == NULL) { - cleanup_context = talloc_named_const(NULL, 0, "autofree_context"); + if (autofree_context == NULL) { + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); + talloc_set_destructor(autofree_context, talloc_autofree_destructor); atexit(talloc_autofree); } - return cleanup_context; + return autofree_context; } size_t talloc_get_size(const void *context) @@ -1287,7 +1372,6 @@ void *talloc_find_parent_byname(const void *context, const char *name) if (tc) { tc = tc->parent; } - } return NULL; } @@ -1313,12 +1397,13 @@ void talloc_show_parents(const void *context, FILE *file) tc = tc->parent; } } + fflush(file); } /* return 1 if ptr is a parent of context */ -int talloc_is_parent(const void *context, const char *ptr) +int talloc_is_parent(const void *context, const void *ptr) { struct talloc_chunk *tc; diff --git a/source/lib/talloc/talloc.h b/source/lib/talloc/talloc.h new file mode 100644 index 00000000000..75c130a2756 --- /dev/null +++ b/source/lib/talloc/talloc.h @@ -0,0 +1,168 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#define _STRING_LINE_(s) #s +#define _STRING_LINE2_(s) _STRING_LINE_(s) +#define __LINESTR__ _STRING_LINE2_(__LINE__) +#define __location__ __FILE__ ":" __LINESTR__ + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) +#endif + +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) + +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) + +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) + +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) + +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#endif + +/* The following definitions come from talloc.c */ +void *_talloc(const void *context, size_t size); +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)); +int talloc_increase_ref_count(const void *ptr); +size_t talloc_reference_count(const void *ptr); +void *_talloc_reference(const void *context, const void *ptr); +int talloc_unlink(const void *context, void *ptr); +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_check_name(const void *ptr, const char *name); +void *talloc_parent(const void *ptr); +const char *talloc_parent_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int talloc_free(void *ptr); +void talloc_free_children(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *_talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_move(const void *new_ctx, const void *pptr); +size_t talloc_total_size(const void *ptr); +size_t talloc_total_blocks(const void *ptr); +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_null_tracking(void); +void talloc_disable_null_tracking(void); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +char *talloc_strdup(const void *t, const char *p); +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_append_string(const void *t, char *orig, const char *append); +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); +void *talloc_autofree_context(void); +size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); +int talloc_is_parent(const void *context, const void *ptr); + +#endif + diff --git a/source/lib/talloc/talloc.pc.in b/source/lib/talloc/talloc.pc.in new file mode 100644 index 00000000000..7f9ef754cbd --- /dev/null +++ b/source/lib/talloc/talloc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: talloc +Description: A hierarchical pool based memory system with destructors +Version: 4.0 +Libs: @LIBS@ -L${libdir} -ltalloc +Cflags: -I${includedir} @CFLAGS@ diff --git a/source/lib/talloc/talloc_guide.txt b/source/lib/talloc/talloc_guide.txt new file mode 100644 index 00000000000..8b252e4ab9b --- /dev/null +++ b/source/lib/talloc/talloc_guide.txt @@ -0,0 +1,653 @@ +Using talloc in Samba4 +---------------------- + +Andrew Tridgell +September 2004 + +The most current version of this document is available at + http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt + +If you are used to the "old" talloc from Samba3 before 3.0.20 then please read +this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the +Samba4 talloc has been ported back to Samba3, so this guide applies to both. + +The new talloc is a hierarchical, reference counted memory pool system +with destructors. Quite a mounthful really, but not too bad once you +get used to it. + +Perhaps the biggest change from Samba3 is that there is no distinction +between a "talloc context" and a "talloc pointer". Any pointer +returned from talloc() is itself a valid talloc context. This means +you can do this: + + struct foo *X = talloc(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + +and the pointer X->name would be a "child" of the talloc context "X" +which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx) +then it is all destroyed, whereas if you do talloc_free(X) then just X +and X->name are destroyed, and if you do talloc_free(X->name) then +just the name element of X is destroyed. + +If you think about this, then what this effectively gives you is an +n-ary tree, where you can free any part of the tree with +talloc_free(). + +If you find this confusing, then I suggest you run the testsuite to +watch talloc in action. You may also like to add your own tests to +testsuite.c to clarify how some particular situation is handled. + + +Performance +----------- + +All the additional features of talloc() over malloc() do come at a +price. We have a simple performance test in Samba4 that measures +talloc() versus malloc() performance, and it seems that talloc() is +about 4% slower than malloc() on my x86 Debian Linux box. For Samba, +the great reduction in code complexity that we get by using talloc +makes this worthwhile, especially as the total overhead of +talloc/malloc in Samba is already quite small. + + +talloc API +---------- + +The following is a complete guide to the talloc API. Read it all at +least twice. + +Multi-threading +--------------- + +talloc itself does not deal with threads. It is thread-safe (assuming +the underlying "malloc" is), as long as each thread uses different +memory contexts. +If two threads uses the same context then they need to synchronize in +order to be safe. In particular: +- when using talloc_enable_leak_report(), giving directly NULL as a +parent context implicitly refers to a hidden "null context" global +variable, so this should not be used in a multi-threaded environment +without proper synchronization ; +- the context returned by talloc_autofree_context() is also global so +shouldn't be used by several threads simultaneously without +synchronization. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc(const void *context, type); + +The talloc() macro is the core of the talloc library. It takes a +memory context and a type, and returns a pointer to a new area of +memory of the given type. + +The returned pointer is itself a talloc context, so you can use it as +the context argument to more calls to talloc if you wish. + +The returned pointer is a "child" of the supplied context. This means +that if you talloc_free() the context then the new child disappears as +well. Alternatively you can free just the child. + +The context argument to talloc() can be NULL, in which case a new top +level context is created. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_size(const void *context, size_t size); + +The function talloc_size() should be used when you don't have a +convenient type to pass to talloc(). Unlike talloc(), it is not type +safe (as it returns a void *), so you are on your own for type checking. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr); + +The talloc_ptrtype() macro should be used when you have a pointer and +want to allocate memory to point at with this pointer. When compiling +with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() +and talloc_get_name() will return the current location in the source file. +and not the type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_free(void *ptr); + +The talloc_free() function frees a piece of talloc memory, and all its +children. You can call talloc_free() on any pointer returned by +talloc(). + +The return value of talloc_free() indicates success or failure, with 0 +returned for success and -1 for failure. The only possible failure +condition is if the pointer had a destructor attached to it and the +destructor returned -1. See talloc_set_destructor() for details on +destructors. + +If this pointer has an additional parent when talloc_free() is called +then the memory is not actually released, but instead the most +recently established parent is destroyed. See talloc_reference() for +details on establishing additional parents. + +For more control on which parent is removed, see talloc_unlink() + +talloc_free() operates recursively on its children. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_free_children(void *ptr); + +The talloc_free_children() walks along the list of all children of a +talloc context and talloc_free()s only the children, not the context +itself. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_reference(const void *context, const void *ptr); + +The talloc_reference() function makes "context" an additional parent +of "ptr". + +The return value of talloc_reference() is always the original pointer +"ptr", unless talloc ran out of memory in creating the reference in +which case it will return NULL (each additional reference consumes +around 48 bytes of memory on intel x86 platforms). + +If "ptr" is NULL, then the function is a no-op, and simply returns NULL. + +After creating a reference you can free it in one of the following +ways: + + - you can talloc_free() any parent of the original pointer. That + will reduce the number of parents of this pointer by 1, and will + cause this pointer to be freed if it runs out of parents. + + - you can talloc_free() the pointer itself. That will destroy the + most recently established parent to the pointer and leave the + pointer as a child of its current parent. + +For more control on which parent to remove, see talloc_unlink() + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_unlink(const void *context, const void *ptr); + +The talloc_unlink() function removes a specific parent from ptr. The +context passed must either be a context used in talloc_reference() +with this pointer, or must be a direct parent of ptr. + +Note that if the parent has already been removed using talloc_free() +then this function will fail and will return -1. Likewise, if "ptr" +is NULL, then the function will make no modifications and return -1. + +Usually you can just use talloc_free() instead of talloc_unlink(), but +sometimes it is useful to have the additional control on which parent +is removed. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + +The function talloc_set_destructor() sets the "destructor" for the +pointer "ptr". A destructor is a function that is called when the +memory used by a pointer is about to be released. The destructor +receives the pointer as an argument, and should return 0 for success +and -1 for failure. + +The destructor can do anything it wants to, including freeing other +pieces of memory. A common use for destructors is to clean up +operating system resources (such as open file descriptors) contained +in the structure the destructor is placed on. + +You can only place one destructor on a pointer. If you need more than +one destructor then you can create a zero-length child of the pointer +and place an additional destructor on that. + +To remove a destructor call talloc_set_destructor() with NULL for the +destructor. + +If your destructor attempts to talloc_free() the pointer that it is +the destructor for then talloc_free() will return -1 and the free will +be ignored. This would be a pointless operation anyway, as the +destructor is only called when the memory is just about to go away. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_increase_ref_count(const void *ptr); + +The talloc_increase_ref_count(ptr) function is exactly equivalent to: + + talloc_reference(NULL, ptr); + +You can use either syntax, depending on which you think is clearer in +your code. + +It returns 0 on success and -1 on failure. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_reference_count(const void *ptr); + +Return the number of references to the pointer. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name(const void *ptr, const char *fmt, ...); + +Each talloc pointer has a "name". The name is used principally for +debugging purposes, although it is also possible to set and get the +name on a pointer in as a way of "marking" pointers in your code. + +The main use for names on pointer is for "talloc reports". See +talloc_report() and talloc_report_full() for details. Also see +talloc_enable_leak_report() and talloc_enable_leak_report_full(). + +The talloc_set_name() function allocates memory as a child of the +pointer. It is logically equivalent to: + talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + +Note that multiple calls to talloc_set_name() will allocate more +memory without releasing the name. All of the memory is released when +the ptr is freed using talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name_const(const void *ptr, const char *name); + +The function talloc_set_name_const() is just like talloc_set_name(), +but it takes a string constant, and is much faster. It is extensively +used by the "auto naming" macros, such as talloc_p(). + +This function does not allocate any memory. It just copies the +supplied pointer into the internal representation of the talloc +ptr. This means you must not pass a name pointer to memory that will +disappear before the ptr is freed with talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named(const void *context, size_t size, const char *fmt, ...); + +The talloc_named() function creates a named talloc pointer. It is +equivalent to: + + ptr = talloc_size(context, size); + talloc_set_name(ptr, fmt, ....); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named_const(const void *context, size_t size, const char *name); + +This is equivalent to: + + ptr = talloc_size(context, size); + talloc_set_name_const(ptr, name); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const char *talloc_get_name(const void *ptr); + +This returns the current name for the given talloc pointer. See +talloc_set_name() for details. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_init(const char *fmt, ...); + +This function creates a zero length named talloc context as a top +level context. It is equivalent to: + + talloc_named(NULL, 0, fmt, ...); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_new(void *ctx); + +This is a utility macro that creates a new memory context hanging +off an exiting context, automatically naming it "talloc_new: __location__" +where __location__ is the source line it is called from. It is +particularly useful for creating a new temporary working context. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_realloc(const void *context, void *ptr, type, count); + +The talloc_realloc() macro changes the size of a talloc +pointer. The "count" argument is the number of elements of type "type" +that you want the resulting pointer to hold. + +talloc_realloc() has the following equivalences: + + talloc_realloc(context, NULL, type, 1) ==> talloc(context, type); + talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N); + talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); + +The "context" argument is only used if "ptr" is NULL, otherwise it is +ignored. + +talloc_realloc() returns the new pointer, or NULL on failure. The call +will fail either due to a lack of memory, or because the pointer has +more than one parent (see talloc_reference()). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_size(const void *context, void *ptr, size_t size); + +the talloc_realloc_size() function is useful when the type is not +known so the typesafe talloc_realloc() cannot be used. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_steal(const void *new_ctx, const void *ptr); + +The talloc_steal() function changes the parent context of a talloc +pointer. It is typically used when the context that the pointer is +currently a child of is going to be freed and you wish to keep the +memory for a longer time. + +The talloc_steal() function returns the pointer that you pass it. It +does not have any failure modes. + +NOTE: It is possible to produce loops in the parent/child relationship +if you are not careful with talloc_steal(). No guarantees are provided +as to your sanity or the safety of your data if you do this. + +talloc_steal (new_ctx, NULL) will return NULL with no sideeffects. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_total_size(const void *ptr); + +The talloc_total_size() function returns the total size in bytes used +by this pointer and all child pointers. Mostly useful for debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_total_blocks(const void *ptr); + +The talloc_total_blocks() function returns the total memory block +count used by this pointer and all child pointers. Mostly useful for +debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *priv), + void *priv); + +This provides a more flexible reports than talloc_report(). It +will recursively call the callback for the entire tree of memory +referenced by the pointer. References in the tree are passed with +is_ref = 1 and the pointer that is referenced. + +You can pass NULL for the pointer, in which case a report is +printed for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() +has been called. + +The recursion is stopped when depth >= max_depth. +max_depth = -1 means only stop at leaf nodes. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); + +This provides a more flexible reports than talloc_report(). It +will let you specify the depth and max_depth. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report(const void *ptr, FILE *f); + +The talloc_report() function prints a summary report of all memory +used by ptr. One line of report is printed for each immediate child of +ptr, showing the total memory and number of blocks used by that child. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_full(const void *ptr, FILE *f); + +This provides a more detailed report than talloc_report(). It will +recursively print the ensire tree of memory referenced by the +pointer. References in the tree are shown by giving the name of the +pointer that is referenced. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report(void); + +This enables calling of talloc_report(NULL, stderr) when the program +exits. In Samba4 this is enabled by using the --leak-report command +line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical talloc report: + +talloc report on 'null_context' (total 267 bytes in 15 blocks) + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(UTF8,CP850) contains 42 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(CP850,UTF8) contains 42 bytes in 2 blocks + iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks + iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report_full(void); + +This enables calling of talloc_report_full(NULL, stderr) when the +program exits. In Samba4 this is enabled by using the +--leak-report-full command line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical full report: + +full talloc report on 'root' (total 18 bytes in 8 blocks) + p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_null_tracking(void); + +This enables tracking of the NULL memory context without enabling leak +reporting on exit. Useful for when you want to do your own leak +reporting call via talloc_report_null_full(); + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_disable_null_tracking(void); + +This disables tracking of the NULL memory context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_zero(const void *ctx, type); + +The talloc_zero() macro is equivalent to: + + ptr = talloc(ctx, type); + if (ptr) memset(ptr, 0, sizeof(type)); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_zero_size(const void *ctx, size_t size) + +The talloc_zero_size() function is useful when you don't have a known type + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_memdup(const void *ctx, const void *p, size_t size); + +The talloc_memdup() function is equivalent to: + + ptr = talloc_size(ctx, size); + if (ptr) memcpy(ptr, p, size); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strdup(const void *ctx, const char *p); + +The talloc_strdup() function is equivalent to: + + ptr = talloc_size(ctx, strlen(p)+1); + if (ptr) memcpy(ptr, p, strlen(p)+1); + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strndup(const void *t, const char *p, size_t n); + +The talloc_strndup() function is the talloc equivalent of the C +library function strndup() + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap); + +The talloc_vasprintf() function is the talloc equivalent of the C +library function vasprintf() + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf(const void *t, const char *fmt, ...); + +The talloc_asprintf() function is the talloc equivalent of the C +library function asprintf() + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf_append(char *s, const char *fmt, ...); + +The talloc_asprintf_append() function appends the given formatted +string to the given string. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_array(const void *ctx, type, uint_t count); + +The talloc_array() macro is equivalent to: + + (type *)talloc_size(ctx, sizeof(type) * count); + +except that it provides integer overflow protection for the multiply, +returning NULL if the multiply overflows. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_array_size(const void *ctx, size_t size, uint_t count); + +The talloc_array_size() function is useful when the type is not +known. It operates in the same way as talloc_array(), but takes a size +instead of a type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count); + +The talloc_ptrtype() macro should be used when you have a pointer to an array +and want to allocate memory of an array to point at with this pointer. When compiling +with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() +and talloc_get_name() will return the current location in the source file. +and not the type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size); + +This is a non-macro version of talloc_realloc(), which is useful +as libraries sometimes want a ralloc function pointer. A realloc() +implementation encapsulates the functionality of malloc(), free() and +realloc() in one call, which is why it is useful to be able to pass +around a single function pointer. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_autofree_context(void); + +This is a handy utility function that returns a talloc context +which will be automatically freed on program exit. This can be used +to reduce the noise in memory leak reports. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_check_name(const void *ptr, const char *name); + +This function checks if a pointer has the specified name. If it does +then the pointer is returned. It it doesn't then NULL is returned. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_get_type(const void *ptr, type); + +This macro allows you to do type checking on talloc pointers. It is +particularly useful for void* private pointers. It is equivalent to +this: + + (type *)talloc_check_name(ptr, #type) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_set_type(const void *ptr, type); + +This macro allows you to force the name of a pointer to be a +particular type. This can be used in conjunction with +talloc_get_type() to do type checking on void* pointers. + +It is equivalent to this: + talloc_set_name_const(ptr, #type) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_get_size(const void *ctx); + +This function lets you know the amount of memory alloced so far by +this context. It does NOT account for subcontext memory. +This can be used to calculate the size of an array. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_find_parent_byname(const void *ctx, const char *name); + +Find a parent memory context of the current context that has the given +name. This can be very useful in complex programs where it may be +difficult to pass all information down to the level you need, but you +know the structure you want is a parent of another context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_find_parent_bytype(ctx, type); + +Like talloc_find_parent_byname() but takes a type, making it typesafe. + diff --git a/source/lib/talloc/testsuite.c b/source/lib/talloc/testsuite.c new file mode 100644 index 00000000000..f51252e57bc --- /dev/null +++ b/source/lib/talloc/testsuite.c @@ -0,0 +1,1061 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "replace.h" +#include "system/time.h" +#include "talloc.h" + +static struct timeval timeval_current(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv; +} + +static double timeval_elapsed(struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return (tv2.tv_sec - tv->tv_sec) + + (tv2.tv_usec - tv->tv_usec)*1.0e-6; +} + +#define torture_assert(test, expr, str) if (!(expr)) { \ + printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str); \ + return false; \ +} + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + if (strcmp(arg1, arg2)) { \ + printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc); \ + return false; \ + } + +#if _SAMBA_BUILD_==3 +#ifdef malloc +#undef malloc +#endif +#ifdef strdup +#undef strdup +#endif +#endif + +#define CHECK_SIZE(test, ptr, tsize) do { \ + if (talloc_total_size(ptr) != (tsize)) { \ + printf("failed: %s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize); \ + talloc_report_full(ptr, stdout); \ + return false; \ + } \ +} while (0) + +#define CHECK_BLOCKS(test, ptr, tblocks) do { \ + if (talloc_total_blocks(ptr) != (tblocks)) { \ + printf("failed: %s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks); \ + talloc_report_full(ptr, stdout); \ + return false; \ + } \ +} while (0) + +#define CHECK_PARENT(test, ptr, parent) do { \ + if (talloc_parent(ptr) != (parent)) { \ + printf("failed: %s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)); \ + talloc_report_full(ptr, stdout); \ + talloc_report_full(parent, stdout); \ + talloc_report_full(NULL, stdout); \ + return false; \ + } \ +} while (0) + + +/* + test references +*/ +static bool test_ref1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref1 [\nSINGLE REFERENCE FREE\n]\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(p1, 1, "p2"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 2, "x2"); + talloc_named_const(p1, 3, "x3"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 2); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", r1, 1); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(NULL, stderr); + + fprintf(stderr, "Testing NULL\n"); + if (talloc_reference(root, NULL)) { + return false; + } + + CHECK_BLOCKS("ref1", root, 1); + + CHECK_SIZE("ref1", root, 0); + + talloc_free(root); + printf("success: ref1\n"); + return true; +} + +/* + test references +*/ +static bool test_ref2(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref2 [\nDOUBLE REFERENCE FREE\n]\n"); + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 2); + + fprintf(stderr, "Freeing ref\n"); + talloc_free(ref); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 4); + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref2", root, 0); + + talloc_free(root); + printf("success: ref2\n"); + return true; +} + +/* + test references +*/ +static bool test_ref3(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref3 [\nPARENT REFERENCE FREE\n]\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(root, 1, "p2"); + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(p2, r1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref3", p1, 2); + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref3", root, 0); + + talloc_free(root); + + printf("success: ref3\n"); + return true; +} + +/* + test references +*/ +static bool test_ref4(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref4 [\nREFERRER REFERENCE FREE\n]\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + CHECK_BLOCKS("ref4", r1, 2); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 4); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref4", root, 0); + + talloc_free(root); + + printf("success: ref4\n"); + return true; +} + + +/* + test references +*/ +static bool test_unlink1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: unlink [\nUNLINK\n]\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("unlink", p1, 7); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 2); + + fprintf(stderr, "Unreferencing r1\n"); + talloc_unlink(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("unlink", p1, 6); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_SIZE("unlink", root, 0); + + talloc_free(root); + + printf("success: unlink\n"); + return true; +} + +static int fail_destructor(void *ptr) +{ + return -1; +} + +/* + miscellaneous tests to try to get a higher test coverage percentage +*/ +static bool test_misc(void) +{ + void *root, *p1; + char *p2; + double *d; + const char *name; + + printf("test: misc [\nMISCELLANEOUS\n]\n"); + + root = talloc_new(NULL); + + p1 = talloc_size(root, 0x7fffffff); + torture_assert("misc", !p1, "failed: large talloc allowed\n"); + + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_free(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + p2 = talloc_strdup(p1, "foo"); + torture_assert("misc", talloc_unlink(root, p2) == -1, + "failed: talloc_unlink() of non-reference context should return -1\n"); + torture_assert("misc", talloc_unlink(p1, p2) == 0, + "failed: talloc_unlink() of parent should succeed\n"); + talloc_free(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + + name = talloc_set_name(p1, "my name is %s", "foo"); + torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", + "failed: wrong name after talloc_set_name(my name is foo)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + talloc_set_name_const(p1, NULL); + torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", + "failed: wrong name after talloc_set_name(NULL)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + torture_assert("misc", talloc_free(NULL) == -1, + "talloc_free(NULL) should give -1\n"); + + talloc_set_destructor(p1, fail_destructor); + torture_assert("misc", talloc_free(p1) == -1, + "Failed destructor should cause talloc_free to fail\n"); + talloc_set_destructor(p1, NULL); + + talloc_report(root, stderr); + + + p2 = (char *)talloc_zero_size(p1, 20); + torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); + talloc_free(p2); + + torture_assert("misc", talloc_strdup(root, NULL) == NULL, + "failed: strdup on NULL should give NULL\n"); + + p2 = talloc_strndup(p1, "foo", 2); + torture_assert("misc", strcmp("fo", p2) == 0, + "strndup doesn't work\n"); + p2 = talloc_asprintf_append(p2, "o%c", 'd'); + torture_assert("misc", strcmp("food", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + + p2 = talloc_asprintf_append(NULL, "hello %s", "world"); + torture_assert("misc", strcmp("hello world", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + talloc_free(p2); + + d = talloc_array(p1, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + d = talloc_realloc(p1, d, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + talloc_free(p1); + CHECK_BLOCKS("misc", root, 1); + + p1 = talloc_named(root, 100, "%d bytes", 100); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(root, p1); + + p1 = talloc_init("%d bytes", 200); + p2 = talloc_asprintf(p1, "my test '%s'", "string"); + torture_assert_str_equal("misc", p2, "my test 'string'", + "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); + CHECK_BLOCKS("misc", p1, 3); + CHECK_SIZE("misc", p2, 17); + CHECK_BLOCKS("misc", root, 1); + talloc_unlink(NULL, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = (char *)talloc_named_const(root, 20, "p2"); + (void)talloc_reference(p1, p2); + talloc_report_full(root, stderr); + talloc_unlink(root, p2); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(p1, p2); + talloc_unlink(root, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = (char *)talloc_named_const(root, 20, "p2"); + (void)talloc_reference(NULL, p2); + talloc_report_full(root, stderr); + talloc_unlink(root, p2); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p2); + talloc_unlink(root, p1); + + /* Test that talloc_unlink is a no-op */ + + torture_assert("misc", talloc_unlink(root, NULL) == -1, + "failed: talloc_unlink(root, NULL) == -1\n"); + + talloc_report(root, stderr); + talloc_report(NULL, stderr); + + CHECK_SIZE("misc", root, 0); + + talloc_free(root); + + CHECK_SIZE("misc", NULL, 0); + + talloc_enable_leak_report(); + talloc_enable_leak_report_full(); + + printf("success: misc\n"); + + return true; +} + + +/* + test realloc +*/ +static bool test_realloc(void) +{ + void *root, *p1, *p2; + + printf("test: realloc [\nREALLOC\n]\n"); + + root = talloc_new(NULL); + + p1 = talloc_size(root, 10); + CHECK_SIZE("realloc", p1, 10); + + p1 = talloc_realloc_size(NULL, p1, 20); + CHECK_SIZE("realloc", p1, 20); + + talloc_new(p1); + + p2 = talloc_realloc_size(p1, NULL, 30); + + talloc_new(p1); + + p2 = talloc_realloc_size(p1, p2, 40); + + CHECK_SIZE("realloc", p2, 40); + CHECK_SIZE("realloc", root, 60); + CHECK_BLOCKS("realloc", p1, 4); + + p1 = talloc_realloc_size(NULL, p1, 20); + CHECK_SIZE("realloc", p1, 60); + + talloc_increase_ref_count(p2); + torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL, + "failed: talloc_realloc() on a referenced pointer should fail\n"); + CHECK_BLOCKS("realloc", p1, 4); + + talloc_realloc_size(NULL, p2, 0); + talloc_realloc_size(NULL, p2, 0); + CHECK_BLOCKS("realloc", p1, 3); + + torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL, + "failed: oversize talloc should fail\n"); + + talloc_realloc_size(NULL, p1, 0); + + CHECK_BLOCKS("realloc", root, 1); + CHECK_SIZE("realloc", root, 0); + + talloc_free(root); + + printf("success: REALLOC\n"); + + return true; +} + +/* + test realloc with a child +*/ +static bool test_realloc_child(void) +{ + void *root; + struct el2 { + const char *name; + } *el2; + struct el1 { + int count; + struct el2 **list, **list2, **list3; + } *el1; + + printf("test: REALLOC WITH CHILD\n"); + + root = talloc_new(NULL); + + el1 = talloc(root, struct el1); + el1->list = talloc(el1, struct el2 *); + el1->list[0] = talloc(el1->list, struct el2); + el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); + + el1->list2 = talloc(el1, struct el2 *); + el1->list2[0] = talloc(el1->list2, struct el2); + el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2"); + + el1->list3 = talloc(el1, struct el2 *); + el1->list3[0] = talloc(el1->list3, struct el2); + el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2"); + + el2 = talloc(el1->list, struct el2); + el2 = talloc(el1->list2, struct el2); + el2 = talloc(el1->list3, struct el2); + + el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100); + el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200); + el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300); + + talloc_free(root); + + printf("success: REALLOC WITH CHILD\n"); + return true; +} + +/* + test type checking +*/ +static bool test_type(void) +{ + void *root; + struct el1 { + int count; + }; + struct el2 { + int count; + }; + struct el1 *el1; + + printf("test: type [\ntalloc type checking\n]\n"); + + root = talloc_new(NULL); + + el1 = talloc(root, struct el1); + + el1->count = 1; + + torture_assert("type", talloc_get_type(el1, struct el1) == el1, + "type check failed on el1\n"); + torture_assert("type", talloc_get_type(el1, struct el2) == NULL, + "type check failed on el1 with el2\n"); + talloc_set_type(el1, struct el2); + torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1, + "type set failed on el1 with el2\n"); + + talloc_free(root); + + printf("success: type\n"); + return true; +} + +/* + test steal +*/ +static bool test_steal(void) +{ + void *root, *p1, *p2; + + printf("test: steal [\nSTEAL\n]\n"); + + root = talloc_new(NULL); + + p1 = talloc_array(root, char, 10); + CHECK_SIZE("steal", p1, 10); + + p2 = talloc_realloc(root, NULL, char, 20); + CHECK_SIZE("steal", p1, 10); + CHECK_SIZE("steal", root, 30); + + torture_assert("steal", talloc_steal(p1, NULL) == NULL, + "failed: stealing NULL should give NULL\n"); + + torture_assert("steal", talloc_steal(p1, p1) == p1, + "failed: stealing to ourselves is a nop\n"); + CHECK_BLOCKS("steal", root, 3); + CHECK_SIZE("steal", root, 30); + + talloc_steal(NULL, p1); + talloc_steal(NULL, p2); + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(p1); + talloc_steal(root, p2); + CHECK_BLOCKS("steal", root, 2); + CHECK_SIZE("steal", root, 20); + + talloc_free(p2); + + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(root); + + p1 = talloc_size(NULL, 3); + talloc_report_full(NULL, stderr); + CHECK_SIZE("steal", NULL, 3); + talloc_free(p1); + + printf("success: steal\n"); + return true; +} + +/* + test move +*/ +static bool test_move(void) +{ + void *root; + struct t_move { + char *p; + int *x; + } *t1, *t2; + + printf("test: move [\nMOVE\n]\n"); + + root = talloc_new(NULL); + + t1 = talloc(root, struct t_move); + t2 = talloc(root, struct t_move); + t1->p = talloc_strdup(t1, "foo"); + t1->x = talloc(t1, int); + *t1->x = 42; + + t2->p = talloc_move(t2, &t1->p); + t2->x = talloc_move(t2, &t1->x); + torture_assert("move", t1->p == NULL && t1->x == NULL && + strcmp(t2->p, "foo") == 0 && *t2->x == 42, + "talloc move failed"); + + talloc_free(root); + + printf("success: move\n"); + + return true; +} + +/* + test talloc_realloc_fn +*/ +static bool test_realloc_fn(void) +{ + void *root, *p1; + + printf("test: realloc_fn [\ntalloc_realloc_fn\n]\n"); + + root = talloc_new(NULL); + + p1 = talloc_realloc_fn(root, NULL, 10); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 10); + p1 = talloc_realloc_fn(root, p1, 20); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 20); + p1 = talloc_realloc_fn(root, p1, 0); + CHECK_BLOCKS("realloc_fn", root, 1); + CHECK_SIZE("realloc_fn", root, 0); + + talloc_free(root); + + printf("success: realloc_fn\n"); + return true; +} + + +static bool test_unref_reparent(void) +{ + void *root, *p1, *p2, *c1; + + printf("test: unref_reparent [\nUNREFERENCE AFTER PARENT FREED\n]\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "orig parent"); + p2 = talloc_named_const(root, 1, "parent by reference"); + + c1 = talloc_named_const(p1, 1, "child"); + talloc_reference(p2, c1); + + CHECK_PARENT("unref_reparent", c1, p1); + + talloc_free(p1); + + CHECK_PARENT("unref_reparent", c1, p2); + + talloc_unlink(p2, c1); + + CHECK_SIZE("unref_reparent", root, 1); + + talloc_free(p2); + talloc_free(root); + + printf("success: unref_reparent\n"); + return true; +} + +/* + measure the speed of talloc versus malloc +*/ +static bool test_speed(void) +{ + void *ctx = talloc_new(NULL); + unsigned count; + const int loop = 1000; + int i; + struct timeval tv; + + printf("test: speed [\nTALLOC VS MALLOC SPEED\n]\n"); + + tv = timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + for (i=0;i<loop;i++) { + p1 = talloc_size(ctx, loop % 100); + p2 = talloc_strdup(p1, "foo bar"); + p3 = talloc_size(p1, 300); + talloc_free(p1); + } + count += 3 * loop; + } while (timeval_elapsed(&tv) < 5.0); + + fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + + talloc_free(ctx); + + tv = timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + for (i=0;i<loop;i++) { + p1 = malloc(loop % 100); + p2 = strdup("foo bar"); + p3 = malloc(300); + free(p1); + free(p2); + free(p3); + } + count += 3 * loop; + } while (timeval_elapsed(&tv) < 5.0); + fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + + printf("success: speed\n"); + + return true; +} + +static bool test_lifeless(void) +{ + void *top = talloc_new(NULL); + char *parent, *child; + void *child_owner = talloc_new(NULL); + + printf("test: lifeless [\nTALLOC_UNLINK LOOP\n]\n"); + + parent = talloc_strdup(top, "parent"); + child = talloc_strdup(parent, "child"); + (void)talloc_reference(child, parent); + (void)talloc_reference(child_owner, child); + talloc_report_full(top, stderr); + talloc_unlink(top, parent); + talloc_free(child); + talloc_report_full(top, stderr); + talloc_free(top); + talloc_free(child_owner); + talloc_free(child); + + printf("success: lifeless\n"); + return true; +} + +static int loop_destructor_count; + +static int test_loop_destructor(char *ptr) +{ + loop_destructor_count++; + return 0; +} + +static bool test_loop(void) +{ + void *top = talloc_new(NULL); + char *parent; + struct req1 { + char *req2, *req3; + } *req1; + + printf("test: loop [\nTALLOC LOOP DESTRUCTION\n]\n"); + + parent = talloc_strdup(top, "parent"); + req1 = talloc(parent, struct req1); + req1->req2 = talloc_strdup(req1, "req2"); + talloc_set_destructor(req1->req2, test_loop_destructor); + req1->req3 = talloc_strdup(req1, "req3"); + (void)talloc_reference(req1->req3, req1); + talloc_report_full(top, stderr); + talloc_free(parent); + talloc_report_full(top, stderr); + talloc_report_full(NULL, stderr); + talloc_free(top); + + torture_assert("loop", loop_destructor_count == 1, + "FAILED TO FIRE LOOP DESTRUCTOR\n"); + loop_destructor_count = 0; + + printf("success: loop\n"); + return true; +} + +static int fail_destructor_str(char *ptr) +{ + return -1; +} + +static bool test_free_parent_deny_child(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *level2; + char *level3; + + printf("test: free_parent_deny_child [\nTALLOC FREE PARENT DENY CHILD\n]\n"); + + level1 = talloc_strdup(top, "level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc_strdup(level2, "level3"); + + talloc_set_destructor(level3, fail_destructor_str); + talloc_free(level1); + talloc_set_destructor(level3, NULL); + + CHECK_PARENT("free_parent_deny_child", level3, top); + + talloc_free(top); + + printf("success: free_parent_deny_child\n"); + return true; +} + +static bool test_talloc_ptrtype(void) +{ + void *top = talloc_new(NULL); + struct struct1 { + int foo; + int bar; + } *s1, *s2, **s3, ***s4; + const char *location1; + const char *location2; + const char *location3; + const char *location4; + + printf("test: ptrtype [\nTALLOC PTRTYPE\n]\n"); + + s1 = talloc_ptrtype(top, s1);location1 = __location__; + + if (talloc_get_size(s1) != sizeof(struct struct1)) { + printf("failure: ptrtype [\n" + "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n" + "]\n", (unsigned long)talloc_get_size(s1), + (unsigned long)sizeof(struct struct1)); + return false; + } + + if (strcmp(location1, talloc_get_name(s1)) != 0) { + printf("failure: ptrtype [\n" + "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s1), location1); + return false; + } + + s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__; + + if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s2), + (unsigned long)(sizeof(struct struct1)*10)); + return false; + } + + if (strcmp(location2, talloc_get_name(s2)) != 0) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s2), location2); + return false; + } + + s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__; + + if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s3), + (unsigned long)(sizeof(struct struct1 *)*10)); + return false; + } + + torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3), + "talloc_array_ptrtype() sets the wrong name"); + + s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__; + + if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) { + printf("failure: TALLOC PTRTYPE [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s4), + (unsigned long)(sizeof(struct struct1 **)*10)); + return false; + } + + torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4), + "talloc_array_ptrtype() sets the wrong name"); + + talloc_free(top); + + printf("success: ptrtype\n"); + return true; +} + +static bool test_autofree(void) +{ + void *p; + printf("test: autofree [\nTALLOC AUTOFREE CONTEXT\n]\n"); + + p = talloc_autofree_context(); + talloc_free(p); + + p = talloc_autofree_context(); + talloc_free(p); + + printf("success: autofree\n"); + return true; +} + +int main(void) +{ + bool ret = true; + + talloc_disable_null_tracking(); + talloc_enable_null_tracking(); + + ret &= test_ref1(); + ret &= test_ref2(); + ret &= test_ref3(); + ret &= test_ref4(); + ret &= test_unlink1(); + ret &= test_misc(); + ret &= test_realloc(); + ret &= test_realloc_child(); + ret &= test_steal(); + ret &= test_move(); + ret &= test_unref_reparent(); + ret &= test_realloc_fn(); + ret &= test_type(); + ret &= test_lifeless(); + ret &= test_loop(); + ret &= test_free_parent_deny_child(); + ret &= test_talloc_ptrtype(); + + if (ret) { + ret &= test_speed(); + } + ret &= test_autofree(); + + if (!ret) + return -1; + return 0; +} diff --git a/source/lib/talloc/web/index.html b/source/lib/talloc/web/index.html new file mode 100644 index 00000000000..106920e8a59 --- /dev/null +++ b/source/lib/talloc/web/index.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> +<TITLE>talloc</TITLE> +</HEAD> +<BODY BGCOLOR="#ffffff" TEXT="#000000" VLINK="#292555" LINK="#292555" ALINK="#cc0033"> + +<h1>talloc</h1> + +talloc is a hierarchical pool based memory allocator with +destructors. It is the core memory allocator used in Samba4, and has +made a huge difference in many aspects of Samba4 development.<p> + +To get started with talloc, I would recommend you read the <a +href="http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt">talloc guide</a>. + +<h2>Discussion and bug reports</h2> + +talloc does not currently have its own mailing list or bug tracking +system. For now, please use the <a +href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a> +mailing list, and the <a href="http://bugzilla.samba.org/">Samba +bugzilla</a> bug tracking system. + +<h2>Download</h2> + +You can download the latest release either via rsync or anonymous +svn. To fetch via svn use the following command: + +<pre> + svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc + svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/replace libreplace +</pre> + +To fetch via rsync use this command: + +<pre> + rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc . + rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/libreplace . +</pre> + +<hr> +<tiny> +<a href="http://samba.org/~tridge/">Andrew Tridgell</a><br> +talloc AT tridgell.net +</tiny> + +</BODY> +</HTML> diff --git a/source/lib/tallocmsg.c b/source/lib/tallocmsg.c index b515093cd69..0f493538f3c 100644 --- a/source/lib/tallocmsg.c +++ b/source/lib/tallocmsg.c @@ -25,31 +25,75 @@ * Glue code between talloc profiling and the Samba messaging system. **/ +struct msg_pool_usage_state { + TALLOC_CTX *mem_ctx; + ssize_t len; + size_t buflen; + char *s; +}; + +static void msg_pool_usage_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_s) +{ + const char *name = talloc_get_name(ptr); + struct msg_pool_usage_state *state = (struct msg_pool_usage_state *)_s; + + if (is_ref) { + sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen, + "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen, + "%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + talloc_reference_count(ptr)); +} /** * Respond to a POOL_USAGE message by sending back string form of memory * usage stats. **/ void msg_pool_usage(int msg_type, struct process_id src_pid, - void *UNUSED(buf), size_t UNUSED(len)) + void *UNUSED(buf), size_t UNUSED(len), + void *private_data) { - char *reply = NULL; + struct msg_pool_usage_state state; SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); DEBUG(2,("Got POOL_USAGE\n")); - reply = talloc_describe_all(); - if (!reply) { + state.mem_ctx = talloc_init("msg_pool_usage"); + if (!state.mem_ctx) { + return; + } + state.len = 0; + state.buflen = 512; + state.s = NULL; + + talloc_report_depth_cb(NULL, 0, -1, msg_pool_usage_helper, &state); + + if (!state.s) { + talloc_destroy(state.mem_ctx); return; } - become_root(); message_send_pid(src_pid, MSG_POOL_USAGE, - reply, strlen(reply)+1, True); - unbecome_root(); + state.s, strlen(state.s)+1, True); - SAFE_FREE(reply); + talloc_destroy(state.mem_ctx); } /** @@ -57,6 +101,6 @@ void msg_pool_usage(int msg_type, struct process_id src_pid, **/ void register_msg_pool_usage(void) { - message_register(MSG_REQ_POOL_USAGE, msg_pool_usage); + message_register(MSG_REQ_POOL_USAGE, msg_pool_usage, NULL); DEBUG(2, ("Registered MSG_REQ_POOL_USAGE\n")); } diff --git a/source/lib/talloctort.c b/source/lib/talloctort.c deleted file mode 100644 index 6504203a7ad..00000000000 --- a/source/lib/talloctort.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - local testing of talloc routines. - - Copyright (C) Andrew Tridgell 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifdef _SAMBA_BUILD_ -#include "includes.h" -#else -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <sys/time.h> -#include <time.h> -#include "talloc.h" -#endif - -/* the test suite can be built standalone, or as part of Samba */ -#ifndef _SAMBA_BUILD_ -typedef enum {False=0,True=1} BOOL; -#endif - -/* Samba3 does not define the timeval functions below */ -#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) - -static double timeval_elapsed(struct timeval *tv) -{ - struct timeval tv2 = timeval_current(); - return (tv2.tv_sec - tv->tv_sec) + - (tv2.tv_usec - tv->tv_usec)*1.0e-6; -} -#endif /* _SAMBA_BUILD_ */ - -#if SAMBA_VERSION_MAJOR<4 -#ifdef malloc -#undef malloc -#endif -#ifdef strdup -#undef strdup -#endif -#endif - -#define CHECK_SIZE(ptr, tsize) do { \ - if (talloc_total_size(ptr) != (tsize)) { \ - printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \ - #ptr, \ - (unsigned)talloc_total_size(ptr), \ - (unsigned)tsize); \ - talloc_report_full(ptr, stdout); \ - return False; \ - } \ -} while (0) - -#define CHECK_BLOCKS(ptr, tblocks) do { \ - if (talloc_total_blocks(ptr) != (tblocks)) { \ - printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \ - #ptr, \ - (unsigned)talloc_total_blocks(ptr), \ - (unsigned)tblocks); \ - talloc_report_full(ptr, stdout); \ - return False; \ - } \ -} while (0) - - -/* - test references -*/ -static BOOL test_ref1(void) -{ - void *root, *p1, *p2, *ref, *r1; - - printf("TESTING SINGLE REFERENCE FREE\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "p1"); - p2 = talloc_named_const(p1, 1, "p2"); - talloc_named_const(p1, 1, "x1"); - talloc_named_const(p1, 2, "x2"); - talloc_named_const(p1, 3, "x3"); - - r1 = talloc_named_const(root, 1, "r1"); - ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); - - printf("Freeing p2\n"); - talloc_free(p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p1\n"); - talloc_free(p1); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(r1, 1); - - printf("Freeing r1\n"); - talloc_free(r1); - talloc_report_full(NULL, stdout); - - printf("Testing NULL\n"); - if (talloc_reference(root, NULL)) { - return False; - } - - CHECK_BLOCKS(root, 1); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - -/* - test references -*/ -static BOOL test_ref2(void) -{ - void *root, *p1, *p2, *ref, *r1; - - printf("TESTING DOUBLE REFERENCE FREE\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "p1"); - talloc_named_const(p1, 1, "x1"); - talloc_named_const(p1, 1, "x2"); - talloc_named_const(p1, 1, "x3"); - p2 = talloc_named_const(p1, 1, "p2"); - - r1 = talloc_named_const(root, 1, "r1"); - ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); - - printf("Freeing ref\n"); - talloc_free(ref); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p2\n"); - talloc_free(p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 4); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p1\n"); - talloc_free(p1); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(r1, 1); - - printf("Freeing r1\n"); - talloc_free(r1); - talloc_report_full(root, stdout); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - -/* - test references -*/ -static BOOL test_ref3(void) -{ - void *root, *p1, *p2, *ref, *r1; - - printf("TESTING PARENT REFERENCE FREE\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "p1"); - p2 = talloc_named_const(root, 1, "p2"); - r1 = talloc_named_const(p1, 1, "r1"); - ref = talloc_reference(p2, r1); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(p2, 2); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p1\n"); - talloc_free(p1); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p2, 2); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p2\n"); - talloc_free(p2); - talloc_report_full(root, stdout); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - -/* - test references -*/ -static BOOL test_ref4(void) -{ - void *root, *p1, *p2, *ref, *r1; - - printf("TESTING REFERRER REFERENCE FREE\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "p1"); - talloc_named_const(p1, 1, "x1"); - talloc_named_const(p1, 1, "x2"); - talloc_named_const(p1, 1, "x3"); - p2 = talloc_named_const(p1, 1, "p2"); - - r1 = talloc_named_const(root, 1, "r1"); - ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); - - printf("Freeing r1\n"); - talloc_free(r1); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - - printf("Freeing p2\n"); - talloc_free(p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 4); - - printf("Freeing p1\n"); - talloc_free(p1); - talloc_report_full(root, stdout); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - - -/* - test references -*/ -static BOOL test_unlink1(void) -{ - void *root, *p1, *p2, *ref, *r1; - - printf("TESTING UNLINK\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "p1"); - talloc_named_const(p1, 1, "x1"); - talloc_named_const(p1, 1, "x2"); - talloc_named_const(p1, 1, "x3"); - p2 = talloc_named_const(p1, 1, "p2"); - - r1 = talloc_named_const(p1, 1, "r1"); - ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 7); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); - - printf("Unreferencing r1\n"); - talloc_unlink(r1, p2); - talloc_report_full(root, stdout); - - CHECK_BLOCKS(p1, 6); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); - - printf("Freeing p1\n"); - talloc_free(p1); - talloc_report_full(root, stdout); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - -static int fail_destructor(void *ptr) -{ - return -1; -} - -/* - miscellaneous tests to try to get a higher test coverage percentage -*/ -static BOOL test_misc(void) -{ - void *root, *p1; - char *p2; - double *d; - - printf("TESTING MISCELLANEOUS\n"); - - root = talloc_new(NULL); - - p1 = talloc_size(root, 0x7fffffff); - if (p1) { - printf("failed: large talloc allowed\n"); - return False; - } - - p1 = talloc_strdup(root, "foo"); - talloc_increase_ref_count(p1); - talloc_increase_ref_count(p1); - talloc_increase_ref_count(p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); - talloc_free(p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); - talloc_unlink(NULL, p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); - p2 = talloc_strdup(p1, "foo"); - if (talloc_unlink(root, p2) != -1) { - printf("failed: talloc_unlink() of non-reference context should return -1\n"); - return False; - } - if (talloc_unlink(p1, p2) != 0) { - printf("failed: talloc_unlink() of parent should succeed\n"); - return False; - } - talloc_free(p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); - - talloc_set_name(p1, "my name is %s", "foo"); - if (strcmp(talloc_get_name(p1), "my name is foo") != 0) { - printf("failed: wrong name after talloc_set_name\n"); - return False; - } - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); - - talloc_set_name_const(p1, NULL); - if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) { - printf("failed: wrong name after talloc_set_name(NULL)\n"); - return False; - } - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); - - - if (talloc_free(NULL) != -1) { - printf("talloc_free(NULL) should give -1\n"); - return False; - } - - talloc_set_destructor(p1, fail_destructor); - if (talloc_free(p1) != -1) { - printf("Failed destructor should cause talloc_free to fail\n"); - return False; - } - talloc_set_destructor(p1, NULL); - - talloc_report(root, stdout); - - - p2 = talloc_zero_size(p1, 20); - if (p2[19] != 0) { - printf("Failed to give zero memory\n"); - return False; - } - talloc_free(p2); - - if (talloc_strdup(root, NULL) != NULL) { - printf("failed: strdup on NULL should give NULL\n"); - return False; - } - - p2 = talloc_strndup(p1, "foo", 2); - if (strcmp("fo", p2) != 0) { - printf("failed: strndup doesn't work\n"); - return False; - } - p2 = talloc_asprintf_append(p2, "o%c", 'd'); - if (strcmp("food", p2) != 0) { - printf("failed: talloc_asprintf_append doesn't work\n"); - return False; - } - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 3); - - p2 = talloc_asprintf_append(NULL, "hello %s", "world"); - if (strcmp("hello world", p2) != 0) { - printf("failed: talloc_asprintf_append doesn't work\n"); - return False; - } - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 3); - talloc_free(p2); - - d = talloc_array(p1, double, 0x20000000); - if (d) { - printf("failed: integer overflow not detected\n"); - return False; - } - - d = talloc_realloc(p1, d, double, 0x20000000); - if (d) { - printf("failed: integer overflow not detected\n"); - return False; - } - - talloc_free(p1); - CHECK_BLOCKS(root, 1); - - p1 = talloc_named(root, 100, "%d bytes", 100); - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); - talloc_unlink(root, p1); - - p1 = talloc_init("%d bytes", 200); - p2 = talloc_asprintf(p1, "my test '%s'", "string"); - CHECK_BLOCKS(p1, 3); - CHECK_SIZE(p2, 17); - CHECK_BLOCKS(root, 1); - talloc_unlink(NULL, p1); - - p1 = talloc_named_const(root, 10, "p1"); - p2 = talloc_named_const(root, 20, "p2"); - talloc_reference(p1, p2); - talloc_report_full(root, stdout); - talloc_unlink(root, p2); - talloc_report_full(root, stdout); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); - talloc_unlink(p1, p2); - talloc_unlink(root, p1); - - p1 = talloc_named_const(root, 10, "p1"); - p2 = talloc_named_const(root, 20, "p2"); - talloc_reference(NULL, p2); - talloc_report_full(root, stdout); - talloc_unlink(root, p2); - talloc_report_full(root, stdout); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); - talloc_unlink(NULL, p2); - talloc_unlink(root, p1); - - /* Test that talloc_unlink is a no-op */ - - if (talloc_unlink(root, NULL) != -1) { - printf("failed: talloc_unlink(root, NULL) == -1\n"); - return False; - } - - talloc_report(root, stdout); - talloc_report(NULL, stdout); - - CHECK_SIZE(root, 0); - - talloc_free(root); - - CHECK_SIZE(NULL, 0); - - talloc_enable_leak_report(); - talloc_enable_leak_report_full(); - - return True; -} - - -/* - test realloc -*/ -static BOOL test_realloc(void) -{ - void *root, *p1, *p2; - - printf("TESTING REALLOC\n"); - - root = talloc_new(NULL); - - p1 = talloc_size(root, 10); - CHECK_SIZE(p1, 10); - - p1 = talloc_realloc_size(NULL, p1, 20); - CHECK_SIZE(p1, 20); - - talloc_new(p1); - - p2 = talloc_realloc_size(p1, NULL, 30); - - talloc_new(p1); - - p2 = talloc_realloc_size(p1, p2, 40); - - CHECK_SIZE(p2, 40); - CHECK_SIZE(root, 60); - CHECK_BLOCKS(p1, 4); - - p1 = talloc_realloc_size(NULL, p1, 20); - CHECK_SIZE(p1, 60); - - talloc_increase_ref_count(p2); - if (talloc_realloc_size(NULL, p2, 5) != NULL) { - printf("failed: talloc_realloc() on a referenced pointer should fail\n"); - return False; - } - CHECK_BLOCKS(p1, 4); - - talloc_realloc_size(NULL, p2, 0); - talloc_realloc_size(NULL, p2, 0); - CHECK_BLOCKS(p1, 3); - - if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) { - printf("failed: oversize talloc should fail\n"); - return False; - } - - talloc_realloc_size(NULL, p1, 0); - - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); - - talloc_free(root); - - return True; -} - - -/* - test realloc with a child -*/ -static BOOL test_realloc_child(void) -{ - void *root; - struct el1 { - int count; - struct el2 { - const char *name; - } **list, **list2, **list3; - } *el1; - struct el2 *el2; - - printf("TESTING REALLOC WITH CHILD\n"); - - root = talloc_new(NULL); - - el1 = talloc(root, struct el1); - el1->list = talloc(el1, struct el2 *); - el1->list[0] = talloc(el1->list, struct el2); - el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); - - el1->list2 = talloc(el1, struct el2 *); - el1->list2[0] = talloc(el1->list2, struct el2); - el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2"); - - el1->list3 = talloc(el1, struct el2 *); - el1->list3[0] = talloc(el1->list3, struct el2); - el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2"); - - el2 = talloc(el1->list, struct el2); - el2 = talloc(el1->list2, struct el2); - el2 = talloc(el1->list3, struct el2); - - el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100); - el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200); - el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300); - - talloc_free(root); - - return True; -} - - -/* - test type checking -*/ -static BOOL test_type(void) -{ - void *root; - struct el1 { - int count; - }; - struct el2 { - int count; - }; - struct el1 *el1; - - printf("TESTING talloc type checking\n"); - - root = talloc_new(NULL); - - el1 = talloc(root, struct el1); - - el1->count = 1; - - if (talloc_get_type(el1, struct el1) != el1) { - printf("type check failed on el1\n"); - return False; - } - if (talloc_get_type(el1, struct el2) != NULL) { - printf("type check failed on el1 with el2\n"); - return False; - } - talloc_set_type(el1, struct el2); - if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) { - printf("type set failed on el1 with el2\n"); - return False; - } - - talloc_free(root); - - return True; -} - -/* - test steal -*/ -static BOOL test_steal(void) -{ - void *root, *p1, *p2; - - printf("TESTING STEAL\n"); - - root = talloc_new(NULL); - - p1 = talloc_array(root, char, 10); - CHECK_SIZE(p1, 10); - - p2 = talloc_realloc(root, NULL, char, 20); - CHECK_SIZE(p1, 10); - CHECK_SIZE(root, 30); - - if (talloc_steal(p1, NULL) != NULL) { - printf("failed: stealing NULL should give NULL\n"); - return False; - } - - if (talloc_steal(p1, p1) != p1) { - printf("failed: stealing to ourselves is a nop\n"); - return False; - } - CHECK_BLOCKS(root, 3); - CHECK_SIZE(root, 30); - - talloc_steal(NULL, p1); - talloc_steal(NULL, p2); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); - - talloc_free(p1); - talloc_steal(root, p2); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 20); - - talloc_free(p2); - - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); - - talloc_free(root); - - p1 = talloc_size(NULL, 3); - CHECK_SIZE(NULL, 3); - talloc_free(p1); - - return True; -} - -/* - test talloc_realloc_fn -*/ -static BOOL test_realloc_fn(void) -{ - void *root, *p1; - - printf("TESTING talloc_realloc_fn\n"); - - root = talloc_new(NULL); - - p1 = talloc_realloc_fn(root, NULL, 10); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 10); - p1 = talloc_realloc_fn(root, p1, 20); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 20); - p1 = talloc_realloc_fn(root, p1, 0); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); - - talloc_free(root); - - - return True; -} - - -static BOOL test_unref_reparent(void) -{ - void *root, *p1, *p2, *c1; - - printf("TESTING UNREFERENCE AFTER PARENT FREED\n"); - - root = talloc_named_const(NULL, 0, "root"); - p1 = talloc_named_const(root, 1, "orig parent"); - p2 = talloc_named_const(root, 1, "parent by reference"); - - c1 = talloc_named_const(p1, 1, "child"); - talloc_reference(p2, c1); - - talloc_free(p1); - talloc_unlink(p2, c1); - - CHECK_SIZE(root, 1); - - talloc_free(p2); - talloc_free(root); - - return True; -} - -/* - measure the speed of talloc versus malloc -*/ -static BOOL test_speed(void) -{ - void *ctx = talloc_new(NULL); - unsigned count; - struct timeval tv; - - printf("MEASURING TALLOC VS MALLOC SPEED\n"); - - tv = timeval_current(); - count = 0; - do { - void *p1, *p2, *p3; - p1 = talloc_size(ctx, count); - p2 = talloc_strdup(p1, "foo bar"); - p3 = talloc_size(p1, 300); - talloc_free(p1); - count += 3; - } while (timeval_elapsed(&tv) < 5.0); - - printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); - - talloc_free(ctx); - - tv = timeval_current(); - count = 0; - do { - void *p1, *p2, *p3; - p1 = malloc(count); - p2 = strdup("foo bar"); - p3 = malloc(300); - free(p1); - free(p2); - free(p3); - count += 3; - } while (timeval_elapsed(&tv) < 5.0); - - printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); - - return True; -} - - -BOOL torture_local_talloc(void) -{ - BOOL ret = True; - - ret &= test_ref1(); - ret &= test_ref2(); - ret &= test_ref3(); - ret &= test_ref4(); - ret &= test_unlink1(); - ret &= test_misc(); - ret &= test_realloc(); - ret &= test_realloc_child(); - ret &= test_steal(); - ret &= test_unref_reparent(); - ret &= test_realloc_fn(); - ret &= test_type(); - if (ret) { - ret &= test_speed(); - } - - return ret; -} - - - -#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) - int main(void) -{ - if (!torture_local_talloc()) { - printf("ERROR: TESTSUIE FAILED\n"); - return -1; - } - return 0; -} -#endif diff --git a/source/lib/time.c b/source/lib/time.c index 9a539d415e8..403fb0594d4 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. time handling functions - Copyright (C) Andrew Tridgell 1992-1998 + + Copyright (C) Andrew Tridgell 1992-2004 Copyright (C) Stefan (metze) Metzmacher 2002 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -20,16 +22,11 @@ #include "includes.h" -/* - This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com> - in May 1996 - */ +/** + * @file + * @brief time handling functions + */ -int extra_time_offset = 0; - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif #ifndef TIME_T_MIN #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ @@ -39,19 +36,17 @@ int extra_time_offset = 0; #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) #endif -/******************************************************************* +/** External access to time_t_min and time_t_max. -********************************************************************/ - +**/ time_t get_time_t_max(void) { return TIME_T_MAX; } -/******************************************************************* - A gettimeofday wrapper. -********************************************************************/ - +/** +a gettimeofday wrapper +**/ void GetTimeOfDay(struct timeval *tval) { #ifdef HAVE_GETTIMEOFDAY_TZ @@ -61,220 +56,35 @@ void GetTimeOfDay(struct timeval *tval) #endif } -#define TM_YEAR_BASE 1900 - -/******************************************************************* - Yield the difference between *A and *B, in seconds, ignoring leap seconds. -********************************************************************/ - -static int tm_diff(struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (TM_YEAR_BASE - 1); - int by = b->tm_year + (TM_YEAR_BASE - 1); - int intervening_leap_days = (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; -} - -/******************************************************************* - Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined. -******************************************************************/ - -int get_time_zone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - - if (!tm) { - return 0; - } - tm_utc = *tm; - tm = localtime(&t); - if (!tm) { - return 0; - } - return tm_diff(&tm_utc,tm) + 60*extra_time_offset; -} - -/******************************************************************* - Accessor function for the server time zone offset. - set_server_zone_offset() must have been called first. -******************************************************************/ - -static int server_zone_offset; - -int get_server_zone_offset(void) -{ - return server_zone_offset; -} - -/******************************************************************* - Initialize the server time zone offset. Called when a client connects. -******************************************************************/ - -int set_server_zone_offset(time_t t) +struct timespec convert_time_t_to_timespec(time_t t) { - server_zone_offset = get_time_zone(t); - return server_zone_offset; + struct timespec ts; + ts.tv_sec = t; + ts.tv_nsec = 0; + return ts; } -/******************************************************************* - Re-read the smb serverzone value. -******************************************************************/ - -static struct timeval start_time_hires; - -void TimeInit(void) -{ - set_server_zone_offset(time(NULL)); - - DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset)); - - /* Save the start time of this process. */ - if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) { - GetTimeOfDay(&start_time_hires); - } -} - -/********************************************************************** - Return a timeval struct of the uptime of this process. As TimeInit is - done before a daemon fork then this is the start time from the parent - daemon start. JRA. -***********************************************************************/ - -void get_process_uptime(struct timeval *ret_time) -{ - struct timeval time_now_hires; - - GetTimeOfDay(&time_now_hires); - ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec; - if (time_now_hires.tv_usec < start_time_hires.tv_usec) { - ret_time->tv_sec -= 1; - ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec); - } else { - ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; - } -} - -#if 0 -/**************************************************************************** - Return the UTC offset in seconds west of UTC, adjusted for extra time offset. -**************************************************************************/ - -int TimeDiff(time_t t) -{ - return get_time_zone(t); -} +#if (SIZEOF_LONG == 8) +#define TIME_FIXUP_CONSTANT_INT 11644473600L +#elif (SIZEOF_LONG_LONG == 8) +#define TIME_FIXUP_CONSTANT_INT 11644473600LL #endif -#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) - /**************************************************************************** Interpret an 8 byte "filetime" structure to a time_t It's originally in "100ns units since jan 1st 1601" - An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0. - - Returns GMT. -****************************************************************************/ - -time_t nt_time_to_unix(NTTIME *nt) -{ - double d; - time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - - if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) { - return(0); - } - - d = ((double)nt->high)*4.0*(double)(1<<30); - d += (nt->low&0xFFF00000); - d *= 1.0e-7; - - /* now adjust by 369 years to make the secs since 1970 */ - d -= TIME_FIXUP_CONSTANT; + An 8 byte value of 0xffffffffffffffff will be returned as a timespec of - if (d <= l_time_min) { - return (l_time_min); - } - - if (d >= l_time_max) { - return (l_time_max); - } - - ret = (time_t)(d+0.5); - return(ret); -} - -/**************************************************************************** - Convert a NTTIME structure to a time_t. - It's originally in "100ns units". - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 - if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM -****************************************************************************/ + tv_sec = 0 + tv_nsec = 0; -time_t nt_time_to_unix_abs(const NTTIME *nt) -{ - double d; - time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - NTTIME neg_nt; - - if (nt->high == 0) { - return(0); - } - - if (nt->high==0x80000000 && nt->low==0) { - return (time_t)-1; - } - - /* reverse the time */ - /* it's a negative value, turn it to positive */ - neg_nt.high=~nt->high; - neg_nt.low=~nt->low; - - d = ((double)neg_nt.high)*4.0*(double)(1<<30); - d += (neg_nt.low&0xFFF00000); - d *= 1.0e-7; - - if (!(l_time_min <= d && d <= l_time_max)) { - return(0); - } - - ret = (time_t)(d+0.5); - - return(ret); -} - -/**************************************************************************** - Interprets an nt time into a unix time_t. - Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff - will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case. + Returns GMT. ****************************************************************************/ -time_t interpret_long_date(char *p) +time_t nt_time_to_unix(NTTIME nt) { - NTTIME nt; - nt.low = IVAL(p,0); - nt.high = IVAL(p,4); - if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) { - return (time_t)-1; - } - return nt_time_to_unix(&nt); + return convert_timespec_to_time_t(nt_time_to_unix_timespec(&nt)); } /**************************************************************************** @@ -283,137 +93,81 @@ time_t interpret_long_date(char *p) void unix_to_nt_time(NTTIME *nt, time_t t) { - double d; + uint64_t t2; - if (t==0) { - nt->low = 0; - nt->high = 0; - return; - } - if (t == TIME_T_MAX) { - nt->low = 0xffffffff; - nt->high = 0x7fffffff; - return; - } if (t == (time_t)-1) { - nt->low = 0xffffffff; - nt->high = 0xffffffff; + *nt = (NTTIME)-1LL; return; } - - d = (double)(t); - d += TIME_FIXUP_CONSTANT; - d *= 1.0e7; - - nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); -} - -/**************************************************************************** - Convert a time_t to a NTTIME structure - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 - If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM -****************************************************************************/ - -void unix_to_nt_time_abs(NTTIME *nt, time_t t) -{ - double d; - - if (t==0) { - nt->low = 0; - nt->high = 0; - return; - } - - if (t == TIME_T_MAX) { - nt->low = 0xffffffff; - nt->high = 0x7fffffff; - return; - } - - if (t == (time_t)-1) { - /* that's what NT uses for infinite */ - nt->low = 0x0; - nt->high = 0x80000000; + if (t == 0) { + *nt = 0; return; } - d = (double)(t); - d *= 1.0e7; - - nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); + t2 = t; + t2 += TIME_FIXUP_CONSTANT_INT; + t2 *= 1000*1000*10; - /* convert to a negative value */ - nt->high=~nt->high; - nt->low=~nt->low; + *nt = t2; } -/**************************************************************************** - Take a Unix time and convert to an NTTIME structure and place in buffer - pointed to by p. -****************************************************************************/ -void put_long_date(char *p, time_t t) +/** +check if it's a null unix time +**/ +BOOL null_time(time_t t) { - NTTIME nt; - unix_to_nt_time(&nt, t); - SIVAL(p, 0, nt.low); - SIVAL(p, 4, nt.high); + return t == 0 || + t == (time_t)0xFFFFFFFF || + t == (time_t)-1; } -/**************************************************************************** - Check if it's a null mtime. -****************************************************************************/ -BOOL null_mtime(time_t mtime) +/** +check if it's a null NTTIME +**/ +BOOL null_nttime(NTTIME t) { - if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1) - return(True); - return(False); + return t == 0 || t == (NTTIME)-1; } /******************************************************************* - Create a 16 bit dos packed date. + create a 16 bit dos packed date ********************************************************************/ - -static uint16 make_dos_date1(struct tm *t) +static uint16_t make_dos_date1(struct tm *t) { - uint16 ret=0; - ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); + uint16_t ret=0; + ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); - return(ret); + return ret; } /******************************************************************* - Create a 16 bit dos packed time. + create a 16 bit dos packed time ********************************************************************/ - -static uint16 make_dos_time1(struct tm *t) +static uint16_t make_dos_time1(struct tm *t) { - uint16 ret=0; - ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); + uint16_t ret=0; + ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3)); ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); - return(ret); + return ret; } /******************************************************************* - Create a 32 bit dos packed date/time from some parameters. - This takes a GMT time and returns a packed localtime structure. + create a 32 bit dos packed date/time from some parameters + This takes a GMT time and returns a packed localtime structure ********************************************************************/ - -static uint32 make_dos_date(time_t unixdate, int zone_offset) +static uint32_t make_dos_date(time_t unixdate, int zone_offset) { struct tm *t; - uint32 ret=0; + uint32_t ret=0; if (unixdate == 0) { return 0; } unixdate -= zone_offset; + t = gmtime(&unixdate); if (!t) { return 0xFFFFFFFF; @@ -422,53 +176,50 @@ static uint32 make_dos_date(time_t unixdate, int zone_offset) ret = make_dos_date1(t); ret = ((ret&0xFFFF)<<16) | make_dos_time1(t); - return(ret); + return ret; } -/******************************************************************* - Put a dos date into a buffer (time/date format). - This takes GMT time and puts local time in the buffer. -********************************************************************/ - -static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset) +/** +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +**/ +void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset) { - uint32 x = make_dos_date(unixdate, zone_offset); + uint32_t x = make_dos_date(unixdate, zone_offset); SIVAL(buf,offset,x); } -/******************************************************************* - Put a dos date into a buffer (date/time format). - This takes GMT time and puts local time in the buffer. -********************************************************************/ - -static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) +/** +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +**/ +void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset) { - uint32 x = make_dos_date(unixdate, zone_offset); + uint32_t x; + x = make_dos_date(unixdate, zone_offset); x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(buf,offset,x); } -/******************************************************************* - Put a dos 32 bit "unix like" date into a buffer. This routine takes - GMT and converts it to LOCAL time before putting it (most SMBs assume - localtime for this sort of date) -********************************************************************/ - -static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) +/** +put a dos 32 bit "unix like" date into a buffer. This routine takes +GMT and converts it to LOCAL time before putting it (most SMBs assume +localtime for this sort of date) +**/ +void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset) { - if (!null_mtime(unixdate)) { + if (!null_time(unixdate)) { unixdate -= zone_offset; } SIVAL(buf,offset,unixdate); } /******************************************************************* - Interpret a 32 bit dos packed date/time to some parameters. + interpret a 32 bit dos packed date/time to some parameters ********************************************************************/ - -static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) +static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second) { - uint32 p0,p1,p2,p3; + uint32_t p0,p1,p2,p3; p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; @@ -481,161 +232,414 @@ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *ho *year = ((p3>>1)&0xFF) + 80; } -/******************************************************************* - Create a unix date (int GMT) from a dos date (which is actually in - localtime). -********************************************************************/ - -static time_t make_unix_date(void *date_ptr, int zone_offset) +/** + create a unix date (int GMT) from a dos date (which is actually in + localtime) +**/ +time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) { - uint32 dos_date=0; + uint32_t dos_date=0; struct tm t; time_t ret; dos_date = IVAL(date_ptr,0); - if (dos_date == 0) { - return 0; - } + if (dos_date == 0) return (time_t)0; interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, - &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); + &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; ret = timegm(&t); ret += zone_offset; - return(ret); + return ret; } -/******************************************************************* - Like make_unix_date() but the words are reversed. -********************************************************************/ - -static time_t make_unix_date2(void *date_ptr, int zone_offset) +/** +like make_unix_date() but the words are reversed +**/ +time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) { - uint32 x,x2; + uint32_t x,x2; x = IVAL(date_ptr,0); x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(&x,0,x2); - return(make_unix_date((void *)&x, zone_offset)); + return pull_dos_date((const uint8_t *)&x, zone_offset); } -/******************************************************************* - Create a unix GMT date from a dos date in 32 bit "unix like" format - these generally arrive as localtimes, with corresponding DST. -******************************************************************/ - -static time_t make_unix_date3(void *date_ptr, int zone_offset) +/** + create a unix GMT date from a dos date in 32 bit "unix like" format + these generally arrive as localtimes, with corresponding DST +**/ +time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) { time_t t = (time_t)IVAL(date_ptr,0); - if (!null_mtime(t)) { + if (!null_time(t)) { t += zone_offset; } - return(t); + return t; } /*************************************************************************** - Server versions of the above functions. + Return a HTTP/1.0 time string. ***************************************************************************/ -void srv_put_dos_date(char *buf,int offset,time_t unixdate) +char *http_timestring(time_t t) { - put_dos_date(buf, offset, unixdate, server_zone_offset); + static fstring buf; + struct tm *tm = localtime(&t); + + if (!tm) { + slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t); + } else { +#ifndef HAVE_STRFTIME + const char *asct = asctime(tm); + fstrcpy(buf, asct ? asct : "unknown"); + } + if(buf[strlen(buf)-1] == '\n') { + buf[strlen(buf)-1] = 0; +#else /* !HAVE_STRFTIME */ + strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); +#endif /* !HAVE_STRFTIME */ + } + return buf; } -void srv_put_dos_date2(char *buf,int offset, time_t unixdate) + +/** + Return the date and time as a string +**/ +char *timestring(TALLOC_CTX *mem_ctx, time_t t) { - put_dos_date2(buf, offset, unixdate, server_zone_offset); + char *TimeBuf; + char tempTime[80]; + struct tm *tm; + + tm = localtime(&t); + if (!tm) { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + +#ifdef HAVE_STRFTIME + /* some versions of gcc complain about using %c. This is a bug + in the gcc warning, not a bug in this code. See a recent + strftime() manual page for details. + */ + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); +#else + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); +#endif + + return TimeBuf; } -void srv_put_dos_date3(char *buf,int offset,time_t unixdate) +/** + return a talloced string representing a NTTIME for human consumption +*/ +const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) { - put_dos_date3(buf, offset, unixdate, server_zone_offset); + time_t t; + if (nt == 0) { + return "NTTIME(0)"; + } + t = nt_time_to_unix(nt); + return timestring(mem_ctx, t); } -time_t srv_make_unix_date(void *date_ptr) + +/** + parse a nttime as a large integer in a string and return a NTTIME +*/ +NTTIME nttime_from_string(const char *s) { - return make_unix_date(date_ptr, server_zone_offset); + return strtoull(s, NULL, 0); } -time_t srv_make_unix_date2(void *date_ptr) +/** + return (tv1 - tv2) in microseconds +*/ +int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2) { - return make_unix_date2(date_ptr, server_zone_offset); + int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; + return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); } -time_t srv_make_unix_date3(void *date_ptr) + +/** + return a zero timeval +*/ +struct timeval timeval_zero(void) { - return make_unix_date3(date_ptr, server_zone_offset); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; } -/*************************************************************************** - Client versions of the above functions. -***************************************************************************/ +/** + return True if a timeval is zero +*/ +BOOL timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} -void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate) +/** + return a timeval for the current time +*/ +struct timeval timeval_current(void) { - put_dos_date(buf, offset, unixdate, cli->serverzone); + struct timeval tv; + GetTimeOfDay(&tv); + return tv; } -void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate) +/** + return a timeval struct with the given elements +*/ +struct timeval timeval_set(uint32_t secs, uint32_t usecs) { - put_dos_date2(buf, offset, unixdate, cli->serverzone); + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; } -void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate) + +/** + return a timeval ofs microseconds after tv +*/ +struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs) { - put_dos_date3(buf, offset, unixdate, cli->serverzone); + struct timeval tv2 = *tv; + const unsigned int million = 1000000; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / million; + tv2.tv_usec = tv2.tv_usec % million; + return tv2; } -time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr) +/** + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2) { - return make_unix_date(date_ptr, cli->serverzone); + return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); } -time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr) +/** + return a timeval secs/usecs into the future +*/ +struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) { - return make_unix_date2(date_ptr, cli->serverzone); + struct timeval tv = timeval_current(); + return timeval_add(&tv, secs, usecs); } -time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr) +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) { - return make_unix_date3(date_ptr, cli->serverzone); + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; } -/*************************************************************************** - Return a HTTP/1.0 time string. -***************************************************************************/ +/** + return True if a timer is in the past +*/ +BOOL timeval_expired(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + if (tv2.tv_sec > tv->tv_sec) return True; + if (tv2.tv_sec < tv->tv_sec) return False; + return (tv2.tv_usec >= tv->tv_usec); +} -char *http_timestring(time_t t) +/** + return the number of seconds elapsed between two times +*/ +double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) { - static fstring buf; - struct tm *tm = localtime(&t); + return (tv2->tv_sec - tv1->tv_sec) + + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; +} - if (!tm) { - slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t); +/** + return the number of seconds elapsed since a given time +*/ +double timeval_elapsed(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return timeval_elapsed2(tv, &tv2); +} + +/** + return the lesser of two timevals +*/ +struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) return *tv1; + if (tv1->tv_sec > tv2->tv_sec) return *tv2; + if (tv1->tv_usec < tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the greater of two timevals +*/ +struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return *tv1; + if (tv1->tv_sec < tv2->tv_sec) return *tv2; + if (tv1->tv_usec > tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (timeval_compare(tv1, tv2) >= 0) { + return timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); } else { -#ifndef HAVE_STRFTIME - const char *asct = asctime(tm); - fstrcpy(buf, asct ? asct : "unknown"); + t.tv_usec = tv2->tv_usec - tv1->tv_usec; } - if(buf[strlen(buf)-1] == '\n') { - buf[strlen(buf)-1] = 0; -#else /* !HAVE_STRFTIME */ - strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); -#endif /* !HAVE_STRFTIME */ + return t; +} + + +/** + convert a timeval to a NTTIME +*/ +NTTIME timeval_to_nttime(const struct timeval *tv) +{ + return 10*(tv->tv_usec + + ((TIME_FIXUP_CONSTANT_INT + (uint64_t)tv->tv_sec) * 1000000)); +} + +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + +int extra_time_offset=0; + +/** + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + */ +int get_time_zone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm)+60*extra_time_offset; +} + +/**************************************************************************** + Check if NTTIME is 0. +****************************************************************************/ + +BOOL nt_time_is_zero(const NTTIME *nt) +{ + return (*nt == 0); +} + +/**************************************************************************** + Convert ASN.1 GeneralizedTime string to unix-time. + Returns 0 on failure; Currently ignores timezone. +****************************************************************************/ + +time_t generalized_to_unix_time(const char *str) +{ + struct tm tm; + + ZERO_STRUCT(tm); + + if (sscanf(str, "%4d%2d%2d%2d%2d%2d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return 0; } - return buf; + tm.tm_year -= 1900; + tm.tm_mon -= 1; + + return timegm(&tm); +} + +/******************************************************************* + Accessor function for the server time zone offset. + set_server_zone_offset() must have been called first. +******************************************************************/ + +static int server_zone_offset; + +int get_server_zone_offset(void) +{ + return server_zone_offset; +} + +/******************************************************************* + Initialize the server time zone offset. Called when a client connects. +******************************************************************/ + +int set_server_zone_offset(time_t t) +{ + server_zone_offset = get_time_zone(t); + return server_zone_offset; } /**************************************************************************** Return the date and time as a string ****************************************************************************/ -char *timestring(BOOL hires) +char *current_timestring(BOOL hires) { static fstring TimeBuf; struct timeval tp; @@ -690,6 +694,85 @@ char *timestring(BOOL hires) return(TimeBuf); } + +/******************************************************************* + Put a dos date into a buffer (time/date format). + This takes GMT time and puts local time in the buffer. +********************************************************************/ + +static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset) +{ + uint32 x = make_dos_date(unixdate, zone_offset); + SIVAL(buf,offset,x); +} + +/******************************************************************* + Put a dos date into a buffer (date/time format). + This takes GMT time and puts local time in the buffer. +********************************************************************/ + +static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) +{ + uint32 x = make_dos_date(unixdate, zone_offset); + x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(buf,offset,x); +} + +/******************************************************************* + Put a dos 32 bit "unix like" date into a buffer. This routine takes + GMT and converts it to LOCAL time before putting it (most SMBs assume + localtime for this sort of date) +********************************************************************/ + +static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) +{ + if (!null_mtime(unixdate)) { + unixdate -= zone_offset; + } + SIVAL(buf,offset,unixdate); +} + + +/*************************************************************************** + Server versions of the above functions. +***************************************************************************/ + +void srv_put_dos_date(char *buf,int offset,time_t unixdate) +{ + put_dos_date(buf, offset, unixdate, server_zone_offset); +} + +void srv_put_dos_date2(char *buf,int offset, time_t unixdate) +{ + put_dos_date2(buf, offset, unixdate, server_zone_offset); +} + +void srv_put_dos_date3(char *buf,int offset,time_t unixdate) +{ + put_dos_date3(buf, offset, unixdate, server_zone_offset); +} + +/**************************************************************************** + Take a Unix time and convert to an NTTIME structure and place in buffer + pointed to by p. +****************************************************************************/ + +void put_long_date_timespec(char *p, struct timespec ts) +{ + NTTIME nt; + unix_timespec_to_nt_time(&nt, ts); + SIVAL(p, 0, nt & 0xFFFFFFFF); + SIVAL(p, 4, nt >> 32); +} + +void put_long_date(char *p, time_t t) +{ + struct timespec ts; + ts.tv_sec = t; + ts.tv_nsec = 0; + put_long_date_timespec(p, ts); +} + /**************************************************************************** Return the best approximation to a 'create time' under UNIX from a stat structure. @@ -717,344 +800,478 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) return ret; } +struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs) +{ + struct timespec ts; + ts.tv_sec = get_create_time(st, fake_dirs); + ts.tv_nsec = 0; + return ts; +} + /**************************************************************************** - Initialise an NTTIME to -1, which means "unknown" or "don't expire". + Get/Set all the possible time fields from a stat struct as a timespec. ****************************************************************************/ -void init_nt_time(NTTIME *nt) +struct timespec get_atimespec(SMB_STRUCT_STAT *pst) { - nt->high = 0x7FFFFFFF; - nt->low = 0xFFFFFFFF; +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; + + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_atime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STAT_ST_ATIM) + return pst->st_atim; +#elif defined(HAVE_STAT_ST_ATIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_atimensec; + return ret; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif } -BOOL nt_time_is_set(const NTTIME *nt) +void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) { - if ((nt->high == 0x7FFFFFFF) && (nt->low == 0xFFFFFFFF)) { - return False; - } +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + /* Old system - no ns timestamp. */ + pst->st_atime = ts.tv_sec; +#else +#if defined(HAVE_STAT_ST_ATIM) + pst->st_atim = ts; +#elif defined(HAVE_STAT_ST_ATIMENSEC) + pst->st_atime = ts.tv_sec; + pst->st_atimensec = ts.tv_nsec +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} - if ((nt->high == 0x80000000) && (nt->low == 0)) { - return False; - } +struct timespec get_mtimespec(SMB_STRUCT_STAT *pst) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; - return True; + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STAT_ST_MTIM) + return pst->st_mtim; +#elif defined(HAVE_STAT_ST_MTIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_mtimensec; + return ret; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif } -/**************************************************************************** - Check if NTTIME is 0. -****************************************************************************/ +void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + /* Old system - no ns timestamp. */ + pst->st_mtime = ts.tv_sec; +#else +#if defined(HAVE_STAT_ST_MTIM) + pst->st_mtim = ts; +#elif defined(HAVE_STAT_ST_MTIMENSEC) + pst->st_mtime = ts.tv_sec; + pst->st_mtimensec = ts.tv_nsec +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} -BOOL nt_time_is_zero(const NTTIME *nt) +struct timespec get_ctimespec(SMB_STRUCT_STAT *pst) { - if(nt->high==0) { - return True; - } - return False; +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; + + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STAT_ST_CTIM) + return pst->st_ctim; +#elif defined(HAVE_STAT_ST_CTIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_ctimensec; + return ret; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif } -/**************************************************************************** - Check if two NTTIMEs are the same. -****************************************************************************/ +void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + /* Old system - no ns timestamp. */ + pst->st_ctime = ts.tv_sec; +#else +#if defined(HAVE_STAT_ST_CTIM) + pst->st_ctim = ts; +#elif defined(HAVE_STAT_ST_CTIMENSEC) + pst->st_ctime = ts.tv_sec; + pst->st_ctimensec = ts.tv_nsec +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} -BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2) +void dos_filetime_timespec(struct timespec *tsp) { - return (nt1->high == nt2->high && nt1->low == nt2->low); + tsp->tv_sec &= ~1; + tsp->tv_nsec = 0; } -/**************************************************************************** - Return a timeval difference in usec. -****************************************************************************/ +/******************************************************************* + Create a unix date (int GMT) from a dos date (which is actually in + localtime). +********************************************************************/ -SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *smallt) +static time_t make_unix_date(const void *date_ptr, int zone_offset) { - SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec; - return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec); + uint32 dos_date=0; + struct tm t; + time_t ret; + + dos_date = IVAL(date_ptr,0); + + if (dos_date == 0) { + return 0; + } + + interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, + &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); + t.tm_isdst = -1; + + ret = timegm(&t); + + ret += zone_offset; + + return(ret); } -/**************************************************************************** - Return a timeval struct with the given elements. -****************************************************************************/ +/******************************************************************* + Like make_unix_date() but the words are reversed. +********************************************************************/ -struct timeval timeval_set(uint32_t secs, uint32_t usecs) +static time_t make_unix_date2(const void *date_ptr, int zone_offset) { - struct timeval tv; - tv.tv_sec = secs; - tv.tv_usec = usecs; - return tv; + uint32 x,x2; + + x = IVAL(date_ptr,0); + x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(&x,0,x2); + + return(make_unix_date((const void *)&x, zone_offset)); } -/**************************************************************************** - Return a zero timeval. -****************************************************************************/ +/******************************************************************* + Create a unix GMT date from a dos date in 32 bit "unix like" format + these generally arrive as localtimes, with corresponding DST. +******************************************************************/ -struct timeval timeval_zero(void) +static time_t make_unix_date3(const void *date_ptr, int zone_offset) { - return timeval_set(0,0); + time_t t = (time_t)IVAL(date_ptr,0); + if (!null_mtime(t)) { + t += zone_offset; + } + return(t); } -/**************************************************************************** - Return True if a timeval is zero. -****************************************************************************/ +time_t srv_make_unix_date(const void *date_ptr) +{ + return make_unix_date(date_ptr, server_zone_offset); +} -BOOL timeval_is_zero(const struct timeval *tv) +time_t srv_make_unix_date2(const void *date_ptr) { - return tv->tv_sec == 0 && tv->tv_usec == 0; + return make_unix_date2(date_ptr, server_zone_offset); } -/**************************************************************************** - Return a timeval for the current time. -****************************************************************************/ +time_t srv_make_unix_date3(const void *date_ptr) +{ + return make_unix_date3(date_ptr, server_zone_offset); +} -struct timeval timeval_current(void) +time_t convert_timespec_to_time_t(struct timespec ts) { - struct timeval tv; - GetTimeOfDay(&tv); - return tv; + /* 1 ns == 1,000,000,000 - one thousand millionths of a second. + increment if it's greater than 500 millionth of a second. */ + if (ts.tv_nsec > 500000000) { + return ts.tv_sec + 1; + } + return ts.tv_sec; } /**************************************************************************** - Return a timeval ofs microseconds after tv. + Interprets an nt time into a unix struct timespec. + Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff + will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case. ****************************************************************************/ -struct timeval timeval_add(const struct timeval *tv, - uint32_t secs, uint32_t usecs) +struct timespec interpret_long_date(const char *p) { - struct timeval tv2 = *tv; - tv2.tv_sec += secs; - tv2.tv_usec += usecs; - tv2.tv_sec += tv2.tv_usec / 1000000; - tv2.tv_usec = tv2.tv_usec % 1000000; - return tv2; + NTTIME nt; + nt = IVAL(p,0) + ((uint64_t)IVAL(p,4) << 32); + if (nt == (uint64_t)-1) { + struct timespec ret; + ret.tv_sec = (time_t)-1; + ret.tv_nsec = 0; + return ret; + } + return nt_time_to_unix_timespec(&nt); } -/**************************************************************************** - Return the sum of two timeval structures. -****************************************************************************/ +/*************************************************************************** + Client versions of the above functions. +***************************************************************************/ -struct timeval timeval_sum(const struct timeval *tv1, - const struct timeval *tv2) +void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate) { - return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); + put_dos_date(buf, offset, unixdate, cli->serverzone); } -/**************************************************************************** - Return a timeval secs/usecs into the future. -****************************************************************************/ +void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate) +{ + put_dos_date2(buf, offset, unixdate, cli->serverzone); +} -struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) +void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate) { - struct timeval tv = timeval_current(); - return timeval_add(&tv, secs, usecs); + put_dos_date3(buf, offset, unixdate, cli->serverzone); } -/**************************************************************************** - Compare two timeval structures. - Return -1 if tv1 < tv2 - Return 0 if tv1 == tv2 - Return 1 if tv1 > tv2 -****************************************************************************/ +time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr) +{ + return make_unix_date(date_ptr, cli->serverzone); +} -int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr) { - if (tv1->tv_sec > tv2->tv_sec) { - return 1; - } - if (tv1->tv_sec < tv2->tv_sec) { - return -1; + return make_unix_date2(date_ptr, cli->serverzone); +} + +time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr) +{ + return make_unix_date3(date_ptr, cli->serverzone); +} + +/* Large integer version. */ +struct timespec nt_time_to_unix_timespec(NTTIME *nt) +{ + int64 d; + struct timespec ret; + + if (*nt == 0 || *nt == (int64)-1) { + ret.tv_sec = 0; + ret.tv_nsec = 0; + return ret; } - if (tv1->tv_usec > tv2->tv_usec) { - return 1; + + d = (int64)*nt; + /* d is now in 100ns units, since jan 1st 1601". + Save off the ns fraction. */ + + ret.tv_nsec = (long) ((d % 100) * 100); + + /* Convert to seconds */ + d /= 1000*1000*10; + + /* Now adjust by 369 years to make the secs since 1970 */ + d -= TIME_FIXUP_CONSTANT_INT; + + if (d <= (int64)TIME_T_MIN) { + ret.tv_sec = TIME_T_MIN; + ret.tv_nsec = 0; + return ret; } - if (tv1->tv_usec < tv2->tv_usec) { - return -1; + + if (d >= (int64)TIME_T_MAX) { + ret.tv_sec = TIME_T_MAX; + ret.tv_nsec = 0; + return ret; } - return 0; -} + ret.tv_sec = (time_t)d; + return ret; +} /**************************************************************************** - Return the difference between two timevals as a timeval. - If tv1 comes after tv2, then return a zero timeval - (this is *tv2 - *tv1). + Check if two NTTIMEs are the same. ****************************************************************************/ -struct timeval timeval_until(const struct timeval *tv1, - const struct timeval *tv2) +BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2) { - struct timeval t; - if (timeval_compare(tv1, tv2) >= 0) { - return timeval_zero(); - } - t.tv_sec = tv2->tv_sec - tv1->tv_sec; - if (tv1->tv_usec > tv2->tv_usec) { - t.tv_sec--; - t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); - } else { - t.tv_usec = tv2->tv_usec - tv1->tv_usec; - } - return t; + return (*nt1 == *nt2); } -/**************************************************************************** - Return the lesser of two timevals. -****************************************************************************/ +/******************************************************************* + Re-read the smb serverzone value. +******************************************************************/ -struct timeval timeval_min(const struct timeval *tv1, - const struct timeval *tv2) +static struct timeval start_time_hires; + +void TimeInit(void) { - if (tv1->tv_sec < tv2->tv_sec) { - return *tv1; - } - if (tv1->tv_sec > tv2->tv_sec) { - return *tv2; + set_server_zone_offset(time(NULL)); + + DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset)); + + /* Save the start time of this process. */ + if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) { + GetTimeOfDay(&start_time_hires); } - if (tv1->tv_usec < tv2->tv_usec) { - return *tv1; +} + +/********************************************************************** + Return a timeval struct of the uptime of this process. As TimeInit is + done before a daemon fork then this is the start time from the parent + daemon start. JRA. +***********************************************************************/ + +void get_process_uptime(struct timeval *ret_time) +{ + struct timeval time_now_hires; + + GetTimeOfDay(&time_now_hires); + ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec; + if (time_now_hires.tv_usec < start_time_hires.tv_usec) { + ret_time->tv_sec -= 1; + ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec); + } else { + ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; } - return *tv2; } /**************************************************************************** - Return the greater of two timevals. + Convert a NTTIME structure to a time_t. + It's originally in "100ns units". + + This is an absolute version of the one above. + By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 + if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM ****************************************************************************/ -struct timeval timeval_max(const struct timeval *tv1, - const struct timeval *tv2) +time_t nt_time_to_unix_abs(const NTTIME *nt) { - if (tv1->tv_sec > tv2->tv_sec) { - return *tv1; + uint64 d; + + if (*nt == 0) { + return (time_t)0; } - if (tv1->tv_sec < tv2->tv_sec) { - return *tv2; + + if (*nt == (uint64)-1) { + return (time_t)-1; } - if (tv1->tv_usec > tv2->tv_usec) { - return *tv1; + + /* reverse the time */ + /* it's a negative value, turn it to positive */ + d=~*nt; + + d += 1000*1000*10/2; + d /= 1000*1000*10; + + if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) { + return (time_t)0; } - return *tv2; + + return (time_t)d; } /**************************************************************************** - Convert ASN.1 GeneralizedTime string to unix-time. - Returns 0 on failure; Currently ignores timezone. + Put a 8 byte filetime from a struct timespec. Uses GMT. ****************************************************************************/ -time_t generalized_to_unix_time(const char *str) -{ - struct tm tm; - - ZERO_STRUCT(tm); +void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts) +{ + uint64 d; - if (sscanf(str, "%4d%2d%2d%2d%2d%2d", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, - &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { - return 0; + if (ts.tv_sec ==0 && ts.tv_nsec == 0) { + *nt = 0; + return; } - tm.tm_year -= 1900; - tm.tm_mon -= 1; + if (ts.tv_sec == TIME_T_MAX) { + *nt = 0x7fffffffffffffffLL; + return; + } + if (ts.tv_sec == (time_t)-1) { + *nt = (uint64)-1; + return; + } - return timegm(&tm); + d = ts.tv_sec; + d += TIME_FIXUP_CONSTANT_INT; + d *= 1000*1000*10; + /* d is now in 100ns units. */ + d += (ts.tv_nsec / 100); + + *nt = d; } /**************************************************************************** - Return all the possible time fields from a stat struct as a timespec. + Convert a time_t to a NTTIME structure + + This is an absolute version of the one above. + By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 + If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM ****************************************************************************/ -struct timespec get_atimespec(SMB_STRUCT_STAT *pst) +void unix_to_nt_time_abs(NTTIME *nt, time_t t) { -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; + double d; - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_atime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STAT_ST_ATIM) - return pst->st_atim; -#elif defined(HAVE_STAT_ST_ATIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_atime; - ret.tv_nsec = pst->st_atimensec; - return ret; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} + if (t==0) { + *nt = 0; + return; + } -struct timespec get_mtimespec(SMB_STRUCT_STAT *pst) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; + if (t == TIME_T_MAX) { + *nt = 0x7fffffffffffffffLL; + return; + } + + if (t == (time_t)-1) { + /* that's what NT uses for infinite */ + *nt = 0x8000000000000000LL; + return; + } - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STAT_ST_MTIM) - return pst->st_mtim; -#elif defined(HAVE_STAT_ST_MTIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = pst->st_mtimensec; - return ret; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} + d = (double)(t); + d *= 1.0e7; -struct timespec get_ctimespec(SMB_STRUCT_STAT *pst) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; + *nt = d; - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STAT_ST_CTIM) - return pst->st_ctim; -#elif defined(HAVE_STAT_ST_CTIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = pst->st_ctimensec; - return ret; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif + /* convert to a negative value */ + *nt=~*nt; } -#if 0 + /**************************************************************************** - Return the best approximation to a 'create time' under UNIX from a stat - structure. + Check if it's a null mtime. ****************************************************************************/ -struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs) +BOOL null_mtime(time_t mtime) { - time_t ret, ret1; - - if(S_ISDIR(st->st_mode) && fake_dirs) { - return (time_t)315493200L; /* 1/1/1980 */ - } - - ret = MIN(st->st_ctime, st->st_mtime); - ret1 = MIN(ret, st->st_atime); - - if(ret1 != (time_t)0) { - return ret1; - } - - /* - * One of ctime, mtime or atime was zero (probably atime). - * Just return MIN(ctime, mtime). - */ - return ret; + if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1) + return(True); + return(False); } -#endif /**************************************************************************** Utility function that always returns a const string even if localtime @@ -1076,3 +1293,52 @@ const char *time_to_asc(const time_t *t) } return asct; } + +const char *display_time(NTTIME nttime) +{ + static fstring string; + + float high; + float low; + int sec; + int days, hours, mins, secs; + + if (nttime==0) + return "Now"; + + if (nttime==0x8000000000000000LL) + return "Never"; + + high = 65536; + high = high/10000; + high = high*65536; + high = high/1000; + high = high * (~(nttime >> 32)); + + low = ~(nttime & 0xFFFFFFFF); + low = low/(1000*1000*10); + + sec=high+low; + + days=sec/(60*60*24); + hours=(sec - (days*60*60*24)) / (60*60); + mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60; + secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60); + + fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs); + return (string); +} + +BOOL nt_time_is_set(const NTTIME *nt) +{ + if (*nt == 0x7FFFFFFFFFFFFFFFLL) { + return False; + } + + if (*nt == 0x8000000000000000LL) { + return False; + } + + return True; +} + diff --git a/source/lib/util.c b/source/lib/util.c index 9738326ce67..67c9c8d37a7 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -61,7 +61,7 @@ extern fstring remote_arch; enum protocol_types Protocol = PROTOCOL_COREPLUS; /* a default finfo structure to ensure all fields are sensible */ -file_info def_finfo = {-1,0,0,0,0,0,0,"",""}; +file_info def_finfo; /* this is used by the chaining code */ int chain_size = 0; @@ -199,10 +199,10 @@ void gfree_all( void ) gfree_case_tables(); gfree_debugsyms(); gfree_charcnv(); - gfree_messsges(); + gfree_messages(); /* release the talloc null_context memory last */ - talloc_nc_free(); + talloc_disable_null_tracking(); } const char *my_netbios_names(int i) @@ -307,7 +307,7 @@ const char *tmpdir(void) Add a gid to an array of gids if it's not already there. ****************************************************************************/ -void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, +BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, gid_t **gids, size_t *num_gids) { int i; @@ -316,26 +316,24 @@ void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, /* * A former call to this routine has failed to allocate memory */ - return; + return False; } for (i=0; i<*num_gids; i++) { - if ((*gids)[i] == gid) - return; - } - - if (mem_ctx != NULL) { - *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1); - } else { - *gids = SMB_REALLOC_ARRAY(*gids, gid_t, *num_gids+1); + if ((*gids)[i] == gid) { + return True; + } } + *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1); if (*gids == NULL) { - return; + *num_gids = 0; + return False; } (*gids)[*num_gids] = gid; *num_gids += 1; + return True; } /**************************************************************************** @@ -760,7 +758,7 @@ ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn) size_t num_to_read_thistime; size_t num_written = 0; - if ((buf = SMB_MALLOC(TRANSFER_BUF_SIZE)) == NULL) + if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL) return -1; while (total < n) { @@ -915,6 +913,17 @@ void *malloc_(size_t size) } /**************************************************************************** + Internal malloc wrapper. Externally visible. +****************************************************************************/ + +void *memalign_(size_t align, size_t size) +{ +#undef memalign + return memalign(align, size); +#define memalign(align, s) __ERROR_DONT_USE_MEMALIGN_DIRECTLY +} + +/**************************************************************************** Internal calloc wrapper. Not externally visible. ****************************************************************************/ @@ -956,6 +965,23 @@ void *malloc_array(size_t el_size, unsigned int count) } /**************************************************************************** + Type-safe memalign +****************************************************************************/ + +void *memalign_array(size_t el_size, size_t align, unsigned int count) +{ + if (count >= MAX_ALLOC_SIZE/el_size) { + return NULL; + } + +#if defined(PARANOID_MALLOC_CHECKER) + return memalign_(align, el_size*count); +#else + return sys_memalign(align, el_size*count); +#endif +} + +/**************************************************************************** Type-safe calloc. ****************************************************************************/ @@ -1059,9 +1085,11 @@ void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_o ****************************************************************************/ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, - void *element, void **array, uint32 *num_elements, + void *element, void *_array, uint32 *num_elements, ssize_t *array_size) { + void **array = (void **)_array; + if (*array_size < 0) { return; } @@ -1075,12 +1103,7 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, goto error; } - if (mem_ctx != NULL) { - *array = TALLOC(mem_ctx, element_size * (*array_size)); - } else { - *array = SMB_MALLOC(element_size * (*array_size)); - } - + *array = TALLOC(mem_ctx, element_size * (*array_size)); if (*array == NULL) { goto error; } @@ -1093,13 +1116,8 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, goto error; } - if (mem_ctx != NULL) { - *array = TALLOC_REALLOC(mem_ctx, *array, - element_size * (*array_size)); - } else { - *array = SMB_REALLOC(*array, - element_size * (*array_size)); - } + *array = TALLOC_REALLOC(mem_ctx, *array, + element_size * (*array_size)); if (*array == NULL) { goto error; @@ -1479,6 +1497,10 @@ BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) BOOL process_exists(const struct process_id pid) { + if (procid_is_me(&pid)) { + return True; + } + if (!procid_is_local(&pid)) { /* This *SEVERELY* needs fixing. */ return True; @@ -1599,9 +1621,6 @@ void smb_panic(const char *const why) (unsigned long long)sys_getpid(), why)); log_stack_trace(); - /* only smbd needs to decrement the smbd counter in connections.tdb */ - decrement_smbd_process_count(); - cmd = lp_panic_action(); if (cmd && *cmd) { DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd)); @@ -2138,6 +2157,7 @@ BOOL is_myworkgroup(const char *s) /******************************************************************* we distinguish between 2K and XP by the "Native Lan Manager" string WinXP => "Windows 2002 5.1" + WinXP 64bit => "Windows XP 5.2" Win2k => "Windows 2000 5.0" NT4 => "Windows NT 4.0" Win9x => "Windows 4.0" @@ -2146,9 +2166,11 @@ BOOL is_myworkgroup(const char *s) ********************************************************************/ void ra_lanman_string( const char *native_lanman ) -{ +{ if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 ) set_remote_arch( RA_WINXP ); + else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 ) + set_remote_arch( RA_WINXP ); else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 ) set_remote_arch( RA_WIN2K3 ); } @@ -2182,6 +2204,9 @@ void set_remote_arch(enum remote_arch_types type) case RA_WIN2K3: fstrcpy(remote_arch, "Win2K3"); break; + case RA_VISTA: + fstrcpy(remote_arch, "Vista"); + break; case RA_SAMBA: fstrcpy(remote_arch,"Samba"); break; @@ -2443,8 +2468,16 @@ char *smb_xstrdup(const char *s) #undef strdup #endif #endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +#endif + char *s1 = strdup(s); #if defined(PARANOID_MALLOC_CHECKER) +#ifdef strdup +#undef strdup +#endif #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY #endif if (!s1) @@ -2464,8 +2497,17 @@ char *smb_xstrndup(const char *s, size_t n) #undef strndup #endif #endif + +#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP)) +#undef HAVE_STRNDUP +#define strndup rep_strndup +#endif + char *s1 = strndup(s, n); #if defined(PARANOID_MALLOC_CHECKER) +#ifdef strndup +#undef strndup +#endif #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY #endif if (!s1) @@ -2612,6 +2654,37 @@ char *parent_dirname(const char *path) return dirpath; } +BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir, + char **parent, const char **name) +{ + char *p; + ptrdiff_t len; + + p = strrchr_m(dir, '/'); /* Find final '/', if any */ + + if (p == NULL) { + if (!(*parent = talloc_strdup(mem_ctx, "."))) { + return False; + } + if (name) { + *name = ""; + } + return True; + } + + len = p-dir; + + if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) { + return False; + } + memcpy(*parent, dir, len); + (*parent)[len] = '\0'; + + if (name) { + *name = p+1; + } + return True; +} /******************************************************************* Determine if a pattern contains any Microsoft wildcard characters. @@ -2829,10 +2902,11 @@ BOOL unix_wild_match(const char *pattern, const char *string) } /********************************************************************** - Converts a name to a fully qalified domain name. + Converts a name to a fully qualified domain name. + Returns True if lookup succeeded, False if not (then fqdn is set to name) ***********************************************************************/ -void name_to_fqdn(fstring fqdn, const char *name) +BOOL name_to_fqdn(fstring fqdn, const char *name) { struct hostent *hp = sys_gethostbyname(name); @@ -2854,7 +2928,7 @@ void name_to_fqdn(fstring fqdn, const char *name) if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) { DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n")); - DEBUGADD(1, (" to Kerberos authentication probelms as localhost.localdomain\n")); + DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n")); DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n")); full = hp->h_name; } @@ -2865,9 +2939,11 @@ void name_to_fqdn(fstring fqdn, const char *name) DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full)); fstrcpy(fqdn, full); + return True; } else { DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name)); fstrcpy(fqdn, name); + return False; } } @@ -2968,11 +3044,24 @@ struct process_id procid_self(void) return pid_to_procid(sys_getpid()); } +struct server_id server_id_self(void) +{ + struct server_id id; + id.id = procid_self(); + return id; +} + BOOL procid_equal(const struct process_id *p1, const struct process_id *p2) { return (p1->pid == p2->pid); } +BOOL cluster_id_equal(const struct server_id *id1, + const struct server_id *id2) +{ + return procid_equal(&id1->id, &id2->id); +} + BOOL procid_is_me(const struct process_id *pid) { return (pid->pid == sys_getpid()); diff --git a/source/lib/util_file.c b/source/lib/util_file.c index ed7be3f6c1d..03246cad8e7 100644 --- a/source/lib/util_file.c +++ b/source/lib/util_file.c @@ -24,241 +24,6 @@ #define MAP_FAILED ((void *)-1) #endif -static int gotalarm; - -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - -/*************************************************************** - Lock or unlock a fd for a known lock type. Abandon after waitsecs - seconds. -****************************************************************/ - -BOOL do_file_lock(int fd, int waitsecs, int type) -{ - SMB_STRUCT_FLOCK lock; - int ret; - void (*oldsig_handler)(int); - - gotalarm = 0; - oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - lock.l_pid = 0; - - alarm(waitsecs); - /* Note we must *NOT* use sys_fcntl here ! JRA */ - ret = fcntl(fd, SMB_F_SETLKW, &lock); - alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler); - - if (gotalarm) { - DEBUG(0, ("do_file_lock: failed to %s file.\n", - type == F_UNLCK ? "unlock" : "lock")); - return False; - } - - return (ret == 0); -} - -/*************************************************************** - Lock an fd. Abandon after waitsecs seconds. -****************************************************************/ - -BOOL file_lock(int fd, int type, int secs, int *plock_depth) -{ - if (fd < 0) - return False; - - (*plock_depth)++; - - if ((*plock_depth) == 0) { - if (!do_file_lock(fd, secs, type)) { - DEBUG(10,("file_lock: locking file failed, error = %s.\n", strerror(errno))); - return False; - } - } - - return True; -} - -/*************************************************************** - Unlock an fd. Abandon after waitsecs seconds. -****************************************************************/ - -BOOL file_unlock(int fd, int *plock_depth) -{ - BOOL ret=True; - - if(*plock_depth == 1) { - ret = do_file_lock(fd, 5, F_UNLCK); - } - - (*plock_depth)--; - - if(!ret) { - DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", strerror(errno))); - } - return ret; -} - -/*************************************************************** - Locks a file for enumeration / modification. - update to be set = True if modification is required. -****************************************************************/ - -void *startfilepwent(char *pfile, char *s_readbuf, int bufsize, - int *file_lock_depth, BOOL update) -{ - FILE *fp = NULL; - - if (!*pfile) { - DEBUG(0, ("startfilepwent: No file set\n")); - return (NULL); - } - DEBUG(10, ("startfilepwent: opening file %s\n", pfile)); - - fp = sys_fopen(pfile, update ? "r+b" : "rb"); - - if (fp == NULL) { - DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile)); - return NULL; - } - - /* Set a buffer to do more efficient reads */ - setvbuf(fp, s_readbuf, _IOFBF, bufsize); - - if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) { - DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile)); - fclose(fp); - return NULL; - } - - /* Make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* We have a lock on the file. */ - return (void *)fp; -} - -/*************************************************************** - End enumeration of the file. -****************************************************************/ - -void endfilepwent(void *vp, int *file_lock_depth) -{ - FILE *fp = (FILE *)vp; - - file_unlock(fileno(fp), file_lock_depth); - fclose(fp); - DEBUG(7, ("endfilepwent: closed file.\n")); -} - -/************************************************************************* - Return the current position in the file list as an SMB_BIG_UINT. - This must be treated as an opaque token. -*************************************************************************/ - -SMB_BIG_UINT getfilepwpos(void *vp) -{ - return (SMB_BIG_UINT)sys_ftell((FILE *)vp); -} - -/************************************************************************* - Set the current position in the file list from an SMB_BIG_UINT. - This must be treated as an opaque token. -*************************************************************************/ - -BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok) -{ - return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET); -} - -/************************************************************************* - Gets a line out of a file. - line is of format "xxxx:xxxxxx:xxxxx:". - lines with "#" at the front are ignored. -*************************************************************************/ - -int getfileline(void *vp, char *linebuf, int linebuf_size) -{ - /* Static buffers we will return. */ - FILE *fp = (FILE *)vp; - unsigned char c; - unsigned char *p; - size_t linebuf_len; - - if (fp == NULL) { - DEBUG(0,("getfileline: Bad file pointer.\n")); - return -1; - } - - /* - * Scan the file, a line at a time. - */ - while (!feof(fp)) { - linebuf[0] = '\0'; - - fgets(linebuf, linebuf_size, fp); - if (ferror(fp)) { - return -1; - } - - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - - linebuf_len = strlen(linebuf); - if (linebuf_len == 0) { - linebuf[0] = '\0'; - return 0; - } - - if (linebuf[linebuf_len - 1] != '\n') { - c = '\0'; - while (!ferror(fp) && !feof(fp)) { - c = fgetc(fp); - if (c == '\n') { - break; - } - } - } else { - linebuf[linebuf_len - 1] = '\0'; - } - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("getfileline: got line |%s|\n", linebuf)); -#endif - if ((linebuf[0] == 0) && feof(fp)) { - DEBUG(4, ("getfileline: end of file reached\n")); - return 0; - } - - if (linebuf[0] == '#' || linebuf[0] == '\0') { - DEBUG(6, ("getfileline: skipping comment or blank line\n")); - continue; - } - - p = (unsigned char *) strchr_m(linebuf, ':'); - if (p == NULL) { - DEBUG(0, ("getfileline: malformed line entry (no :)\n")); - continue; - } - return linebuf_len; - } - return -1; -} - /**************************************************************************** Read a line from a file with possible \ continuation chars. Blanks at the start or end of a line are stripped. @@ -353,7 +118,7 @@ char *file_pload(char *syscmd, size_t *size) total = 0; while ((n = read(fd, buf, sizeof(buf))) > 0) { - p = SMB_REALLOC(p, total + n + 1); + p = (char *)SMB_REALLOC(p, total + n + 1); if (!p) { DEBUG(0,("file_pload: failed to expand buffer!\n")); close(fd); @@ -520,9 +285,6 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) return NULL; } memset(ret, 0, sizeof(ret[0])*(i+2)); - if (numlines) { - *numlines = i; - } ret[0] = p; for (s = p, i=0; s < p+size; s++) { @@ -536,6 +298,15 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) } } + /* remove any blank lines at the end */ + while (i > 0 && ret[i-1][0] == 0) { + i--; + } + + if (numlines) { + *numlines = i; + } + return ret; } diff --git a/source/lib/util_pw.c b/source/lib/util_pw.c index 754899f420e..dc184233a6d 100644 --- a/source/lib/util_pw.c +++ b/source/lib/util_pw.c @@ -74,7 +74,7 @@ struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) if ((pwnam_cache[i] != NULL) && (strcmp(name, pwnam_cache[i]->pw_name) == 0)) { DEBUG(10, ("Got %s from pwnam_cache\n", name)); - return talloc_reference(mem_ctx, pwnam_cache[i]); + return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]); } } @@ -103,7 +103,7 @@ struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) pwnam_cache[i] = tcopy_passwd(pwnam_cache, temp); if (pwnam_cache[i]!= NULL && mem_ctx != NULL) { - return talloc_reference(mem_ctx, pwnam_cache[i]); + return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]); } return tcopy_passwd(NULL, pwnam_cache[i]); diff --git a/source/lib/util_seaccess.c b/source/lib/util_seaccess.c index 73fc45c844d..7d14ed896f6 100644 --- a/source/lib/util_seaccess.c +++ b/source/lib/util_seaccess.c @@ -31,7 +31,7 @@ extern NT_USER_TOKEN anonymous_token; static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired, NTSTATUS *status) { - uint32 mask = ace->info.mask; + uint32 mask = ace->access_mask; /* * Inherit only is ignored. @@ -97,8 +97,8 @@ static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32 size_t i; for ( i = 0 ; i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - uint32 mask = ace->info.mask; + SEC_ACE *ace = &the_acl->aces[i]; + uint32 mask = ace->access_mask; if (!token_sid_in_ace( token, ace)) continue; @@ -281,12 +281,12 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, } for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) { - SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *ace = &the_acl->aces[i]; DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n", (unsigned int)i, ace->type, ace->flags, sid_to_string(sid_str, &ace->trustee), - (unsigned int) ace->info.mask, + (unsigned int) ace->access_mask, (unsigned int)tmp_acc_desired )); tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status); diff --git a/source/lib/util_sec.c b/source/lib/util_sec.c index 3f8cb690cd0..3d997ee76ac 100644 --- a/source/lib/util_sec.c +++ b/source/lib/util_sec.c @@ -198,7 +198,13 @@ void set_effective_uid(uid_t uid) { #if USE_SETRESUID /* Set the effective as well as the real uid. */ - setresuid(uid,uid,-1); + if (setresuid(uid,uid,-1) == -1) { + if (errno == EAGAIN) { + DEBUG(0, ("setresuid failed with EAGAIN. uid(%d) " + "might be over its NPROC limit\n", + (int)uid)); + } + } #endif #if USE_SETREUID diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c index 09fe30f81bb..032be9aa93b 100644 --- a/source/lib/util_sid.c +++ b/source/lib/util_sid.c @@ -110,7 +110,7 @@ NT_USER_TOKEN system_token = { 1, system_sid_array, SE_ALL_PRIVS }; ****************************************************************************/ static const struct { - enum SID_NAME_USE sid_type; + enum lsa_SidType sid_type; const char *string; } sid_name_type[] = { {SID_NAME_USER, "User"}, @@ -123,7 +123,7 @@ static const struct { {SID_NAME_UNKNOWN, "UNKNOWN"}, {SID_NAME_COMPUTER, "Computer"}, - {(enum SID_NAME_USE)0, NULL} + {(enum lsa_SidType)0, NULL} }; const char *sid_type_lookup(uint32 sid_type) @@ -531,7 +531,7 @@ char *sid_binstring(const DOM_SID *sid) { char *buf, *s; int len = sid_size(sid); - buf = SMB_MALLOC(len); + buf = (char *)SMB_MALLOC(len); if (!buf) return NULL; sid_linearize(buf, len, sid); @@ -549,7 +549,7 @@ char *sid_binstring_hex(const DOM_SID *sid) { char *buf, *s; int len = sid_size(sid); - buf = SMB_MALLOC(len); + buf = (char *)SMB_MALLOC(len); if (!buf) return NULL; sid_linearize(buf, len, sid); @@ -580,24 +580,20 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src) Add SID to an array SIDs ********************************************************************/ -void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, +BOOL add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, DOM_SID **sids, size_t *num) { - if (mem_ctx != NULL) { - *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID, + *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID, (*num)+1); - } else { - *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1); - } - if (*sids == NULL) { - return; + *num = 0; + return False; } sid_copy(&((*sids)[*num]), sid); *num += 1; - return; + return True; } @@ -605,17 +601,17 @@ void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, Add SID to an array SIDs ensuring that it is not already there ********************************************************************/ -void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, +BOOL add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, DOM_SID **sids, size_t *num_sids) { size_t i; for (i=0; i<(*num_sids); i++) { if (sid_compare(sid, &(*sids)[i]) == 0) - return; + return True; } - add_sid_to_array(mem_ctx, sid, sids, num_sids); + return add_sid_to_array(mem_ctx, sid, sids, num_sids); } /******************************************************************** @@ -647,23 +643,26 @@ void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num) return; } -void add_rid_to_array_unique(TALLOC_CTX *mem_ctx, +BOOL add_rid_to_array_unique(TALLOC_CTX *mem_ctx, uint32 rid, uint32 **pp_rids, size_t *p_num) { size_t i; for (i=0; i<*p_num; i++) { if ((*pp_rids)[i] == rid) - return; + return True; } *pp_rids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_rids, uint32, *p_num+1); - if (*pp_rids == NULL) - return; + if (*pp_rids == NULL) { + *p_num = 0; + return False; + } (*pp_rids)[*p_num] = rid; *p_num += 1; + return True; } BOOL is_null_sid(const DOM_SID *sid) diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c index 1a73a310b62..2866a443d47 100644 --- a/source/lib/util_sock.c +++ b/source/lib/util_sock.c @@ -974,7 +974,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs, } if (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) { + errno == EAGAIN || errno == EINTR) { /* These are the error messages that something is progressing. */ good_connect = True; diff --git a/source/lib/util_str.c b/source/lib/util_str.c index c106c4433aa..ccf0af8b623 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 1992-2001 Copyright (C) Simo Sorce 2001-2002 Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,13 +30,18 @@ **/ /** - * Get the next token from a string, return False if none found. - * Handles double-quotes. - * + * Internal function to get the next token from a string, return False if none + * found. Handles double-quotes. This is the work horse function called by + * next_token() and next_token_no_ltrim(). + * * Based on a routine by GJC@VILLAGE.COM. * Extensively modified by Andrew.Tridgell@anu.edu.au - **/ -BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) + */ +static BOOL next_token_internal(const char **ptr, + char *buff, + const char *sep, + size_t bufsize, + BOOL ltrim) { char *s; char *pbuf; @@ -51,9 +57,11 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) if (!sep) sep = " \t\n\r"; - /* find the first non sep char */ - while (*s && strchr_m(sep,*s)) - s++; + /* find the first non sep char, if left-trimming is requested */ + if (ltrim) { + while (*s && strchr_m(sep,*s)) + s++; + } /* nothing left? */ if (! *s) @@ -76,6 +84,29 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) return(True); } +/* + * Get the next token from a string, return False if none found. Handles + * double-quotes. This version trims leading separator characters before + * looking for a token. + */ +BOOL next_token(const char **ptr, char *buff, const char *sep, size_t bufsize) +{ + return next_token_internal(ptr, buff, sep, bufsize, True); +} + +/* + * Get the next token from a string, return False if none found. Handles + * double-quotes. This version does not trim leading separator characters + * before looking for a token. + */ +BOOL next_token_no_ltrim(const char **ptr, + char *buff, + const char *sep, + size_t bufsize) +{ + return next_token_internal(ptr, buff, sep, bufsize, False); +} + /** This is like next_token but is not re-entrant and "remembers" the first parameter so you can pass NULL. This is useful for user interface code @@ -1043,7 +1074,7 @@ char *realloc_string_sub(char *string, const char *pattern, while ((p = strstr_m(s,pattern))) { if (ld > 0) { int offset = PTR_DIFF(s,string); - string = SMB_REALLOC(string, ls + ld + 1); + string = (char *)SMB_REALLOC(string, ls + ld + 1); if (!string) { DEBUG(0, ("realloc_string_sub: out of memory!\n")); SAFE_FREE(in); @@ -1112,7 +1143,8 @@ char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src, while ((p = strstr_m(s,pattern))) { if (ld > 0) { int offset = PTR_DIFF(s,string); - string = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1); + string = (char *)TALLOC_REALLOC(mem_ctx, string, + ls + ld + 1); if (!string) { DEBUG(0, ("talloc_string_sub: out of " "memory!\n")); @@ -1561,6 +1593,76 @@ void strupper_m(char *s) } /** + Count the number of UCS2 characters in a string. Normally this will + be the same as the number of bytes in a string for single byte strings, + but will be different for multibyte. +**/ + +size_t strlen_m(const char *s) +{ + size_t count = 0; + + if (!s) { + return 0; + } + + while (*s && !(((uint8_t)*s) & 0x80)) { + s++; + count++; + } + + if (!*s) { + return count; + } + + while (*s) { + size_t c_size; + codepoint_t c = next_codepoint(s, &c_size); + if (c < 0x10000) { + /* Unicode char fits into 16 bits. */ + count += 1; + } else { + /* Double-width unicode char - 32 bits. */ + count += 2; + } + s += c_size; + } + + return count; +} + +/** + Count the number of UCS2 characters in a string including the null + terminator. +**/ + +size_t strlen_m_term(const char *s) +{ + if (!s) { + return 0; + } + return strlen_m(s) + 1; +} + +/* + * Weird helper routine for the winreg pipe: If nothing is around, return 0, + * if a string is there, include the terminator. + */ + +size_t strlen_m_term_null(const char *s) +{ + size_t len; + if (!s) { + return 0; + } + len = strlen_m(s); + if (len == 0) { + return 0; + } + + return len+1; +} +/** Return a RFC2254 binary string representation of a buffer. Used in LDAP filters. Caller must free. @@ -1571,7 +1673,7 @@ char *binary_string_rfc2254(char *buf, int len) char *s; int i, j; const char *hex = "0123456789ABCDEF"; - s = SMB_MALLOC(len * 3 + 1); + s = (char *)SMB_MALLOC(len * 3 + 1); if (!s) return NULL; for (j=i=0;i<len;i++) { @@ -1589,7 +1691,7 @@ char *binary_string(char *buf, int len) char *s; int i, j; const char *hex = "0123456789ABCDEF"; - s = SMB_MALLOC(len * 2 + 1); + s = (char *)SMB_MALLOC(len * 2 + 1); if (!s) return NULL; for (j=i=0;i<len;i++) { @@ -1631,49 +1733,6 @@ int fstr_sprintf(fstring s, const char *fmt, ...) return ret; } - -#if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP) -/** - Some platforms don't have strndup. -**/ -#if defined(PARANOID_MALLOC_CHECKER) -#undef strndup -#endif - - char *strndup(const char *s, size_t n) -{ - char *ret; - - n = strnlen(s, n); - ret = SMB_MALLOC(n+1); - if (!ret) - return NULL; - memcpy(ret, s, n); - ret[n] = 0; - - return ret; -} - -#if defined(PARANOID_MALLOC_CHECKER) -#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY -#endif - -#endif - -#if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN) -/** - Some platforms don't have strnlen -**/ - - size_t strnlen(const char *s, size_t n) -{ - size_t i; - for (i=0; i<n && s[i] != '\0'; i++) - /* noop */ ; - return i; -} -#endif - /** List of Strings manipulation functions **/ @@ -1884,13 +1943,14 @@ int str_list_count( const char **list ) for the work *****************************************************************************/ -BOOL str_list_sub_basic( char **list, const char *smb_name ) +BOOL str_list_sub_basic( char **list, const char *smb_name, + const char *domain_name ) { char *s, *tmpstr; while ( *list ) { s = *list; - tmpstr = alloc_sub_basic(smb_name, s); + tmpstr = alloc_sub_basic(smb_name, domain_name, s); if ( !tmpstr ) { DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n")); return False; @@ -2210,7 +2270,7 @@ char * base64_encode_data_blob(DATA_BLOB data) out_cnt = 0; len = data.length; output_len = data.length * 2; - result = SMB_MALLOC(output_len); /* get us plenty of space */ + result = (char *)SMB_MALLOC(output_len); /* get us plenty of space */ while (len-- && out_cnt < (data.length * 2) - 5) { int c = (unsigned char) *(data.data++); @@ -2274,16 +2334,83 @@ SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr) return val; } +/* Convert a size specification to a count of bytes. We accept the following + * suffixes: + * bytes if there is no suffix + * kK kibibytes + * mM mebibytes + * gG gibibytes + * tT tibibytes + * pP whatever the ISO name for petabytes is + * + * Returns 0 if the string can't be converted. + */ +SMB_OFF_T conv_str_size(const char * str) +{ + SMB_OFF_T lval; + char * end; + + if (str == NULL || *str == '\0') { + return 0; + } + +#ifdef HAVE_STRTOULL + if (sizeof(SMB_OFF_T) == 8) { + lval = strtoull(str, &end, 10 /* base */); + } else { + lval = strtoul(str, &end, 10 /* base */); + } +#else + lval = strtoul(str, &end, 10 /* base */); +#endif + + if (end == NULL || end == str) { + return 0; + } + + if (*end) { + SMB_OFF_T lval_orig = lval; + + if (strwicmp(end, "K") == 0) { + lval *= (SMB_OFF_T)1024; + } else if (strwicmp(end, "M") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024); + } else if (strwicmp(end, "G") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024); + } else if (strwicmp(end, "T") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024 * (SMB_OFF_T)1024); + } else if (strwicmp(end, "P") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024); + } else { + return 0; + } + + /* Primitive attempt to detect wrapping on platforms with + * 4-byte SMB_OFF_T. It's better to let the caller handle + * a failure than some random number. + */ + if (lval_orig <= lval) { + return 0; + } + } + + return lval; +} + void string_append(char **left, const char *right) { int new_len = strlen(right) + 1; if (*left == NULL) { - *left = SMB_MALLOC(new_len); + *left = (char *)SMB_MALLOC(new_len); *left[0] = '\0'; } else { new_len += strlen(*left); - *left = SMB_REALLOC(*left, new_len); + *left = (char *)SMB_REALLOC(*left, new_len); } if (*left == NULL) { @@ -2301,8 +2428,10 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx, *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings, const char *, (*num)+1); - if ((*strings == NULL) || (dup_str == NULL)) + if ((*strings == NULL) || (dup_str == NULL)) { + *num = 0; return False; + } (*strings)[*num] = dup_str; *num += 1; @@ -2329,11 +2458,7 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len, if (*bufsize == 0) *bufsize = 128; - if (mem_ctx != NULL) - *string = TALLOC_ARRAY(mem_ctx, char, *bufsize); - else - *string = SMB_MALLOC_ARRAY(char, *bufsize); - + *string = TALLOC_ARRAY(mem_ctx, char, *bufsize); if (*string == NULL) goto error; } @@ -2355,13 +2480,8 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len, } if (increased) { - if (mem_ctx != NULL) { - *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char, - *bufsize); - } else { - *string = SMB_REALLOC_ARRAY(*string, char, *bufsize); - } - + *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char, + *bufsize); if (*string == NULL) { goto error; } @@ -2374,9 +2494,6 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len, error: *len = -1; - if (mem_ctx == NULL) { - SAFE_FREE(*string); - } *string = NULL; } @@ -2426,3 +2543,52 @@ BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len return True; } + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +size_t ascii_len_n(const char *src, size_t n) +{ + size_t len; + + len = strnlen(src, n); + if (len+1 <= n) { + len += 1; + } + + return len; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +**/ +size_t utf16_len(const void *buf) +{ + size_t len; + + for (len = 0; SVAL(buf,len); len += 2) ; + + return len + 2; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes +**/ +size_t utf16_len_n(const void *src, size_t n) +{ + size_t len; + + for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ; + + if (len+2 <= n) { + len += 2; + } + + return len; +} + diff --git a/source/lib/util_tdb.c b/source/lib/util_tdb.c new file mode 100644 index 00000000000..9136e2d6c1e --- /dev/null +++ b/source/lib/util_tdb.c @@ -0,0 +1,938 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Rafal Szczesniak 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#undef malloc +#undef realloc +#undef calloc +#undef strdup + +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +static void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = CONST_DISCARD(char *, dptr); + ret.dsize = dsize; + return ret; +} + +TDB_DATA string_tdb_data(const char *string) +{ + return make_tdb_data(string, strlen(string)); +} + +/**************************************************************************** + Lock a chain with timeout (in seconds). +****************************************************************************/ + +static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +{ + /* Allow tdb_chainlock to be interrupted by an alarm. */ + int ret; + gotalarm = 0; + tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm)); + + if (timeout) { + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + if (rw_type == F_RDLCK) + ret = tdb_chainlock_read(tdb, key); + else + ret = tdb_chainlock(tdb, key); + + if (timeout) { + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) { + DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb_name(tdb))); + /* TODO: If we time out waiting for a lock, it might + * be nice to use F_GETLK to get the pid of the + * process currently holding the lock and print that + * as part of the debugging message. -- mbp */ + return -1; + } + } + + return ret; +} + +/**************************************************************************** + Write lock a chain. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +{ + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock(tdb, key); +} + +int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, + int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout(tdb, key, timeout); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32 value by a arbitrary blob key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + int32 ret; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(int32)) { + SAFE_FREE(data.dptr); + return -1; + } + + ret = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return ret; +} + +/**************************************************************************** + Fetch a int32 value by string key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); +} + +/**************************************************************************** + Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + int32 v_store; + + SIVAL(&v_store,0,v); + data.dptr = (char *)&v_store; + data.dsize = sizeof(int32); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32 value by string key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) +{ + return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); +} + +/**************************************************************************** + Fetch a uint32 value by a arbitrary blob key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(uint32)) { + SAFE_FREE(data.dptr); + return False; + } + + *value = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return True; +} + +/**************************************************************************** + Fetch a uint32 value by string key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +{ + return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} + +/**************************************************************************** + Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + uint32 v_store; + BOOL ret = True; + + SIVAL(&v_store, 0, value); + data.dptr = (char *)&v_store; + data.dsize = sizeof(uint32); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) + ret = False; + + return ret; +} + +/**************************************************************************** + Store a uint32 value by string key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +{ + return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -1 + on failure. +****************************************************************************/ + +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) +{ + int32 val; + int32 ret = -1; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) == -1) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +{ + uint32 val; + BOOL ret = False; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return False; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = True; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap) +{ + uint8 bt; + uint16 w; + uint32 d; + int i; + void *p; + int len; + char *s; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + while (*fmt) { + switch ((c = *fmt++)) { + case 'b': /* unsigned 8-bit integer */ + len = 1; + bt = (uint8)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, bt); + break; + case 'w': /* unsigned 16-bit integer */ + len = 2; + w = (uint16)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, w); + break; + case 'd': /* signed 32-bit integer (standard int in most systems) */ + len = 4; + d = va_arg(ap, uint32); + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'p': /* pointer */ + len = 4; + p = va_arg(ap, void *); + d = p?1:0; + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'P': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'f': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'B': /* fixed-length string */ + i = va_arg(ap, int); + s = va_arg(ap, char *); + len = 4+i; + if (bufsize && bufsize >= len) { + SIVAL(buf, 0, i); + memcpy(buf+4, s, i); + } + break; + default: + DEBUG(0,("Unknown tdb_pack format %c in %s\n", + c, fmt)); + len = 0; + break; + } + + buf += len; + if (bufsize) + bufsize -= len; + if (bufsize < 0) + bufsize = 0; + } + + DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); +} + +size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + size_t result; + + va_start(ap, fmt); + result = tdb_pack_va(buf, bufsize, fmt, ap); + va_end(ap); + return result; +} + +BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, + const char *fmt, ...) +{ + va_list ap; + size_t len1, len2; + + va_start(ap, fmt); + len1 = tdb_pack_va(NULL, 0, fmt, ap); + va_end(ap); + + if (mem_ctx != NULL) { + *buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8, + (*len) + len1); + } else { + *buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1); + } + + if (*buf == NULL) { + return False; + } + + va_start(ap, fmt); + len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap); + va_end(ap); + + if (len1 != len2) { + return False; + } + + *len += len2; + + return True; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8 *bt; + uint16 *w; + uint32 *d; + int len; + int *i; + void **p; + char *s, **b; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c=*fmt++)) { + case 'b': + len = 1; + bt = va_arg(ap, uint8 *); + if (bufsize < len) + goto no_space; + *bt = SVAL(buf, 0); + break; + case 'w': + len = 2; + w = va_arg(ap, uint16 *); + if (bufsize < len) + goto no_space; + *w = SVAL(buf, 0); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32 *); + if (bufsize < len) + goto no_space; + *d = IVAL(buf, 0); + break; + case 'p': + len = 4; + p = va_arg(ap, void **); + if (bufsize < len) + goto no_space; + /* + * This isn't a real pointer - only a token (1 or 0) + * to mark the fact a pointer is present. + */ + + *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); + break; + case 'P': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(pstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'f': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(fstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'B': + i = va_arg(ap, int *); + b = va_arg(ap, char **); + len = 4; + if (bufsize < len) + goto no_space; + *i = IVAL(buf, 0); + if (! *i) { + *b = NULL; + break; + } + len += *i; + if (bufsize < len) + goto no_space; + *b = (char *)SMB_MALLOC(*i); + if (! *b) + goto no_space; + memcpy(*b, buf+4, *i); + break; + default: + DEBUG(0,("Unknown tdb_unpack format %c in %s\n", + c, fmt)); + + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); + + no_space: + return -1; +} + + +/**************************************************************************** + Log tdb messages via DEBUG(). +****************************************************************************/ + +static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr)); + SAFE_FREE(ptr); +} + +/**************************************************************************** + Like tdb_open() but also setup a logging function that redirects to + the samba DEBUG() system. +****************************************************************************/ + +TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + TDB_CONTEXT *tdb; + struct tdb_logging_context log_ctx; + + if (!lp_use_mmap()) + tdb_flags |= TDB_NOMMAP; + + log_ctx.log_fn = tdb_log; + log_ctx.log_private = NULL; + + tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, &log_ctx, NULL); + if (!tdb) + return NULL; + + return tdb; +} + +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + +/** + * Search across the whole tdb for keys that match the given pattern + * return the result as a list of keys + * + * @param tdb pointer to opened tdb file context + * @param pattern searching pattern used by fnmatch(3) functions + * + * @return list of keys found by looking up with given pattern + **/ +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) +{ + TDB_DATA key, next; + TDB_LIST_NODE *list = NULL; + TDB_LIST_NODE *rec = NULL; + + for (key = tdb_firstkey(tdb); key.dptr; key = next) { + /* duplicate key string to ensure null-termination */ + char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize); + if (!key_str) { + DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); + smb_panic("strndup failed!\n"); + } + + DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern)); + + next = tdb_nextkey(tdb, key); + + /* do the pattern checking */ + if (fnmatch(pattern, key_str, 0) == 0) { + rec = SMB_MALLOC_P(TDB_LIST_NODE); + ZERO_STRUCTP(rec); + + rec->node_key = key; + + DLIST_ADD_END(list, rec, TDB_LIST_NODE *); + + DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern)); + } else { + free(key.dptr); + } + + /* free duplicated key string */ + free(key_str); + } + + return list; + +} + + +/** + * Free the list returned by tdb_search_keys + * + * @param node list of results found by tdb_search_keys + **/ +void tdb_search_list_free(TDB_LIST_NODE* node) +{ + TDB_LIST_NODE *next_node; + + while (node) { + next_node = node->next; + SAFE_FREE(node->node_key.dptr); + SAFE_FREE(node); + node = next_node; + }; +} + +/**************************************************************************** + tdb_store, wrapped in a transaction. This way we make sure that a process + that dies within writing does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) { + DEBUG(10, ("tdb_store failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} + +/**************************************************************************** + tdb_delete, wrapped in a transaction. This way we make sure that a process + that dies within deleting does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_delete(tdb, key)) != 0) { + DEBUG(10, ("tdb_delete failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} + +/* + Log tdb messages via DEBUG(). +*/ +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); + +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, + const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + int debuglevel = 0; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + switch (level) { + case TDB_DEBUG_FATAL: + debug_level = 0; + break; + case TDB_DEBUG_ERROR: + debuglevel = 1; + break; + case TDB_DEBUG_WARNING: + debuglevel = 2; + break; + case TDB_DEBUG_TRACE: + debuglevel = 5; + break; + default: + debuglevel = 0; + } + + if (ptr != NULL) { + const char *name = tdb_name(tdb); + DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr)); + free(ptr); + } +} + +static struct tdb_wrap *tdb_list; + +/* destroy the last connection to a tdb */ +static int tdb_wrap_destructor(struct tdb_wrap *w) +{ + tdb_close(w->tdb); + DLIST_REMOVE(tdb_list, w); + return 0; +} + +/* + wrapped connection to a tdb database + to close just talloc_free() the tdb_wrap pointer + */ +struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + struct tdb_wrap *w; + struct tdb_logging_context log_ctx; + log_ctx.log_fn = tdb_wrap_log; + + for (w=tdb_list;w;w=w->next) { + if (strcmp(name, w->name) == 0) { + /* + * Yes, talloc_reference is exactly what we want + * here. Otherwise we would have to implement our own + * reference counting. + */ + return talloc_reference(mem_ctx, w); + } + } + + w = talloc(mem_ctx, struct tdb_wrap); + if (w == NULL) { + return NULL; + } + + if (!(w->name = talloc_strdup(w, name))) { + talloc_free(w); + return NULL; + } + + w->tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, &log_ctx, NULL); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, tdb_wrap_destructor); + + DLIST_ADD(tdb_list, w); + + return w; +} diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c index a0015c265fb..cf040a2dfc0 100644 --- a/source/lib/util_unistr.c +++ b/source/lib/util_unistr.c @@ -88,10 +88,12 @@ void load_case_tables(void) } initialised = 1; - upcase_table = map_file(lib_path("upcase.dat"), 0x20000); + upcase_table = (smb_ucs2_t *)map_file(lib_path("upcase.dat"), + 0x20000); upcase_table_use_unmap = ( upcase_table != NULL ); - lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000); + lowcase_table = (smb_ucs2_t *)map_file(lib_path("lowcase.dat"), + 0x20000); lowcase_table_use_unmap = ( lowcase_table != NULL ); #ifdef HAVE_SETLOCALE @@ -111,7 +113,7 @@ void load_case_tables(void) not available */ if (!upcase_table) { DEBUG(1,("creating lame upcase table\n")); - upcase_table = SMB_MALLOC(0x20000); + upcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000); for (i=0;i<0x10000;i++) { smb_ucs2_t v; SSVAL(&v, 0, i); @@ -126,7 +128,7 @@ void load_case_tables(void) if (!lowcase_table) { DEBUG(1,("creating lame lowcase table\n")); - lowcase_table = SMB_MALLOC(0x20000); + lowcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000); for (i=0;i<0x10000;i++) { smb_ucs2_t v; SSVAL(&v, 0, i); @@ -169,11 +171,11 @@ static int check_dos_char_slowly(smb_ucs2_t c) smb_ucs2_t c2 = 0; int len1, len2; - len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf),False); + len1 = convert_string(CH_UTF16LE, CH_DOS, &c, 2, buf, sizeof(buf),False); if (len1 == 0) { return 0; } - len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2,False); + len2 = convert_string(CH_DOS, CH_UTF16LE, buf, len1, &c2, 2,False); if (len2 != 2) { return 0; } @@ -228,7 +230,7 @@ void init_valid_table(void) return; } - valid_file = map_file(lib_path("valid.dat"), 0x10000); + valid_file = (uint8 *)map_file(lib_path("valid.dat"), 0x10000); if (valid_file) { valid_table = valid_file; mapped_file = 1; @@ -247,7 +249,7 @@ void init_valid_table(void) valid_table_use_unmap = False; DEBUG(2,("creating default valid table\n")); - valid_table = SMB_MALLOC(0x10000); + valid_table = (uint8 *)SMB_MALLOC(0x10000); for (i=0;i<128;i++) { valid_table[i] = isalnum(i) || strchr(allowed,i); } @@ -482,7 +484,7 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max) size_t len; smb_ucs2_t c; - for(len = 0; *(COPY_UCS2_CHAR(&c,src)) && (len < max); src++, len++) { + for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) { ; } diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c index df70740b33c..6374c2d8a94 100644 --- a/source/lib/util_uuid.c +++ b/source/lib/util_uuid.c @@ -27,7 +27,7 @@ #define TIME_OFFSET_HIGH 0x01B21DD2 #define TIME_OFFSET_LOW 0x13814000 -void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr) +void smb_uuid_pack(const struct GUID uu, UUID_FLAT *ptr) { SIVAL(ptr->info, 0, uu.time_low); SSVAL(ptr->info, 4, uu.time_mid); @@ -36,7 +36,7 @@ void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr) memcpy(ptr->info+10, uu.node, 6); } -void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu) +void smb_uuid_unpack(const UUID_FLAT in, struct GUID *uu) { uu->time_low = IVAL(in.info, 0); uu->time_mid = SVAL(in.info, 4); @@ -45,15 +45,15 @@ void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu) memcpy(uu->node, in.info+10, 6); } -struct uuid smb_uuid_unpack_static(const UUID_FLAT in) +struct GUID smb_uuid_unpack_static(const UUID_FLAT in) { - static struct uuid uu; + static struct GUID uu; smb_uuid_unpack(in, &uu); return uu; } -void smb_uuid_generate_random(struct uuid *uu) +void smb_uuid_generate_random(struct GUID *uu) { UUID_FLAT tmp; @@ -64,7 +64,7 @@ void smb_uuid_generate_random(struct uuid *uu) uu->time_hi_and_version = (uu->time_hi_and_version & 0x0FFF) | 0x4000; } -char *smb_uuid_to_string(const struct uuid uu) +char *smb_uuid_to_string(const struct GUID uu) { char *out; @@ -77,7 +77,7 @@ char *smb_uuid_to_string(const struct uuid uu) return out; } -const char *smb_uuid_string_static(const struct uuid uu) +const char *smb_uuid_string_static(const struct GUID uu) { static char out[37]; @@ -90,7 +90,7 @@ const char *smb_uuid_string_static(const struct uuid uu) return out; } -BOOL smb_string_to_uuid(const char *in, struct uuid* uu) +BOOL smb_string_to_uuid(const char *in, struct GUID* uu) { BOOL ret = False; const char *ptr = in; diff --git a/source/lib/xfile.c b/source/lib/xfile.c index 2e90a62df45..8824ca2c3c7 100644 --- a/source/lib/xfile.c +++ b/source/lib/xfile.c @@ -80,7 +80,7 @@ static int x_allocate_buffer(XFILE *f) { if (f->buf) return 1; if (f->bufsize == 0) return 0; - f->buf = SMB_MALLOC(f->bufsize); + f->buf = (char *)SMB_MALLOC(f->bufsize); if (!f->buf) return 0; f->next = f->buf; return 1; |