[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / smbd / srvstr.c
index 36fecf5bd2ea9533fe4291e65a1a0072ed73d172..68e61033ae1a30b482073a53ca62fb534a52afef 100644 (file)
@@ -2,10 +2,11 @@
    Unix SMB/CIFS implementation.
    server specific string routines
    Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+extern int max_send;
 
-int srvstr_push(void *base_ptr, void *dest, const char *src, int dest_len, int flags)
-{
-       return push_string(base_ptr, dest, src, dest_len, flags);
-}
+/* Make sure we can't write a string past the end of the buffer */
 
-int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int src_len, 
-               int flags)
+size_t srvstr_push_fn(const char *function, unsigned int line, 
+                     const char *base_ptr, uint16 smb_flags2, void *dest,
+                     const char *src, int dest_len, int flags)
 {
-       return pull_string(base_ptr, dest, src, dest_len, src_len, flags);
+       size_t buf_used = PTR_DIFF(dest, base_ptr);
+       if (dest_len == -1) {
+               if (((ptrdiff_t)dest < (ptrdiff_t)base_ptr) || (buf_used > (size_t)max_send)) {
+#if 0
+                       DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n"));
+#endif
+                       return push_string_fn(function, line, base_ptr,
+                                             smb_flags2, dest, src, -1,
+                                             flags);
+               }
+               return push_string_fn(function, line, base_ptr, smb_flags2,
+                                     dest, src, max_send - buf_used, flags);
+       }
+       
+       /* 'normal' push into size-specified buffer */
+       return push_string_fn(function, line, base_ptr, smb_flags2, dest, src,
+                             dest_len, flags);
 }
 
-/* pull a string from the smb_buf part of a packet. In this case the
-   string can either be null terminated or it can be terminated by the
-   end of the smbbuf area 
-*/
-int srvstr_pull_buf(void *inbuf, char *dest, const void *src, int dest_len, int flags)
+/*******************************************************************
+ Add a string to the end of a smb_buf, adjusting bcc and smb_len.
+ Return the bytes added
+********************************************************************/
+
+ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
 {
-       return pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags);
+       size_t buf_size = smb_len(*outbuf) + 4;
+       size_t grow_size;
+       size_t result;
+       uint8 *tmp;
+
+       /*
+        * We need to over-allocate, now knowing what srvstr_push will
+        * actually use. This is very generous by incorporating potential
+        * padding, the terminating 0 and at most 4 chars per UTF-16 code
+        * point.
+        */
+       grow_size = (strlen(str) + 2) * 4;
+
+       if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8,
+                                        buf_size + grow_size))) {
+               DEBUG(0, ("talloc failed\n"));
+               return -1;
+       }
+
+       result = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
+                            tmp + buf_size, str, grow_size, flags);
+
+       if (result == (size_t)-1) {
+               DEBUG(0, ("srvstr_push failed\n"));
+               return -1;
+       }
+       set_message_bcc((char *)tmp, smb_buflen(tmp) + result);
+
+       *outbuf = tmp;
+
+       return result;
 }