summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/access.c38
-rw-r--r--source3/lib/bitmap.c2
-rw-r--r--source3/lib/charcnv.c204
-rw-r--r--source3/lib/charset.c6
-rw-r--r--source3/lib/crc32.c6
-rw-r--r--source3/lib/debug.c256
-rw-r--r--source3/lib/doscalls.c51
-rw-r--r--source3/lib/genrand.c6
-rw-r--r--source3/lib/interface.c452
-rw-r--r--source3/lib/kanji.c195
-rw-r--r--source3/lib/md4.c4
-rw-r--r--source3/lib/pidfile.c9
-rw-r--r--source3/lib/replace.c5
-rw-r--r--source3/lib/signal.c68
-rw-r--r--source3/lib/smbrun.c86
-rw-r--r--source3/lib/snprintf.c62
-rw-r--r--source3/lib/system.c197
-rw-r--r--source3/lib/time.c68
-rw-r--r--source3/lib/username.c542
-rw-r--r--source3/lib/util.c1456
-rw-r--r--source3/lib/util_file.c70
-rw-r--r--source3/lib/util_sid.c708
-rw-r--r--source3/lib/util_sock.c529
-rw-r--r--source3/lib/util_str.c281
-rw-r--r--source3/lib/util_unistr.c639
25 files changed, 2890 insertions, 3050 deletions
diff --git a/source3/lib/access.c b/source3/lib/access.c
index 0fa383d84a..01f559750f 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -38,12 +38,14 @@ static int masked_match(char *tok, char *slash, char *s)
}
/* string_match - match string against token */
-static int string_match(char *tok,char *s)
+static int string_match(char *tok,char *s, char *invalid_char)
{
- int tok_len;
- int str_len;
+ size_t tok_len;
+ size_t str_len;
char *cut;
+ *invalid_char = '\0';
+
/* Return True if a token has the magic value "ALL". Return
* FAIL if the token is "FAIL". If the token starts with a "."
* (domain name), return True if it matches the last fields of
@@ -108,6 +110,10 @@ static int string_match(char *tok,char *s)
} else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */
if (isdigit((int)s[0]) && masked_match(tok, cut, s))
return (True);
+ } else if (strchr(tok, '*') != 0) {
+ *invalid_char = '*';
+ } else if (strchr(tok, '?') != 0) {
+ *invalid_char = '?';
}
return (False);
}
@@ -118,15 +124,26 @@ static int client_match(char *tok,char *item)
{
char **client = (char **)item;
int match;
+ char invalid_char = '\0';
/*
* Try to match the address first. If that fails, try to match the host
* name if available.
*/
- if ((match = string_match(tok, client[1])) == 0)
- if (client[0][0] != 0)
- match = string_match(tok, client[0]);
+ if ((match = string_match(tok, client[1], &invalid_char)) == 0) {
+ if(invalid_char)
+ DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
+token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
+
+ if (client[0][0] != 0)
+ match = string_match(tok, client[0], &invalid_char);
+
+ if(invalid_char)
+ DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
+token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
+ }
+
return (match);
}
@@ -184,6 +201,15 @@ BOOL allow_access(char *deny_list,char *allow_list,
client[0] = cname;
client[1] = caddr;
+ /* if it is loopback then always allow unless specifically denied */
+ if (strcmp(caddr, "127.0.0.1") == 0) {
+ if (deny_list &&
+ list_match(deny_list,(char *)client,client_match)) {
+ return False;
+ }
+ return True;
+ }
+
/* if theres no deny list and no allow list then allow access */
if ((!deny_list || *deny_list == 0) &&
(!allow_list || *allow_list == 0)) {
diff --git a/source3/lib/bitmap.c b/source3/lib/bitmap.c
index 93c821c528..1813d63ff7 100644
--- a/source3/lib/bitmap.c
+++ b/source3/lib/bitmap.c
@@ -35,10 +35,10 @@ struct bitmap *bitmap_allocate(int n)
struct bitmap *bm;
bm = (struct bitmap *)malloc(sizeof(*bm));
- bm->n = n;
if (!bm) return NULL;
+ bm->n = n;
bm->b = (uint32 *)malloc(sizeof(bm->b[0])*(n+31)/32);
if (!bm->b) {
free(bm);
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index 29ef72d7ac..8f91e4573a 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -23,7 +23,7 @@
#define CTRLZ 26
extern int DEBUGLEVEL;
-static char cvtbuf[1024];
+static char cvtbuf[sizeof(pstring)];
static BOOL mapsinited = 0;
@@ -39,7 +39,7 @@ static void initmaps(void) {
mapsinited = True;
}
-static void update_map(char * str) {
+static void update_map(char *str) {
char *p;
for (p = str; *p; p++) {
@@ -51,47 +51,55 @@ static void update_map(char * str) {
}
}
-static void init_iso8859_1(void) {
-
+static void setupmaps(void)
+{
int i;
if (!mapsinited) initmaps();
/* Do not map undefined characters to some accidental code */
- for (i = 128; i < 256; i++)
+ for (i = 128; i < 256; i++)
{
unix2dos[i] = CTRLZ;
dos2unix[i] = CTRLZ;
}
+}
-/* MSDOS Code Page 850 -> ISO-8859 */
-update_map("\240\377\241\255\242\275\243\234\244\317\245\276\246\335\247\365");
-update_map("\250\371\251\270\252\246\253\256\254\252\255\360\256\251\257\356");
-update_map("\260\370\261\361\262\375\263\374\264\357\265\346\266\364\267\372");
-update_map("\270\367\271\373\272\247\273\257\274\254\275\253\276\363\277\250");
-update_map("\300\267\301\265\302\266\303\307\304\216\305\217\306\222\307\200");
-update_map("\310\324\311\220\312\322\313\323\314\336\315\326\316\327\317\330");
-update_map("\320\321\321\245\322\343\323\340\324\342\325\345\326\231\327\236");
-update_map("\330\235\331\353\332\351\333\352\334\232\335\355\336\350\337\341");
-update_map("\340\205\341\240\342\203\343\306\344\204\345\206\346\221\347\207");
-update_map("\350\212\351\202\352\210\353\211\354\215\355\241\356\214\357\213");
-update_map("\360\320\361\244\362\225\363\242\364\223\365\344\366\224\367\366");
-update_map("\370\233\371\227\372\243\373\226\374\201\375\354\376\347\377\230");
+static void init_iso8859_1(int codepage) {
+ setupmaps();
+
+ if (codepage == 437) {
+ /* MSDOS Code Page 437 -> ISO-8859-1 */
+ update_map("\xA1\xAD\xA2\x98\xA3\x9C\xA4\xED\xA5\x9D\xA6\xB3\xA7\xEE");
+ update_map("\xAA\xA6\xAB\xAE\xAC\xAA\xAE\xE9\xAF\xC4");
+ update_map("\xB0\xF8\xB1\xF1\xB2\xFD\xB5\xE6\xB7\xFA\xBA\xA7\xBC\xAC\xBD\xAB\xBF\xA8");
+ update_map("\xC0\x85\xC1\xA0\xC2\x83\xC4\x8E\xC5\x8F\xC6\x92\xC7\x80\xC8\x8A");
+ update_map("\xC9\x90\xCA\x88\xCB\x89\xCC\x8D\xCD\xA1\xCE\x8C\xCF\x8B");
+ update_map("\xD1\xA5\xD2\x96\xD3\xA2\xD4\x93\xD6\x99\xD9\x97\xDA\xA3\xDB\x96\xDC\x9A\xDF\xE1");
+ update_map("\xE0\x85\xE1\xA0\xE2\x83\xE4\x84\xE5\x86\xE6\x91\xE7\x87\xE8\x8A\xE9\x82\xEA\x88\xEB\x89\xEC\x8D\xED\xA1\xEE\x8C\xEF\x8B");
+ update_map("\xF0\xEB\xF1\xA4\xF2\x95\xF3\xA2\xF4\x93\xF6\x94\xF7\xF6\xF8\xED\xF9\x97\xFA\xA3\xFB\x96\xFC\x81\xFF\x98");
+ } else {
+ /* MSDOS Code Page 850 -> ISO-8859-1 */
+ update_map("\240\377\241\255\242\275\243\234\244\317\245\276\246\335\247\365");
+ update_map("\250\371\251\270\252\246\253\256\254\252\255\360\256\251\257\356");
+ update_map("\260\370\261\361\262\375\263\374\264\357\265\346\266\364\267\372");
+ update_map("\270\367\271\373\272\247\273\257\274\254\275\253\276\363\277\250");
+ update_map("\300\267\301\265\302\266\303\307\304\216\305\217\306\222\307\200");
+ update_map("\310\324\311\220\312\322\313\323\314\336\315\326\316\327\317\330");
+ update_map("\320\321\321\245\322\343\323\340\324\342\325\345\326\231\327\236");
+ update_map("\330\235\331\353\332\351\333\352\334\232\335\355\336\350\337\341");
+ update_map("\340\205\341\240\342\203\343\306\344\204\345\206\346\221\347\207");
+ update_map("\350\212\351\202\352\210\353\211\354\215\355\241\356\214\357\213");
+ update_map("\360\320\361\244\362\225\363\242\364\223\365\344\366\224\367\366");
+ update_map("\370\233\371\227\372\243\373\226\374\201\375\354\376\347\377\230");
+ }
}
/* Init for eastern european languages. */
static void init_iso8859_2(void) {
- int i;
- if (!mapsinited) initmaps();
-
- /* Do not map undefined characters to some accidental code */
- for (i = 128; i < 256; i++)
- {
- unix2dos[i] = CTRLZ;
- dos2unix[i] = CTRLZ;
- }
+ setupmaps();
/*
* Tranlation table created by Petr Hubeny <psh@capitol.cz>
@@ -120,36 +128,48 @@ update_map("\370\375\371\205\372\243\373\373\374\201\375\354\376\356\377\372");
static void init_iso8859_5(void)
{
- int i;
- if (!mapsinited) initmaps();
-
- /* Do not map undefined characters to some accidental code */
- for (i = 128; i < 256; i++)
- {
- unix2dos[i] = CTRLZ;
- dos2unix[i] = CTRLZ;
- }
+ setupmaps();
/* MSDOS Code Page 866 -> ISO8859-5 */
-update_map("\200\260\201\261\202\262\203\263\204\264\205\265\206\266\207\267");
-update_map("\210\270\211\271\212\272\213\273\214\274\215\275\216\276\217\277");
-update_map("\220\300\221\301\222\302\223\303\224\304\225\305\226\306\227\307");
-update_map("\230\310\231\311\232\312\233\313\234\314\235\315\236\316\237\317");
-update_map("\240\320\241\321\242\322\243\323\244\324\245\325\246\326\247\327");
-update_map("\250\330\251\331\252\332\253\333\254\334\255\335\256\336\257\337");
+update_map("\260\200\261\201\262\202\263\203\264\204\265\205\266\206\267\207");
+update_map("\270\210\271\211\272\212\273\213\274\214\275\215\276\216\277\217");
+update_map("\300\220\301\221\302\222\303\223\304\224\305\225\306\226\307\227");
+update_map("\310\230\311\231\312\232\313\233\314\234\315\235\316\236\317\237");
+update_map("\320\240\321\241\322\242\323\243\324\244\325\245\326\246\327\247");
+update_map("\330\250\331\251\332\252\333\253\334\254\335\255\336\256\337\257");
update_map("\340\340\341\341\342\342\343\343\344\344\345\345\346\346\347\347");
update_map("\350\350\351\351\352\352\353\353\354\354\355\355\356\356\357\357");
-update_map("\360\241\361\361\362\244\363\364\364\247\365\367\366\256\367\376");
-update_map("\374\360\377\240");
+update_map("\241\360\361\361\244\362\364\363\247\364\367\365\256\366\376\367");
+update_map("\360\374\240\377");
+}
+
+/* Added by Antonios Kavarnos (Antonios.Kavarnos@softlab.ece.ntua.gr */
+
+static void init_iso8859_7(void)
+{
+ setupmaps();
+
+/* MSDOS Code Page 737 -> ISO-8859-7 (Greek-Hellenic) */
+
+update_map("\301\200\302\201\303\202\304\203\305\204\306\205\307\206");
+update_map("\310\207\311\210\312\211\313\212\314\213\315\214\316\215\317\216");
+update_map("\320\217\321\220\323\221\324\222\325\223\326\224\327\225");
+update_map("\330\226\331\227");
+update_map("\341\230\342\231\343\232\344\233\345\234\346\235\347\236");
+update_map("\350\237\351\240\352\241\353\242\354\243\355\244\356\245\357\246");
+update_map("\360\247\361\250\362\252\363\251\364\253\365\254\366\255\367\256");
+update_map("\370\257\371\340");
+update_map("\332\364\333\365\334\341\335\342\336\343\337\345");
+update_map("\372\344\373\350\374\346\375\347\376\351");
+update_map("\266\352");
+update_map("\270\353\271\354\272\355\274\356\276\357\277\360");
}
/* Init for russian language (koi8) */
static void init_koi8_r(void)
{
- if (!mapsinited) initmaps();
-
- /* There aren't undefined characters between 128 and 255 */
+ setupmaps();
/* MSDOS Code Page 866 -> KOI8-R */
update_map("\200\304\201\263\202\332\203\277\204\300\205\331\206\303\207\264");
@@ -170,24 +190,49 @@ update_map("\360\217\361\237\362\220\363\221\364\222\365\223\366\206\367\202");
update_map("\370\234\371\233\372\207\373\230\374\235\375\231\376\227\377\232");
}
+
+/* Init for ROMAN-8 (HP-UX) */
+
+static void init_roman8(void) {
+
+ setupmaps();
+
+/* MSDOS Code Page 850 -> ROMAN8 */
+update_map("\240\377\241\267\242\266\243\324\244\322\245\323\246\327\247\330");
+update_map("\250\357\253\371\255\353\256\352\257\234");
+update_map("\260\356\261\355\262\354\263\370\264\200\265\207\266\245\267\244");
+update_map("\270\255\271\250\272\317\273\234\274\276\275\365\276\237\277\275");
+update_map("\300\203\301\210\302\223\303\226\304\240\305\202\306\242\307\243");
+update_map("\310\205\311\212\312\225\313\227\314\204\315\211\316\224\317\201");
+update_map("\320\217\321\214\322\235\323\222\324\206\325\241\326\233\327\221");
+update_map("\330\216\331\215\332\231\333\232\334\220\335\213\336\341\337\342");
+update_map("\340\265\341\307\342\306\343\321\344\320\345\326\346\336\347\340");
+update_map("\350\343\351\345\352\344\355\351\357\230");
+update_map("\360\350\361\347\362\372\363\346\364\364\365\363\366\360\367\254");
+update_map("\370\253\371\246\372\247\373\256\374\376\375\257\376\361");
+}
+
/*
* Convert unix to dos
*/
char *unix2dos_format(char *str,BOOL overwrite)
{
- char *p;
- char *dp;
-
- if (!mapsinited) initmaps();
-
- if (overwrite) {
- for (p = str; *p; p++) *p = unix2dos[(unsigned char)*p];
- return str;
- } else {
- for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = unix2dos[(unsigned char)*p];
- *dp = 0;
- return cvtbuf;
- }
+ char *p;
+ char *dp;
+
+ if (!mapsinited)
+ initmaps();
+
+ if (overwrite) {
+ for (p = str; *p; p++)
+ *p = unix2dos[(unsigned char)*p];
+ return str;
+ } else {
+ for (p = str, dp = cvtbuf;*p && (dp - cvtbuf < sizeof(cvtbuf) - 1); p++,dp++)
+ *dp = unix2dos[(unsigned char)*p];
+ *dp = 0;
+ return cvtbuf;
+ }
}
/*
@@ -195,36 +240,45 @@ char *unix2dos_format(char *str,BOOL overwrite)
*/
char *dos2unix_format(char *str, BOOL overwrite)
{
- char *p;
- char *dp;
-
- if (!mapsinited) initmaps();
-
- if (overwrite) {
- for (p = str; *p; p++) *p = dos2unix[(unsigned char)*p];
- return str;
- } else {
- for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = dos2unix[(unsigned char)*p];
- *dp = 0;
- return cvtbuf;
- }
+ char *p;
+ char *dp;
+
+ if (!mapsinited)
+ initmaps();
+
+ if (overwrite) {
+ for (p = str; *p; p++)
+ *p = dos2unix[(unsigned char)*p];
+ return str;
+ } else {
+ for (p = str, dp = cvtbuf;*p && (dp - cvtbuf < sizeof(cvtbuf) - 1); p++,dp++)
+ *dp = dos2unix[(unsigned char)*p];
+ *dp = 0;
+ return cvtbuf;
+ }
}
/*
* Interpret character set.
*/
-void interpret_character_set(char *str)
+void interpret_character_set(char *str, int codepage)
{
if (strequal (str, "iso8859-1")) {
- init_iso8859_1();
+ init_iso8859_1(codepage);
} else if (strequal (str, "iso8859-2")) {
init_iso8859_2();
} else if (strequal (str, "iso8859-5")) {
init_iso8859_5();
+ } else if (strequal (str, "iso8859-7")) {
+ init_iso8859_7();
} else if (strequal (str, "koi8-r")) {
init_koi8_r();
+ } else if (strequal (str, "roman8")) {
+ init_roman8();
} else {
DEBUG(0,("unrecognized character set %s\n", str));
}
+
+ load_unix_unicode_map(str);
}
diff --git a/source3/lib/charset.c b/source3/lib/charset.c
index fc2924a155..6e5a4b48cb 100644
--- a/source3/lib/charset.c
+++ b/source3/lib/charset.c
@@ -320,8 +320,9 @@ clean_and_exit:
}
/****************************************************************************
-initialise the client codepage.
+ Initialise the client codepage.
****************************************************************************/
+
void codepage_initialise(int client_codepage)
{
int i;
@@ -369,6 +370,9 @@ for code page %d failed. Using default client codepage 850\n",
for(i = 0; !((cp[i][0] == '\0') && (cp[i][1] == '\0')); i++)
add_dos_char(cp[i][0], (BOOL)cp[i][2], cp[i][1], (BOOL)cp[i][3]);
}
+
+ /* Try and load the unicode map. */
+ load_dos_unicode_map(client_codepage);
}
/*******************************************************************
diff --git a/source3/lib/crc32.c b/source3/lib/crc32.c
index 39c01fa30f..16b337c764 100644
--- a/source3/lib/crc32.c
+++ b/source3/lib/crc32.c
@@ -56,14 +56,12 @@ static unsigned long CRCTable[256] =
0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D
};
-uint32 crc32_calc_buffer( uint32 count, char *buffer)
+uint32 crc32_calc_buffer( char *buffer, uint32 count)
{
uint32 crc=0xffffffff;
- uint32 i;
+ int i;
for(i=0;i<count;i++)
- {
crc = (crc>>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff];
- }
crc^=0xffffffff;
DEBUG(10,("crc32_calc_buffer: %x\n", crc));
dump_data(100, buffer, count);
diff --git a/source3/lib/debug.c b/source3/lib/debug.c
index ab11d81a21..a0dfe61f7d 100644
--- a/source3/lib/debug.c
+++ b/source3/lib/debug.c
@@ -75,7 +75,6 @@
* debugf - Debug file name.
* append_log - If True, then the output file will be opened in append
* mode.
- * timestamp_log -
* DEBUGLEVEL - System-wide debug message limit. Messages with message-
* levels higher than DEBUGLEVEL will not be processed.
*/
@@ -83,7 +82,6 @@
FILE *dbf = NULL;
pstring debugf = "";
BOOL append_log = False;
-BOOL timestamp_log = True;
int DEBUGLEVEL = 1;
@@ -114,51 +112,40 @@ static int debug_count = 0;
static int syslog_level = 0;
#endif
static pstring format_bufr = { '\0' };
-static int format_pos = 0;
+static size_t format_pos = 0;
/* -------------------------------------------------------------------------- **
* Functions...
*/
-/* ************************************************************************** **
- * tells us if interactive logging was requested
- * ************************************************************************** **
- */
-BOOL dbg_interactive(void)
-{
- return stdout_logging;
-}
-
-#if defined(SIGUSR2) && !defined(MEM_MAN)
+#if defined(SIGUSR2)
/* ************************************************************************** **
* catch a sigusr2 - decrease the debug log level.
* ************************************************************************** **
*/
void sig_usr2( int sig )
{
- BlockSignals( True, SIGUSR2 );
-
DEBUGLEVEL--;
if( DEBUGLEVEL < 0 )
DEBUGLEVEL = 0;
DEBUG( 0, ( "Got SIGUSR2; set debug level to %d.\n", DEBUGLEVEL ) );
- BlockSignals( False, SIGUSR2 );
+#if !defined(HAVE_SIGACTION)
CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
+#endif
} /* sig_usr2 */
#endif /* SIGUSR2 */
-#if defined(SIGUSR1) && !defined(MEM_MAN)
+#if defined(SIGUSR1)
/* ************************************************************************** **
* catch a sigusr1 - increase the debug log level.
* ************************************************************************** **
*/
void sig_usr1( int sig )
{
- BlockSignals( True, SIGUSR1 );
DEBUGLEVEL++;
@@ -167,8 +154,9 @@ void sig_usr1( int sig )
DEBUG( 0, ( "Got SIGUSR1; set debug level to %d.\n", DEBUGLEVEL ) );
- BlockSignals( False, SIGUSR1 );
+#if !defined(HAVE_SIGACTION)
CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
+#endif
} /* sig_usr1 */
#endif /* SIGUSR1 */
@@ -260,11 +248,11 @@ void force_check_log_size( void )
* ************************************************************************** **
*/
static void check_log_size( void )
- {
+{
int maxlog;
SMB_STRUCT_STAT st;
- if( debug_count++ < 100 || getuid() != 0 )
+ if( debug_count++ < 100 || geteuid() != 0 )
return;
maxlog = lp_max_log_size() * 1024;
@@ -276,7 +264,7 @@ static void check_log_size( void )
(void)fclose( dbf );
dbf = NULL;
reopen_logs();
- if( dbf && file_size( debugf ) > maxlog )
+ if( dbf && get_file_size( debugf ) > maxlog )
{
pstring name;
@@ -287,8 +275,23 @@ static void check_log_size( void )
reopen_logs();
}
}
+ /*
+ * Here's where we need to panic if dbf == NULL..
+ */
+ if(dbf == NULL) {
+ dbf = sys_fopen( "/dev/console", "w" );
+ if(dbf) {
+ DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
+ debugf ));
+ } else {
+ /*
+ * We cannot continue without a debug file handle.
+ */
+ abort();
+ }
+ }
debug_count = 0;
- } /* check_log_size */
+} /* check_log_size */
/* ************************************************************************** **
* Write an debug message on the debugfile.
@@ -382,6 +385,8 @@ va_dcl
}
#endif
+ check_log_size();
+
#ifdef WITH_SYSLOG
if( !lp_syslog_only() )
#endif
@@ -397,8 +402,6 @@ va_dcl
(void)fflush( dbf );
}
- check_log_size();
-
errno = old_errno;
return( 0 );
@@ -439,8 +442,8 @@ static void bufr_print( void )
*/
static void format_debug_text( char *msg )
{
- int i;
- BOOL timestamp = (timestamp_log && !stdout_logging && (lp_timestamp_logs() ||
+ size_t i;
+ BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() ||
!(lp_loaded())));
for( i = 0; msg[i]; i++ )
@@ -510,10 +513,13 @@ void dbgflush( void )
*
* ************************************************************************** **
*/
+
BOOL dbghdr( int level, char *file, char *func, int line )
- {
- if( format_pos )
- {
+{
+ /* Ensure we don't lose any real errno value. */
+ int old_errno = errno;
+
+ if( format_pos ) {
/* This is a fudge. If there is stuff sitting in the format_bufr, then
* the *right* thing to do is to call
* format_debug_text( "\n" );
@@ -524,7 +530,7 @@ BOOL dbghdr( int level, char *file, char *func, int line )
* that a new header is *not* desired.
*/
return( True );
- }
+ }
#ifdef WITH_SYSLOG
/* Set syslog_level. */
@@ -538,15 +544,32 @@ BOOL dbghdr( int level, char *file, char *func, int line )
/* Print the header if timestamps are turned on. If parameters are
* not yet loaded, then default to timestamps on.
*/
- if( timestamp_log && (lp_timestamp_logs() || !(lp_loaded()) ))
- {
+ if( lp_timestamp_logs() || !(lp_loaded()) ) {
+ char header_str[200];
+
+ header_str[0] = '\0';
+
+ if( lp_debug_pid())
+ slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)getpid());
+
+ if( lp_debug_uid()) {
+ size_t hs_len = strlen(header_str);
+ slprintf(header_str + hs_len,
+ sizeof(header_str) - 1 - hs_len,
+ ", effective(%u, %u), real(%u, %u)",
+ (unsigned int)geteuid(), (unsigned int)getegid(),
+ (unsigned int)getuid(), (unsigned int)getgid());
+ }
+
/* Print it all out at once to prevent split syslog output. */
- (void)Debug1( "[%s, %d] %s:%s(%d)\n",
- timestring(), level, file, func, line );
- }
+ (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
+ timestring(lp_debug_hires_timestamp()), level,
+ header_str, file, func, line );
+ }
+ errno = old_errno;
return( True );
- } /* dbghdr */
+}
/* ************************************************************************** **
* Add text to the body of the "current" debug message via the format buffer.
@@ -596,163 +619,4 @@ BOOL dbghdr( int level, char *file, char *func, int line )
#endif
-dbg_Token dbg_char2token( dbg_Token *state, int c )
- /* ************************************************************************ **
- * Parse input one character at a time.
- *
- * Input: state - A pointer to a token variable. This is used to
- * maintain the parser state between calls. For
- * each input stream, you should set up a separate
- * state variable and initialize it to dbg_null.
- * Pass a pointer to it into this function with each
- * character in the input stream. See dbg_test()
- * for an example.
- * c - The "current" character in the input stream.
- *
- * Output: A token.
- * The token value will change when delimiters are found,
- * which indicate a transition between syntactical objects.
- * Possible return values are:
- *
- * dbg_null - The input character was an end-of-line.
- * This resets the parser to its initial state
- * in preparation for parsing the next line.
- * dbg_eof - Same as dbg_null, except that the character
- * was an end-of-file.
- * dbg_ignore - Returned for whitespace and delimiters.
- * These lexical tokens are only of interest
- * to the parser.
- * dbg_header - Indicates the start of a header line. The
- * input character was '[' and was the first on
- * the line.
- * dbg_timestamp - Indicates that the input character was part
- * of a header timestamp.
- * dbg_level - Indicates that the input character was part
- * of the debug-level value in the header.
- * dbg_sourcefile - Indicates that the input character was part
- * of the sourcefile name in the header.
- * dbg_function - Indicates that the input character was part
- * of the function name in the header.
- * dbg_lineno - Indicates that the input character was part
- * of the DEBUG call line number in the header.
- * dbg_message - Indicates that the input character was part
- * of the DEBUG message text.
- *
- * ************************************************************************ **
- */
- {
- /* The terminating characters that we see will greatly depend upon
- * how they are read. For example, if gets() is used instead of
- * fgets(), then we will not see newline characters. A lot also
- * depends on the calling function, which may handle terminators
- * itself.
- *
- * '\n', '\0', and EOF are all considered line terminators. The
- * dbg_eof token is sent back if an EOF is encountered.
- *
- * Warning: only allow the '\0' character to be sent if you are
- * using gets() to read whole lines (thus replacing '\n'
- * with '\0'). Sending '\0' at the wrong time will mess
- * up the parsing.
- */
- switch( c )
- {
- case EOF:
- *state = dbg_null; /* Set state to null (initial state) so */
- return( dbg_eof ); /* that we can restart with new input. */
- case '\n':
- case '\0':
- *state = dbg_null; /* A newline or eoln resets to the null state. */
- return( dbg_null );
- }
-
- /* When within the body of the message, only a line terminator
- * can cause a change of state. We've already checked for line
- * terminators, so if the current state is dbg_msgtxt, simply
- * return that as our current token.
- */
- if( dbg_message == *state )
- return( dbg_message );
-
- /* If we are at the start of a new line, and the input character
- * is an opening bracket, then the line is a header line, otherwise
- * it's a message body line.
- */
- if( dbg_null == *state )
- {
- if( '[' == c )
- {
- *state = dbg_timestamp;
- return( dbg_header );
- }
- *state = dbg_message;
- return( dbg_message );
- }
-
- /* We've taken care of terminators, text blocks and new lines.
- * The remaining possibilities are all within the header line
- * itself.
- */
-
- /* Within the header line, whitespace can be ignored *except*
- * within the timestamp.
- */
- if( isspace( c ) )
- {
- /* Fudge. The timestamp may contain space characters. */
- if( (' ' == c) && (dbg_timestamp == *state) )
- return( dbg_timestamp );
- /* Otherwise, ignore whitespace. */
- return( dbg_ignore );
- }
-
- /* Okay, at this point we know we're somewhere in the header.
- * Valid header *states* are: dbg_timestamp, dbg_level,
- * dbg_sourcefile, dbg_function, and dbg_lineno.
- */
- switch( c )
- {
- case ',':
- if( dbg_timestamp == *state )
- {
- *state = dbg_level;
- return( dbg_ignore );
- }
- break;
- case ']':
- if( dbg_level == *state )
- {
- *state = dbg_sourcefile;
- return( dbg_ignore );
- }
- break;
- case ':':
- if( dbg_sourcefile == *state )
- {
- *state = dbg_function;
- return( dbg_ignore );
- }
- break;
- case '(':
- if( dbg_function == *state )
- {
- *state = dbg_lineno;
- return( dbg_ignore );
- }
- break;
- case ')':
- if( dbg_lineno == *state )
- {
- *state = dbg_null;
- return( dbg_ignore );
- }
- break;
- }
-
- /* If the previous block did not result in a state change, then
- * return the current state as the current token.
- */
- return( *state );
- } /* dbg_char2token */
-
/* ************************************************************************** */
diff --git a/source3/lib/doscalls.c b/source3/lib/doscalls.c
index 2098b5e350..e6f9d19879 100644
--- a/source3/lib/doscalls.c
+++ b/source3/lib/doscalls.c
@@ -52,23 +52,18 @@ int dos_open(char *fname,int flags,mode_t mode)
}
/*******************************************************************
- Opendir() wrapper that calls dos_to_unix. Should use the
- vfs_ops->opendir() function instead.
+ Opendir() wrapper that calls dos_to_unix.
********************************************************************/
-#if 0
DIR *dos_opendir(char *dname)
{
return(opendir(dos_to_unix(dname,False)));
}
-#endif
/*******************************************************************
- Readdirname() wrapper that calls unix_to_dos. Should use the
- vfs_readdirname() function instead.
+ Readdirname() wrapper that calls unix_to_dos.
********************************************************************/
-#if 0
char *dos_readdirname(DIR *p)
{
char *dname = readdirname(p);
@@ -79,7 +74,15 @@ char *dos_readdirname(DIR *p)
unix_to_dos(dname, True);
return(dname);
}
-#endif
+
+/*******************************************************************
+ A chown() wrapper that calls dos_to_unix.
+********************************************************************/
+
+int dos_chown(char *fname, uid_t uid, gid_t gid)
+{
+ return(sys_chown(dos_to_unix(fname,False),uid,gid));
+}
/*******************************************************************
A stat() wrapper that calls dos_to_unix.
@@ -100,14 +103,18 @@ int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf)
}
/*******************************************************************
- Mkdir() that calls dos_to_unix. Don't use this call unless you
- really want to access a file on disk. Use the vfs_ops.mkdir()
- function instead.
+ Mkdir() that calls dos_to_unix.
+ Cope with UNIXes that don't allow high order mode bits on mkdir.
+ Patch from gcarter@lanier.com.
********************************************************************/
int dos_mkdir(char *dname,mode_t mode)
{
- return(mkdir(dos_to_unix(dname,False),mode));
+ int ret = mkdir(dos_to_unix(dname,False),mode);
+ if(!ret)
+ return(dos_chmod(dname,mode));
+ else
+ return ret;
}
/*******************************************************************
@@ -151,7 +158,7 @@ int dos_utime(char *fname,struct utimbuf *times)
<warrenb@hpcvscdp.cv.hp.com>
**********************************************************/
-int copy_reg(char *source, const char *dest)
+static int copy_reg(char *source, const char *dest)
{
SMB_STRUCT_STAT source_stats;
int ifd;
@@ -243,11 +250,19 @@ int copy_reg(char *source, const char *dest)
int dos_rename(char *from, char *to)
{
+ int rcode;
pstring zfrom, zto;
pstrcpy (zfrom, dos_to_unix (from, False));
pstrcpy (zto, dos_to_unix (to, False));
- return file_rename(zfrom, zto);
+ rcode = rename (zfrom, zto);
+
+ if (errno == EXDEV)
+ {
+ /* Rename across filesystems needed. */
+ rcode = copy_reg (zfrom, zto);
+ }
+ return rcode;
}
/*******************************************************************
@@ -274,15 +289,13 @@ char *dos_getwd(char *unix_path)
}
/*******************************************************************
- Check if a DOS file exists. Use vfs_file_exist function instead.
+ Check if a DOS file exists.
********************************************************************/
-#if 0
BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
{
return file_exist(dos_to_unix(fname, False), sbuf);
}
-#endif
/*******************************************************************
Check if a DOS directory exists.
@@ -308,7 +321,7 @@ time_t dos_file_modtime(char *fname)
SMB_OFF_T dos_file_size(char *file_name)
{
- return file_size(dos_to_unix(file_name, False));
+ return get_file_size(dos_to_unix(file_name, False));
}
/*******************************************************************
@@ -404,7 +417,7 @@ char *dos_GetWd(char *path)
if (sys_stat(".",&st) == -1)
{
- DEBUG(0,("Very strange, couldn't stat \".\"\n"));
+ DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
return(dos_getwd(path));
}
diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c
index ab0dadebcf..a9698d4cd1 100644
--- a/source3/lib/genrand.c
+++ b/source3/lib/genrand.c
@@ -58,8 +58,8 @@ static void do_dirrand(char *name, unsigned char *buf, int buf_len)
{
DIR *dp = opendir(name);
pstring fullname;
- size_t len_left;
- size_t fullname_len;
+ int len_left;
+ int fullname_len;
char *pos;
pstrcpy(fullname, name);
@@ -150,7 +150,7 @@ static uint32 do_reseed(unsigned char *md4_outbuf)
/* add in the root encrypted password. On any system where security is taken
seriously this will be secret */
- pw = getpwnam("root");
+ pw = sys_getpwnam("root");
if (pw && pw->pw_passwd) {
int i;
unsigned char md4_tmp[16];
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 65d276021c..9266427959 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -21,230 +21,225 @@
#include "includes.h"
+#define MAX_INTERFACES 128
+
+static struct iface_struct *probed_ifaces;
+static int total_probed;
+
extern int DEBUGLEVEL;
struct in_addr ipzero;
struct in_addr allones_ip;
struct in_addr loopback_ip;
-static struct in_addr default_ip;
-static struct in_addr default_bcast;
-static struct in_addr default_nmask;
-static BOOL got_ip=False;
-static BOOL got_bcast=False;
-static BOOL got_nmask=False;
static struct interface *local_interfaces = NULL;
-struct interface *last_iface;
-
#define ALLONES ((uint32)0xFFFFFFFF)
#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
+#define MKNETADDR(_IP, _NM) (_IP & _NM)
+
/****************************************************************************
-calculate the default netmask for an address
-****************************************************************************/
-static void default_netmask(struct in_addr *inm, struct in_addr *iad)
+Try and find an interface that matches an ip. If we cannot, return NULL
+ **************************************************************************/
+static struct interface *iface_find(struct in_addr ip)
{
- /*
- ** Guess a netmask based on the class of the IP address given.
- */
- switch((ntohl(iad->s_addr) & 0xE0000000)) {
- case 0x00000000: /* Class A addr */
- case 0x20000000:
- case 0x40000000:
- case 0x60000000:
- inm->s_addr = htonl(0xFF000000);
- break;
-
- case 0x80000000: /* Class B addr */
- case 0xA0000000:
- inm->s_addr = htonl(0xFFFF0000);
- break;
-
- case 0xC0000000: /* Class C addr */
- inm->s_addr = htonl(0xFFFFFF00);
- break;
-
- default: /* ??? */
- inm->s_addr = htonl(0xFFFFFFF0);
- }
+ struct interface *i;
+ if (zero_ip(ip)) return local_interfaces;
+
+ for (i=local_interfaces;i;i=i->next)
+ if (same_net(i->ip,ip,i->nmask)) return i;
+
+ return NULL;
}
/****************************************************************************
- get the broadcast address for our address
-(troyer@saifr00.ateng.az.honeywell.com)
+add an interface to the linked list of interfaces
****************************************************************************/
-static void get_broadcast(struct in_addr *if_ipaddr,
- struct in_addr *if_bcast,
- struct in_addr *if_nmask)
-{
- uint32 nm;
- short onbc;
- short offbc;
-
- /* get a default netmask and broadcast */
- default_netmask(if_nmask, if_ipaddr);
-
- get_netmask(if_ipaddr, if_nmask);
-
- /* sanity check on the netmask */
- nm = ntohl(if_nmask->s_addr);
- onbc = 0;
- offbc = 0;
- while((onbc + offbc) < 32) {
- if(nm & 0x80000000) {
- onbc++;
- if(offbc) {
- /* already found an off bit, so mask
- is wrong */
- onbc = 34;
- }
- } else {
- offbc++;
- }
- nm <<= 1;
+static void add_interface(struct in_addr ip, struct in_addr nmask)
+{
+ struct interface *iface;
+ if (iface_find(ip)) {
+ DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
+ return;
}
- if ((onbc < 8)||(onbc == 34)) {
- DEBUG(0,("Impossible netmask %s - using defaults\n",
- inet_ntoa(*if_nmask)));
- default_netmask(if_nmask, if_ipaddr);
+
+ if (ip_equal(nmask, allones_ip)) {
+ DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
+ return;
}
- /* derive the broadcast assuming a 1's broadcast, as this is what
- all MS operating systems do, we have to comply even if the unix
- box is setup differently */
- if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
-
- DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
+ iface = (struct interface *)malloc(sizeof(*iface));
+ if (!iface) return;
+
+ ZERO_STRUCTPN(iface);
+
+ iface->ip = ip;
+ iface->nmask = nmask;
+ iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
+
+ DLIST_ADD(local_interfaces, iface);
+
+ DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
+ DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
+ DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
}
/****************************************************************************
-load a list of network interfaces
+interpret a single element from a interfaces= config line
+
+This handles the following different forms:
+
+1) wildcard interface name
+2) DNS name
+3) IP/masklen
+4) ip/mask
+5) bcast/mask
****************************************************************************/
-static void interpret_interfaces(char *s, struct interface **interfaces,
- char *description)
+static void interpret_interface(char *token)
{
- char *ptr;
- fstring token;
- struct interface *iface;
- struct in_addr ip;
-
- ptr = s;
- ipzero = *interpret_addr2("0.0.0.0");
- allones_ip = *interpret_addr2("255.255.255.255");
- loopback_ip = *interpret_addr2("127.0.0.1");
-
- while (next_token(&ptr,token,NULL,sizeof(token))) {
- /* parse it into an IP address/netmasklength pair */
- char *p = strchr(token,'/');
- if (p) *p++ = 0;
-
- ip = *interpret_addr2(token);
-
- /* maybe we already have it listed */
- {
- struct interface *i;
- for (i=(*interfaces);i;i=i->next)
- if (ip_equal(ip,i->ip)) break;
- if (i) continue;
- }
-
- iface = (struct interface *)malloc(sizeof(*iface));
- if (!iface) return;
-
- iface->ip = ip;
-
- if (p) {
- if (strlen(p) > 2)
- iface->nmask = *interpret_addr2(p);
- else
- iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
- } else {
- default_netmask(&iface->nmask,&iface->ip);
- }
- iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
- iface->next = NULL;
-
- if (!(*interfaces)) {
- (*interfaces) = iface;
- } else {
- last_iface->next = iface;
- }
- last_iface = iface;
- DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
- DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
- DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
- }
-
- if (*interfaces) return;
-
- /* setup a default interface */
- iface = (struct interface *)malloc(sizeof(*iface));
- if (!iface) return;
-
- iface->next = NULL;
-
- if (got_ip) {
- iface->ip = default_ip;
- } else {
- get_myname(NULL,&iface->ip);
- }
-
- if (got_bcast) {
- iface->bcast = default_bcast;
- } else {
- get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
- }
-
- if (got_nmask) {
- iface->nmask = default_nmask;
- iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
- }
-
- if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
- DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
- }
-
- iface->next = NULL;
- (*interfaces) = last_iface = iface;
-
- DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
- DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
- DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
+ struct in_addr ip, nmask;
+ char *p;
+ int i, added=0;
+
+ ip = ipzero;
+ nmask = ipzero;
+
+ /* first check if it is an interface name */
+ for (i=0;i<total_probed;i++) {
+ if (fnmatch(token, probed_ifaces[i].name, 0) == 0) {
+ add_interface(probed_ifaces[i].ip,
+ probed_ifaces[i].netmask);
+ added = 1;
+ }
+ }
+ if (added) return;
+
+ /* maybe it is a DNS name */
+ p = strchr(token,'/');
+ if (!p) {
+ ip = *interpret_addr2(token);
+ for (i=0;i<total_probed;i++) {
+ if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
+ !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
+ add_interface(probed_ifaces[i].ip,
+ probed_ifaces[i].netmask);
+ return;
+ }
+ }
+ DEBUG(2,("can't determine netmask for %s\n", token));
+ return;
+ }
+
+ /* parse it into an IP address/netmasklength pair */
+ *p++ = 0;
+
+ ip = *interpret_addr2(token);
+
+ if (strlen(p) > 2) {
+ nmask = *interpret_addr2(p);
+ } else {
+ nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
+ }
+
+ /* maybe the first component was a broadcast address */
+ if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
+ ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
+ for (i=0;i<total_probed;i++) {
+ if (same_net(ip, probed_ifaces[i].ip, nmask)) {
+ add_interface(probed_ifaces[i].ip, nmask);
+ return;
+ }
+ }
+ DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
+ return;
+ }
+
+ add_interface(ip, nmask);
}
/****************************************************************************
-load the remote and local interfaces
+load the list of network interfaces
****************************************************************************/
void load_interfaces(void)
{
- /* add the machine's interfaces to local interface structure*/
- interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
+ char *ptr;
+ fstring token;
+ int i;
+ struct iface_struct ifaces[MAX_INTERFACES];
+
+ ptr = lp_interfaces();
+
+ ipzero = *interpret_addr2("0.0.0.0");
+ allones_ip = *interpret_addr2("255.255.255.255");
+ loopback_ip = *interpret_addr2("127.0.0.1");
+
+ if (probed_ifaces) {
+ free(probed_ifaces);
+ probed_ifaces = NULL;
+ }
+
+ /* dump the current interfaces if any */
+ while (local_interfaces) {
+ struct interface *iface = local_interfaces;
+ DLIST_REMOVE(local_interfaces, local_interfaces);
+ ZERO_STRUCTPN(iface);
+ free(iface);
+ }
+
+ /* probe the kernel for interfaces */
+ total_probed = get_interfaces(ifaces, MAX_INTERFACES);
+
+ if (total_probed > 0) {
+ probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
+ }
+
+ /* if we don't have a interfaces line then use all broadcast capable
+ interfaces except loopback */
+ if (!ptr || !*ptr) {
+ if (total_probed <= 0) {
+ DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
+ exit(1);
+ }
+ for (i=0;i<total_probed;i++) {
+ if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
+ probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
+ add_interface(probed_ifaces[i].ip,
+ probed_ifaces[i].netmask);
+ }
+ }
+ return;
+ }
+
+ while (next_token(&ptr,token,NULL,sizeof(token))) {
+ interpret_interface(token);
+ }
+
+ if (!local_interfaces) {
+ DEBUG(0,("WARNING: no network interfaces found\n"));
+ }
}
/****************************************************************************
- override the defaults
- **************************************************************************/
-void iface_set_default(char *ip,char *bcast,char *nmask)
+return True if the list of probed interfaces has changed
+****************************************************************************/
+BOOL interfaces_changed(void)
{
- if (ip) {
- got_ip = True;
- default_ip = *interpret_addr2(ip);
- }
-
- if (bcast) {
- got_bcast = True;
- default_bcast = *interpret_addr2(bcast);
- }
-
- if (nmask) {
- got_nmask = True;
- default_nmask = *interpret_addr2(nmask);
- }
+ int n;
+ struct iface_struct ifaces[MAX_INTERFACES];
+
+ n = get_interfaces(ifaces, MAX_INTERFACES);
+
+ if (n != total_probed ||
+ memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n)) {
+ return True;
+ }
+
+ return False;
}
@@ -253,10 +248,10 @@ void iface_set_default(char *ip,char *bcast,char *nmask)
**************************************************************************/
BOOL ismyip(struct in_addr ip)
{
- struct interface *i;
- for (i=local_interfaces;i;i=i->next)
- if (ip_equal(i->ip,ip)) return True;
- return False;
+ struct interface *i;
+ for (i=local_interfaces;i;i=i->next)
+ if (ip_equal(i->ip,ip)) return True;
+ return False;
}
/****************************************************************************
@@ -264,11 +259,13 @@ BOOL ismyip(struct in_addr ip)
**************************************************************************/
BOOL is_local_net(struct in_addr from)
{
- struct interface *i;
- for (i=local_interfaces;i;i=i->next)
- if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
- return True;
- return False;
+ struct interface *i;
+ for (i=local_interfaces;i;i=i->next) {
+ if((from.s_addr & i->nmask.s_addr) ==
+ (i->ip.s_addr & i->nmask.s_addr))
+ return True;
+ }
+ return False;
}
/****************************************************************************
@@ -276,12 +273,12 @@ BOOL is_local_net(struct in_addr from)
**************************************************************************/
int iface_count(void)
{
- int ret = 0;
- struct interface *i;
+ int ret = 0;
+ struct interface *i;
- for (i=local_interfaces;i;i=i->next)
- ret++;
- return ret;
+ for (i=local_interfaces;i;i=i->next)
+ ret++;
+ return ret;
}
/****************************************************************************
@@ -289,12 +286,12 @@ int iface_count(void)
**************************************************************************/
BOOL we_are_multihomed(void)
{
- static int multi = -1;
+ static int multi = -1;
- if(multi == -1)
- multi = (iface_count() > 1 ? True : False);
-
- return multi;
+ if(multi == -1)
+ multi = (iface_count() > 1 ? True : False);
+
+ return multi;
}
/****************************************************************************
@@ -302,13 +299,13 @@ BOOL we_are_multihomed(void)
**************************************************************************/
struct interface *get_interface(int n)
{
- struct interface *i;
+ struct interface *i;
- for (i=local_interfaces;i && n;i=i->next)
- n--;
+ for (i=local_interfaces;i && n;i=i->next)
+ n--;
- if (i) return i;
- return NULL;
+ if (i) return i;
+ return NULL;
}
/****************************************************************************
@@ -316,27 +313,27 @@ struct interface *get_interface(int n)
**************************************************************************/
struct in_addr *iface_n_ip(int n)
{
- struct interface *i;
+ struct interface *i;
- for (i=local_interfaces;i && n;i=i->next)
- n--;
+ for (i=local_interfaces;i && n;i=i->next)
+ n--;
- if (i) return &i->ip;
- return NULL;
+ if (i) return &i->ip;
+ return NULL;
}
/****************************************************************************
-Try and find an interface that matches an ip. If we cannot, return NULL
+ return bcast of the Nth interface
**************************************************************************/
-static struct interface *iface_find(struct in_addr ip)
+struct in_addr *iface_n_bcast(int n)
{
- struct interface *i;
- if (zero_ip(ip)) return local_interfaces;
-
- for (i=local_interfaces;i;i=i->next)
- if (same_net(i->ip,ip,i->nmask)) return i;
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next)
+ n--;
- return NULL;
+ if (i) return &i->bcast;
+ return NULL;
}
@@ -368,15 +365,12 @@ unsigned iface_hash(void)
struct in_addr *iface_bcast(struct in_addr ip)
{
- struct interface *i = iface_find(ip);
- return(i ? &i->bcast : &local_interfaces->bcast);
+ struct interface *i = iface_find(ip);
+ return(i ? &i->bcast : &local_interfaces->bcast);
}
struct in_addr *iface_ip(struct in_addr ip)
{
- struct interface *i = iface_find(ip);
- return(i ? &i->ip : &local_interfaces->ip);
+ struct interface *i = iface_find(ip);
+ return(i ? &i->ip : &local_interfaces->ip);
}
-
-
-
diff --git a/source3/lib/kanji.c b/source3/lib/kanji.c
index 871a4a059c..1983bb1161 100644
--- a/source3/lib/kanji.c
+++ b/source3/lib/kanji.c
@@ -377,7 +377,7 @@ static size_t skip_generic_multibyte_char(char c)
********************************************************************/
/* convesion buffer */
-static char cvtbuf[1024];
+static char cvtbuf[2*sizeof(pstring)];
/*******************************************************************
EUC <-> SJIS
@@ -412,7 +412,7 @@ static char *sj_to_euc(char *from, BOOL overwrite)
char *save;
save = (char *) from;
- for (out = cvtbuf; *from;) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) {
if (is_shift_jis (*from)) {
int code = sjis2euc ((int) from[0] & 0xff, (int) from[1] & 0xff);
*out++ = (code >> 8) & 0xff;
@@ -445,7 +445,7 @@ static char *euc_to_sj(char *from, BOOL overwrite)
char *save;
save = (char *) from;
- for (out = cvtbuf; *from; ) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3); ) {
if (is_euc (*from)) {
int code = euc2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
*out++ = (code >> 8) & 0xff;
@@ -496,48 +496,51 @@ static int jis2sjis(int hi, int lo)
static char *jis8_to_sj(char *from, BOOL overwrite)
{
- char *out;
- int shifted;
- char *save;
+ char *out;
+ int shifted;
+ char *save;
- shifted = _KJ_ROMAN;
- save = (char *) from;
- for (out = cvtbuf; *from;) {
- if (is_esc (*from)) {
- if (is_so1 (from[1]) && is_so2 (from[2])) {
- shifted = _KJ_KANJI;
- from += 3;
- } else if (is_si1 (from[1]) && is_si2 (from[2])) {
- shifted = _KJ_ROMAN;
- from += 3;
- } else { /* sequence error */
- goto normal;
- }
- } else {
- normal:
- switch (shifted) {
- default:
- case _KJ_ROMAN:
- *out++ = *from++;
- break;
- case _KJ_KANJI:
- {
- int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
- *out++ = (code >> 8) & 0xff;
- *out++ = code;
- from += 2;
- }
- break;
- }
- }
- }
- *out = 0;
- if (overwrite) {
- pstrcpy (save, (char *) cvtbuf);
- return save;
+ shifted = _KJ_ROMAN;
+ save = (char *) from;
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) {
+ if (is_esc (*from)) {
+ if (is_so1 (from[1]) && is_so2 (from[2])) {
+ shifted = _KJ_KANJI;
+ from += 3;
+ } else if (is_si1 (from[1]) && is_si2 (from[2])) {
+ shifted = _KJ_ROMAN;
+ from += 3;
+ } else { /* sequence error */
+ goto normal;
+ }
} else {
- return cvtbuf;
+
+normal:
+
+ switch (shifted) {
+ default:
+ case _KJ_ROMAN:
+ *out++ = *from++;
+ break;
+ case _KJ_KANJI:
+ {
+ int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
+ *out++ = (code >> 8) & 0xff;
+ *out++ = code;
+ from += 2;
+ break;
+ }
+ }
}
+ }
+
+ *out = 0;
+ if (overwrite) {
+ pstrcpy (save, (char *) cvtbuf);
+ return save;
+ } else {
+ return cvtbuf;
+ }
}
/*******************************************************************
@@ -547,54 +550,55 @@ static char *jis8_to_sj(char *from, BOOL overwrite)
static char *sj_to_jis8(char *from, BOOL overwrite)
{
- char *out;
- int shifted;
- char *save;
+ char *out;
+ int shifted;
+ char *save;
- shifted = _KJ_ROMAN;
- save = (char *) from;
- for (out = cvtbuf; *from; ) {
- if (is_shift_jis (*from)) {
- int code;
- switch (shifted) {
- case _KJ_ROMAN: /* to KANJI */
- *out++ = jis_esc;
- *out++ = jis_so1;
- *out++ = jis_kso;
- shifted = _KJ_KANJI;
- break;
- }
- code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
- *out++ = (code >> 8) & 0xff;
- *out++ = code;
- from += 2;
- } else {
- switch (shifted) {
- case _KJ_KANJI: /* to ROMAN/KANA */
- *out++ = jis_esc;
- *out++ = jis_si1;
- *out++ = jis_ksi;
- shifted = _KJ_ROMAN;
- break;
- }
- *out++ = *from++;
- }
- }
- switch (shifted) {
- case _KJ_KANJI: /* to ROMAN/KANA */
- *out++ = jis_esc;
- *out++ = jis_si1;
- *out++ = jis_ksi;
- shifted = _KJ_ROMAN;
- break;
- }
- *out = 0;
- if (overwrite) {
- pstrcpy (save, (char *) cvtbuf);
- return save;
+ shifted = _KJ_ROMAN;
+ save = (char *) from;
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) {
+ if (is_shift_jis (*from)) {
+ int code;
+ switch (shifted) {
+ case _KJ_ROMAN: /* to KANJI */
+ *out++ = jis_esc;
+ *out++ = jis_so1;
+ *out++ = jis_kso;
+ shifted = _KJ_KANJI;
+ break;
+ }
+ code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
+ *out++ = (code >> 8) & 0xff;
+ *out++ = code;
+ from += 2;
} else {
- return cvtbuf;
+ switch (shifted) {
+ case _KJ_KANJI: /* to ROMAN/KANA */
+ *out++ = jis_esc;
+ *out++ = jis_si1;
+ *out++ = jis_ksi;
+ shifted = _KJ_ROMAN;
+ break;
+ }
+ *out++ = *from++;
}
+ }
+
+ switch (shifted) {
+ case _KJ_KANJI: /* to ROMAN/KANA */
+ *out++ = jis_esc;
+ *out++ = jis_si1;
+ *out++ = jis_ksi;
+ shifted = _KJ_ROMAN;
+ break;
+ }
+ *out = 0;
+ if (overwrite) {
+ pstrcpy (save, (char *) cvtbuf);
+ return save;
+ } else {
+ return cvtbuf;
+ }
}
/*******************************************************************
@@ -609,7 +613,7 @@ static char *jis7_to_sj(char *from, BOOL overwrite)
shifted = _KJ_ROMAN;
save = (char *) from;
- for (out = cvtbuf; *from;) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) {
if (is_esc (*from)) {
if (is_so1 (from[1]) && is_so2 (from[2])) {
shifted = _KJ_KANJI;
@@ -668,7 +672,7 @@ static char *sj_to_jis7(char *from, BOOL overwrite)
shifted = _KJ_ROMAN;
save = (char *) from;
- for (out = cvtbuf; *from; ) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) {
if (is_shift_jis (*from)) {
int code;
switch (shifted) {
@@ -736,6 +740,7 @@ static char *sj_to_jis7(char *from, BOOL overwrite)
Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes
return converted buffer
********************************************************************/
+
static char *junet_to_sj(char *from, BOOL overwrite)
{
char *out;
@@ -744,7 +749,7 @@ static char *junet_to_sj(char *from, BOOL overwrite)
shifted = _KJ_ROMAN;
save = (char *) from;
- for (out = cvtbuf; *from;) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) {
if (is_esc (*from)) {
if (is_so1 (from[1]) && is_so2 (from[2])) {
shifted = _KJ_KANJI;
@@ -800,7 +805,7 @@ static char *sj_to_junet(char *from, BOOL overwrite)
shifted = _KJ_ROMAN;
save = (char *) from;
- for (out = cvtbuf; *from; ) {
+ for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) {
if (is_shift_jis (*from)) {
int code;
switch (shifted) {
@@ -867,7 +872,7 @@ static char *hex_to_sj(char *from, BOOL overwrite)
sp = (char *) from;
dp = cvtbuf;
- while (*sp) {
+ while (*sp && (dp - cvtbuf < sizeof(cvtbuf)-3)) {
if (*sp == hex_tag && isxdigit((int)sp[1]) && isxdigit((int)sp[2])) {
*dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2]));
sp += 3;
@@ -892,7 +897,7 @@ static char *sj_to_hex(char *from, BOOL overwrite)
sp = (unsigned char*) from;
dp = (unsigned char*) cvtbuf;
- while (*sp) {
+ while (*sp && (((char *)dp)- cvtbuf < sizeof(cvtbuf)-7)) {
if (is_kana(*sp)) {
*dp++ = hex_tag;
*dp++ = bin2hex (((*sp)>>4)&0x0f);
@@ -929,7 +934,7 @@ static char *cap_to_sj(char *from, BOOL overwrite)
sp = (char *) from;
dp = cvtbuf;
- while (*sp) {
+ while (*sp && (dp- cvtbuf < sizeof(cvtbuf)-2)) {
/*
* The only change between this and hex_to_sj is here. sj_to_cap only
* translates characters greater or equal to 0x80 - make sure that here
@@ -960,7 +965,7 @@ static char *sj_to_cap(char *from, BOOL overwrite)
sp = (unsigned char*) from;
dp = (unsigned char*) cvtbuf;
- while (*sp) {
+ while (*sp && (((char *)dp) - cvtbuf < sizeof(cvtbuf)-4)) {
if (*sp >= 0x80) {
*dp++ = hex_tag;
*dp++ = bin2hex (((*sp)>>4)&0x0f);
diff --git a/source3/lib/md4.c b/source3/lib/md4.c
index 56c9e02ffb..30f2b6b8c6 100644
--- a/source3/lib/md4.c
+++ b/source3/lib/md4.c
@@ -101,7 +101,7 @@ static void mdfour64(uint32 *M)
X[j] = 0;
}
-static void copy64(uint32 *M, const unsigned char *in)
+static void copy64(uint32 *M, unsigned char *in)
{
int i;
@@ -119,7 +119,7 @@ static void copy4(unsigned char *out,uint32 x)
}
/* produce a md4 message digest from data of length n bytes */
-void mdfour(unsigned char *out, const unsigned char *in, int n)
+void mdfour(unsigned char *out, unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
diff --git a/source3/lib/pidfile.c b/source3/lib/pidfile.c
index 6fc64aafe2..726e8c1f21 100644
--- a/source3/lib/pidfile.c
+++ b/source3/lib/pidfile.c
@@ -39,7 +39,7 @@ pid_t pidfile_pid(char *name)
slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_lockdir(), name);
- fd = open(pidFile, O_NONBLOCK | O_RDWR);
+ fd = sys_open(pidFile, O_NONBLOCK | O_RDWR, 0644);
if (fd == -1) {
return 0;
}
@@ -52,7 +52,7 @@ pid_t pidfile_pid(char *name)
ret = atoi(pidstr);
- if (!process_exists(ret)) {
+ if (!process_exists((pid_t)ret)) {
goto ok;
}
@@ -76,14 +76,14 @@ void pidfile_create(char *name)
int fd;
char buf[20];
pstring pidFile;
- int pid;
+ pid_t pid;
slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_lockdir(), name);
pid = pidfile_pid(name);
if (pid != 0) {
DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n",
- name, pidFile, pid));
+ name, pidFile, (int)pid));
exit(1);
}
@@ -109,4 +109,3 @@ void pidfile_create(char *name)
}
/* Leave pid file open & locked for the duration... */
}
-
diff --git a/source3/lib/replace.c b/source3/lib/replace.c
index c6a4259417..6a492f977c 100644
--- a/source3/lib/replace.c
+++ b/source3/lib/replace.c
@@ -70,7 +70,7 @@ Corrections by richard.kettlewell@kewill.com
epoch = (t->tm_year - 70) * YEAR +
((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
- y = t->tm_year;
+ y = t->tm_year + 1900;
m = 0;
for(i = 0; i < t->tm_mon; i++) {
@@ -168,7 +168,6 @@ Corrections by richard.kettlewell@kewill.com
struct group *g;
char *gr;
- setgrent();
grouplst[0] = id;
i = 1;
while (i < NGROUPS_MAX &&
@@ -188,7 +187,7 @@ Corrections by richard.kettlewell@kewill.com
}
}
endgrent();
- return(setgroups(i,grouplst));
+ return(sys_setgroups(i,grouplst));
#endif /* HAVE_SETGROUPS */
}
#endif /* HAVE_INITGROUPS */
diff --git a/source3/lib/signal.c b/source3/lib/signal.c
index bb1c6fe189..5651e942d7 100644
--- a/source3/lib/signal.c
+++ b/source3/lib/signal.c
@@ -22,22 +22,51 @@
#include "includes.h"
-
/****************************************************************************
-catch child exits
+ Catch child exits and reap the child zombie status.
****************************************************************************/
+
static void sig_cld(int signum)
{
- while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ;
+ while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0)
+ ;
+
+ /*
+ * Turns out it's *really* important not to
+ * restore the signal handler here if we have real POSIX
+ * signal handling. If we do, then we get the signal re-delivered
+ * immediately - hey presto - instant loop ! JRA.
+ */
+#if !defined(HAVE_SIGACTION)
CatchSignal(SIGCLD, sig_cld);
+#endif
}
+/****************************************************************************
+catch child exits - leave status;
+****************************************************************************/
+static void sig_cld_leave_status(int signum)
+{
+ /*
+ * Turns out it's *really* important not to
+ * restore the signal handler here if we have real POSIX
+ * signal handling. If we do, then we get the signal re-delivered
+ * immediately - hey presto - instant loop ! JRA.
+ */
+
+#if !defined(HAVE_SIGACTION)
+ CatchSignal(SIGCLD, sig_cld_leave_status);
+#else
+ ;
+#endif
+}
/*******************************************************************
-block sigs
+ Block sigs.
********************************************************************/
+
void BlockSignals(BOOL block,int signum)
{
#ifdef HAVE_SIGPROCMASK
@@ -63,14 +92,13 @@ void BlockSignals(BOOL block,int signum)
#endif
}
-
-
/*******************************************************************
-catch a signal. This should implement the following semantics:
+ Catch a signal. This should implement the following semantics:
-1) the handler remains installed after being called
-2) the signal should be blocked during handler execution
+ 1) The handler remains installed after being called.
+ 2) The signal should be blocked during handler execution.
********************************************************************/
+
void CatchSignal(int signum,void (*handler)(int ))
{
#ifdef HAVE_SIGACTION
@@ -80,23 +108,35 @@ void CatchSignal(int signum,void (*handler)(int ))
act.sa_handler = handler;
#ifdef SA_RESTART
- act.sa_flags = 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,NULL);
-#else
+#else /* !HAVE_SIGACTION */
/* FIXME: need to handle sigvec and systems with broken signal() */
signal(signum, handler);
#endif
}
-
-
/*******************************************************************
-ignore SIGCLD via whatever means is necessary for this OS
+ Ignore SIGCLD via whatever means is necessary for this OS.
********************************************************************/
+
void CatchChild(void)
{
CatchSignal(SIGCLD, sig_cld);
}
+
+/*******************************************************************
+ Catch SIGCLD but leave the child around so it's status can be reaped.
+********************************************************************/
+
+void CatchChildLeaveStatus(void)
+{
+ CatchSignal(SIGCLD, sig_cld_leave_status);
+}
diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c
index da7632a67a..5a016cd5cd 100644
--- a/source3/lib/smbrun.c
+++ b/source3/lib/smbrun.c
@@ -28,7 +28,7 @@ extern int DEBUGLEVEL;
/****************************************************************************
This is a utility function of smbrun(). It must be called only from
-the child as it may leave the caller in a privilaged state.
+the child as it may leave the caller in a privileged state.
****************************************************************************/
static BOOL setup_stdout_file(char *outfile,BOOL shared)
{
@@ -40,14 +40,9 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared)
close(1);
if (shared) {
- /* become root - unprivilaged users can't delete these files */
-#ifdef HAVE_SETRESUID
- setresgid(0,0,0);
- setresuid(0,0,0);
-#else
- setuid(0);
- seteuid(0);
-#endif
+ /* become root - unprivileged users can't delete these files */
+ gain_root_privilege();
+ gain_root_group_privilege();
}
if(sys_stat(outfile, &st) == 0) {
@@ -85,9 +80,10 @@ if shared is not set then open the file with O_EXCL set
****************************************************************************/
int smbrun(char *cmd,char *outfile,BOOL shared)
{
- int fd,pid;
- int uid = current_user.uid;
- int gid = current_user.gid;
+ int fd;
+ pid_t pid;
+ uid_t uid = current_user.uid;
+ gid_t gid = current_user.gid;
/*
* Lose any kernel oplock capabilities we may have.
@@ -110,7 +106,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
}
slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"",
- path,uid,gid,cmd,
+ path,(int)uid,(int)gid,cmd,
outfile?outfile:"/dev/null");
DEBUG(5,("smbrun - running %s ",syscmd));
@@ -120,17 +116,52 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
#else
/* in this newer method we will exec /bin/sh with the correct
arguments, after first setting stdout to point at the file */
-
- if ((pid=fork())) {
+
+ /*
+ * We need to temporarily stop CatchChild from eating
+ * SIGCLD signals as it also eats the exit status code. JRA.
+ */
+
+ CatchChildLeaveStatus();
+
+ if ((pid=fork()) < 0) {
+ DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) ));
+ CatchChild();
+ return errno;
+ }
+
+ if (pid) {
+ /*
+ * Parent.
+ */
int status=0;
+ pid_t wpid;
+
+
/* the parent just waits for the child to exit */
- if (sys_waitpid(pid,&status,0) != pid) {
- DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno)));
+ while((wpid = sys_waitpid(pid,&status,0)) < 0) {
+ if(errno == EINTR) {
+ errno = 0;
+ continue;
+ }
+ break;
+ }
+
+ CatchChild();
+
+ if (wpid != pid) {
+ DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno)));
return -1;
}
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ }
+#endif
return status;
}
+ CatchChild();
/* we are in the child. we exec /bin/sh to do the work for us. we
don't directly exec the command we want because it may be a
@@ -141,25 +172,14 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
exit(80);
}
- /* now completely lose our privilages. This is a fairly paranoid
+ /* now completely lose our privileges. This is a fairly paranoid
way of doing it, but it does work on all systems that I know of */
-#ifdef HAVE_SETRESUID
- setresgid(0,0,0);
- setresuid(0,0,0);
- setresgid(gid,gid,gid);
- setresuid(uid,uid,uid);
-#else
- setuid(0);
- seteuid(0);
- setgid(gid);
- setegid(gid);
- setuid(uid);
- seteuid(uid);
-#endif
-
+
+ become_user_permanently(uid, gid);
+
if (getuid() != uid || geteuid() != uid ||
getgid() != gid || getegid() != gid) {
- /* we failed to lose our privilages - do not execute
+ /* we failed to lose our privileges - do not execute
the command */
exit(81); /* we can't print stuff at this stage,
instead use exit codes for debugging */
diff --git a/source3/lib/snprintf.c b/source3/lib/snprintf.c
index 5798732643..f149d3e667 100644
--- a/source3/lib/snprintf.c
+++ b/source3/lib/snprintf.c
@@ -581,8 +581,21 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
{
int signvalue = 0;
LDOUBLE ufvalue;
+#ifndef HAVE_FCVT
char iconvert[20];
char fconvert[20];
+#else
+ char iconvert[311];
+ char fconvert[311];
+ char *result;
+ int dec_pt, sig;
+ int r_length;
+# ifdef HAVE_FCVTL
+ extern char *fcvtl(long double value, int ndigit, int *decpt, int *sign);
+# else
+ extern char *fcvt(double value, int ndigit, int *decpt, int *sign);
+# endif
+#endif
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
@@ -613,6 +626,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
+#ifndef HAVE_FCVT
intpart = (long)ufvalue;
/*
@@ -655,7 +669,53 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
} while(fracpart && (fplace < 20));
if (fplace == 20) fplace--;
fconvert[fplace] = 0;
+#else /* use fcvt() */
+ if (max > 310)
+ max = 310;
+# ifdef HAVE_FCVTL
+ result = fcvtl(ufvalue, max, &dec_pt, &sig);
+# else
+ result = fcvt(ufvalue, max, &dec_pt, &sig);
+# endif
+
+ r_length = strlen(result);
+
+ if (r_length == 0)
+ {
+ result[0] = '0';
+ result[1] = '\0';
+ r_length = 1;
+ }
+
+ if (dec_pt <= 0)
+ {
+ iplace = 1;
+ iconvert[0] = '0';
+ iconvert[1] = '\0';
+
+ fplace = 0;
+
+ while(r_length)
+ fconvert[fplace++] = result[--r_length];
+ while(dec_pt < 0)
+ fconvert[fplace++] = '0';
+ }
+ else
+ {
+ int c;
+
+ iplace=0;
+ for(c=dec_pt; c; iconvert[iplace++] = result[--c]);
+ iconvert[iplace] = '\0';
+
+ result += dec_pt;
+ fplace = 0;
+
+ for(c=(r_length-dec_pt); c; fconvert[fplace++] = result[--c]);
+ }
+#endif /* fcvt */
+
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
@@ -791,7 +851,7 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
NULL
};
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
- 0.9996, 1.996, 4.136, 0};
+ 0.9996, 1.996, 4.136, 6442452944.1234, 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
diff --git a/source3/lib/system.c b/source3/lib/system.c
index f9de800bd3..a59f94a6a9 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -60,7 +60,7 @@ static int pollfd(int fd)
return(r);
}
-int sys_select(int maxfd, fd_set *fds, fd_set *w_fds, struct timeval *tval)
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
{
fd_set fds2;
int counter=0;
@@ -90,7 +90,7 @@ int sys_select(int maxfd, fd_set *fds, fd_set *w_fds, struct timeval *tval)
}
#else /* !NO_SELECT */
-int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval)
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
{
#ifdef USE_POLL
struct pollfd pfd[256];
@@ -131,8 +131,7 @@ int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval)
do {
if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
errno = 0;
- selrtn = select(maxfd,SELECT_CAST r_fds,SELECT_CAST w_fds,
- NULL,tval?&t2:NULL);
+ selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
} while (selrtn<0 && errno == EINTR);
return(selrtn);
@@ -141,16 +140,54 @@ int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval)
#endif /* NO_SELECT */
/*******************************************************************
+ A wrapper for usleep in case we don't have one.
+********************************************************************/
+
+int sys_usleep(long usecs)
+{
+#ifndef HAVE_USLEEP
+ struct timeval tval;
+#endif
+
+ /*
+ * We need this braindamage as the glibc usleep
+ * is not SPEC1170 complient... grumble... JRA.
+ */
+
+ if(usecs < 0 || usecs > 1000000) {
+ errno = EINVAL;
+ return -1;
+ }
+
+#if HAVE_USLEEP
+ usleep(usecs);
+ return 0;
+#else /* HAVE_USLEEP */
+ /*
+ * Fake it with select...
+ */
+ tval.tv_sec = 0;
+ tval.tv_usec = usecs/1000;
+ select(0,NULL,NULL,NULL,&tval);
+ return 0;
+#endif /* HAVE_USLEEP */
+}
+
+/*******************************************************************
A stat() wrapper that will deal with 64 bit filesizes.
********************************************************************/
int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
{
-#if defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
- return stat64(fname, sbuf);
+ int ret;
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
+ ret = stat64(fname, sbuf);
#else
- return stat(fname, sbuf);
+ ret = stat(fname, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -159,11 +196,15 @@ int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
{
-#if defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
- return fstat64(fd, sbuf);
+ int ret;
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
+ ret = fstat64(fd, sbuf);
#else
- return fstat(fd, sbuf);
+ ret = fstat(fd, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -172,11 +213,15 @@ int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
{
-#if defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
- return lstat64(fname, sbuf);
+ int ret;
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
+ ret = lstat64(fname, sbuf);
#else
- return lstat(fname, sbuf);
+ ret = lstat(fname, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -185,7 +230,7 @@ int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
int sys_ftruncate(int fd, SMB_OFF_T offset)
{
-#if defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
return ftruncate64(fd, offset);
#else
return ftruncate(fd, offset);
@@ -198,7 +243,7 @@ int sys_ftruncate(int fd, SMB_OFF_T offset)
SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
{
-#if defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
return lseek64(fd, offset, whence);
#else
return lseek(fd, offset, whence);
@@ -211,8 +256,10 @@ SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
{
-#if defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
return fseek64(fp, offset, whence);
+#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
+ return fseeko64(fp, offset, whence);
#else
return fseek(fp, offset, whence);
#endif
@@ -224,8 +271,10 @@ int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
SMB_OFF_T sys_ftell(FILE *fp)
{
-#if defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
return (SMB_OFF_T)ftell64(fp);
+#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
+ return (SMB_OFF_T)ftello64(fp);
#else
return (SMB_OFF_T)ftell(fp);
#endif
@@ -237,7 +286,7 @@ SMB_OFF_T sys_ftell(FILE *fp)
int sys_creat(const char *path, mode_t mode)
{
-#if defined(HAVE_CREAT64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
return creat64(path, mode);
#else
/*
@@ -254,7 +303,7 @@ int sys_creat(const char *path, mode_t mode)
int sys_open(const char *path, int oflag, mode_t mode)
{
-#if defined(HAVE_OPEN64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
return open64(path, oflag, mode);
#else
return open(path, oflag, mode);
@@ -267,26 +316,43 @@ int sys_open(const char *path, int oflag, mode_t mode)
FILE *sys_fopen(const char *path, const char *type)
{
-#if defined(HAVE_FOPEN64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
return fopen64(path, type);
#else
return fopen(path, type);
#endif
}
+#if defined(HAVE_MMAP)
+
/*******************************************************************
An mmap() wrapper that will deal with 64 bit filesizes.
********************************************************************/
void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
{
-#if defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
return mmap64(addr, len, prot, flags, fd, offset);
#else
return mmap(addr, len, prot, flags, fd, offset);
#endif
}
+#endif /* HAVE_MMAP */
+
+/*******************************************************************
+ A readdir wrapper that will deal with 64 bit filesizes.
+********************************************************************/
+
+SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
+{
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
+ return readdir64(dirp);
+#else
+ return readdir(dirp);
+#endif
+}
+
/*******************************************************************
The wait() calls vary between systems
********************************************************************/
@@ -305,18 +371,19 @@ system wrapper for getwd
********************************************************************/
char *sys_getwd(char *s)
{
- char *wd;
+ char *wd;
#ifdef HAVE_GETCWD
- wd = (char *)getcwd(s, sizeof (pstring));
+ wd = (char *)getcwd(s, sizeof (pstring));
#else
- wd = (char *)getwd(s);
+ wd = (char *)getwd(s);
#endif
- return wd;
+ return wd;
}
/*******************************************************************
chown isn't used much but OS/2 doesn't have it
********************************************************************/
+
int sys_chown(const char *fname,uid_t uid,gid_t gid)
{
#ifndef HAVE_CHOWN
@@ -413,9 +480,12 @@ BOOL set_process_capability( uint32 cap_flag, BOOL enable )
if (cap_set_proc(cap) == -1) {
DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
strerror(errno)));
+ cap_free(cap);
return False;
}
+ cap_free(cap);
+
DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
}
#endif
@@ -447,9 +517,12 @@ BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
if (cap_set_proc(cap) == -1) {
DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
strerror(errno)));
+ cap_free(cap);
return False;
}
+ cap_free(cap);
+
DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
}
#endif
@@ -516,7 +589,8 @@ int sys_getgroups(int setlen, gid_t *gidset)
return -1;
}
- if (setlen == 0) setlen = 1;
+ if (setlen == 0)
+ setlen = 1;
if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
DEBUG(0,("sys_getgroups: Malloc fail.\n"));
@@ -538,6 +612,62 @@ int sys_getgroups(int setlen, gid_t *gidset)
#endif /* HAVE_BROKEN_GETGROUPS */
}
+#ifdef HAVE_SETGROUPS
+
+/**************************************************************************
+ Wrapper for setgroups. Deals with broken (int) case. Automatically used
+ if we have broken getgroups.
+****************************************************************************/
+
+int sys_setgroups(int setlen, gid_t *gidset)
+{
+#if !defined(HAVE_BROKEN_GETGROUPS)
+ return setgroups(setlen, gidset);
+#else
+
+ GID_T *group_list;
+ int i ;
+
+ if (setlen == 0)
+ return 0 ;
+
+#ifdef NGROUPS_MAX
+ if (setlen > NGROUPS_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+#endif
+
+ /*
+ * Broken case. We need to allocate a
+ * GID_T array of size setlen.
+ */
+
+ if (setlen == 0)
+ setlen = 1;
+
+ if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
+ DEBUG(0,("sys_setgroups: Malloc fail.\n"));
+ return -1;
+ }
+
+ for(i = 0; i < setlen; i++)
+ group_list[i] = (GID_T) gidset[i];
+
+ if(setgroups(setlen, group_list) != 0) {
+ int saved_errno = errno;
+ free((char *)group_list);
+ errno = saved_errno;
+ return -1;
+ }
+
+ free((char *)group_list);
+ return 0 ;
+#endif /* HAVE_BROKEN_GETGROUPS */
+}
+
+#endif /* HAVE_SETGROUPS */
+
/*
* We only wrap pw_name and pw_passwd for now as these
* are the only potentially modified fields.
@@ -547,7 +677,7 @@ int sys_getgroups(int setlen, gid_t *gidset)
Helper function for getpwnam/getpwuid wrappers.
****************************************************************************/
-struct passwd *copy_passwd_struct(struct passwd *pass)
+static struct passwd *setup_pwret(struct passwd *pass)
{
static pstring pw_name;
static pstring pw_passwd;
@@ -558,25 +688,16 @@ struct passwd *copy_passwd_struct(struct passwd *pass)
return NULL;
}
- if (pass == &pw_ret)
- {
- /* catch silly error where buffer was already copied */
- DEBUG(0,("copy_passwd_struct: can't copy internal buffer!\n"));
- return NULL;
- }
-
memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
if (pass->pw_name)
{
- pw_name[0] = '\0';
pw_ret.pw_name = pw_name;
pstrcpy(pw_ret.pw_name, pass->pw_name);
}
if (pass->pw_passwd)
{
- pw_passwd[0] = '\0';
pw_ret.pw_passwd = pw_passwd;
pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
}
@@ -590,7 +711,7 @@ struct passwd *copy_passwd_struct(struct passwd *pass)
struct passwd *sys_getpwnam(const char *name)
{
- return copy_passwd_struct(getpwnam(name));
+ return setup_pwret(getpwnam(name));
}
/**************************************************************************
@@ -599,5 +720,5 @@ struct passwd *sys_getpwnam(const char *name)
struct passwd *sys_getpwuid(uid_t uid)
{
- return copy_passwd_struct(getpwuid(uid));
+ return setup_pwret(getpwuid(uid));
}
diff --git a/source3/lib/time.c b/source3/lib/time.c
index c332b906a0..5fd260e5c9 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -247,7 +247,7 @@ its the GMT you get by taking a localtime and adding the
serverzone. This is NOT the same as GMT in some cases. This routine
converts this to real GMT.
****************************************************************************/
-time_t nt_time_to_unix(const NTTIME *nt)
+time_t nt_time_to_unix(NTTIME *nt)
{
double d;
time_t ret;
@@ -298,6 +298,13 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
{
double d;
+ if (t==0)
+ {
+ nt->low = 0;
+ nt->high = 0;
+ return;
+ }
+
/* this converts GMT to kludge-GMT */
t -= LocTimeDiff(t) - serverzone;
@@ -309,15 +316,6 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
}
-/****************************************************************************
-initialise an NTTIME to -1, which means "unknown" or "don't expire"
-****************************************************************************/
-
-void init_nt_time(NTTIME *nt)
-{
- nt->high = 0x7FFFFFFF;
- nt->low = 0xFFFFFFFF;
-}
/****************************************************************************
take an NTTIME structure, containing high / low time. convert to unix time.
@@ -506,21 +504,57 @@ char *http_timestring(time_t t)
/****************************************************************************
- return the date and time as a string
+ Return the date and time as a string
****************************************************************************/
-char *timestring(void )
+
+char *timestring(BOOL hires)
{
static fstring TimeBuf;
- time_t t = time(NULL);
- struct tm *tm = LocalTime(&t);
+ struct timeval tp;
+ time_t t;
+ struct tm *tm;
+ if (hires) {
+ GetTimeOfDay(&tp);
+ t = (time_t)tp.tv_sec;
+ } else {
+ t = time(NULL);
+ }
+ tm = LocalTime(&t);
if (!tm) {
- slprintf(TimeBuf,sizeof(TimeBuf)-1,"%ld seconds since the Epoch",(long)t);
+ if (hires) {
+ slprintf(TimeBuf,
+ sizeof(TimeBuf)-1,
+ "%ld.%06ld seconds since the Epoch",
+ (long)tp.tv_sec,
+ (long)tp.tv_usec);
+ } else {
+ slprintf(TimeBuf,
+ sizeof(TimeBuf)-1,
+ "%ld seconds since the Epoch",
+ (long)t);
+ }
} else {
#ifdef HAVE_STRFTIME
- strftime(TimeBuf,100,"%Y/%m/%d %T",tm);
+ if (hires) {
+ strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
+ slprintf(TimeBuf+strlen(TimeBuf),
+ sizeof(TimeBuf)-1 - strlen(TimeBuf),
+ ".%06ld",
+ (long)tp.tv_usec);
+ } else {
+ strftime(TimeBuf,100,"%Y/%m/%d %H:%M:%S",tm);
+ }
#else
- fstrcpy(TimeBuf, asctime(tm));
+ if (hires)() {
+ slprintf(TimeBuf,
+ sizeof(TimeBuf)-1,
+ "%s.%06ld",
+ asctime(tm),
+ (long)tp.tv_usec);
+ } else {
+ fstrcpy(TimeBuf, asctime(tm));
+ }
#endif
}
return(TimeBuf);
diff --git a/source3/lib/username.c b/source3/lib/username.c
index 23bdb54faf..9a189980d5 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -27,306 +27,31 @@ static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (
static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (char *), int N);
/****************************************************************************
- Since getpwnam() makes samba really slow with the NT-domain code
- (reading /etc/passwd again and again and again), here is an implementation
- of very simple passwd cache
+ Get a users home directory.
****************************************************************************/
-#define PASSWD_HASH_SIZE 1009
-/* The hashtable is rebuild every 15 seconds */
-#define PASSWD_HASH_AGE 15
-struct passwd_hash_entry {
- int entry;
- int next;
-};
-
-struct passwd_hash_table_s {
- struct passwd *passwds;
- int passwds_size;
- int *names;
- int *uids;
- struct passwd_hash_entry *entries;
- int entries_size;
- struct timeval build_time;
-} passwd_hash_table = {
- NULL,0,NULL,NULL,NULL,0,{0,0}
-};
-
-static int name_hash_function(const char *name)
-{
- /* I guess that there must be better hash functions. This one was the
- * first to come into mind :) */
- unsigned int value=0;
- while (*name) {
- value=(value<<8)|(unsigned char)(*name);
- if (value>1048576) value=value%PASSWD_HASH_SIZE;
- name++;
- }
- value=value%PASSWD_HASH_SIZE;
- return value;
-}
-
-static int uid_hash_function(uid_t uid)
-{
- return uid%PASSWD_HASH_SIZE;
-}
-
-static BOOL build_passwd_hash_table(void)
+char *get_user_home_dir(char *user)
{
- struct passwd_hash_table_s *pht=&passwd_hash_table; /* Convenience */
- int num_passwds=0;
- int num_entries=0;
- struct passwd *pass;
- int i;
- int name_i,uid_i;
-
- DEBUG(3,("Building passwd hash table\n"));
- /* Free the allocated strings in old hash table */
- for (i=0;i<pht->passwds_size;i++) {
- free(pht->passwds[i].pw_name);
- free(pht->passwds[i].pw_passwd);
- free(pht->passwds[i].pw_gecos);
- free(pht->passwds[i].pw_dir);
- free(pht->passwds[i].pw_shell);
- }
-
- /* Initialize hash table if first table build */
- if (pht->passwds_size==0) {
- DEBUG(3,("Building passwd hash table for the first time\n"));
- pht->passwds=malloc(sizeof(struct passwd)*64); /* A reasonable default */
- pht->passwds_size=64;
- }
- if (pht->names==NULL) {
- pht->names=malloc(sizeof(struct passwd_hash_entry *)*PASSWD_HASH_SIZE);
- }
- if (pht->uids==NULL) {
- pht->uids=malloc(sizeof(struct passwd_hash_entry *)*PASSWD_HASH_SIZE);
- }
- if (pht->entries==NULL) {
- pht->entries=malloc(sizeof(struct passwd_hash_entry)*128);
- pht->entries_size=128;
- }
- if (pht->passwds==NULL || pht->names==NULL ||
- pht->uids==NULL || pht->entries==NULL) {
- goto fail;
- }
-
- /* Clear out the hash table */
- for(i=0;i<PASSWD_HASH_SIZE;i++) pht->uids[i]=-1;
- for(i=0;i<PASSWD_HASH_SIZE;i++) pht->names[i]=-1;
-
- /* Now do the build */
- setpwent();
-
- while((pass=getpwent())) {
-
- /* Check that we have enough space */
- if (num_passwds==pht->passwds_size) {
- struct passwd *new_passwds=NULL;
- pht->passwds_size+=pht->passwds_size/2;
- new_passwds=realloc(pht->passwds,
- sizeof(struct passwd)*pht->passwds_size);
- if (new_passwds==NULL) goto fail;
- pht->passwds=new_passwds;
- }
- if (num_entries+1>=pht->entries_size) {
- pht->entries_size+=pht->entries_size/2;
- pht->entries=realloc(pht->entries,
- sizeof(struct passwd_hash_entry)*pht->entries_size);
- if (pht->entries==NULL) goto fail;
- }
+ static struct passwd *pass;
- /* Copy the passwd struct */
- memset(&pht->passwds[num_passwds],0,sizeof(struct passwd));
- pht->passwds[num_passwds].pw_uid=pass->pw_uid;
- pht->passwds[num_passwds].pw_gid=pass->pw_gid;
- if (
- (pht->passwds[num_passwds].pw_name=strdup(pass->pw_name))==NULL ||
- (pht->passwds[num_passwds].pw_passwd=strdup(pass->pw_passwd))==NULL ||
- (pht->passwds[num_passwds].pw_gecos=strdup(pass->pw_gecos))==NULL ||
- (pht->passwds[num_passwds].pw_dir=strdup(pass->pw_dir))==NULL ||
- (pht->passwds[num_passwds].pw_shell=strdup(pass->pw_shell))==NULL ) {
- num_passwds++;
- goto fail;
- }
-
- /* Add to the hash table */
- /* Add the name */
- pht->entries[num_entries].entry=num_passwds;
- name_i=name_hash_function(pass->pw_name);
- pht->entries[num_entries].next=pht->names[name_i];
- pht->names[name_i]=num_entries;
- num_entries++;
- /* Add the uid */
- pht->entries[num_entries].entry=num_passwds;
- uid_i=uid_hash_function(pass->pw_uid);
- pht->entries[num_entries].next=pht->uids[uid_i];
- pht->uids[uid_i]=num_entries;
- num_entries++;
-
- /* This entry has been done */
- num_passwds++;
- }
- endpwent();
-
- if (pht->passwds_size>num_passwds) {
- struct passwd *passwds;
- passwds=realloc(pht->passwds,sizeof(pht->passwds[0])*num_passwds);
- if (passwds==NULL) goto fail;
- pht->passwds=passwds;
- pht->passwds_size=num_passwds;
- }
- if (pht->entries_size>num_entries) {
- struct passwd_hash_entry *entries;
- entries=realloc(pht->entries,sizeof(pht->entries[0])*num_entries);
- if (entries==NULL) goto fail;
- pht->entries=entries;
- pht->entries_size=num_entries;
- }
+ pass = Get_Pwnam(user, False);
- /* Mark the creation time */
- GetTimeOfDay(&pht->build_time);
- /* Everything went smoothly. */
- return True;
-
- fail:
- DEBUG(0,("Failed to create passwd hash table: %s",strerror(errno)));
- /* OK: now the untested part. Normally this should never happen:
- * Only running out of memory could cause this and even then
- * we have enough trouble already. */
- while (num_passwds>0) {
- num_passwds--;
- free(pht->passwds[num_passwds].pw_name);
- free(pht->passwds[num_passwds].pw_passwd);
- free(pht->passwds[num_passwds].pw_gecos);
- free(pht->passwds[num_passwds].pw_dir);
- free(pht->passwds[num_passwds].pw_shell);
- }
- free(pht->entries);
- free(pht->uids);
- free(pht->names);
- free(pht->passwds);
- pht->passwds_size=0;
- pht->entries_size=0;
- /* Also mark fail time, so that retry will happen after PASSWD_HASH_AGE */
- GetTimeOfDay(&pht->build_time);
- return False;
+ if (!pass) return(NULL);
+ return(pass->pw_dir);
}
-static BOOL have_passwd_hash(void)
-{
- struct passwd_hash_table_s *pht=&passwd_hash_table;
- struct timeval tv;
- GetTimeOfDay(&tv);
- /* I'm ignoring microseconds. If you think they matter, go ahead
- * and implement them */
- if (tv.tv_sec - pht->build_time.tv_sec > PASSWD_HASH_AGE) {
- return build_passwd_hash_table();
- }
- return pht->passwds_size>0;
-}
-
-struct passwd *hashed_getpwnam(const char *name)
-{
- struct passwd_hash_table_s *pht=&passwd_hash_table;
-
- DEBUG(5,("getpwnam(%s)\n", name));
-
- if (have_passwd_hash())
- {
- int name_i=name_hash_function(name);
- int hash_index=pht->names[name_i];
- while(hash_index!=-1) {
- struct passwd *pass=&pht->passwds[pht->entries[hash_index].entry];
- if (strcmp(name,pass->pw_name)==0) {
- DEBUG(5,("Found: %s:%s:%d:%d:%s:%s:%s\n",
- pass->pw_name,
- pass->pw_passwd,
- pass->pw_uid,
- pass->pw_gid,
- pass->pw_gecos,
- pass->pw_dir,
- pass->pw_shell));
- return copy_passwd_struct(pass);
- }
- hash_index=pht->entries[hash_index].next;
- }
-
- /* Not found */
- DEBUG(5,("%s not found\n",name));
- return NULL;
- }
-
- /* Fall back to real getpwnam() */
- return sys_getpwnam(name);
-}
/*******************************************************************
-turn a uid into a user name
+ Map a username from a dos name to a unix name by looking in the username
+ map. Note that this modifies the name in place.
+ This is the main function that should be called *once* on
+ any incoming or new username - in order to canonicalize the name.
+ This is being done to de-couple the case conversions from the user mapping
+ function. Previously, the map_username was being called
+ every time Get_Pwnam was called.
+ Returns True if username was changed, false otherwise.
********************************************************************/
-char *uidtoname(uid_t uid)
-{
- static char name[40];
- struct passwd_hash_table_s *pht=&passwd_hash_table;
- struct passwd *pass=NULL;
-
- DEBUG(5,("uidtoname(%d)\n",uid));
- if (have_passwd_hash()) {
- int hash_index=pht->uids[uid_hash_function(uid)];
- while(hash_index!=-1) {
- pass=&pht->passwds[pht->entries[hash_index].entry];
- if (pass->pw_uid==uid) {
- DEBUG(5,("Found: %s:%s:%d:%d:%s:%s:%s\n",
- pass->pw_name,
- pass->pw_passwd,
- pass->pw_uid,
- pass->pw_gid,
- pass->pw_gecos,
- pass->pw_dir,
- pass->pw_shell));
- return pass->pw_name;
- }
- hash_index=pht->entries[hash_index].next;
- }
- DEBUG(5,("Hash miss"));
- pass=NULL;
- } else {
- /* No hash table, fall back to getpwuid */
- pass = getpwuid(uid);
- }
- if (pass) return(pass->pw_name);
- slprintf(name, sizeof(name) - 1, "%d",(int)uid);
- return(name);
-}
-
-/****************************************************************************
-get a users home directory.
-****************************************************************************/
-char *get_unixhome_dir(char *user)
-{
- const struct passwd *pass;
- static pstring home_dir;
- pass = Get_Pwnam(user, False);
-
- if (pass == NULL || pass->pw_dir == NULL) return(NULL);
-
- pstrcpy(home_dir, pass->pw_dir);
- DEBUG(10,("get_smbhome_dir: returning %s for user %s\n", home_dir, user));
- return home_dir;
-}
-
-
-/*******************************************************************
-map a username from a dos name to a unix name by looking in the username
-map. Note that this modifies the name in place.
-This is the main function that should be called *once* on
-any incoming or new username - in order to canonicalize the name.
-This is being done to de-couple the case conversions from the user mapping
-function. Previously, the map_username was being called
-every time Get_Pwnam was called.
-Returns True if username was changed, false otherwise.
-********************************************************************/
BOOL map_username(char *user)
{
static BOOL initialised=False;
@@ -420,38 +145,36 @@ BOOL map_username(char *user)
return mapped_user;
}
-
/****************************************************************************
Get_Pwnam wrapper
****************************************************************************/
+
static struct passwd *_Get_Pwnam(char *s)
{
- struct passwd *ret;
+ struct passwd *ret;
- ret = hashed_getpwnam(s);
+ ret = sys_getpwnam(s);
+ if (ret) {
#ifdef HAVE_GETPWANAM
- if (ret)
- {
- struct passwd_adjunct *pwret;
- pwret = getpwanam(s);
- if (pwret != NULL && pwret->pwa_passwd != NULL)
- {
- pstrcpy(ret->pw_passwd, pwret->pwa_passwd);
- }
- }
+ struct passwd_adjunct *pwret;
+ pwret = getpwanam(s);
+ if (pwret && pwret->pwa_passwd) {
+ pstrcpy(ret->pw_passwd,pwret->pwa_passwd);
+ }
#endif
+ }
- return ret;
+ return(ret);
}
+
/****************************************************************************
-a wrapper for getpwnam() that tries with all lower and all upper case
-if the initial name fails. Also tried with first letter capitalised
-Note that this can change user! Function returns const to emphasise
-the fact that most of the members of the struct passwd * returned are
-dynamically allocated.
+ A wrapper for getpwnam() that tries with all lower and all upper case
+ if the initial name fails. Also tried with first letter capitalised
+ Note that this can change user!
****************************************************************************/
-const struct passwd *Get_Pwnam(char *user,BOOL allow_change)
+
+struct passwd *Get_Pwnam(char *user,BOOL allow_change)
{
fstring user2;
int last_char;
@@ -469,33 +192,39 @@ const struct passwd *Get_Pwnam(char *user,BOOL allow_change)
}
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
strlower(user);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
strupper(user);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
- /* try with first letter capitalised */
+ /* Try with first letter capitalised. */
if (strlen(user) > 1)
strlower(user+1);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
/* try with last letter capitalised */
strlower(user);
last_char = strlen(user)-1;
user[last_char] = toupper(user[last_char]);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
- /* try all combinations up to usernamelevel */
+ /* Try all combinations up to usernamelevel. */
strlower(user);
ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
if (allow_change)
fstrcpy(user,user2);
@@ -504,8 +233,9 @@ const struct passwd *Get_Pwnam(char *user,BOOL allow_change)
}
/****************************************************************************
-check if a user is in a netgroup user list
+ Check if a user is in a netgroup user list.
****************************************************************************/
+
static BOOL user_in_netgroup_list(char *user,char *ngname)
{
#ifdef HAVE_NETGROUP
@@ -513,12 +243,9 @@ static BOOL user_in_netgroup_list(char *user,char *ngname)
if (mydomain == NULL)
yp_get_default_domain(&mydomain);
- if(mydomain == NULL)
- {
+ if(mydomain == NULL) {
DEBUG(5,("Unable to get default yp domain\n"));
- }
- else
- {
+ } else {
DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
user, mydomain, ngname));
DEBUG(5,("innetgr is %s\n",
@@ -533,78 +260,51 @@ static BOOL user_in_netgroup_list(char *user,char *ngname)
}
/****************************************************************************
-check if a user is in a UNIX user list
+ Check if a user is in a UNIX user list.
****************************************************************************/
+
static BOOL user_in_group_list(char *user,char *gname)
{
-#ifdef HAVE_GETGRNAM
- struct group *gptr;
- char **member;
- const struct passwd *pass = Get_Pwnam(user,False);
-
- if (pass)
- {
- gptr = getgrgid(pass->pw_gid);
- if (gptr && strequal(gptr->gr_name,gname))
- return(True);
- }
-
- gptr = (struct group *)getgrnam(gname);
-
- if (gptr)
- {
- member = gptr->gr_mem;
- while (member && *member)
- {
- if (strequal(*member,user))
- return(True);
- member++;
- }
- }
+#ifdef HAVE_GETGRENT
+ struct group *gptr;
+ char **member;
+ struct passwd *pass = Get_Pwnam(user,False);
+
+ if (pass) {
+ gptr = getgrgid(pass->pw_gid);
+ if (gptr && strequal(gptr->gr_name,gname))
+ return(True);
+ }
+
+ while ((gptr = (struct group *)getgrent())) {
+ if (!strequal(gptr->gr_name,gname))
+ continue;
+ member = gptr->gr_mem;
+ while (member && *member) {
+ if (strequal(*member,user)) {
+ endgrent();
+ return(True);
+ }
+ member++;
+ }
+ }
+
+ endgrent();
#endif /* HAVE_GETGRNAM */
- return False;
+ return False;
}
/****************************************************************************
-check if a username is valid
+ Check if a user is in a user list - can check combinations of UNIX
+ and netgroup lists.
****************************************************************************/
-BOOL user_ok(char *user,int snum)
-{
- pstring valid, invalid;
- BOOL ret;
-
- StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
- StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
-
- string_sub(valid,"%S",lp_servicename(snum));
- string_sub(invalid,"%S",lp_servicename(snum));
-
- ret = !user_in_list(user,invalid);
-
- if (ret && valid && *valid) {
- ret = user_in_list(user,valid);
- }
-
- if (ret && lp_onlyuser(snum)) {
- char *user_list = lp_username(snum);
- string_sub(user_list,"%S",lp_servicename(snum));
- ret = user_in_list(user,user_list);
- }
- return(ret);
-}
-
-/****************************************************************************
-check if a user is in a user list - can check combinations of UNIX
-and netgroup lists.
-****************************************************************************/
BOOL user_in_list(char *user,char *list)
{
pstring tok;
char *p=list;
- while (next_token(&p,tok,LIST_SEP, sizeof(tok)))
- {
+ while (next_token(&p,tok,LIST_SEP, sizeof(tok))) {
/*
* Check raw username.
*/
@@ -616,8 +316,7 @@ BOOL user_in_list(char *user,char *list)
* of UNIX and netgroups has been specified.
*/
- if(*tok == '@')
- {
+ if(*tok == '@') {
/*
* Old behaviour. Check netgroup list
* followed by UNIX list.
@@ -626,11 +325,9 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_group_list(user,&tok[1]))
return True;
- }
- else if (*tok == '+')
- {
- if(tok[1] == '&')
- {
+ } else if (*tok == '+') {
+
+ if(tok[1] == '&') {
/*
* Search UNIX list followed by netgroup.
*/
@@ -638,20 +335,20 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_netgroup_list(user,&tok[2]))
return True;
- }
- else
- {
+
+ } else {
+
/*
* Just search UNIX list.
*/
+
if(user_in_group_list(user,&tok[1]))
return True;
}
- }
- else if (*tok == '&')
- {
- if(tok[1] == '&')
- {
+
+ } else if (*tok == '&') {
+
+ if(tok[1] == '+') {
/*
* Search netgroup list followed by UNIX list.
*/
@@ -659,9 +356,7 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_group_list(user,&tok[2]))
return True;
- }
- else
- {
+ } else {
/*
* Just search netgroup list.
*/
@@ -675,15 +370,16 @@ BOOL user_in_list(char *user,char *list)
/* The functions below have been taken from password.c and slightly modified */
/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
+ Apply a function to upper/lower case combinations
+ of a string and return true if one of them returns true.
+ Try all combinations with N uppercase letters.
+ offset is the first char to try and change (start with 0)
+ it assumes the string starts lowercased
****************************************************************************/
+
static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(char *),int N)
{
- int len = strlen(s);
+ ssize_t len = (ssize_t)strlen(s);
int i;
struct passwd *ret;
@@ -694,36 +390,36 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw
if (N <= 0 || offset >= len)
return(fn(s));
-
- for (i=offset;i<(len-(N-1));i++)
-
- {
- char c = s[i];
- if (!islower(c)) continue;
- s[i] = toupper(c);
- ret = uname_string_combinations2(s,i+1,fn,N-1);
- if(ret) return(ret);
- s[i] = c;
- }
+ for (i=offset;i<(len-(N-1));i++) {
+ char c = s[i];
+ if (!islower(c))
+ continue;
+ s[i] = toupper(c);
+ ret = uname_string_combinations2(s,i+1,fn,N-1);
+ if(ret)
+ return(ret);
+ s[i] = c;
+ }
return(NULL);
}
/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with up to N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
+ Apply a function to upper/lower case combinations
+ of a string and return true if one of them returns true.
+ Try all combinations with up to N uppercase letters.
+ offset is the first char to try and change (start with 0)
+ it assumes the string starts lowercased
****************************************************************************/
+
static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(char *),int N)
{
int n;
struct passwd *ret;
- for (n=1;n<=N;n++)
- {
+ for (n=1;n<=N;n++) {
ret = uname_string_combinations2(s,0,fn,n);
- if(ret) return(ret);
+ if(ret)
+ return(ret);
}
return(NULL);
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 25769298be..8f904d486d 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -23,12 +23,34 @@
#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
#ifdef WITH_NISPLUS_HOME
-#include <rpcsvc/nis.h>
-#else
-#include "rpcsvc/ypclnt.h"
+#ifdef BROKEN_NISPLUS_INCLUDE_FILES
+/*
+ * The following lines are needed due to buggy include files
+ * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
+ * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
+ * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
+ * an enum in /usr/include/rpcsvc/nis.h.
+ */
+
+#if defined(GROUP)
+#undef GROUP
#endif
+
+#if defined(GROUP_OBJ)
+#undef GROUP_OBJ
#endif
+#endif /* BROKEN_NISPLUS_INCLUDE_FILES */
+
+#include <rpcsvc/nis.h>
+
+#else /* !WITH_NISPLUS_HOME */
+
+#include "rpcsvc/ypclnt.h"
+
+#endif /* WITH_NISPLUS_HOME */
+#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
+
#ifdef WITH_SSL
#include <ssl.h>
#undef Realloc /* SSLeay defines this and samba has a function of this name */
@@ -71,8 +93,7 @@ fstring local_machine="";
fstring remote_arch="UNKNOWN";
static enum remote_arch_types ra_type = RA_UNKNOWN;
fstring remote_proto="UNKNOWN";
-pstring myhostname="";
-pstring user_socket_options="";
+pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;
pstring sesssetup_user="";
pstring samlogon_user="";
@@ -85,23 +106,7 @@ char **my_netbios_names;
static char *filename_dos(char *path,char *buf);
-char *daynames[] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
-char *daynames_short[] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"};
-
-/*************************************************************
- initialise password databases, domain names, domain sid.
-**************************************************************/
-BOOL init_myworkgroup(void)
-{
- fstrcpy(global_myworkgroup, lp_workgroup());
- if (strequal(global_myworkgroup,"*"))
- {
- DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
- return False;
- }
- return True;
-}
/****************************************************************************
find a suitable temporary directory. The result should be copied immediately
@@ -135,39 +140,19 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
/****************************************************************************
-gets either a hex number (0xNNN) or decimal integer (NNN).
-****************************************************************************/
-uint32 get_number(const char *tmp)
-{
- if (strnequal(tmp, "0x", 2))
- {
- return strtoul(tmp, (char**)NULL, 16);
- }
- else
- {
- return strtoul(tmp, (char**)NULL, 10);
- }
-}
-
-/****************************************************************************
like atoi but gets the value up to the separater character
****************************************************************************/
char *Atoic(char *p, int *n, char *c)
{
- if (!isdigit(*p))
+ if (!isdigit((int)*p))
{
DEBUG(5, ("Atoic: malformed number\n"));
return NULL;
}
- (*n) = (int)get_number(p);
+ (*n) = atoi(p);
- if (strnequal(p, "0x", 2))
- {
- p += 2;
- }
-
- while ((*p) && isdigit(*p))
+ while ((*p) && isdigit((int)*p))
{
p++;
}
@@ -181,19 +166,6 @@ char *Atoic(char *p, int *n, char *c)
return p;
}
-uint32 *add_num_to_list(uint32 **num, int *count, int val)
-{
- (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
- if ((*num) == NULL)
- {
- return NULL;
- }
- (*num)[(*count)] = val;
- (*count)++;
-
- return (*num);
-}
-
/*************************************************************************
reads a list of numbers
*************************************************************************/
@@ -211,10 +183,13 @@ char *get_numlist(char *p, uint32 **num, int *count)
while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
{
- if (add_num_to_list(num, count, val) == NULL)
+ (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
+ if ((*num) == NULL)
{
return NULL;
}
+ (*num)[(*count)] = val;
+ (*count)++;
p++;
}
@@ -357,7 +332,7 @@ int name_mangle( char *In, char *Out, char name_type )
case '.':
p[0] = len;
p += (len + 1);
- len = 0;
+ len = -1;
break;
default:
p[len+1] = scope[i];
@@ -383,21 +358,6 @@ BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
}
/*******************************************************************
- rename a unix file
-********************************************************************/
-int file_rename(char *from, char *to)
-{
- int rcode = rename (from, to);
-
- if (errno == EXDEV)
- {
- /* Rename across filesystems needed. */
- rcode = copy_reg (from, to);
- }
- return rcode;
-}
-
-/*******************************************************************
check a files mod time
********************************************************************/
time_t file_modtime(char *fname)
@@ -432,7 +392,7 @@ BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
/*******************************************************************
returns the size in bytes of the named file
********************************************************************/
-SMB_OFF_T file_size(char *file_name)
+SMB_OFF_T get_file_size(char *file_name)
{
SMB_STRUCT_STAT buf;
buf.st_size = 0;
@@ -460,6 +420,8 @@ char *attrib_string(uint16 mode)
return(attrstr);
}
+
+
/****************************************************************************
make a file into unix format
****************************************************************************/
@@ -558,7 +520,7 @@ void smb_setlen(char *buf,int len)
int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
{
if (zero)
- bzero(buf + smb_size,num_words*2 + num_bytes);
+ memset(buf + smb_size,'\0',num_words*2 + num_bytes);
CVAL(buf,smb_wct) = num_words;
SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
@@ -605,8 +567,6 @@ int smb_offset(char *p,char *buf)
return(PTR_DIFF(p,buf+4) + chain_size);
}
-
-
/*******************************************************************
reduce a file name, removing .. elements.
********************************************************************/
@@ -617,7 +577,7 @@ void dos_clean_name(char *s)
DEBUG(3,("dos_clean_name [%s]\n",s));
/* remove any double slashes */
- string_sub(s, "\\\\", "\\");
+ all_string_sub(s, "\\\\", "\\", 0);
while ((p = strstr(s,"\\..\\")) != NULL)
{
@@ -635,7 +595,7 @@ void dos_clean_name(char *s)
trim_string(s,NULL,"\\..");
- string_sub(s, "\\.\\", "\\");
+ all_string_sub(s, "\\.\\", "\\", 0);
}
/*******************************************************************
@@ -648,7 +608,7 @@ void unix_clean_name(char *s)
DEBUG(3,("unix_clean_name [%s]\n",s));
/* remove any double slashes */
- string_sub(s, "//","/");
+ all_string_sub(s, "//","/", 0);
/* Remove leading ./ characters */
if(strncmp(s, "./", 2) == 0) {
@@ -676,7 +636,7 @@ void unix_clean_name(char *s)
/*******************************************************************
reduce a file name, removing .. elements and checking that
-it is below dir in the heirachy. This uses GetWd() and so must be run
+it is below dir in the heirachy. This uses dos_GetWd() and so must be run
on the system that has the referenced file system.
widelinks are allowed if widelinks is true
@@ -697,25 +657,25 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
*dir2 = *wd = *base_name = *newname = 0;
if (widelinks)
+ {
+ unix_clean_name(s);
+ /* can't have a leading .. */
+ if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
{
- unix_clean_name(s);
- /* can't have a leading .. */
- if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
- {
- DEBUG(3,("Illegal file name? (%s)\n",s));
- return(False);
- }
+ DEBUG(3,("Illegal file name? (%s)\n",s));
+ return(False);
+ }
- if (strlen(s) == 0)
- pstrcpy(s,"./");
+ if (strlen(s) == 0)
+ pstrcpy(s,"./");
- return(True);
- }
+ return(True);
+ }
DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
/* remove any double slashes */
- string_sub(s,"//","/");
+ all_string_sub(s,"//","/",0);
pstrcpy(base_name,s);
p = strrchr(base_name,'/');
@@ -724,53 +684,52 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
return(True);
if (!dos_GetWd(wd))
- {
- DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
- return(False);
- }
+ {
+ DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
+ return(False);
+ }
if (dos_ChDir(dir) != 0)
- {
- DEBUG(0,("couldn't chdir to %s\n",dir));
- return(False);
- }
+ {
+ DEBUG(0,("couldn't chdir to %s\n",dir));
+ return(False);
+ }
if (!dos_GetWd(dir2))
- {
- DEBUG(0,("couldn't getwd for %s\n",dir));
- dos_ChDir(wd);
- return(False);
- }
-
+ {
+ DEBUG(0,("couldn't getwd for %s\n",dir));
+ dos_ChDir(wd);
+ return(False);
+ }
- if (p && (p != base_name))
- {
- *p = 0;
- if (strcmp(p+1,".")==0)
- p[1]=0;
- if (strcmp(p+1,"..")==0)
- *p = '/';
- }
+ if (p && (p != base_name))
+ {
+ *p = 0;
+ if (strcmp(p+1,".")==0)
+ p[1]=0;
+ if (strcmp(p+1,"..")==0)
+ *p = '/';
+ }
if (dos_ChDir(base_name) != 0)
- {
- dos_ChDir(wd);
- DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
- return(False);
- }
+ {
+ dos_ChDir(wd);
+ DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
+ return(False);
+ }
if (!dos_GetWd(newname))
- {
- dos_ChDir(wd);
- DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
- return(False);
- }
+ {
+ dos_ChDir(wd);
+ DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
+ return(False);
+ }
if (p && (p != base_name))
- {
- pstrcat(newname,"/");
- pstrcat(newname,p+1);
- }
+ {
+ pstrcat(newname,"/");
+ pstrcat(newname,p+1);
+ }
{
size_t l = strlen(dir2);
@@ -778,19 +737,19 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
l--;
if (strncmp(newname,dir2,l) != 0)
- {
- dos_ChDir(wd);
- DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
- return(False);
- }
+ {
+ dos_ChDir(wd);
+ DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
+ return(False);
+ }
if (relative)
- {
- if (newname[l] == '/')
- pstrcpy(s,newname + l + 1);
- else
- pstrcpy(s,newname+l);
- }
+ {
+ if (newname[l] == '/')
+ pstrcpy(s,newname + l + 1);
+ else
+ pstrcpy(s,newname+l);
+ }
else
pstrcpy(s,newname);
}
@@ -918,7 +877,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,ti
else
memcpy(buf+1,mask2,MIN(strlen(mask2),11));
- bzero(buf+21,DIR_STRUCT_SIZE-21);
+ memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
CVAL(buf,21) = mode;
put_dos_date(buf,22,date);
SSVAL(buf,26,size & 0xFFFF);
@@ -1083,11 +1042,7 @@ static char *name_ptr(char *buf,int ofs)
if ((c & 0xC0) == 0xC0)
{
- uint16 l;
- char p[2];
- memcpy(p,buf+ofs,2);
- p[0] &= ~0xC0;
- l = RSVAL(p,0);
+ uint16 l = RSVAL(buf, ofs) & 0x3FFF;
DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
return(buf + l);
}
@@ -1148,7 +1103,7 @@ void msleep(int t)
FD_ZERO(&fds);
errno = 0;
- sys_select(0,&fds,NULL, &tval);
+ sys_select(0,&fds,&tval);
GetTimeOfDay(&t2);
tdiff = TvalDiff(&t1,&t2);
@@ -1161,7 +1116,8 @@ void msleep(int t)
* Does the actual matching. This is the 'original code'
* used by the unix matcher.
*********************************************************/
-static BOOL unix_do_match(char *str, char *regexp, int case_sig)
+
+BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
{
char *p;
@@ -1226,7 +1182,7 @@ static BOOL unix_do_match(char *str, char *regexp, int case_sig)
* This is the 'original code' used by the unix matcher.
*********************************************************/
-static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
{
char *p;
pstring p1, p2;
@@ -1286,9 +1242,14 @@ static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
* Recursive routine that is called by mask_match.
* Does the actual matching. Returns True if matched,
* False if failed. This is the 'new' NT style matcher.
+* The win9x_semantics parameter is needed as Win9x matching
+* is *actually different*. In Win9x, trailing '?' characters
+* will only match the *exact* number of characters. Under
+* DOS and NT they match any number. This makes no
+* sense.....
*********************************************************/
-BOOL do_match(char *str, char *regexp, int case_sig)
+static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
{
char *p;
@@ -1312,7 +1273,7 @@ BOOL do_match(char *str, char *regexp, int case_sig)
while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
str++;
str--; /* We've eaten the match char after the '*' */
- if(do_match(str,p,case_sig)) {
+ if(do_match(str,p,case_sig,win9x_semantics)) {
return True;
}
if(!*str) {
@@ -1345,10 +1306,12 @@ BOOL do_match(char *str, char *regexp, int case_sig)
return(True);
}
- if (!*str && *p == '?') {
- while (*p == '?')
- p++;
- return(!*p);
+ if (!win9x_semantics) {
+ if (!*str && *p == '?') {
+ while (*p == '?')
+ p++;
+ return(!*p);
+ }
}
if(!*str && (*p == '*' && p[1] == '\0')) {
@@ -1358,6 +1321,15 @@ BOOL do_match(char *str, char *regexp, int case_sig)
return False;
}
+/*********************************************************
+* Routine to check if a given string matches exactly.
+* Case can be significant or not.
+**********************************************************/
+
+BOOL exact_match(char *str, char *regexp, BOOL case_sig)
+{
+ return ((case_sig?strcmp(str,regexp):strcasecmp(str,regexp)) == 0);
+}
/*********************************************************
* Routine to match a given string with a regexp - uses
@@ -1367,18 +1339,37 @@ BOOL do_match(char *str, char *regexp, int case_sig)
* This is the new 'NT style' matcher.
*********************************************************/
-BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
{
char *p;
pstring t_pattern, t_filename, te_pattern, te_filename;
fstring ebase,eext,sbase,sext;
-
BOOL matched = False;
+ BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
+
+ /* special case - if it is exactly the same then it always matches! */
+ if(exact_match(str, regexp, case_sig))
+ return True;
/* Make local copies of str and regexp */
pstrcpy(t_pattern,regexp);
pstrcpy(t_filename,str);
+ if(trans2) {
+
+ /* a special case for 16 bit apps */
+ if (strequal(t_pattern,"????????.???"))
+ pstrcpy(t_pattern,"*");
+
+#if 0
+ /*
+ * Handle broken clients that send us old 8.3 format.
+ */
+ pstring_sub(t_pattern,"????????","*");
+ pstring_sub(t_pattern,".???",".*");
+#endif
+ }
+
#if 0
/*
* Not sure if this is a good idea. JRA.
@@ -1394,8 +1385,8 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
#endif
/* Remove any *? and ** as they are meaningless */
- string_sub(t_pattern, "*?", "*");
- string_sub(t_pattern, "**", "*");
+ pstring_sub(t_pattern, "*?", "*");
+ pstring_sub(t_pattern, "**", "*");
if (strequal(t_pattern,"*"))
return(True);
@@ -1416,7 +1407,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
/*
* Remove multiple "*." patterns.
*/
- string_sub(te_pattern, "*.*.", "*.");
+ pstring_sub(te_pattern, "*.*.", "*.");
num_regexp_components = count_chars(te_pattern, '.');
num_path_components = count_chars(te_filename, '.');
@@ -1424,7 +1415,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
* Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
*/
if(num_regexp_components == 0)
- matched = do_match( te_filename, te_pattern, case_sig);
+ matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
else {
for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
fp = strchr(cp2, '.');
@@ -1434,14 +1425,24 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
if(rp)
*rp = '\0';
- if(cp1[strlen(cp1)-1] == '*')
+ if(cp1[0] && cp1[strlen(cp1)-1] == '*')
last_wcard_was_star = True;
else
last_wcard_was_star = False;
- if(!do_match(cp2, cp1, case_sig))
+ if(!do_match(cp2, cp1, case_sig, win9x_semantics))
break;
+ /*
+ * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
+ * is '*' or all '?' then disallow match.
+ */
+
+ if (win9x_semantics) {
+ if (*cp2 == '\0' && str_is_all(cp1, '?'))
+ break;
+ }
+
cp1 = rp ? rp + 1 : NULL;
cp2 = fp ? fp + 1 : "";
@@ -1454,7 +1455,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
if(fp)
*fp = '\0';
- if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
+ if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
cp2 = fp ? fp + 1 : "";
break;
}
@@ -1475,19 +1476,21 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
*/
if (strequal (t_filename, ".")) {
/*
- * Patterns: *.* *. ?. ? are valid
- *
+ * Patterns: *.* *. ?. ? ????????.??? are valid.
+ *
*/
if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
- strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
+ strequal(t_pattern, "????????.???") ||
+ strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
matched = True;
} else if (strequal (t_filename, "..")) {
/*
- * Patterns: *.* *. ?. ? *.? are valid
+ * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
*
*/
if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
+ strequal(t_pattern, "????????.???") ||
strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
matched = True;
} else {
@@ -1531,12 +1534,12 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
fstrcpy (sbase, t_filename);
fstrcpy (sext, p + 1);
if (*eext) {
- matched = do_match(sbase, ebase, case_sig)
- && do_match(sext, eext, case_sig);
+ matched = do_match(sbase, ebase, case_sig, False)
+ && do_match(sext, eext, case_sig, False);
} else {
/* pattern has no extension */
/* Really: match complete filename with pattern ??? means exactly 3 chars */
- matched = do_match(str, ebase, case_sig);
+ matched = do_match(str, ebase, case_sig, False);
}
} else {
/*
@@ -1546,10 +1549,11 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
fstrcpy (sext, "");
if (*eext) {
/* pattern has extension */
- matched = do_match(sbase, ebase, case_sig)
- && do_match(sext, eext, case_sig);
+ matched = do_match(sbase, ebase, case_sig, False)
+ && do_match(sext, eext, case_sig, False);
+
} else {
- matched = do_match(sbase, ebase, case_sig);
+ matched = do_match(sbase, ebase, case_sig, False);
#ifdef EMULATE_WEIRD_W95_MATCHING
/*
* Even Microsoft has some problems
@@ -1560,7 +1564,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
if (!matched) {
/* a? matches aa and a in w95 */
fstrcat (sbase, ".");
- matched = do_match(sbase, ebase, case_sig);
+ matched = do_match(sbase, ebase, case_sig, False);
}
#endif
}
@@ -1617,12 +1621,11 @@ BOOL yesno(char *p)
return(False);
}
-
-
/****************************************************************************
set the length of a file from a filedescriptor.
Returns 0 on success, -1 on failure.
****************************************************************************/
+
int set_filelen(int fd, SMB_OFF_T len)
{
/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
@@ -1646,7 +1649,8 @@ int set_filelen(int fd, SMB_OFF_T len)
return -1;
#ifdef S_ISFIFO
- if (S_ISFIFO(st.st_mode)) return 0;
+ if (S_ISFIFO(st.st_mode))
+ return 0;
#endif
if(st.st_size == len)
@@ -1720,7 +1724,7 @@ void *Realloc(void *p,size_t size)
#endif
if (!ret)
- DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
+ DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
return(ret);
}
@@ -1729,40 +1733,30 @@ void *Realloc(void *p,size_t size)
/****************************************************************************
get my own name and IP
****************************************************************************/
-BOOL get_myname(char *my_name,struct in_addr *ip)
+BOOL get_myname(char *my_name)
{
- struct hostent *hp;
- pstring hostname;
-
- *hostname = 0;
-
- /* get my host name */
- if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
- {
- DEBUG(0,("gethostname failed\n"));
- return False;
- }
-
- /* get host info */
- if ((hp = Get_Hostbyname(hostname)) == 0)
- {
- DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
- return False;
- }
+ pstring hostname;
- if (my_name)
- {
- /* split off any parts after an initial . */
- char *p = strchr(hostname,'.');
- if (p) *p = 0;
+ *hostname = 0;
- fstrcpy(my_name,hostname);
- }
+ /* get my host name */
+ if (gethostname(hostname, sizeof(hostname)) == -1) {
+ DEBUG(0,("gethostname failed\n"));
+ return False;
+ }
- if (ip)
- putip((char *)ip,(char *)hp->h_addr);
+ /* Ensure null termination. */
+ hostname[sizeof(hostname)-1] = '\0';
- return(True);
+ if (my_name) {
+ /* split off any parts after an initial . */
+ char *p = strchr(hostname,'.');
+ if (p) *p = 0;
+
+ fstrcpy(my_name,hostname);
+ }
+
+ return(True);
}
@@ -1771,10 +1765,7 @@ true if two IP addresses are equal
****************************************************************************/
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
{
- uint32 a1,a2;
- a1 = ntohl(ip1.s_addr);
- a2 = ntohl(ip2.s_addr);
- return(a1 == a2);
+ return ip1.s_addr == ip2.s_addr;
}
@@ -1801,26 +1792,39 @@ int interpret_protocol(char *str,int def)
return(def);
}
+/****************************************************************************
+ Return true if a string could be a pure IP address.
+****************************************************************************/
+
+BOOL is_ipaddress(const char *str)
+{
+ BOOL pure_address = True;
+ int i;
+
+ for (i=0; pure_address && str[i]; i++)
+ if (!(isdigit((int)str[i]) || str[i] == '.'))
+ pure_address = False;
+
+ /* Check that a pure number is not misinterpreted as an IP */
+ pure_address = pure_address && (strchr(str, '.') != NULL);
+
+ return pure_address;
+}
/****************************************************************************
interpret an internet address or name into an IP address in 4 byte form
****************************************************************************/
+
uint32 interpret_addr(char *str)
{
struct hostent *hp;
uint32 res;
- int i;
- BOOL pure_address = True;
if (strcmp(str,"0.0.0.0") == 0) return(0);
if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
- for (i=0; pure_address && str[i]; i++)
- if (!(isdigit((int)str[i]) || str[i] == '.'))
- pure_address = False;
-
/* if it's in the form of an IP address then get the lib to interpret it */
- if (pure_address) {
+ if (is_ipaddress(str)) {
res = inet_addr(str);
} else {
/* otherwise assume it's a network name of some sort and use
@@ -1872,7 +1876,7 @@ BOOL matchname(char *remotehost,struct in_addr addr)
int i;
if ((hp = Get_Hostbyname(remotehost)) == 0) {
- DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
+ DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
return False;
}
@@ -1886,7 +1890,7 @@ BOOL matchname(char *remotehost,struct in_addr addr)
if (strcasecmp(remotehost, hp->h_name)
&& strcasecmp(remotehost, "localhost")) {
- DEBUG(0,("host name/name mismatch: %s != %s",
+ DEBUG(0,("host name/name mismatch: %s != %s\n",
remotehost, hp->h_name));
return False;
}
@@ -1903,7 +1907,7 @@ BOOL matchname(char *remotehost,struct in_addr addr)
* it, but that could be dangerous, too.
*/
- DEBUG(0,("host name/address mismatch: %s != %s",
+ DEBUG(0,("host name/address mismatch: %s != %s\n",
inet_ntoa(addr), hp->h_name));
return False;
}
@@ -1981,7 +1985,7 @@ static char *automount_lookup(char *user_name)
DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
- string_sub(last_value, "&", user_name);
+ pstring_sub(last_value, "&", user_name);
fstrcpy(last_key, user_name);
}
}
@@ -2091,8 +2095,8 @@ static char *automount_path(char *user_name)
/* use the passwd entry as the default */
/* this will be the default if WITH_AUTOMOUNT is not used or fails */
- /* pstrcpy() copes with get_unixhome_dir() returning NULL */
- pstrcpy(server_path, get_unixhome_dir(user_name));
+ /* pstrcpy() copes with get_user_home_dir() returning NULL */
+ pstrcpy(server_path, get_user_home_dir(user_name));
#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
@@ -2115,92 +2119,114 @@ static char *automount_path(char *user_name)
return server_path;
}
+/*******************************************************************
+ Given a pointer to a %$(NAME) expand it as an environment variable.
+ Return the number of characters by which the pointer should be advanced.
+ Based on code by Branko Cibej <branko.cibej@hermes.si>
+ When this is called p points at the '%' character.
+********************************************************************/
+
+static size_t expand_env_var(char *p, int len)
+{
+ fstring envname;
+ char *envval;
+ char *q, *r;
+ int copylen;
+
+ if (p[1] != '$')
+ return 1;
+
+ if (p[2] != '(')
+ return 2;
+
+ /*
+ * Look for the terminating ')'.
+ */
+
+ if ((q = strchr(p,')')) == NULL) {
+ DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
+ return 2;
+ }
+
+ /*
+ * Extract the name from within the %$(NAME) string.
+ */
+
+ r = p+3;
+ copylen = MIN((q-r),(sizeof(envname)-1));
+ strncpy(envname,r,copylen);
+ envname[copylen] = '\0';
+
+ if ((envval = getenv(envname)) == NULL) {
+ DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
+ return 2;
+ }
+
+ /*
+ * Copy the full %$(NAME) into envname so it
+ * can be replaced.
+ */
+
+ copylen = MIN((q+1-p),(sizeof(envname)-1));
+ strncpy(envname,p,copylen);
+ envname[copylen] = '\0';
+ string_sub(p,envname,envval,len);
+ return 0; /* Allow the environment contents to be parsed. */
+}
/*******************************************************************
-sub strings with useful parameters
-Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
-Paul Rippin <pr3245@nopc.eurostat.cec.be>
+ Substitute strings with useful parameters.
+ Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
+ Paul Rippin <pr3245@nopc.eurostat.cec.be>.
********************************************************************/
+
void standard_sub_basic(char *str)
{
char *s, *p;
char pidstr[10];
- const struct passwd *pass;
+ struct passwd *pass;
char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
{
+ int l = sizeof(pstring) - (int)(p-str);
+
+ if (l < 0) {
+ DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n",
+ -l, str));
+
+ return;
+ }
+
switch (*(p+1))
{
case 'G' :
{
- if ((pass = Get_Pwnam(username,False))!=NULL)
- {
- string_sub(p,"%G",gidtoname(pass->pw_gid));
- }
- else
- {
+ if ((pass = Get_Pwnam(username,False))!=NULL) {
+ string_sub(p,"%G",gidtoname(pass->pw_gid),l);
+ } else {
p += 2;
}
break;
}
- case 'N' : string_sub(p,"%N", automount_server(username)); break;
- case 'I' : string_sub(p,"%I", client_addr(Client)); break;
- case 'L' : string_sub(p,"%L", local_machine); break;
- case 'M' : string_sub(p,"%M", client_name(Client)); break;
- case 'R' : string_sub(p,"%R", remote_proto); break;
- case 'T' : string_sub(p,"%T", timestring()); break;
- case 'U' : string_sub(p,"%U", username); break;
- case 'a' : string_sub(p,"%a", remote_arch); break;
+ case 'N' : string_sub(p,"%N", automount_server(username),l); break;
+ case 'I' : string_sub(p,"%I", client_addr(Client),l); break;
+ case 'L' : string_sub(p,"%L", local_machine,l); break;
+ case 'M' : string_sub(p,"%M", client_name(Client),l); break;
+ case 'R' : string_sub(p,"%R", remote_proto,l); break;
+ case 'T' : string_sub(p,"%T", timestring(False),l); break;
+ case 'U' : string_sub(p,"%U", username,l); break;
+ case 'a' : string_sub(p,"%a", remote_arch,l); break;
case 'd' :
{
slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
- string_sub(p,"%d", pidstr);
- break;
- }
- case 'h' : string_sub(p,"%h", myhostname); break;
- case 'm' : string_sub(p,"%m", remote_machine); break;
- case 'v' : string_sub(p,"%v", VERSION); break;
- case '$' : /* Expand environment variables */
- {
- /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
- fstring envname;
- char *envval;
- char *q, *r;
- int copylen;
-
- if (*(p+2) != '(')
- {
- p+=2;
- break;
- }
- if ((q = strchr(p,')')) == NULL)
- {
- DEBUG(0,("standard_sub_basic: Unterminated environment \
- variable [%s]\n", p));
- p+=2;
- break;
- }
-
- r = p+3;
- copylen = MIN((q-r),(sizeof(envname)-1));
- strncpy(envname,r,copylen);
- envname[copylen] = '\0';
-
- if ((envval = getenv(envname)) == NULL)
- {
- DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
- envname));
- p+=2;
- break;
- }
-
- copylen = MIN((q+1-p),(sizeof(envname)-1));
- strncpy(envname,p,copylen);
- envname[copylen] = '\0';
- string_sub(p,envname,envval);
+ string_sub(p,"%d", pidstr,l);
break;
}
+ case 'h' : string_sub(p,"%h", myhostname(),l); break;
+ case 'm' : string_sub(p,"%m", remote_machine,l); break;
+ case 'v' : string_sub(p,"%v", VERSION,l); break;
+ case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
case '\0': p++; break; /* don't run off end if last character is % */
default : p+=2; break;
}
@@ -2210,24 +2236,42 @@ void standard_sub_basic(char *str)
/****************************************************************************
-do some standard substitutions in a string
+ Do some standard substitutions in a string.
****************************************************************************/
+
void standard_sub(connection_struct *conn,char *str)
{
char *p, *s, *home;
- for (s=str; (p=strchr(s, '%'));s=p)
- {
- switch (*(p+1))
- {
- case 'H':
- if ((home = get_unixhome_dir(conn->user)) != NULL) {
- string_sub(p,"%H",home);
- } else {
- p += 2;
- }
- break;
-
+ for (s=str; (p=strchr(s, '%'));s=p) {
+ int l = sizeof(pstring) - (int)(p-str);
+
+ switch (*(p+1)) {
+ case 'H':
+ if ((home = get_user_home_dir(conn->user))) {
+ string_sub(p,"%H",home,l);
+ } else {
+ p += 2;
+ }
+ break;
+
+ case 'P':
+ string_sub(p,"%P",conn->connectpath,l);
+ break;
+
+ case 'S':
+ string_sub(p,"%S",
+ lp_servicename(SNUM(conn)),l);
+ break;
+
+ case 'g':
+ string_sub(p,"%g",
+ gidtoname(conn->gid),l);
+ break;
+ case 'u':
+ string_sub(p,"%u",conn->user,l);
+ break;
+
/* Patch from jkf@soton.ac.uk Left the %N (NIS
* server name) in standard_sub_basic as it is
* a feature for logon servers, hence uses the
@@ -2235,14 +2279,17 @@ void standard_sub(connection_struct *conn,char *str)
* here as it is used instead of the default
* "path =" string in [homes] and so needs the
* service name, not the username. */
- case 'p': string_sub(p,"%p", automount_path(lp_servicename(SNUM(conn)))); break;
- case 'P': string_sub(p,"%P",conn->connectpath); break;
- case 'S': string_sub(p,"%S", lp_servicename(SNUM(conn))); break;
- case 'g': string_sub(p,"%g", gidtoname(conn->gid)); break;
- case 'u': string_sub(p,"%u", conn->user); break;
-
- case '\0': p++; break; /* don't run off the end of the string */
- default : p+=2; break;
+ case 'p':
+ string_sub(p,"%p",
+ automount_path(lp_servicename(SNUM(conn))),l);
+ break;
+ case '\0':
+ p++;
+ break; /* don't run off the end of the string
+ */
+
+ default: p+=2;
+ break;
}
}
@@ -2331,131 +2378,24 @@ struct hostent *Get_Hostbyname(const char *name)
check if a process exists. Does this work on all unixes?
****************************************************************************/
-BOOL process_exists(int pid)
+BOOL process_exists(pid_t pid)
{
return(kill(pid,0) == 0 || errno != ESRCH);
}
-/****************************************************************************
-Setup the groups a user belongs to.
-****************************************************************************/
-int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups)
+/*******************************************************************
+turn a uid into a user name
+********************************************************************/
+char *uidtoname(uid_t uid)
{
- int i,ngroups;
- gid_t grp = 0;
- gid_t *groups = NULL;
-
- if (-1 == initgroups(user,gid))
- {
- if (getuid() == 0)
- {
- DEBUG(0,("Unable to initgroups!\n"));
- if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
- {
- DEBUG(0,("This is probably a problem with the account %s\n", user));
- }
- }
- return -1;
- }
-
- ngroups = sys_getgroups(0,&grp);
- if (ngroups <= 0)
- {
- ngroups = 32;
- }
-
- if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL)
- {
- DEBUG(0,("get_unixgroups malloc fail !\n"));
- return -1;
- }
-
- ngroups = sys_getgroups(ngroups,groups);
-
- (*p_ngroups) = ngroups;
- (*p_groups) = groups;
-
- DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) );
- for (i = 0; i < ngroups; i++ )
- {
- DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
- }
- DEBUG( 3, ( "\n" ) );
-
- return 0;
+ static char name[40];
+ struct passwd *pass = sys_getpwuid(uid);
+ if (pass) return(pass->pw_name);
+ slprintf(name, sizeof(name) - 1, "%d",(int)uid);
+ return(name);
}
-/****************************************************************************
-get all unix groups. copying group members is hideous on memory, so it's
-NOT done here. however, names of unix groups _are_ string-allocated so
-free_unix_grps() must be called.
-****************************************************************************/
-BOOL get_unix_grps(int *p_ngroups, struct group **p_groups)
-{
- struct group *grp;
-
- DEBUG(10,("get_unix_grps\n"));
-
- if (p_ngroups == NULL || p_groups == NULL)
- {
- return False;
- }
-
- (*p_ngroups) = 0;
- (*p_groups) = NULL;
-
- setgrent();
-
- while ((grp = getgrent()) != NULL)
- {
- struct group *copy_grp;
-
- (*p_groups) = (struct group*)Realloc((*p_groups), (size_t)((*p_ngroups)+1) * sizeof(struct group));
- if ((*p_groups) == NULL)
- {
- (*p_ngroups) = 0;
- endgrent();
-
- return False;
- }
-
- copy_grp = &(*p_groups)[*p_ngroups];
- memcpy(copy_grp, grp, sizeof(*grp));
- copy_grp->gr_name = strdup(copy_grp->gr_name);
- copy_grp->gr_mem = NULL;
-
- (*p_ngroups)++;
- }
-
- endgrent();
-
- DEBUG(10,("get_unix_grps: %d groups\n", (*p_ngroups)));
- return True;
-}
-
-/****************************************************************************
-free memory associated with unix groups.
-****************************************************************************/
-void free_unix_grps(int ngroups, struct group *p_groups)
-{
- int i;
-
- if (p_groups == NULL)
- {
- return;
- }
-
- for (i = 0; i < ngroups; i++)
- {
- if (p_groups[i].gr_name != NULL)
- {
- free(p_groups[i].gr_name);
- }
- }
-
- free(p_groups);
-}
/*******************************************************************
turn a gid into a group name
@@ -2471,48 +2411,37 @@ char *gidtoname(gid_t gid)
}
/*******************************************************************
-turn a group name into a gid
+turn a user name into a uid
********************************************************************/
-
-BOOL nametogid(const char *name, gid_t *gid)
+uid_t nametouid(const char *name)
{
- struct group *grp = getgrnam(name);
- if (grp)
- {
- *gid = grp->gr_gid;
- return True;
- }
- else if (isdigit(name[0]))
- {
- *gid = (gid_t)get_number(name);
- return True;
- }
- else
- {
- return False;
- }
+ struct passwd *pass;
+ char *p;
+ uid_t u;
+
+ u = strtol(name, &p, 0);
+ if (p != name) return u;
+
+ pass = sys_getpwnam(name);
+ if (pass) return(pass->pw_uid);
+ return (uid_t)-1;
}
/*******************************************************************
-turn a user name into a uid
+turn a group name into a gid
********************************************************************/
-BOOL nametouid(const char *name, uid_t *uid)
+gid_t nametogid(const char *name)
{
- const struct passwd *pass = Get_Pwnam(name, False);
- if (pass)
- {
- *uid = pass->pw_uid;
- return True;
- }
- else if (isdigit(name[0]))
- {
- *uid = (uid_t)get_number(name);
- return True;
- }
- else
- {
- return False;
- }
+ struct group *grp;
+ char *p;
+ gid_t g;
+
+ g = strtol(name, &p, 0);
+ if (p != name) return g;
+
+ grp = getgrnam(name);
+ if (grp) return(grp->gr_gid);
+ return (gid_t)-1;
}
/*******************************************************************
@@ -2535,12 +2464,12 @@ a readdir wrapper which just returns the file name
********************************************************************/
char *readdirname(DIR *p)
{
- struct dirent *ptr;
+ SMB_STRUCT_DIRENT *ptr;
char *dname;
if (!p) return(NULL);
- ptr = (struct dirent *)readdir(p);
+ ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
if (!ptr) return(NULL);
dname = ptr->d_name;
@@ -2731,13 +2660,55 @@ void free_namearray(name_compare_entry *name_array)
}
/****************************************************************************
+ Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
+****************************************************************************/
+
+uint32 map_lock_offset(uint32 high, uint32 low)
+{
+ unsigned int i;
+ uint32 mask = 0;
+ uint32 highcopy = high;
+
+ /*
+ * Try and find out how many significant bits there are in high.
+ */
+
+ for(i = 0; highcopy; i++)
+ highcopy >>= 1;
+
+ /*
+ * We use 31 bits not 32 here as POSIX
+ * lock offsets may not be negative.
+ */
+
+ mask = (~0) << (31 - i);
+
+ if(low & mask)
+ return 0; /* Fail. */
+
+ high <<= (31 - i);
+
+ return (high|low);
+}
+
+/****************************************************************************
routine to do file locking
****************************************************************************/
+
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
#if HAVE_FCNTL_LOCK
SMB_STRUCT_FLOCK lock;
int ret;
+#if defined(LARGE_SMB_OFF_T)
+ /*
+ * In the 64 bit locking case we store the original
+ * values in case we have to map to a 32 bit lock on
+ * a filesystem that doesn't support 64 bit locks.
+ */
+ SMB_OFF_T orig_offset = offset;
+ SMB_OFF_T orig_count = count;
+#endif /* LARGE_SMB_OFF_T */
if(lp_ole_locking_compat()) {
SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
@@ -2794,7 +2765,7 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
}
/* 32 bit NFS file system, retry with smaller offset */
errno = 0;
- lock.l_len = count & 0xffffffff;
+ lock.l_len = count & 0x7fffffff;
ret = fcntl(fd,op,&lock);
}
@@ -2826,8 +2797,38 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
/* perhaps it doesn't support this sort of locking?? */
if (errno == EINVAL)
{
+
+#if defined(LARGE_SMB_OFF_T)
+ {
+ /*
+ * Ok - if we get here then we have a 64 bit lock request
+ * that has returned EINVAL. Try and map to 31 bits for offset
+ * and length and try again. This may happen if a filesystem
+ * doesn't support 64 bit offsets (efs/ufs) although the underlying
+ * OS does.
+ */
+ uint32 off_low = (orig_offset & 0xFFFFFFFF);
+ uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
+
+ lock.l_len = (orig_count & 0x7FFFFFFF);
+ lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
+ ret = fcntl(fd,op,&lock);
+ if (ret == -1)
+ {
+ if (errno == EINVAL)
+ {
+ DEBUG(3,("locking not supported? returning True\n"));
+ return(True);
+ }
+ return False;
+ }
+ DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
+ return True;
+ }
+#else /* LARGE_SMB_OFF_T */
DEBUG(3,("locking not supported? returning True\n"));
return(True);
+#endif /* LARGE_SMB_OFF_T */
}
return(False);
@@ -2879,6 +2880,9 @@ void set_remote_arch(enum remote_arch_types type)
case RA_WINNT:
fstrcpy(remote_arch, "WinNT");
return;
+ case RA_WIN2K:
+ fstrcpy(remote_arch, "Win2K");
+ return;
case RA_SAMBA:
fstrcpy(remote_arch,"Samba");
return;
@@ -2899,30 +2903,18 @@ enum remote_arch_types get_remote_arch(void)
/*******************************************************************
- align a pointer to a multiple of 4 bytes.
- ********************************************************************/
-char *align4(char *q, char *base)
-{
- int mod = PTR_DIFF(q, base) & 3;
- if (mod != 0)
- {
- q += mod;
- }
- return q;
-}
-/*******************************************************************
align a pointer to a multiple of 2 bytes
********************************************************************/
char *align2(char *q, char *base)
{
- if (PTR_DIFF(q, base) & 1)
+ if ((q - base) & 1)
{
q++;
}
return q;
}
-void out_ascii(FILE *f, const unsigned char *buf,int len)
+void out_ascii(FILE *f, unsigned char *buf,int len)
{
int i;
for (i=0;i<len;i++)
@@ -2931,36 +2923,9 @@ void out_ascii(FILE *f, const unsigned char *buf,int len)
}
}
-void out_struct(FILE *f, const char *buf1,int len, int per_line)
-{
- const unsigned char *buf = (const unsigned char *)buf1;
- int i;
-
- if (len<=0)
- {
- return;
- }
-
- fprintf(f, "{\n\t");
- for (i=0;i<len;)
- {
- fprintf(f, "0x%02X",(int)buf[i]);
- i++;
- if (i != len)
- {
- fprintf(f, ", ");
- }
- if (i%per_line == 0 && i != len)
- {
- fprintf(f, "\n\t");
- }
- }
- fprintf(f, "\n};\n");
-}
-
-void out_data(FILE *f, const char *buf1,int len, int per_line)
+void out_data(FILE *f,char *buf1,int len, int per_line)
{
- const unsigned char *buf = (const unsigned char *)buf1;
+ unsigned char *buf = (unsigned char *)buf1;
int i=0;
if (len<=0)
{
@@ -2999,55 +2964,44 @@ void out_data(FILE *f, const char *buf1,int len, int per_line)
}
}
-void print_asc(int level, unsigned char const *buf,int len)
+void print_asc(int level, unsigned char *buf,int len)
{
int i;
for (i=0;i<len;i++)
- {
- DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
- }
+ DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
}
-void dump_data(int level, const char *buf1, int len)
+void dump_data(int level,char *buf1,int len)
{
- unsigned char const *buf = (unsigned char const *)buf1;
- int i=0;
- if (len<0) return;
- if (len == 0)
- {
- DEBUG(level,("\n"));
- return;
- }
-
- DEBUG(level,("[%03X] ",i));
- for (i=0;i<len;)
- {
- DEBUGADD(level,("%02X ",(int)buf[i]));
- i++;
- if (i%8 == 0) DEBUGADD(level,(" "));
- if (i%16 == 0)
- {
- print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
- print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
- if (i<len) DEBUGADD(level,("[%03X] ",i));
- }
- }
+ unsigned char *buf = (unsigned char *)buf1;
+ int i=0;
+ if (len<=0) return;
- if (i%16 != 0) /* finish off a non-16-char-length row */
- {
- int n;
-
- n = 16 - (i%16);
- DEBUGADD(level,(" "));
- if (n>8) DEBUGADD(level,(" "));
- while (n--) DEBUGADD(level,(" "));
-
- n = MIN(8,i%16);
- print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,(" "));
- n = (i%16) - n;
- if (n>0) print_asc(level,&buf[i-n],n);
- DEBUGADD(level,("\n"));
- }
+ DEBUG(level,("[%03X] ",i));
+ for (i=0;i<len;) {
+ DEBUG(level,("%02X ",(int)buf[i]));
+ i++;
+ if (i%8 == 0) DEBUG(level,(" "));
+ if (i%16 == 0) {
+ print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
+ print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
+ if (i<len) DEBUG(level,("[%03X] ",i));
+ }
+ }
+ if (i%16) {
+ int n;
+
+ n = 16 - (i%16);
+ DEBUG(level,(" "));
+ if (n>8) DEBUG(level,(" "));
+ while (n--) DEBUG(level,(" "));
+
+ n = MIN(8,i%16);
+ print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
+ n = (i%16) - n;
+ if (n>0) print_asc(level,&buf[i-n],n);
+ DEBUG(level,("\n"));
+ }
}
char *tab_depth(int depth)
@@ -3102,16 +3056,50 @@ int set_maxfiles(int requested_max)
{
#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
struct rlimit rlp;
- getrlimit(RLIMIT_NOFILE, &rlp);
- /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
+ int saved_current_limit;
+
+ if(getrlimit(RLIMIT_NOFILE, &rlp)) {
+ DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
+ strerror(errno) ));
+ /* just guess... */
+ return requested_max;
+ }
+
+ /*
+ * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
* account for the extra fd we need
* as well as the log files and standard
- * handles etc. */
- rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
- setrlimit(RLIMIT_NOFILE, &rlp);
- getrlimit(RLIMIT_NOFILE, &rlp);
+ * handles etc. Save the limit we want to set in case
+ * we are running on an OS that doesn't support this limit (AIX)
+ * which always returns RLIM_INFINITY for rlp.rlim_max.
+ */
+
+ saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
+
+ if(setrlimit(RLIMIT_NOFILE, &rlp)) {
+ DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
+ (int)rlp.rlim_cur, strerror(errno) ));
+ /* just guess... */
+ return saved_current_limit;
+ }
+
+ if(getrlimit(RLIMIT_NOFILE, &rlp)) {
+ DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
+ strerror(errno) ));
+ /* just guess... */
+ return saved_current_limit;
+ }
+
+#if defined(RLIM_INFINITY)
+ if(rlp.rlim_cur == RLIM_INFINITY)
+ return saved_current_limit;
+#endif
+
+ if((int)rlp.rlim_cur > saved_current_limit)
+ return saved_current_limit;
+
return rlp.rlim_cur;
-#else
+#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
/*
* No way to know - just guess...
*/
@@ -3131,11 +3119,11 @@ void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
/*****************************************************************
splits out the start of the key (HKLM or HKU) and the rest of the key
*****************************************************************/
-BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name)
+BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
{
pstring tmp;
- if (!next_token((char**)(&full_keyname), tmp, "\\", sizeof(tmp)))
+ if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
{
return False;
}
@@ -3144,15 +3132,7 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name)
DEBUG(10, ("reg_split_key: hive %s\n", tmp));
- if (strequal(tmp, "HKCR") || strequal(tmp, "HKEY_CLASSES_ROOT"))
- {
- (*reg_type) = HKEY_CLASSES_ROOT;
- }
- else if (strequal(tmp, "HKCU") || strequal(tmp, "HKEY_CURRENT_USER"))
- {
- (*reg_type) = HKEY_CURRENT_USER;
- }
- else if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
+ if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
{
(*reg_type) = HKEY_LOCAL_MACHINE;
}
@@ -3180,326 +3160,56 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name)
return True;
}
-/****************************************************************************
- become the specified uid - permanently !
-****************************************************************************/
-BOOL become_user_permanently(uid_t uid, gid_t gid)
-{
- /* now completely lose our privilages. This is a fairly paranoid
- way of doing it, but it does work on all systems that I know of */
-
-#ifdef HAVE_SETRESUID
- /*
- * Firstly ensure all our uids are set to root.
- */
- setresgid(0,0,0);
- setresuid(0,0,0);
-
- /*
- * Now ensure we change all our gids.
- */
- setresgid(gid,gid,gid);
-
- /*
- * Now ensure all the uids are the user.
- */
- setresuid(uid,uid,uid);
-#else
- /*
- * Firstly ensure all our uids are set to root.
- */
- setuid(0);
- seteuid(0);
-
- /*
- * Now ensure we change all our gids.
- */
- setgid(gid);
- setegid(gid);
-
- /*
- * Now ensure all the uids are the user.
- */
- setuid(uid);
- seteuid(uid);
-#endif
-
- if (getuid() != uid || geteuid() != uid ||
- getgid() != gid || getegid() != gid) {
- /* We failed to lose our privilages. */
- return False;
- }
-
- return(True);
-}
-
-char *get_trusted_serverlist(const char* domain)
-{
- pstring tmp;
- static char *server_list = NULL;
- static pstring srv_list;
- char *trusted_list = lp_trusted_domains();
- if (strequal(lp_workgroup(), domain))
- {
- DEBUG(10,("local domain server list: %s\n", server_list));
- pstrcpy(srv_list, lp_passwordserver());
- return srv_list;
- }
-
- if (!next_token(&trusted_list, tmp, NULL, sizeof(tmp)))
- {
- return NULL;
- }
-
- do
- {
- fstring trust_dom;
- split_at_first_component(tmp, trust_dom, '=', srv_list);
-
- if (strequal(domain, trust_dom))
- {
- return srv_list;
- DEBUG(10,("trusted: %s\n", server_list));
- }
-
- } while (next_token(NULL, tmp, NULL, sizeof(tmp)));
-
- return NULL;
-}
-
-/**********************************************************
- Encode the account control bits into a string.
- length = length of string to encode into (including terminating
- null). length *MUST BE MORE THAN 2* !
- **********************************************************/
-
-char *pwdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
-{
- static fstring acct_str;
- size_t i = 0;
-
- acct_str[i++] = '[';
-
- if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
- if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
- if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
- if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
- if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
- if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
- if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
- if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
- if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
- if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
- if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
- if (acct_ctrl & ACB_PWLOCK ) acct_str[i++] = 'P';
-
- for ( ; i < length - 2 ; i++ )
- {
- acct_str[i] = ' ';
- }
-
- i = length - 2;
- acct_str[i++] = ']';
- acct_str[i++] = '\0';
-
- return acct_str;
-}
-
-/**********************************************************
- Decode the account control bits from a string.
-
- this function breaks coding standards minimum line width of 80 chars.
- reason: vertical line-up code clarity - all case statements fit into
- 15 lines, which is more important.
- **********************************************************/
-
-uint16 pwdb_decode_acct_ctrl(const char *p)
+/*****************************************************************
+like mktemp() but make sure that no % characters are used
+% characters are bad for us because of the macro subs
+ *****************************************************************/
+char *smbd_mktemp(char *template)
{
- uint16 acct_ctrl = 0;
- BOOL finished = False;
-
- /*
- * Check if the account type bits have been encoded after the
- * NT password (in the form [NDHTUWSLXI]).
- */
+ char *p = mktemp(template);
+ char *p2;
+ SMB_STRUCT_STAT st;
- if (*p != '[') return 0;
+ if (!p) return NULL;
- for (p++; *p && !finished; p++)
- {
- switch (*p)
- {
- case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
- case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
- case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
- case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
- case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
- case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
- case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
- case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
- case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
- case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
- case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
- case 'P': { acct_ctrl |= ACB_PWLOCK ; break; /* 'P'assword cannot be changed remotely */ }
- case ' ': { break; }
- case ':':
- case '\n':
- case '\0':
- case ']':
- default: { finished = True; }
+ while ((p2=strchr(p,'%'))) {
+ p2[0] = 'A';
+ while (sys_stat(p,&st) == 0 && p2[0] < 'Z') {
+ /* damn, it exists */
+ p2[0]++;
}
- }
-
- return acct_ctrl;
-}
-
-/*******************************************************************
- gets password-database-format time from a string.
- ********************************************************************/
-
-static time_t get_time_from_string(const char *p)
-{
- int i;
-
- for (i = 0; i < 8; i++)
- {
- if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
- {
- break;
+ if (p2[0] == 'Z') {
+ /* oh well ... better return something */
+ p2[0] = '%';
+ return p;
}
}
- if (i == 8)
- {
- /*
- * p points at 8 characters of hex digits -
- * read into a time_t as the seconds since
- * 1970 that the password was last changed.
- */
- return (time_t)strtol(p, NULL, 16);
- }
- return (time_t)-1;
-}
-
-/*******************************************************************
- gets password last set time
- ********************************************************************/
-
-time_t pwdb_get_last_set_time(const char *p)
-{
- if (*p && !StrnCaseCmp(p, "LCT-", 4))
- {
- return get_time_from_string(p + 4);
- }
- return (time_t)-1;
-}
-
-
-/*******************************************************************
- sets password-database-format time in a string.
- ********************************************************************/
-static void set_time_in_string(char *p, int max_len, char *type, time_t t)
-{
- slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
-}
-
-/*******************************************************************
- sets logon time
- ********************************************************************/
-void pwdb_set_logon_time(char *p, int max_len, time_t t)
-{
- set_time_in_string(p, max_len, "LNT", t);
-}
-/*******************************************************************
- sets logoff time
- ********************************************************************/
-void pwdb_set_logoff_time(char *p, int max_len, time_t t)
-{
- set_time_in_string(p, max_len, "LOT", t);
-}
-
-/*******************************************************************
- sets kickoff time
- ********************************************************************/
-void pwdb_set_kickoff_time(char *p, int max_len, time_t t)
-{
- set_time_in_string(p, max_len, "KOT", t);
-}
-
-/*******************************************************************
- sets password can change time
- ********************************************************************/
-void pwdb_set_can_change_time(char *p, int max_len, time_t t)
-{
- set_time_in_string(p, max_len, "CCT", t);
+ return p;
}
-/*******************************************************************
- sets password last set time
- ********************************************************************/
-void pwdb_set_must_change_time(char *p, int max_len, time_t t)
-{
- set_time_in_string(p, max_len, "MCT", t);
-}
-/*******************************************************************
- sets password last set time
- ********************************************************************/
-void pwdb_set_last_set_time(char *p, int max_len, time_t t)
+/*****************************************************************
+like strdup but for memory
+ *****************************************************************/
+void *memdup(void *p, size_t size)
{
- set_time_in_string(p, max_len, "LCT", t);
+ void *p2;
+ p2 = malloc(size);
+ if (!p2) return NULL;
+ memcpy(p2, p, size);
+ return p2;
}
-
-/*************************************************************
- Routine to set 32 hex password characters from a 16 byte array.
-**************************************************************/
-void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl)
-{
- if (pwd != NULL)
- {
- int i;
- for (i = 0; i < 16; i++)
- {
- slprintf(&p[i*2], 33, "%02X", pwd[i]);
- }
- }
- else
- {
- if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
- {
- safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
- }
- else
- {
- safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
- }
- }
-}
-
-/*************************************************************
- Routine to get the 32 hex characters and turn them
- into a 16 byte array.
-**************************************************************/
-BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl)
+/*****************************************************************
+get local hostname and cache result
+ *****************************************************************/
+char *myhostname(void)
{
- if (strnequal(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32))
- {
- if (acct_ctrl != NULL)
- {
- *acct_ctrl |= ACB_PWNOTREQ;
- }
- pwd[0] = 0;
- return True;
- }
- else if (strnequal(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32))
- {
- pwd[0] = 0;
- return True;
- }
- else
- {
- return strhex_to_str(pwd, 32, p) == 16;
+ static pstring ret;
+ if (ret[0] == 0) {
+ get_myname(ret);
}
+ return ret;
}
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index f4325b813b..9eb38460d9 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -51,7 +51,7 @@ BOOL do_file_lock(int fd, int waitsecs, int type)
lock.l_len = 1;
lock.l_pid = 0;
- alarm(5);
+ alarm(waitsecs);
ret = fcntl(fd, SMB_F_SETLKW, &lock);
alarm(0);
CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
@@ -113,22 +113,22 @@ BOOL file_unlock(int fd, int *plock_depth)
update to be set = True if modification is required.
****************************************************************/
-void *startfileent(char *pfile, char *s_readbuf, int bufsize,
+void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
int *file_lock_depth, BOOL update)
{
FILE *fp = NULL;
if (!*pfile)
{
- DEBUG(0, ("startfileent: No file set\n"));
+ DEBUG(0, ("startfilepwent: No file set\n"));
return (NULL);
}
- DEBUG(10, ("startfileent: opening file %s\n", pfile));
+ DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
fp = sys_fopen(pfile, update ? "r+b" : "rb");
if (fp == NULL) {
- DEBUG(0, ("startfileent: unable to open file %s\n", pfile));
+ DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
return NULL;
}
@@ -137,7 +137,7 @@ void *startfileent(char *pfile, char *s_readbuf, int bufsize,
if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
{
- DEBUG(0, ("startfileent: unable to lock file %s\n", pfile));
+ DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
fclose(fp);
return NULL;
}
@@ -152,13 +152,13 @@ void *startfileent(char *pfile, char *s_readbuf, int bufsize,
/***************************************************************
End enumeration of the file.
****************************************************************/
-void endfileent(void *vp, int *file_lock_depth)
+void endfilepwent(void *vp, int *file_lock_depth)
{
FILE *fp = (FILE *)vp;
file_unlock(fileno(fp), file_lock_depth);
fclose(fp);
- DEBUG(7, ("endfileent: closed file.\n"));
+ DEBUG(7, ("endfilepwent: closed file.\n"));
}
/*************************************************************************
@@ -181,6 +181,7 @@ BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
/*************************************************************************
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)
@@ -188,6 +189,7 @@ 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)
@@ -247,6 +249,12 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
continue;
}
+ p = (unsigned char *) strchr(linebuf, ':');
+ if (p == NULL)
+ {
+ DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
+ continue;
+ }
return linebuf_len;
}
return -1;
@@ -319,49 +327,3 @@ char *fgets_slash(char *s2,int maxlen,FILE *f)
return(s);
}
-/****************************************************************************
-checks if a file has changed since last read
-****************************************************************************/
-BOOL file_modified(const char *filename, time_t *lastmodified)
-{
- SMB_STRUCT_STAT st;
-
- if (sys_stat(filename, &st) != 0)
- {
- DEBUG(0, ("file_changed: Unable to stat file %s. Error was %s\n",
- filename, strerror(errno) ));
- return False;
- }
-
- if(st.st_mtime <= *lastmodified)
- {
- DEBUG(20, ("file_modified: %s not modified\n", filename));
- return False;
- }
-
- DEBUG(20, ("file_modified: %s modified\n", filename));
- *lastmodified = st.st_mtime;
- return True;
-}
-
-/***************************************************************************
-opens a file if modified otherwise returns NULL
-***************************************************************************/
-void *open_file_if_modified(const char *filename, char *mode, time_t *lastmodified)
-{
- FILE *f;
-
- if (!file_modified(filename, lastmodified))
- {
- return NULL;
- }
-
- if( (f = fopen(filename, mode)) == NULL)
- {
- DEBUG(0, ("open_file_if_modified: can't open file %s. Error was %s\n",
- filename, strerror(errno)));
- return NULL;
- }
-
- return (void *)f;
-}
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index a966484484..9e5154d259 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -3,6 +3,8 @@
Version 1.9.
Samba utility functions
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
+ Copyright (C) Jeremy Allison 1999
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
@@ -23,13 +25,206 @@
extern int DEBUGLEVEL;
+DOM_SID global_sam_sid;
+extern pstring global_myname;
+extern fstring global_myworkgroup;
+
+/*
+ * Some useful sids
+ */
+
+DOM_SID global_sid_S_1_5_0x20; /* local well-known domain */
+DOM_SID global_sid_World_Domain; /* everyone */
+DOM_SID global_sid_World; /* everyone */
+DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner */
+DOM_SID global_sid_Creator_Owner; /* Creator Owner */
+DOM_SID global_sid_NT_Authority; /* NT Authority */
+
+typedef struct _known_sid_users {
+ uint32 rid;
+ uint8 sid_name_use;
+ char *known_user_name;
+} known_sid_users;
+
+/* static known_sid_users no_users[] = {{0, 0, NULL}}; */
+static known_sid_users everyone_users[] = {{ 0, SID_NAME_WKN_GRP, "Everyone" }, {0, 0, NULL}};
+static known_sid_users creator_owner_users[] = {{ 0, SID_NAME_ALIAS, "Creator Owner" }, {0, 0, NULL}};
+static known_sid_users nt_authority_users[] = {{ 1, SID_NAME_ALIAS, "Dialup" },
+ { 2, SID_NAME_ALIAS, "Network"},
+ { 3, SID_NAME_ALIAS, "Batch"},
+ { 4, SID_NAME_ALIAS, "Interactive"},
+ { 6, SID_NAME_ALIAS, "Service"},
+ { 7, SID_NAME_ALIAS, "AnonymousLogon"},
+ { 8, SID_NAME_ALIAS, "Proxy"},
+ { 9, SID_NAME_ALIAS, "ServerLogon"},
+ {0, 0, NULL}};
+
+static struct sid_name_map_info
+{
+ DOM_SID *sid;
+ char *name;
+ known_sid_users *known_users;
+}
+sid_name_map[] =
+{
+ { &global_sam_sid, global_myname, NULL},
+ { &global_sam_sid, global_myworkgroup, NULL},
+ { &global_sid_S_1_5_0x20, "BUILTIN", NULL},
+ { &global_sid_World_Domain, "", &everyone_users[0] },
+ { &global_sid_Creator_Owner_Domain, "", &creator_owner_users[0] },
+ { &global_sid_NT_Authority, "NT Authority", &nt_authority_users[0] },
+ { NULL, NULL, NULL}
+};
+
+/****************************************************************************
+ Creates some useful well known sids
+****************************************************************************/
+
+void generate_wellknown_sids(void)
+{
+ string_to_sid(&global_sid_S_1_5_0x20, "S-1-5-32");
+ string_to_sid(&global_sid_World_Domain, "S-1-1");
+ string_to_sid(&global_sid_World, "S-1-1-0");
+ string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3");
+ string_to_sid(&global_sid_Creator_Owner, "S-1-3-0");
+ string_to_sid(&global_sid_NT_Authority, "S-1-5");
+}
+
+/**************************************************************************
+ Turns a domain SID into a name, returned in the nt_domain argument.
+***************************************************************************/
+
+BOOL map_domain_sid_to_name(DOM_SID *sid, char *nt_domain)
+{
+ fstring sid_str;
+ int i = 0;
+ sid_to_string(sid_str, sid);
+
+ DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
+
+ if (nt_domain == NULL)
+ return False;
+
+ while (sid_name_map[i].sid != NULL) {
+ sid_to_string(sid_str, sid_name_map[i].sid);
+ DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
+ if (sid_equal(sid_name_map[i].sid, sid)) {
+ fstrcpy(nt_domain, sid_name_map[i].name);
+ DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
+ return True;
+ }
+ i++;
+ }
+
+ DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));
+
+ return False;
+}
+
+/**************************************************************************
+ Looks up a known username from one of the known domains.
+***************************************************************************/
+
+BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, uint8 *psid_name_use)
+{
+ int i = 0;
+ struct sid_name_map_info *psnm;
+
+ for(i = 0; sid_name_map[i].sid != NULL; i++) {
+ psnm = &sid_name_map[i];
+ if(sid_equal(psnm->sid, sid)) {
+ int j;
+ for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
+ if(rid == psnm->known_users[j].rid) {
+ DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n",
+ (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
+ fstrcpy( name, psnm->known_users[j].known_user_name);
+ *psid_name_use = psnm->known_users[j].sid_name_use;
+ return True;
+ }
+ }
+ }
+ }
+
+ return False;
+}
+
+/**************************************************************************
+ Turns a domain name into a SID.
+ *** side-effect: if the domain name is NULL, it is set to our domain ***
+***************************************************************************/
+
+BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain)
+{
+ int i = 0;
+
+ if (nt_domain == NULL) {
+ DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n"));
+ sid_copy(sid, &global_sam_sid);
+ return True;
+ }
+
+ if (nt_domain[0] == 0) {
+ fstrcpy(nt_domain, global_myname);
+ DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain));
+ sid_copy(sid, &global_sam_sid);
+ return True;
+ }
+
+ DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain));
+
+ while (sid_name_map[i].name != NULL) {
+ DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name));
+ if (strequal(sid_name_map[i].name, nt_domain)) {
+ fstring sid_str;
+ sid_copy(sid, sid_name_map[i].sid);
+ sid_to_string(sid_str, sid_name_map[i].sid);
+ DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str));
+ return True;
+ }
+ i++;
+ }
+
+ DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain));
+ return False;
+}
+
+/**************************************************************************
+ Splits a name of format \DOMAIN\name or name into its two components.
+ Sets the DOMAIN name to global_myname if it has not been specified.
+***************************************************************************/
+
+void split_domain_name(const char *fullname, char *domain, char *name)
+{
+ pstring full_name;
+ char *p;
+
+ *domain = *name = '\0';
+ if (fullname[0] == '\\')
+ fullname++;
+
+ pstrcpy(full_name, fullname);
+ p = strchr(full_name+1, '\\');
+
+ if (p != NULL) {
+ *p = 0;
+ fstrcpy(domain, full_name);
+ fstrcpy(name, p+1);
+ } else {
+ fstrcpy(domain, global_myname);
+ fstrcpy(name, full_name);
+ }
+
+ DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n",
+ fullname, domain, name));
+}
/*****************************************************************
Convert a SID to an ascii string.
*****************************************************************/
-char *sid_to_string(pstring sidstr_out, const DOM_SID *sid)
+char *sid_to_string(fstring sidstr_out, DOM_SID *sid)
{
char subauth[16];
int i;
@@ -39,12 +234,11 @@ char *sid_to_string(pstring sidstr_out, const DOM_SID *sid)
(sid->id_auth[3] << 16) +
(sid->id_auth[2] << 24);
- slprintf(sidstr_out, sizeof(pstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia);
+ slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia);
- for (i = 0; i < sid->num_auths; i++)
- {
+ for (i = 0; i < sid->num_auths; i++) {
slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]);
- pstrcat(sidstr_out, subauth);
+ fstrcat(sidstr_out, subauth);
}
DEBUG(7,("sid_to_string returning %s\n", sidstr_out));
@@ -55,72 +249,68 @@ char *sid_to_string(pstring sidstr_out, const DOM_SID *sid)
Convert a string to a SID. Returns True on success, False on fail.
*****************************************************************/
-BOOL string_to_sid(DOM_SID *sidout, const char *sidstr)
+BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
{
- const char *p = sidstr;
- /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
- uint32 ia;
+ pstring tok;
+ char *p = sidstr;
+ /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+ uint32 ia;
- memset((char *)sidout, '\0', sizeof(DOM_SID));
+ memset((char *)sidout, '\0', sizeof(DOM_SID));
- if (StrnCaseCmp( sidstr, "S-", 2))
- {
- DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
- return False;
- }
+ if (StrnCaseCmp( sidstr, "S-", 2)) {
+ DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
+ return False;
+ }
- if ((p = strchr(p, '-')) == NULL)
- {
- DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
- return False;
- }
+ p += 2;
+ if (!next_token(&p, tok, "-", sizeof(tok))) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
- p++;
+ /* Get the revision number. */
+ sidout->sid_rev_num = (uint8)strtoul(tok, NULL, 10);
- /* Get the revision number. */
- sidout->sid_rev_num = (uint8)strtoul(p,NULL,10);
+ if (!next_token(&p, tok, "-", sizeof(tok))) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
- if ((p = strchr(p, '-')) == NULL)
- {
- DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
- return False;
- }
+ /* identauth in decimal should be < 2^32 */
+ ia = (uint32)strtoul(tok, NULL, 10);
+
+ /* NOTE - the ia value is in big-endian format. */
+ sidout->id_auth[0] = 0;
+ sidout->id_auth[1] = 0;
+ sidout->id_auth[2] = (ia & 0xff000000) >> 24;
+ sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
+ sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
+ sidout->id_auth[5] = (ia & 0x000000ff);
+
+ sidout->num_auths = 0;
+
+ while(next_token(&p, tok, "-", sizeof(tok)) &&
+ sidout->num_auths < MAXSUBAUTHS) {
+ /*
+ * NOTE - the subauths are in native machine-endian format. They
+ * are converted to little-endian when linearized onto the wire.
+ */
+ sid_append_rid(sidout, (uint32)strtoul(tok, NULL, 10));
+ }
- p++;
-
- /* identauth in decimal should be < 2^32 */
- ia = (uint32)strtoul(p,NULL,10);
-
- /* NOTE - the ia value is in big-endian format. */
- sidout->id_auth[0] = 0;
- sidout->id_auth[1] = 0;
- sidout->id_auth[2] = (ia & 0xff000000) >> 24;
- sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
- sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
- sidout->id_auth[5] = (ia & 0x000000ff);
-
- sidout->num_auths = 0;
-
- while (((p = strchr(p, '-')) != NULL) && sidout->num_auths < MAXSUBAUTHS)
- {
- p++;
- /*
- * NOTE - the subauths are in native machine-endian format. They
- * are converted to little-endian when linearized onto the wire.
- */
- sid_append_rid(sidout, (uint32)strtoul(p, NULL, 10));
- }
+ DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr));
- return True;
+ return True;
}
/*****************************************************************
- add a rid to the end of a sid
+ Add a rid to the end of a sid
*****************************************************************/
+
BOOL sid_append_rid(DOM_SID *sid, uint32 rid)
{
- if (sid->num_auths < MAXSUBAUTHS)
- {
+ if (sid->num_auths < MAXSUBAUTHS) {
sid->sub_auths[sid->num_auths++] = rid;
return True;
}
@@ -128,413 +318,109 @@ BOOL sid_append_rid(DOM_SID *sid, uint32 rid)
}
/*****************************************************************
- removes the last rid from the end of a sid
+ Removes the last rid from the end of a sid
*****************************************************************/
+
BOOL sid_split_rid(DOM_SID *sid, uint32 *rid)
{
- if (sid->num_auths > 0)
- {
+ if (sid->num_auths > 0) {
sid->num_auths--;
- if (rid != NULL)
- {
- (*rid) = sid->sub_auths[sid->num_auths];
- }
+ *rid = sid->sub_auths[sid->num_auths];
return True;
}
return False;
}
/*****************************************************************
- copies a sid
+ Copies a sid
*****************************************************************/
-void sid_copy(DOM_SID *sid1, const DOM_SID *sid2)
-{
- int i;
-
- for (i = 0; i < 6; i++)
- {
- sid1->id_auth[i] = sid2->id_auth[i];
- }
-
- for (i = 0; i < sid2->num_auths; i++)
- {
- sid1->sub_auths[i] = sid2->sub_auths[i];
- }
- sid1->num_auths = sid2->num_auths;
- sid1->sid_rev_num = sid2->sid_rev_num;
-}
-
-/*****************************************************************
- compare two sids up to the auths of the first sid
-*****************************************************************/
-BOOL sid_front_equal(const DOM_SID *sid1, const DOM_SID *sid2)
+void sid_copy(DOM_SID *dst, DOM_SID *src)
{
int i;
- /* compare most likely different rids, first: i.e start at end */
- for (i = sid1->num_auths-1; i >= 0; --i)
- {
- if (sid1->sub_auths[i] != sid2->sub_auths[i]) return False;
- }
-
- if (sid1->num_auths > sid2->num_auths ) return False;
- if (sid1->sid_rev_num != sid2->sid_rev_num) return False;
+ dst->sid_rev_num = src->sid_rev_num;
+ dst->num_auths = src->num_auths;
- for (i = 0; i < 6; i++)
- {
- if (sid1->id_auth[i] != sid2->id_auth[i]) return False;
- }
+ memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
- return True;
+ for (i = 0; i < src->num_auths; i++)
+ dst->sub_auths[i] = src->sub_auths[i];
}
/*****************************************************************
- compare two sids
-*****************************************************************/
-BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
-{
- int i;
-
- /* compare most likely different rids, first: i.e start at end */
- for (i = sid1->num_auths-1; i >= 0; --i)
- {
- if (sid1->sub_auths[i] != sid2->sub_auths[i]) return False;
- }
-
- if (sid1->num_auths != sid2->num_auths ) return False;
- if (sid1->sid_rev_num != sid2->sid_rev_num) return False;
-
- for (i = 0; i < 6; i++)
- {
- if (sid1->id_auth[i] != sid2->id_auth[i]) return False;
- }
-
- return True;
-}
-
-
-/*****************************************************************
- calculates size of a sid
-*****************************************************************/
-int sid_size(const DOM_SID *sid)
-{
- if (sid == NULL)
- {
- return 0;
- }
- return sid->num_auths * sizeof(uint32) + 8;
-}
-
-
-/*****************************************************************
Duplicates a sid - mallocs the target.
*****************************************************************/
-DOM_SID *sid_dup(const DOM_SID *src)
+DOM_SID *sid_dup(DOM_SID *src)
{
DOM_SID *dst;
if(!src)
return NULL;
- if((dst = (DOM_SID*)malloc(sizeof(DOM_SID))) != NULL) {
- memset(dst, '\0', sizeof(DOM_SID));
- sid_copy( dst, src);
+ if((dst = malloc(sizeof(DOM_SID))) != NULL) {
+ memset(dst, '\0', sizeof(DOM_SID));
+ sid_copy( dst, src);
}
return dst;
}
+/*****************************************************************
+ Write a sid out into on-the-wire format.
+*****************************************************************/
-/****************************************************************************
- Read a SID from a file.
-****************************************************************************/
-
-static BOOL read_sid_from_file(int fd, char *sid_file, DOM_SID *sid)
-{
- fstring fline;
- fstring sid_str;
-
- memset(fline, '\0', sizeof(fline));
-
- if (read(fd, fline, sizeof(fline) -1 ) < 0) {
- DEBUG(0,("unable to read file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- return False;
- }
-
- /*
- * Convert to the machine SID.
- */
-
- fline[sizeof(fline)-1] = '\0';
- if (!string_to_sid(sid, fline)) {
- DEBUG(0,("unable to read sid.\n"));
- return False;
- }
-
- sid_to_string(sid_str, sid);
- DEBUG(5,("read_sid_from_file: sid %s\n", sid_str));
-
- return True;
-}
-
-/****************************************************************************
- Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
- not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
-****************************************************************************/
-BOOL read_sid(char *domain_name, DOM_SID *sid)
+BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid)
{
- int fd;
- char *p;
- pstring sid_file;
- fstring file_name;
- SMB_STRUCT_STAT st;
-
- pstrcpy(sid_file, lp_smb_passwd_file());
-
- DEBUG(10,("read_sid: Domain: %s\n", domain_name));
+ size_t i;
- if (sid_file[0] == 0)
- {
- DEBUG(0,("cannot find smb passwd file\n"));
+ if(len < sid_size(sid))
return False;
- }
-
- p = strrchr(sid_file, '/');
- if (p != NULL)
- {
- *++p = '\0';
- }
- if (!directory_exist(sid_file, NULL))
- {
- if (mkdir(sid_file, 0700) != 0)
- {
- DEBUG(0,("can't create private directory %s : %s\n",
- sid_file, strerror(errno)));
- return False;
- }
- }
+ SCVAL(outbuf,0,sid->sid_rev_num);
+ SCVAL(outbuf,1,sid->num_auths);
+ memcpy(&outbuf[2], sid->id_auth, 6);
+ for(i = 0; i < sid->num_auths; i++)
+ SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]);
- slprintf(file_name, sizeof(file_name)-1, "%s.SID", domain_name);
- strupper(file_name);
- pstrcat(sid_file, file_name);
-
- if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
- DEBUG(0,("unable to open or create file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- return False;
- }
-
- /*
- * Check if the file contains data.
- */
-
- if (sys_fstat(fd, &st) < 0) {
- DEBUG(0,("unable to stat file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- if (st.st_size == 0)
- {
- close(fd);
- return False;
- }
-
- /*
- * We have a valid SID - read it.
- */
-
- if (!read_sid_from_file(fd, sid_file, sid))
- {
- DEBUG(0,("unable to read file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
- close(fd);
return True;
-}
+}
+/*****************************************************************
+ Compare two sids.
+*****************************************************************/
-/****************************************************************************
- Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
- not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
-****************************************************************************/
-BOOL write_sid(char *domain_name, DOM_SID *sid)
+BOOL sid_equal(DOM_SID *sid1, DOM_SID *sid2)
{
- int fd;
- char *p;
- pstring sid_file;
- fstring sid_string;
- fstring file_name;
- SMB_STRUCT_STAT st;
-
- pstrcpy(sid_file, lp_smb_passwd_file());
- sid_to_string(sid_string, sid);
+ int i;
- DEBUG(10,("write_sid: Domain: %s SID: %s\n", domain_name, sid_string));
- fstrcat(sid_string, "\n");
+ /* compare most likely different rids, first: i.e start at end */
+ for (i = sid1->num_auths-1; i >= 0; --i)
+ if (sid1->sub_auths[i] != sid2->sub_auths[i])
+ return False;
- if (sid_file[0] == 0)
- {
- DEBUG(0,("cannot find smb passwd file\n"));
+ if (sid1->num_auths != sid2->num_auths)
+ return False;
+ if (sid1->sid_rev_num != sid2->sid_rev_num)
return False;
- }
-
- p = strrchr(sid_file, '/');
- if (p != NULL)
- {
- *++p = '\0';
- }
- if (!directory_exist(sid_file, NULL)) {
- if (mkdir(sid_file, 0700) != 0) {
- DEBUG(0,("can't create private directory %s : %s\n",
- sid_file, strerror(errno)));
+ for (i = 0; i < 6; i++)
+ if (sid1->id_auth[i] != sid2->id_auth[i])
return False;
- }
- }
- slprintf(file_name, sizeof(file_name)-1, "%s.SID", domain_name);
- strupper(file_name);
- pstrcat(sid_file, file_name);
-
- if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
- DEBUG(0,("unable to open or create file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- return False;
- }
-
- /*
- * Check if the file contains data.
- */
-
- if (sys_fstat(fd, &st) < 0) {
- DEBUG(0,("unable to stat file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- if (st.st_size > 0)
- {
- /*
- * We have a valid SID already.
- */
- close(fd);
- DEBUG(0,("SID file %s already exists\n", sid_file));
- return False;
- }
-
- if (!do_file_lock(fd, 60, F_WRLCK))
- {
- DEBUG(0,("unable to lock file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- /*
- * At this point we have a blocking lock on the SID
- * file - check if in the meantime someone else wrote
- * SID data into the file. If so - they were here first,
- * use their data.
- */
-
- if (sys_fstat(fd, &st) < 0)
- {
- DEBUG(0,("unable to stat file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- if (st.st_size > 0)
- {
- /*
- * Unlock as soon as possible to reduce
- * contention on the exclusive lock.
- */
- do_file_lock(fd, 60, F_UNLCK);
-
- /*
- * We have a valid SID already.
- */
-
- DEBUG(0,("SID file %s already exists\n", sid_file));
- close(fd);
- return False;
- }
-
- /*
- * The file is still empty and we have an exlusive lock on it.
- * Write out out SID data into the file.
- */
-
- if (fchmod(fd, 0644) < 0)
- {
- DEBUG(0,("unable to set correct permissions on file %s. \
-Error was %s\n", sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- if (write(fd, sid_string, strlen(sid_string)) != strlen(sid_string))
- {
- DEBUG(0,("unable to write file %s. Error was %s\n",
- sid_file, strerror(errno) ));
- close(fd);
- return False;
- }
-
- /*
- * Unlock & exit.
- */
-
- do_file_lock(fd, 60, F_UNLCK);
- close(fd);
return True;
-}
+}
-/****************************************************************************
-create a random SID.
-****************************************************************************/
-BOOL create_new_sid(DOM_SID *sid)
-{
- uchar raw_sid_data[12];
- fstring sid_string;
- int i;
- /*
- * Generate the new sid data & turn it into a string.
- */
- generate_random_buffer(raw_sid_data, 12, True);
-
- fstrcpy(sid_string, "S-1-5-21");
- for(i = 0; i < 3; i++)
- {
- fstring tmp_string;
- slprintf(tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
- fstrcat(sid_string, tmp_string);
- }
-
- fstrcat(sid_string, "\n");
-
- /*
- * Ensure our new SID is valid.
- */
-
- if (!string_to_sid(sid, sid_string))
- {
- DEBUG(0,("unable to generate machine SID.\n"));
- return False;
- }
+/*****************************************************************
+ Calculates size of a sid.
+*****************************************************************/
- return True;
+size_t sid_size(DOM_SID *sid)
+{
+ if (sid == NULL)
+ return 0;
+
+ return sid->num_auths * sizeof(uint32) + 8;
}
-
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index d9b0f97259..77ba4a7f4c 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -35,22 +35,18 @@ BOOL passive = False;
/* the client file descriptor */
int Client = -1;
-/* the port, where client connected */
-int ClientPort = 0;
-
/* the last IP received from */
struct in_addr lastip;
/* the last port received from */
int lastport=0;
-
int smb_read_error = 0;
-
/****************************************************************************
-determine if a file descriptor is in fact a socket
+ Determine if a file descriptor is in fact a socket.
****************************************************************************/
+
BOOL is_a_socket(int fd)
{
int v,l;
@@ -58,7 +54,6 @@ BOOL is_a_socket(int fd)
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
-
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
struct
@@ -101,69 +96,63 @@ struct
#endif
{NULL,0,0,0,0}};
-
-
/****************************************************************************
-set user socket options
+ Set user socket options.
****************************************************************************/
+
void set_socket_options(int fd, char *options)
{
- fstring tok;
-
- while (next_token(&options,tok," \t,", sizeof(tok)))
- {
- int ret=0,i;
- int value = 1;
- char *p;
- BOOL got_value = False;
-
- if ((p = strchr(tok,'=')))
- {
- *p = 0;
- value = atoi(p+1);
- got_value = True;
- }
+ fstring tok;
+
+ while (next_token(&options,tok," \t,", sizeof(tok))) {
+ int ret=0,i;
+ int value = 1;
+ char *p;
+ BOOL got_value = False;
+
+ if ((p = strchr(tok,'='))) {
+ *p = 0;
+ value = atoi(p+1);
+ got_value = True;
+ }
- for (i=0;socket_options[i].name;i++)
- if (strequal(socket_options[i].name,tok))
- break;
+ for (i=0;socket_options[i].name;i++)
+ if (strequal(socket_options[i].name,tok))
+ break;
- if (!socket_options[i].name)
- {
- DEBUG(0,("Unknown socket option %s\n",tok));
- continue;
- }
+ if (!socket_options[i].name) {
+ DEBUG(0,("Unknown socket option %s\n",tok));
+ continue;
+ }
- switch (socket_options[i].opttype)
- {
- case OPT_BOOL:
- case OPT_INT:
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,(char *)&value,sizeof(int));
- break;
-
- case OPT_ON:
- if (got_value)
- DEBUG(0,("syntax error - %s does not take a value\n",tok));
-
- {
- int on = socket_options[i].value;
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,(char *)&on,sizeof(int));
- }
- break;
- }
+ switch (socket_options[i].opttype) {
+ case OPT_BOOL:
+ case OPT_INT:
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&value,sizeof(int));
+ break;
+
+ case OPT_ON:
+ if (got_value)
+ DEBUG(0,("syntax error - %s does not take a value\n",tok));
+
+ {
+ int on = socket_options[i].value;
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&on,sizeof(int));
+ }
+ break;
+ }
- if (ret != 0)
- DEBUG(0,("Failed to set socket option %s\n",tok));
- }
+ if (ret != 0)
+ DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
+ }
}
-
-
/****************************************************************************
- close the socket communication
+ Close the socket communication.
****************************************************************************/
+
void close_sockets(void )
{
#ifdef WITH_SSL
@@ -174,31 +163,10 @@ void close_sockets(void )
Client = -1;
}
-
-
/****************************************************************************
-write to a socket
+ Read from a socket.
****************************************************************************/
-ssize_t write_socket(int fd,char *buf,size_t len)
-{
- ssize_t ret=0;
-
- if (passive)
- return(len);
- DEBUG(6,("write_socket(%d,%d)\n",fd,len));
- ret = write_data(fd,buf,len);
-
- DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
- if(ret <= 0)
- DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
- len, fd, strerror(errno) ));
- return(ret);
-}
-
-/****************************************************************************
-read from a socket
-****************************************************************************/
ssize_t read_udp_socket(int fd,char *buf,size_t len)
{
ssize_t ret;
@@ -206,8 +174,8 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len)
int socklen;
socklen = sizeof(sock);
- bzero((char *)&sock,socklen);
- bzero((char *)&lastip,sizeof(lastip));
+ memset((char *)&sock,'\0',socklen);
+ memset((char *)&lastip,'\0',sizeof(lastip));
ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
if (ret <= 0) {
DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
@@ -224,13 +192,13 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len)
}
/****************************************************************************
-read data from a device with a timout in msec.
-mincount = if timeout, minimum to read before returning
-maxcount = number to be read.
-time_out = timeout in milliseconds
+ Read data from a socket with a timout in msec.
+ mincount = if timeout, minimum to read before returning
+ maxcount = number to be read.
+ time_out = timeout in milliseconds
****************************************************************************/
-ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
+static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
{
fd_set fds;
int selrtn;
@@ -239,7 +207,8 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
struct timeval timeout;
/* just checking .... */
- if (maxcnt <= 0) return(0);
+ if (maxcnt <= 0)
+ return(0);
smb_read_error = 0;
@@ -259,11 +228,13 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
#endif /* WITH_SSL */
if (readret == 0) {
+ DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
smb_read_error = READ_EOF;
return -1;
}
if (readret == -1) {
+ DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
smb_read_error = READ_ERROR;
return -1;
}
@@ -282,22 +253,23 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
timeout.tv_sec = (time_t)(time_out / 1000);
timeout.tv_usec = (long)(1000 * (time_out % 1000));
- for (nread=0; nread < mincnt; )
- {
+ for (nread=0; nread < mincnt; ) {
FD_ZERO(&fds);
FD_SET(fd,&fds);
- selrtn = sys_select(fd+1,&fds,NULL, &timeout);
+ selrtn = sys_select(fd+1,&fds,&timeout);
/* Check if error */
if(selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */
+ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));
smb_read_error = READ_ERROR;
return -1;
}
-
+
/* Did we timeout ? */
if (selrtn == 0) {
+ DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));
smb_read_error = READ_TIMEOUT;
return -1;
}
@@ -314,12 +286,14 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
if (readret == 0) {
/* we got EOF on the file descriptor */
+ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
smb_read_error = READ_EOF;
return -1;
}
if (readret == -1) {
/* the descriptor is probably dead */
+ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
smb_read_error = READ_ERROR;
return -1;
}
@@ -331,10 +305,91 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
return((ssize_t)nread);
}
+/****************************************************************************
+ Read data from a fd with a timout in msec.
+ mincount = if timeout, minimum to read before returning
+ maxcount = number to be read.
+ time_out = timeout in milliseconds
+****************************************************************************/
+
+ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
+{
+ fd_set fds;
+ int selrtn;
+ ssize_t readret;
+ size_t nread = 0;
+ struct timeval timeout;
+
+ /* just checking .... */
+ if (maxcnt <= 0)
+ return(0);
+
+ /* Blocking read */
+ if (time_out <= 0) {
+ if (mincnt == 0) mincnt = maxcnt;
+
+ while (nread < mincnt) {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
+ }
+#else /* WITH_SSL */
+ readret = read(fd, buf + nread, maxcnt - nread);
+#endif /* WITH_SSL */
+
+ if (readret <= 0)
+ return readret;
+
+ nread += readret;
+ }
+ return((ssize_t)nread);
+ }
+
+ /* Most difficult - timeout read */
+ /* If this is ever called on a disk file and
+ mincnt is greater then the filesize then
+ system performance will suffer severely as
+ select always returns true on disk files */
+
+ /* Set initial timeout */
+ timeout.tv_sec = (time_t)(time_out / 1000);
+ timeout.tv_usec = (long)(1000 * (time_out % 1000));
+
+ for (nread=0; nread < mincnt; ) {
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+
+ selrtn = sys_select(fd+1,&fds,&timeout);
+
+ if(selrtn <= 0)
+ return selrtn;
+
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
+ }
+#else /* WITH_SSL */
+ readret = read(fd, buf+nread, maxcnt-nread);
+#endif /* WITH_SSL */
+
+ if (readret <= 0)
+ return readret;
+
+ nread += readret;
+ }
+
+ /* Return the number we got */
+ return((ssize_t)nread);
+}
/****************************************************************************
send a keepalive packet (rfc1002)
****************************************************************************/
+
BOOL send_keepalive(int client)
{
unsigned char buf[4];
@@ -342,14 +397,13 @@ BOOL send_keepalive(int client)
buf[0] = 0x85;
buf[1] = buf[2] = buf[3] = 0;
- return(write_data(client,(char *)buf,4) == 4);
+ return(write_socket_data(client,(char *)buf,4) == 4);
}
-
-
/****************************************************************************
read data from the client, reading exactly N bytes.
****************************************************************************/
+
ssize_t read_data(int fd,char *buffer,size_t N)
{
ssize_t ret;
@@ -371,11 +425,13 @@ ssize_t read_data(int fd,char *buffer,size_t N)
if (ret == 0)
{
+ DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
smb_read_error = READ_EOF;
return 0;
}
if (ret == -1)
{
+ DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
smb_read_error = READ_ERROR;
return -1;
}
@@ -384,10 +440,50 @@ ssize_t read_data(int fd,char *buffer,size_t N)
return (ssize_t)total;
}
+/****************************************************************************
+ Read data from a socket, reading exactly N bytes.
+****************************************************************************/
+
+static ssize_t read_socket_data(int fd,char *buffer,size_t N)
+{
+ ssize_t ret;
+ size_t total=0;
+
+ smb_read_error = 0;
+
+ while (total < N)
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_read(ssl, buffer + total, N - total);
+ }else{
+ ret = read(fd,buffer + total,N - total);
+ }
+#else /* WITH_SSL */
+ ret = read(fd,buffer + total,N - total);
+#endif /* WITH_SSL */
+
+ if (ret == 0)
+ {
+ DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_EOF;
+ return 0;
+ }
+ if (ret == -1)
+ {
+ DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
+}
/****************************************************************************
- write data to a fd
+ Write data to a fd.
****************************************************************************/
+
ssize_t write_data(int fd,char *buffer,size_t N)
{
size_t total=0;
@@ -405,7 +501,42 @@ ssize_t write_data(int fd,char *buffer,size_t N)
ret = write(fd,buffer + total,N - total);
#endif /* WITH_SSL */
- if (ret == -1) return -1;
+ if (ret == -1) {
+ DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
+ return -1;
+ }
+ if (ret == 0) return total;
+
+ total += ret;
+ }
+ return (ssize_t)total;
+}
+
+/****************************************************************************
+ Write data to a socket - use send rather than write.
+****************************************************************************/
+
+ssize_t write_socket_data(int fd,char *buffer,size_t N)
+{
+ size_t total=0;
+ ssize_t ret;
+
+ while (total < N)
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_write(ssl,buffer + total,N - total);
+ }else{
+ ret = send(fd,buffer + total,N - total, 0);
+ }
+#else /* WITH_SSL */
+ ret = send(fd,buffer + total,N - total,0);
+#endif /* WITH_SSL */
+
+ if (ret == -1) {
+ DEBUG(0,("write_socket_data: write failure. Error = %s\n", strerror(errno) ));
+ return -1;
+ }
if (ret == 0) return total;
total += ret;
@@ -413,7 +544,26 @@ ssize_t write_data(int fd,char *buffer,size_t N)
return (ssize_t)total;
}
+/****************************************************************************
+write to a socket
+****************************************************************************/
+ssize_t write_socket(int fd,char *buf,size_t len)
+{
+ ssize_t ret=0;
+
+ if (passive)
+ return(len);
+ DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
+ ret = write_socket_data(fd,buf,len);
+
+ DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
+ if(ret <= 0)
+ DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
+ (int)len, fd, strerror(errno) ));
+
+ return(ret);
+}
/****************************************************************************
read 4 bytes of a smb packet and return the smb length of the packet
@@ -422,6 +572,7 @@ This version of the function will return a length of zero on receiving
a keepalive packet.
timeout is in milliseconds.
****************************************************************************/
+
static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
{
ssize_t len=0;
@@ -431,9 +582,9 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int
while (!ok)
{
if (timeout > 0)
- ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4);
+ ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);
else
- ok = (read_data(fd,inbuf,4) == 4);
+ ok = (read_socket_data(fd,inbuf,4) == 4);
if (!ok)
return(-1);
@@ -456,6 +607,7 @@ store the result in the buffer. This version of the function will
never return a session keepalive (length of zero).
timeout is in milliseconds.
****************************************************************************/
+
ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
{
ssize_t len;
@@ -472,6 +624,8 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
break;
}
+ DEBUG(10,("read_smb_length: got smb length of %d\n",len));
+
return len;
}
@@ -482,13 +636,14 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
This function will return on a
receipt of a session keepalive packet.
****************************************************************************/
+
BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
{
ssize_t len,ret;
smb_read_error = 0;
- bzero(buffer,smb_size + 100);
+ memset(buffer,'\0',smb_size + 100);
len = read_smb_length_return_keepalive(fd,buffer,timeout);
if (len < 0)
@@ -506,7 +661,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
}
if(len > 0) {
- ret = read_data(fd,buffer+4,len);
+ ret = read_socket_data(fd,buffer+4,len);
if (ret != len) {
smb_read_error = READ_ERROR;
return False;
@@ -529,7 +684,6 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
{
BOOL ret;
- uint8 msg_type;
for(;;)
{
@@ -543,25 +697,45 @@ BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
}
/* Ignore session keepalive packets. */
- msg_type = CVAL(buffer,0);
- if (msg_type != 0x85)
+ if(CVAL(buffer,0) != 0x85)
break;
}
- if (msg_type == 0)
- {
- show_msg(buffer);
- }
- else
- {
- dump_data(10, buffer, smb_len(buffer) + 4);
- }
show_msg(buffer);
return ret;
}
/****************************************************************************
+ send an null session message to a fd
+****************************************************************************/
+
+BOOL send_null_session_msg(int fd)
+{
+ ssize_t ret;
+ uint32 blank = 0;
+ size_t len = 4;
+ size_t nwritten=0;
+ char *buffer = (char *)&blank;
+
+ while (nwritten < len)
+ {
+ ret = write_socket(fd,buffer+nwritten,len - nwritten);
+ if (ret <= 0)
+ {
+ DEBUG(0,("send_null_session_msg: Error writing %d bytes to client. %d. Exiting\n",(int)len,(int)ret));
+ close_sockets();
+ exit(1);
+ }
+ nwritten += ret;
+ }
+
+ DEBUG(10,("send_null_session_msg: sent 4 null bytes to client.\n"));
+ return True;
+}
+
+/****************************************************************************
send an smb to a fd
****************************************************************************/
+
BOOL send_smb(int fd,char *buffer)
{
size_t len;
@@ -574,7 +748,7 @@ BOOL send_smb(int fd,char *buffer)
ret = write_socket(fd,buffer+nwritten,len - nwritten);
if (ret <= 0)
{
- DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
+ DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",(int)len,(int)ret));
close_sockets();
exit(1);
}
@@ -584,11 +758,10 @@ BOOL send_smb(int fd,char *buffer)
return True;
}
-
-
/****************************************************************************
send a single packet to a port on another machine
****************************************************************************/
+
BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
{
BOOL ret;
@@ -607,7 +780,7 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
}
/* set the address and port */
- bzero((char *)&sock_out,sizeof(sock_out));
+ memset((char *)&sock_out,'\0',sizeof(sock_out));
putip((char *)&sock_out.sin_addr,(char *)&ip);
sock_out.sin_port = htons( port );
sock_out.sin_family = AF_INET;
@@ -627,11 +800,11 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
return(ret);
}
-
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
-int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
+
+int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebind)
{
struct hostent *hp;
struct sockaddr_in sock;
@@ -649,7 +822,7 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
return -1;
}
- bzero((char *)&sock,sizeof(sock));
+ memset((char *)&sock,'\0',sizeof(sock));
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
#ifdef HAVE_SOCK_SIN_LEN
@@ -663,8 +836,12 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
{ DEBUG(0,("socket failed\n")); return -1; }
{
- int one=1;
- setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+ int val=1;
+ if(rebind)
+ val=1;
+ else
+ val=0;
+ setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
}
/* now we've got a socket - we need to bind it */
@@ -680,7 +857,7 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
port = 7999;
if (port >= 1000 && port < 9000)
- return(open_socket_in(type,port+1,dlevel,socket_addr));
+ return(open_socket_in(type,port+1,dlevel,socket_addr,rebind));
}
return(-1);
@@ -690,16 +867,16 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
return res;
}
-
/****************************************************************************
- create an outgoing socket
+ create an outgoing socket. timeout is in milliseconds.
**************************************************************************/
+
int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
{
struct sockaddr_in sock_out;
int res,ret;
int connect_loop = 250; /* 250 milliseconds */
- int loops = (timeout * 1000) / connect_loop;
+ int loops = (timeout) / connect_loop;
/* create a socket to write to */
res = socket(PF_INET, type, 0);
@@ -708,7 +885,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
if (type != SOCK_STREAM) return(res);
- bzero((char *)&sock_out,sizeof(sock_out));
+ memset((char *)&sock_out,'\0',sizeof(sock_out));
putip((char *)&sock_out.sin_addr,(char *)addr);
sock_out.sin_port = htons( port );
@@ -786,6 +963,7 @@ void reset_globals_after_fork(void)
/*******************************************************************
return the DNS name of the client
******************************************************************/
+
char *client_name(int fd)
{
struct sockaddr sa;
@@ -832,6 +1010,7 @@ char *client_name(int fd)
/*******************************************************************
return the IP addr of the client as a string
******************************************************************/
+
char *client_addr(int fd)
{
struct sockaddr sa;
@@ -862,101 +1041,3 @@ char *client_addr(int fd)
global_client_addr_done = True;
return addr_buf;
}
-
-/*******************************************************************
- opens and connects to a unix pipe socket
- ******************************************************************/
-int open_pipe_sock(char *path)
-{
- int sock;
- struct sockaddr_un sa;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (sock < 0)
- {
- DEBUG(0, ("unix socket open failed\n"));
- return sock;
- }
-
- ZERO_STRUCT(sa);
- sa.sun_family = AF_UNIX;
- safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
-
- DEBUG(10, ("socket open succeeded. file name: %s\n", sa.sun_path));
-
- if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
- {
- DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
- close(sock);
- return -1;
- }
-
- return sock;
-}
-
-int create_pipe_socket(char *dir, int dir_perms,
- char *path, int path_perms)
-{
- int s;
- struct sockaddr_un sa;
-
- DEBUG(10,("create_pipe_socket: %s %d %s %d\n",
- dir, dir_perms, path, path_perms));
-
- mkdir(dir, dir_perms);
-
- if (chmod(dir, dir_perms) < 0)
- {
- DEBUG(0, ("chmod on %s failed\n", dir));
- return -1;
- }
-
- if (!remove(path))
- {
- DEBUG(0, ("remove on %s failed\n", path));
- }
-
- /* start listening on unix socket */
- s = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (s < 0)
- {
- DEBUG(0, ("socket open failed\n"));
- return -1;
- }
-
- ZERO_STRUCT(sa);
- sa.sun_family = AF_UNIX;
- safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
-
- if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0)
- {
- DEBUG(0, ("socket bind to %s failed\n", sa.sun_path));
- close(s);
- remove(path);
- return -1;
- }
-
- if (s == -1)
- {
- DEBUG(0,("bind failed\n"));
- remove(path);
- return -1;
- }
-
- if (path_perms != 0)
- {
- chmod(path, path_perms);
- }
-
- if (listen(s, 5) == -1)
- {
- DEBUG(0,("listen failed\n"));
- return -1;
- }
-
- DEBUG(5,("unix socket opened: %s\n", path));
-
- return s;
-}
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index a25043df78..58718f395a 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -462,7 +462,7 @@ char *skip_string(char *buf,size_t n)
{
while (n--)
buf += strlen(buf) + 1;
- return buf;
+ return(buf);
}
/*******************************************************************
@@ -733,21 +733,69 @@ size_t count_chars(const char *s,char c)
return(count);
}
+/*******************************************************************
+Return True if a string consists only of one particular character.
+********************************************************************/
+BOOL str_is_all(const char *s,char c)
+{
+ if(s == NULL)
+ return False;
+ if(!*s)
+ return False;
+
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ while (*s)
+ {
+ if (is_shift_jis (*s))
+ s += 2;
+ else
+ {
+ if (*s != c)
+ return False;
+ s++;
+ }
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s)
+ {
+ size_t skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (*s != c)
+ return False;
+ s++;
+ }
+ }
+ }
+ return True;
+}
/*******************************************************************
safe string copy into a known length string. maxlength does not
include the terminating zero.
********************************************************************/
+
char *safe_strcpy(char *dest,const char *src, size_t maxlength)
{
size_t len;
- if (maxlength == 0)
- {
- return dest;
- }
-
if (!dest) {
DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
return NULL;
@@ -762,7 +810,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
if (len > maxlength) {
DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
- len-maxlength, src));
+ (int)(len-maxlength), src));
len = maxlength;
}
@@ -775,6 +823,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
safe string cat into a string. maxlength does not
include the terminating zero.
********************************************************************/
+
char *safe_strcat(char *dest, const char *src, size_t maxlength)
{
size_t src_len, dest_len;
@@ -793,7 +842,7 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
if (src_len + dest_len > maxlength) {
DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
- src_len + dest_len - maxlength, src));
+ (int)(src_len + dest_len - maxlength), src));
src_len = maxlength - dest_len;
}
@@ -802,28 +851,48 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
return dest;
}
-/****************************************************************************
-this is a safer strcpy(), meant to prevent core dumps when nasty things happen
-****************************************************************************/
-char *StrCpy(char *dest,const char *src)
+/*******************************************************************
+ Paranoid strcpy into a buffer of given length (includes terminating
+ zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately
+ does *NOT* check for multibyte characters. Don't change it !
+********************************************************************/
+
+char *alpha_strcpy(char *dest, const char *src, size_t maxlength)
{
- char *d = dest;
+ size_t len, i;
- /* I don't want to get lazy with these ... */
- SMB_ASSERT(dest && src);
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
+ return NULL;
+ }
- if (!dest) return(NULL);
- if (!src) {
- *dest = 0;
- return(dest);
- }
- while ((*d++ = *src++)) ;
- return(dest);
+ if (!src) {
+ *dest = 0;
+ return dest;
+ }
+
+ len = strlen(src);
+ if (len >= maxlength)
+ len = maxlength - 1;
+
+ for(i = 0; i < len; i++) {
+ int val = (src[i] & 0xff);
+ if(isupper(val) ||islower(val) || isdigit(val))
+ dest[i] = src[i];
+ else
+ dest[i] = '_';
+ }
+
+ dest[i] = '\0';
+
+ return dest;
}
/****************************************************************************
-like strncpy but always null terminates. Make sure there is room!
+ Like strncpy but always null terminates. Make sure there is room!
+ The variable n should always be one less than the available size.
****************************************************************************/
+
char *StrnCpy(char *dest,const char *src,size_t n)
{
char *d = dest;
@@ -837,12 +906,11 @@ char *StrnCpy(char *dest,const char *src,size_t n)
return(dest);
}
-
/****************************************************************************
like strncpy but copies up to the character marker. always null terminates.
returns a pointer to the character marker in the source string (src).
****************************************************************************/
-char *strncpyn(char *dest, char *src,size_t n, char c)
+char *strncpyn(char *dest, const char *src,size_t n, char c)
{
char *p;
size_t str_len;
@@ -1003,29 +1071,42 @@ enough room!
This routine looks for pattern in s and replaces it with
insert. It may do multiple replacements.
-any of " ; ' or ` in the insert string are replaced with _
+any of " ; ' $ or ` in the insert string are replaced with _
+if len==0 then no length check is performed
****************************************************************************/
-void string_sub(char *s,const char *pattern,const char *insert)
+void string_sub(char *s,const char *pattern,const char *insert, size_t len)
{
char *p;
- size_t ls,lp,li, i;
+ ssize_t ls,lp,li, i;
if (!insert || !pattern || !s) return;
- ls = strlen(s);
- lp = strlen(pattern);
- li = strlen(insert);
+ ls = (ssize_t)strlen(s);
+ lp = (ssize_t)strlen(pattern);
+ li = (ssize_t)strlen(insert);
if (!*pattern) return;
while (lp <= ls && (p = strstr(s,pattern))) {
- memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
+ if (len && (ls + (li-lp) >= len)) {
+ DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
+ (int)(ls + (li-lp) - len),
+ pattern, (int)len));
+ break;
+ }
+ if (li != lp) {
+ memmove(p+li,p+lp,strlen(p+lp)+1);
+ }
for (i=0;i<li;i++) {
switch (insert[i]) {
case '`':
case '"':
case '\'':
case ';':
+ case '$':
+ case '%':
+ case '\r':
+ case '\n':
p[i] = '_';
break;
default:
@@ -1037,26 +1118,44 @@ void string_sub(char *s,const char *pattern,const char *insert)
}
}
+void fstring_sub(char *s,const char *pattern,const char *insert)
+{
+ string_sub(s, pattern, insert, sizeof(fstring));
+}
+
+void pstring_sub(char *s,const char *pattern,const char *insert)
+{
+ string_sub(s, pattern, insert, sizeof(pstring));
+}
/****************************************************************************
similar to string_sub() but allows for any character to be substituted.
Use with caution!
+if len==0 then no length check is performed
****************************************************************************/
-void all_string_sub(char *s,const char *pattern,const char *insert)
+void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
{
char *p;
- size_t ls,lp,li;
+ ssize_t ls,lp,li;
if (!insert || !pattern || !s) return;
- ls = strlen(s);
- lp = strlen(pattern);
- li = strlen(insert);
+ ls = (ssize_t)strlen(s);
+ lp = (ssize_t)strlen(pattern);
+ li = (ssize_t)strlen(insert);
if (!*pattern) return;
while (lp <= ls && (p = strstr(s,pattern))) {
- memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
+ if (len && (ls + (li-lp) >= len)) {
+ DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
+ (int)(ls + (li-lp) - len),
+ pattern, (int)len));
+ break;
+ }
+ if (li != lp) {
+ memmove(p+li,p+lp,strlen(p+lp)+1);
+ }
memcpy(p, insert, li);
s = p + li;
ls += (li-lp);
@@ -1066,38 +1165,6 @@ void all_string_sub(char *s,const char *pattern,const char *insert)
/****************************************************************************
splits out the front and back at a separator.
****************************************************************************/
-void split_at_first_component(char *path, char *front, char sep, char *back)
-{
- char *p = strchr(path, sep);
-
- if (p != NULL)
- {
- *p = 0;
- }
- if (front != NULL)
- {
- pstrcpy(front, path);
- }
- if (p != NULL)
- {
- if (back != NULL)
- {
- pstrcpy(back, p+1);
- }
- *p = sep;
- }
- else
- {
- if (back != NULL)
- {
- back[0] = 0;
- }
- }
-}
-
-/****************************************************************************
- splits out the front and back at a separator.
-****************************************************************************/
void split_at_last_component(char *path, char *front, char sep, char *back)
{
char *p = strrchr(path, sep);
@@ -1116,7 +1183,7 @@ void split_at_last_component(char *path, char *front, char sep, char *back)
{
pstrcpy(back, p+1);
}
- *p = sep;
+ *p = '\\';
}
else
{
@@ -1127,72 +1194,28 @@ void split_at_last_component(char *path, char *front, char sep, char *back)
}
}
-/****************************************************************************
-convert a bit field to a string. if you want multiple bits to be detected
-set them first, e.g SV_TYPE_ALL to be "All" or "Full Control" for ACB_INFOs.
-
-strings are expected to contain their own separators, although the code
-below only assumes that separators are spaces.
+/****************************************************************************
+write an octal as a string
****************************************************************************/
-char *bit_field_to_str(uint32 type, struct field_info *bs)
+char *octal_string(int i)
{
- static fstring typestr;
- int i = 0;
-
- typestr[0] = 0;
-
- if (type == 0 || bs == NULL)
- {
- return NULL;
- }
-
- while (bs[i].str != NULL && type != 0)
- {
- if (IS_BITS_SET_ALL(bs[i].bits, type))
- {
- fstrcat(typestr, bs[i].str);
- type &= ~bs[i].bits;
- }
- i++;
- }
-
- i = strlen(typestr)-1;
- if (i > 0 && typestr[i] == ' ')
- {
- typestr[i] = 0;
+ static char ret[64];
+ if (i == -1) {
+ return "-1";
}
-
- return typestr;
+ slprintf(ret, sizeof(ret), "0%o", i);
+ return ret;
}
+
/****************************************************************************
-convert an enumeration to a string. first item is the default.
+truncate a string at a specified length
****************************************************************************/
-char *enum_field_to_str(uint32 type, struct field_info *bs, BOOL first_default)
+char *string_truncate(char *s, int length)
{
- int i = 0;
-
- if (bs == NULL)
- {
- return NULL;
+ if (s && strlen(s) > length) {
+ s[length] = 0;
}
-
- while (bs[i].str != NULL && type != 0)
- {
- if (bs[i].bits == type)
- {
- return bs[i].str;
- }
- i++;
- }
-
- /* oops - none found */
-
- if (first_default)
- {
- return bs[0].str;
- }
-
- return NULL;
+ return s;
}
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index 6f90528bf4..aee2a21fc0 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -21,287 +21,538 @@
#include "includes.h"
-/*******************************************************************
- Put an ASCII string into a UNICODE buffer (little endian).
- ********************************************************************/
+extern int DEBUGLEVEL;
-char *ascii_to_unibuf(char *dest, const char *src, int maxlen)
-{
- char *destend = dest + maxlen;
- register char c;
-
- while (dest < destend)
- {
- c = *(src++);
- if (c == 0)
- {
- break;
- }
+/*
+ * The following are the codepage to ucs2 and vica versa maps.
+ * These are dynamically loaded from a unicode translation file.
+ */
- *(dest++) = c;
- *(dest++) = 0;
- }
+static smb_ucs2_t *doscp_to_ucs2;
+static uint16 *ucs2_to_doscp;
- *dest++ = 0;
- *dest++ = 0;
- return dest;
-}
+static smb_ucs2_t *unixcp_to_ucs2;
+static uint16 *ucs2_to_unixcp;
+#ifndef MAXUNI
+#define MAXUNI 1024
+#endif
/*******************************************************************
- Pull an ASCII string out of a UNICODE buffer (little endian).
- ********************************************************************/
+ Write a string in (little-endian) unicode format. src is in
+ the current DOS codepage. len is the length in bytes of the
+ string pointed to by dst.
-const char* unibuf_to_ascii(char *dest, const char *src, int maxlen)
-{
- char *destend = dest + maxlen;
- register char c;
-
- while (dest < destend)
- {
- c = *(src++);
- if ((c == 0) && (*src == 0))
- {
- break;
- }
+ the return value is the length of the string *without* the trailing
+ two bytes of zero
+********************************************************************/
- *dest++ = c;
- src++;
+int dos_PutUniCode(char *dst,const char *src, ssize_t len)
+{
+ int ret = 0;
+ while (*src && (len > 2)) {
+ size_t skip = skip_multibyte_char(*src);
+ smb_ucs2_t val = (*src & 0xff);
+
+ /*
+ * If this is a multibyte character (and all DOS/Windows
+ * codepages have at maximum 2 byte multibyte characters)
+ * then work out the index value for the unicode conversion.
+ */
+
+ if (skip == 2)
+ val = ((val << 8) | src[1]);
+
+ SSVAL(dst,ret,doscp_to_ucs2[val]);
+ ret += 2;
+ len -= 2;
+ if (skip)
+ src += skip;
+ else
+ src++;
}
+ SSVAL(dst,ret,0);
+ return(ret);
+}
- *dest = 0;
+/*******************************************************************
+ Skip past some unicode strings in a buffer.
+********************************************************************/
- return src;
+char *skip_unicode_string(char *buf,int n)
+{
+ while (n--) {
+ while (*buf)
+ buf += 2;
+ buf += 2;
+ }
+ return(buf);
}
-
/*******************************************************************
- Put an ASCII string into a UNICODE array (uint16's).
- ********************************************************************/
+ Return a DOS codepage version of a little-endian unicode string.
+ Hack alert: uses fixed buffer(s).
+********************************************************************/
-void ascii_to_unistr(uint16 *dest, const char *src, int maxlen)
+char *dos_unistrn2(uint16 *src, int len)
{
- uint16 *destend = dest + maxlen;
- register char c;
-
- while (dest < destend)
- {
- c = *(src++);
- if (c == 0)
- {
- break;
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
+
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
}
-
- *(dest++) = (uint16)c;
}
- *dest = 0;
+ *p = 0;
+ return lbuf;
}
+static char lbufs[8][MAXUNI];
+static int nexti;
/*******************************************************************
- Pull an ASCII string out of a UNICODE array (uint16's).
- ********************************************************************/
+ Return a DOS codepage version of a little-endian unicode string.
+ Hack alert: uses fixed buffer(s).
+********************************************************************/
-void unistr_to_ascii(char *dest, const uint16 *src, int len)
+char *dos_unistr2(uint16 *src)
{
- char *destend = dest + len;
- register uint16 c;
-
- while (dest < destend)
- {
- c = *(src++);
- if (c == 0)
- {
- break;
- }
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *src && (p-lbuf < MAXUNI-3); src++) {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
- *(dest++) = (char)c;
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
+ }
}
- *dest = 0;
+ *p = 0;
+ return lbuf;
}
-
/*******************************************************************
- Convert a UNISTR2 structure to an ASCII string
- ********************************************************************/
+Return a DOS codepage version of a little-endian unicode string
+********************************************************************/
-void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
+char *dos_unistr2_to_str(UNISTR2 *str)
{
- char *destend;
- const uint16 *src;
- size_t len;
- register uint16 c;
-
- src = str->buffer;
- len = MIN(str->uni_str_len, maxlen);
- destend = dest + len;
-
- while (dest < destend)
- {
- c = *(src++);
- if (c == 0)
- {
- break;
+ char *lbuf = lbufs[nexti];
+ char *p;
+ uint16 *src = str->buffer;
+ int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len);
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *src && p-lbuf < max_size; src++) {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
+
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
}
-
- *(dest++) = (char)c;
}
- *dest = 0;
+ *p = 0;
+ return lbuf;
}
-
/*******************************************************************
- Skip a UNICODE string in a little endian buffer.
- ********************************************************************/
+Return a number stored in a buffer
+********************************************************************/
-char *skip_unibuf(char *srcbuf, int len)
+uint32 buffer2_to_uint32(BUFFER2 *str)
{
- uint16 *src = (uint16 *)srcbuf;
- uint16 *srcend = src + len/2;
+ if (str->buf_len == 4)
+ return IVAL(str->buffer, 0);
+ else
+ return 0;
+}
- while ((src < srcend) && (*(src++) != 0))
- {
+/*******************************************************************
+Return a DOS codepage version of a NOTunicode string
+********************************************************************/
+
+char *dos_buffer2_to_str(BUFFER2 *str)
+{
+ char *lbuf = lbufs[nexti];
+ char *p;
+ uint16 *src = str->buffer;
+ int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *src && p-lbuf < max_size; src++) {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
+
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
+ }
}
- return (char *)src;
+ *p = 0;
+ return lbuf;
}
-
/*******************************************************************
- UNICODE strcpy between buffers.
- ********************************************************************/
+ Return a dos codepage version of a NOTunicode string
+********************************************************************/
-char *uni_strncpy(char *destbuf, const char *srcbuf, int len)
+char *dos_buffer2_to_multistr(BUFFER2 *str)
{
- const uint16 *src = (const uint16 *)srcbuf;
- uint16 *dest = (uint16 *)destbuf;
- uint16 *destend = dest + len/2;
- register uint16 c;
-
- while (dest < destend)
- {
- c = *(src++);
- if (c == 0)
- {
- break;
+ char *lbuf = lbufs[nexti];
+ char *p;
+ uint16 *src = str->buffer;
+ int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; p-lbuf < max_size; src++) {
+ if (*src == 0) {
+ *p++ = ' ';
+ } else {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
+
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
+ }
}
-
- *(dest++) = c;
}
- *dest++ = 0;
- return (char *)dest;
+ *p = 0;
+ return lbuf;
}
-
/*******************************************************************
- Return a number stored in a buffer
- ********************************************************************/
+ Create a null-terminated unicode string from a null-terminated DOS
+ codepage string.
+ Return number of unicode chars copied, excluding the null character.
+ Unicode strings created are in little-endian format.
+********************************************************************/
-uint32 buffer2_to_uint32(const BUFFER2 *str)
+size_t dos_struni2(char *dst, const char *src, size_t max_len)
{
- if (str->buf_len == 4)
- {
- const uchar *src = str->buffer;
- return IVAL(src, 0);
- }
- else
- {
+ size_t len = 0;
+
+ if (dst == NULL)
return 0;
+
+ if (src != NULL) {
+ for (; *src && len < max_len-2; len++, dst +=2) {
+ size_t skip = skip_multibyte_char(*src);
+ smb_ucs2_t val = (*src & 0xff);
+
+ /*
+ * If this is a multibyte character (and all DOS/Windows
+ * codepages have at maximum 2 byte multibyte characters)
+ * then work out the index value for the unicode conversion.
+ */
+
+ if (skip == 2)
+ val = ((val << 8) | src[1]);
+
+ SSVAL(dst,0,doscp_to_ucs2[val]);
+ if (skip)
+ src += skip;
+ else
+ src++;
+ }
}
-}
+ SSVAL(dst,0,0);
+
+ return len;
+}
/*******************************************************************
- Convert a 'multi-string' buffer to space-separated ASCII.
- ********************************************************************/
-void buffer2_to_multistr(char *dest, const BUFFER2 *str, size_t maxlen)
+ Return a DOS codepage version of a little-endian unicode string.
+ Hack alert: uses fixed buffer(s).
+********************************************************************/
+
+char *dos_unistr(char *buf)
{
- char *destend;
- const uchar *src;
- size_t len;
- register uint16 c;
-
- src = str->buffer;
- len = MIN(str->buf_len/2, maxlen);
- destend = dest + len;
-
- while (dest < destend)
- {
- c = *(src++);
- *(dest++) = (c == 0) ? ' ' : (char)c;
- src++;
+ char *lbuf = lbufs[nexti];
+ uint16 *src = (uint16 *)buf;
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *src && p-lbuf < MAXUNI-3; src++) {
+ uint16 ucs2_val = SVAL(src,0);
+ uint16 cp_val = ucs2_to_doscp[ucs2_val];
+
+ if (cp_val < 256)
+ *p++ = (char)cp_val;
+ else {
+ *p++ = (cp_val >> 8) & 0xff;
+ *p++ = (cp_val & 0xff);
+ }
}
- *dest = 0;
+ *p = 0;
+ return lbuf;
}
/*******************************************************************
- Convert a buffer4 to space-separated ASCII.
- ********************************************************************/
-void buffer4_to_str(char *dest, const BUFFER4 *str, size_t maxlen)
+ Strcpy for unicode strings. returns length (in num of wide chars)
+********************************************************************/
+
+int unistrcpy(char *dst, char *src)
{
- char *destend;
- const uchar *src;
- size_t len;
- register uint16 c;
-
- src = str->buffer;
- len = MIN(str->buf_len, maxlen);
- destend = dest + len;
-
- while (dest < destend)
- {
- c = *(src++);
- *(dest++) = (char)c;
+ int num_wchars = 0;
+ uint16 *wsrc = (uint16 *)src;
+ uint16 *wdst = (uint16 *)dst;
+
+ while (*wsrc) {
+ *wdst++ = *wsrc++;
+ num_wchars++;
}
+ *wdst = 0;
- *dest = 0;
+ return num_wchars;
}
+
+
/*******************************************************************
-copies a UNISTR2 structure.
+ free any existing maps
********************************************************************/
-BOOL copy_unistr2(UNISTR2 *str, const UNISTR2 *from)
+static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
- if (from != NULL)
- {
- /* set up string lengths. add one if string is not null-terminated */
- str->uni_max_len = from->uni_max_len;
- str->undoc = from->undoc;
- str->uni_str_len = from->uni_str_len;
-
- /* copy the string */
- memcpy(str->buffer, from->buffer, sizeof(from->buffer));
+ /* this handles identity mappings where we share the pointer */
+ if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
+ *pp_ucs2_to_cp = NULL;
}
- else
- {
- str->uni_max_len = 1;
- str->undoc = 0;
- str->uni_str_len = 1;
- str->buffer[0] = 0;
+
+ if (*pp_cp_to_ucs2) {
+ free(*pp_cp_to_ucs2);
+ *pp_cp_to_ucs2 = NULL;
}
- return True;
+ if (*pp_ucs2_to_cp) {
+ free(*pp_ucs2_to_cp);
+ *pp_ucs2_to_cp = NULL;
+ }
}
+
/*******************************************************************
-duplicates a UNISTR2 structure.
+ Build a default (null) codepage to unicode map.
********************************************************************/
-UNISTR2 *unistr2_dup(const UNISTR2 *name)
+
+void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
- UNISTR2 *copy = (UNISTR2*)malloc(sizeof(*copy));
- copy_unistr2(copy, name);
- return copy;
+ int i;
+
+ free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
+
+ if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) {
+ DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536));
+ abort();
+ }
+
+ *pp_cp_to_ucs2 = *pp_ucs2_to_cp; /* Default map is an identity. */
+ for (i = 0; i < 65536; i++)
+ (*pp_cp_to_ucs2)[i] = i;
}
/*******************************************************************
-frees a UNISTR2 structure.
+ Load a codepage to unicode and vica-versa map.
********************************************************************/
-void unistr2_free(UNISTR2 *name)
+
+BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
- free(name);
+ pstring unicode_map_file_name;
+ FILE *fp = NULL;
+ SMB_STRUCT_STAT st;
+ smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2;
+ uint16 *ucs2_to_cp = *pp_ucs2_to_cp;
+ size_t cp_to_ucs2_size;
+ size_t ucs2_to_cp_size;
+ size_t i;
+ size_t size;
+ char buf[UNICODE_MAP_HEADER_SIZE];
+
+ DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage));
+
+ if (*codepage == '\0')
+ goto clean_and_exit;
+
+ if(strlen(CODEPAGEDIR) + 13 + strlen(codepage) > sizeof(unicode_map_file_name)) {
+ DEBUG(0,("load_unicode_map: filename too long to load\n"));
+ goto clean_and_exit;
+ }
+
+ pstrcpy(unicode_map_file_name, CODEPAGEDIR);
+ pstrcat(unicode_map_file_name, "/");
+ pstrcat(unicode_map_file_name, "unicode_map.");
+ pstrcat(unicode_map_file_name, codepage);
+
+ if(sys_stat(unicode_map_file_name,&st)!=0) {
+ DEBUG(0,("load_unicode_map: filename %s does not exist.\n",
+ unicode_map_file_name));
+ goto clean_and_exit;
+ }
+
+ size = st.st_size;
+
+ if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) {
+ DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \
+unicode map file (size=%d).\n", unicode_map_file_name, (int)size));
+ goto clean_and_exit;
+ }
+
+ if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) {
+ DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n",
+ unicode_map_file_name, strerror(errno)));
+ goto clean_and_exit;
+ }
+
+ if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) {
+ DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n",
+ unicode_map_file_name, strerror(errno)));
+ goto clean_and_exit;
+ }
+
+ /* Check the version value */
+ if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) {
+ DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \
+Needed %hu, got %hu.\n",
+ unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID,
+ SVAL(buf,UNICODE_MAP_VERSION_OFFSET)));
+ goto clean_and_exit;
+ }
+
+ /* Check the codepage value */
+ if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) {
+ DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \
+requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage ));
+ goto clean_and_exit;
+ }
+
+ ucs2_to_cp_size = 2*65536;
+ if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) {
+ /*
+ * This is a multibyte code page.
+ */
+ cp_to_ucs2_size = 2*65536;
+ } else {
+ /*
+ * Single byte code page.
+ */
+ cp_to_ucs2_size = 2*256;
+ }
+
+ /*
+ * Free any old translation tables.
+ */
+
+ free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
+
+ if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) {
+ DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size ));
+ goto clean_and_exit;
+ }
+
+ if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) {
+ DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size ));
+ goto clean_and_exit;
+ }
+
+ if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) {
+ DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n",
+ unicode_map_file_name, strerror(errno)));
+ goto clean_and_exit;
+ }
+
+ if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) {
+ DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n",
+ unicode_map_file_name, strerror(errno)));
+ goto clean_and_exit;
+ }
+
+ /*
+ * Now ensure the 16 bit values are in the correct endianness.
+ */
+
+ for (i = 0; i < cp_to_ucs2_size/2; i++)
+ cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2);
+
+ for (i = 0; i < ucs2_to_cp_size/2; i++)
+ ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2);
+
+ fclose(fp);
+
+ *pp_cp_to_ucs2 = cp_to_ucs2;
+ *pp_ucs2_to_cp = ucs2_to_cp;
+
+ return True;
+
+clean_and_exit:
+
+ /* pseudo destructor :-) */
+
+ if(fp != NULL)
+ fclose(fp);
+
+ free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
+
+ default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp);
+
+ return False;
+}
+
+/*******************************************************************
+ Load a dos codepage to unicode and vica-versa map.
+********************************************************************/
+
+BOOL load_dos_unicode_map(int codepage)
+{
+ fstring codepage_str;
+
+ slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
+ return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
+}
+
+/*******************************************************************
+ Load a UNIX codepage to unicode and vica-versa map.
+********************************************************************/
+
+BOOL load_unix_unicode_map(const char *unix_char_set)
+{
+ fstring upper_unix_char_set;
+
+ fstrcpy(upper_unix_char_set, unix_char_set);
+ strupper(upper_unix_char_set);
+ return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);
}