Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Samba utility functions
4 :
5 : Copyright (C) Andrew Tridgell 1992-2001
6 : Copyright (C) Simo Sorce 2001-2002
7 : Copyright (C) Martin Pool 2003
8 : Copyright (C) James Peach 2006
9 : Copyright (C) Jeremy Allison 1992-2007
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "lib/param/loadparm.h"
27 : #include "lib/util/smb_strtox.h"
28 :
29 : static const char toupper_ascii_fast_table[128] = {
30 : 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
31 : 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
32 : 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
33 : 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34 : 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
35 : 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
36 : 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
37 : 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
38 : };
39 :
40 : /**
41 : * Compare 2 strings up to and including the nth char.
42 : *
43 : * @note The comparison is case-insensitive.
44 : **/
45 4079453 : bool strnequal(const char *s1,const char *s2,size_t n)
46 : {
47 4079453 : if (s1 == s2)
48 0 : return(true);
49 4079453 : if (!s1 || !s2 || !n)
50 0 : return(false);
51 :
52 4079453 : return(strncasecmp_m(s1,s2,n)==0);
53 : }
54 :
55 : /**
56 : Skip past a string in a buffer. Buffer may not be
57 : null terminated. end_ptr points to the first byte after
58 : then end of the buffer.
59 : **/
60 :
61 1685 : char *skip_string(const char *base, size_t len, char *buf)
62 : {
63 1685 : const char *end_ptr = base + len;
64 :
65 1685 : if (end_ptr < base || !base || !buf || buf >= end_ptr) {
66 0 : return NULL;
67 : }
68 :
69 : /* Skip the string */
70 20636 : while (*buf) {
71 18951 : buf++;
72 18951 : if (buf >= end_ptr) {
73 0 : return NULL;
74 : }
75 : }
76 : /* Skip the '\0' */
77 1685 : buf++;
78 1685 : return buf;
79 : }
80 :
81 : /**
82 : Count the number of characters in a string. Normally this will
83 : be the same as the number of bytes in a string for single byte strings,
84 : but will be different for multibyte.
85 : **/
86 :
87 6 : size_t str_charnum(const char *s)
88 : {
89 0 : size_t ret, converted_size;
90 6 : smb_ucs2_t *tmpbuf2 = NULL;
91 6 : if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
92 0 : return 0;
93 : }
94 6 : ret = strlen_w(tmpbuf2);
95 6 : TALLOC_FREE(tmpbuf2);
96 6 : return ret;
97 : }
98 :
99 3242559 : bool trim_char(char *s,char cfront,char cback)
100 : {
101 3242559 : bool ret = false;
102 37105 : char *ep;
103 3242559 : char *fp = s;
104 :
105 : /* Ignore null or empty strings. */
106 3242559 : if (!s || (s[0] == '\0'))
107 1295900 : return false;
108 :
109 1932718 : if (cfront) {
110 1926035 : while (*fp && *fp == cfront)
111 150 : fp++;
112 1925885 : if (!*fp) {
113 : /* We ate the string. */
114 4 : s[0] = '\0';
115 4 : return true;
116 : }
117 1925881 : if (fp != s)
118 18 : ret = true;
119 : }
120 :
121 1932714 : ep = fp + strlen(fp) - 1;
122 1932714 : if (cback) {
123 : /* Attempt ascii only. Bail for mb strings. */
124 1950417 : while ((ep >= fp) && (*ep == cback)) {
125 17721 : ret = true;
126 17721 : if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
127 : /* Could be mb... bail back to tim_string. */
128 0 : char fs[2], bs[2];
129 0 : if (cfront) {
130 0 : fs[0] = cfront;
131 0 : fs[1] = '\0';
132 : }
133 0 : bs[0] = cback;
134 0 : bs[1] = '\0';
135 0 : return trim_string(s, cfront ? fs : NULL, bs);
136 : } else {
137 17721 : ep--;
138 : }
139 : }
140 1932696 : if (ep < fp) {
141 : /* We ate the string. */
142 0 : s[0] = '\0';
143 0 : return true;
144 : }
145 : }
146 :
147 1932714 : ep[1] = '\0';
148 1932714 : memmove(s, fp, ep-fp+2);
149 1932714 : return ret;
150 : }
151 :
152 : /**
153 : Check if a string is part of a list.
154 : **/
155 :
156 32027 : bool in_list(const char *s, const char *list, bool casesensitive)
157 : {
158 32027 : char *tok = NULL;
159 32027 : bool ret = false;
160 176 : TALLOC_CTX *frame;
161 :
162 32027 : if (!list) {
163 952 : return false;
164 : }
165 :
166 31075 : frame = talloc_stackframe();
167 31075 : while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
168 0 : if (casesensitive) {
169 0 : if (strcmp(tok,s) == 0) {
170 0 : ret = true;
171 0 : break;
172 : }
173 : } else {
174 0 : if (strcasecmp_m(tok,s) == 0) {
175 0 : ret = true;
176 0 : break;
177 : }
178 : }
179 : }
180 31075 : TALLOC_FREE(frame);
181 30899 : return ret;
182 : }
183 :
184 : /**
185 : Truncate a string at a specified length.
186 : **/
187 :
188 746 : char *string_truncate(char *s, unsigned int length)
189 : {
190 746 : if (s && strlen(s) > length)
191 0 : s[length] = 0;
192 746 : return s;
193 : }
194 :
195 :
196 : /***********************************************************************
197 : Return the equivalent of doing strrchr 'n' times - always going
198 : backwards.
199 : ***********************************************************************/
200 :
201 0 : char *strnrchr_m(const char *s, char c, unsigned int n)
202 : {
203 0 : smb_ucs2_t *ws = NULL;
204 0 : char *s2 = NULL;
205 0 : smb_ucs2_t *p;
206 0 : char *ret;
207 0 : size_t converted_size;
208 :
209 0 : if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
210 : /* Too hard to try and get right. */
211 0 : return NULL;
212 : }
213 0 : p = strnrchr_w(ws, UCS2_CHAR(c), n);
214 0 : if (!p) {
215 0 : TALLOC_FREE(ws);
216 0 : return NULL;
217 : }
218 0 : *p = 0;
219 0 : if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
220 0 : TALLOC_FREE(ws);
221 : /* Too hard to try and get right. */
222 0 : return NULL;
223 : }
224 0 : ret = discard_const_p(char, (s+strlen(s2)));
225 0 : TALLOC_FREE(ws);
226 0 : TALLOC_FREE(s2);
227 0 : return ret;
228 : }
229 :
230 0 : static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
231 : {
232 0 : size_t size;
233 0 : smb_ucs2_t *buffer = NULL;
234 0 : bool ret;
235 :
236 0 : if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
237 : (void **)(void *)&buffer, &size))
238 : {
239 0 : return false;
240 : }
241 0 : if (!strlower_w(buffer) && (dest == src)) {
242 0 : TALLOC_FREE(buffer);
243 0 : return true;
244 : }
245 0 : ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
246 0 : TALLOC_FREE(buffer);
247 0 : return ret;
248 : }
249 :
250 : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
251 :
252 : /**
253 : Convert a string to lower case.
254 : **/
255 : _PUBLIC_ void strlower_m(char *s)
256 : {
257 : char *d;
258 : struct smb_iconv_handle *iconv_handle;
259 :
260 : iconv_handle = get_iconv_handle();
261 :
262 : d = s;
263 :
264 : while (*s) {
265 : size_t c_size, c_size2;
266 : codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
267 : c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
268 : if (c_size2 > c_size) {
269 : DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
270 : c, tolower_m(c), (int)c_size, (int)c_size2));
271 : smb_panic("codepoint expansion in strlower_m\n");
272 : }
273 : s += c_size;
274 : d += c_size2;
275 : }
276 : *d = 0;
277 : }
278 :
279 : #endif
280 :
281 : /**
282 : Convert a string to lower case.
283 : **/
284 :
285 4843200 : bool strlower_m(char *s)
286 : {
287 6209 : size_t len;
288 6209 : int errno_save;
289 4843200 : bool ret = false;
290 :
291 : /* this is quite a common operation, so we want it to be
292 : fast. We optimise for the ascii case, knowing that all our
293 : supported multi-byte character sets are ascii-compatible
294 : (ie. they match for the first 128 chars) */
295 :
296 55703266 : while (*s && !(((unsigned char)s[0]) & 0x80)) {
297 50860066 : *s = tolower_m((unsigned char)*s);
298 50860066 : s++;
299 : }
300 :
301 4843200 : if (!*s)
302 4836991 : return true;
303 :
304 : /* I assume that lowercased string takes the same number of bytes
305 : * as source string even in UTF-8 encoding. (VIV) */
306 0 : len = strlen(s) + 1;
307 0 : errno_save = errno;
308 0 : errno = 0;
309 0 : ret = unix_strlower(s,len,s,len);
310 : /* Catch mb conversion errors that may not terminate. */
311 0 : if (errno) {
312 0 : s[len-1] = '\0';
313 : }
314 0 : errno = errno_save;
315 0 : return ret;
316 : }
317 :
318 44 : static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
319 : {
320 0 : size_t size;
321 0 : smb_ucs2_t *buffer;
322 0 : bool ret;
323 :
324 44 : if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
325 40 : return false;
326 : }
327 :
328 4 : if (!strupper_w(buffer) && (dest == src)) {
329 4 : TALLOC_FREE(buffer);
330 4 : return true;
331 : }
332 :
333 0 : ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
334 0 : TALLOC_FREE(buffer);
335 0 : return ret;
336 : }
337 :
338 : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
339 :
340 : /**
341 : Convert a string to UPPER case.
342 : **/
343 : _PUBLIC_ void strupper_m(char *s)
344 : {
345 : char *d;
346 : struct smb_iconv_handle *iconv_handle;
347 :
348 : iconv_handle = get_iconv_handle();
349 :
350 : d = s;
351 :
352 : while (*s) {
353 : size_t c_size, c_size2;
354 : codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
355 : c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
356 : if (c_size2 > c_size) {
357 : DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
358 : c, toupper_m(c), (int)c_size, (int)c_size2));
359 : smb_panic("codepoint expansion in strupper_m\n");
360 : }
361 : s += c_size;
362 : d += c_size2;
363 : }
364 : *d = 0;
365 : }
366 :
367 : #endif
368 :
369 : /**
370 : Convert a string to upper case.
371 : **/
372 :
373 7852362 : bool strupper_m(char *s)
374 : {
375 6700 : size_t len;
376 7852362 : bool ret = false;
377 :
378 : /* this is quite a common operation, so we want it to be
379 : fast. We optimise for the ascii case, knowing that all our
380 : supported multi-byte character sets are ascii-compatible
381 : (ie. they match for the first 128 chars) */
382 :
383 328829468 : while (*s && !(((unsigned char)s[0]) & 0x80)) {
384 320977106 : *s = toupper_ascii_fast_table[(unsigned char)s[0]];
385 320977106 : s++;
386 : }
387 :
388 7852362 : if (!*s)
389 7845618 : return true;
390 :
391 : /* I assume that uppercased string takes the same number of bytes
392 : * as source string even in multibyte encoding. (VIV) */
393 44 : len = strlen(s) + 1;
394 44 : ret = unix_strupper(s,len,s,len);
395 : /* Catch mb conversion errors that may not terminate. */
396 44 : if (!ret) {
397 40 : s[len-1] = '\0';
398 : }
399 44 : return ret;
400 : }
401 :
402 : /**
403 : Just a typesafety wrapper for snprintf into a fstring.
404 : **/
405 :
406 2170119 : int fstr_sprintf(fstring s, const char *fmt, ...)
407 : {
408 18259 : va_list ap;
409 18259 : int ret;
410 :
411 2170119 : va_start(ap, fmt);
412 2170119 : ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
413 2170119 : va_end(ap);
414 2170119 : return ret;
415 : }
416 :
417 : /* read a SMB_BIG_UINT from a string */
418 5948 : uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
419 : {
420 :
421 5948 : uint64_t val = (uint64_t)-1;
422 5948 : const char *p = nptr;
423 :
424 5948 : if (!p) {
425 0 : if (entptr) {
426 0 : *entptr = p;
427 : }
428 0 : return val;
429 : }
430 :
431 5948 : while (*p && isspace(*p))
432 0 : p++;
433 :
434 5948 : sscanf(p,"%"SCNu64,&val);
435 5948 : if (entptr) {
436 8540 : while (*p && isdigit(*p))
437 3024 : p++;
438 5516 : *entptr = p;
439 : }
440 :
441 5948 : return val;
442 : }
443 :
444 : /* Convert a size specification to a count of bytes. We accept the following
445 : * suffixes:
446 : * bytes if there is no suffix
447 : * kK kibibytes
448 : * mM mebibytes
449 : * gG gibibytes
450 : * tT tibibytes
451 : * pP whatever the ISO name for petabytes is
452 : *
453 : * Returns 0 if the string can't be converted.
454 : */
455 24 : uint64_t conv_str_size(const char * str)
456 : {
457 0 : uint64_t lval;
458 0 : char *end;
459 24 : int error = 0;
460 :
461 24 : if (str == NULL || *str == '\0') {
462 16 : return 0;
463 : }
464 :
465 8 : lval = smb_strtoull(str, &end, 10, &error, SMB_STR_STANDARD);
466 :
467 8 : if (error != 0) {
468 0 : return 0;
469 : }
470 :
471 8 : if (*end == '\0') {
472 0 : return lval;
473 : }
474 :
475 8 : if (strwicmp(end, "K") == 0) {
476 8 : lval *= 1024ULL;
477 0 : } else if (strwicmp(end, "M") == 0) {
478 0 : lval *= (1024ULL * 1024ULL);
479 0 : } else if (strwicmp(end, "G") == 0) {
480 0 : lval *= (1024ULL * 1024ULL *
481 : 1024ULL);
482 0 : } else if (strwicmp(end, "T") == 0) {
483 0 : lval *= (1024ULL * 1024ULL *
484 : 1024ULL * 1024ULL);
485 0 : } else if (strwicmp(end, "P") == 0) {
486 0 : lval *= (1024ULL * 1024ULL *
487 : 1024ULL * 1024ULL *
488 : 1024ULL);
489 : } else {
490 0 : return 0;
491 : }
492 :
493 8 : return lval;
494 : }
495 :
496 134768 : char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
497 : {
498 2010 : va_list ap;
499 2010 : char *ret;
500 :
501 134768 : va_start(ap, fmt);
502 134768 : ret = talloc_vasprintf(t, fmt, ap);
503 134768 : va_end(ap);
504 :
505 134768 : if (ret == NULL) {
506 0 : return NULL;
507 : }
508 134768 : if (!strupper_m(ret)) {
509 0 : TALLOC_FREE(ret);
510 0 : return NULL;
511 : }
512 132758 : return ret;
513 : }
514 :
515 28 : char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
516 : {
517 0 : va_list ap;
518 0 : char *ret;
519 :
520 28 : va_start(ap, fmt);
521 28 : ret = talloc_vasprintf(t, fmt, ap);
522 28 : va_end(ap);
523 :
524 28 : if (ret == NULL) {
525 0 : return NULL;
526 : }
527 28 : if (!strlower_m(ret)) {
528 0 : TALLOC_FREE(ret);
529 0 : return NULL;
530 : }
531 28 : return ret;
532 : }
533 :
534 :
535 : /********************************************************************
536 : Check a string for any occurrences of a specified list of invalid
537 : characters.
538 : ********************************************************************/
539 :
540 998 : bool validate_net_name( const char *name,
541 : const char *invalid_chars,
542 : int max_len)
543 : {
544 0 : int i;
545 :
546 998 : if (!name) {
547 0 : return false;
548 : }
549 :
550 36172 : for ( i=0; i<max_len && name[i]; i++ ) {
551 : /* fail if strchr_m() finds one of the invalid characters */
552 35286 : if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
553 112 : return false;
554 : }
555 : }
556 :
557 886 : return true;
558 : }
559 :
560 :
561 : /*******************************************************************
562 : Add a shell escape character '\' to any character not in a known list
563 : of characters. UNIX charset format.
564 : *******************************************************************/
565 :
566 : #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
567 : #define INSIDE_DQUOTE_LIST "$`\n\"\\"
568 :
569 1004 : char *escape_shell_string(const char *src)
570 : {
571 1004 : size_t srclen = strlen(src);
572 1004 : char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
573 1004 : char *dest = ret;
574 1004 : bool in_s_quote = false;
575 1004 : bool in_d_quote = false;
576 1004 : bool next_escaped = false;
577 :
578 1004 : if (!ret) {
579 0 : return NULL;
580 : }
581 :
582 229490 : while (*src) {
583 0 : size_t c_size;
584 228486 : codepoint_t c = next_codepoint(src, &c_size);
585 :
586 228486 : if (c == INVALID_CODEPOINT) {
587 0 : SAFE_FREE(ret);
588 0 : return NULL;
589 : }
590 :
591 228486 : if (c_size > 1) {
592 0 : memcpy(dest, src, c_size);
593 0 : src += c_size;
594 0 : dest += c_size;
595 0 : next_escaped = false;
596 8676 : continue;
597 : }
598 :
599 : /*
600 : * Deal with backslash escaped state.
601 : * This only lasts for one character.
602 : */
603 :
604 228486 : if (next_escaped) {
605 50 : *dest++ = *src++;
606 50 : next_escaped = false;
607 50 : continue;
608 : }
609 :
610 : /*
611 : * Deal with single quote state. The
612 : * only thing we care about is exiting
613 : * this state.
614 : */
615 :
616 228436 : if (in_s_quote) {
617 0 : if (*src == '\'') {
618 0 : in_s_quote = false;
619 : }
620 0 : *dest++ = *src++;
621 0 : continue;
622 : }
623 :
624 : /*
625 : * Deal with double quote state. The most
626 : * complex state. We must cope with \, meaning
627 : * possibly escape next char (depending what it
628 : * is), ", meaning exit this state, and possibly
629 : * add an \ escape to any unprotected character
630 : * (listed in INSIDE_DQUOTE_LIST).
631 : */
632 :
633 228436 : if (in_d_quote) {
634 8115 : if (*src == '\\') {
635 : /*
636 : * Next character might be escaped.
637 : * We have to peek. Inside double
638 : * quotes only INSIDE_DQUOTE_LIST
639 : * characters are escaped by a \.
640 : */
641 :
642 0 : char nextchar;
643 :
644 100 : c = next_codepoint(&src[1], &c_size);
645 100 : if (c == INVALID_CODEPOINT) {
646 0 : SAFE_FREE(ret);
647 0 : return NULL;
648 : }
649 100 : if (c_size > 1) {
650 : /*
651 : * Don't escape the next char.
652 : * Just copy the \.
653 : */
654 0 : *dest++ = *src++;
655 0 : continue;
656 : }
657 :
658 100 : nextchar = src[1];
659 :
660 100 : if (nextchar && strchr(INSIDE_DQUOTE_LIST,
661 : (int)nextchar)) {
662 50 : next_escaped = true;
663 : }
664 100 : *dest++ = *src++;
665 100 : continue;
666 : }
667 :
668 8015 : if (*src == '\"') {
669 : /* Exit double quote state. */
670 511 : in_d_quote = false;
671 511 : *dest++ = *src++;
672 511 : continue;
673 : }
674 :
675 : /*
676 : * We know the character isn't \ or ",
677 : * so escape it if it's any of the other
678 : * possible unprotected characters.
679 : */
680 :
681 7504 : if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
682 0 : *dest++ = '\\';
683 : }
684 7504 : *dest++ = *src++;
685 7504 : continue;
686 : }
687 :
688 : /*
689 : * From here to the end of the loop we're
690 : * not in the single or double quote state.
691 : */
692 :
693 220321 : if (*src == '\\') {
694 : /* Next character must be escaped. */
695 0 : next_escaped = true;
696 0 : *dest++ = *src++;
697 0 : continue;
698 : }
699 :
700 220321 : if (*src == '\'') {
701 : /* Go into single quote state. */
702 0 : in_s_quote = true;
703 0 : *dest++ = *src++;
704 0 : continue;
705 : }
706 :
707 220321 : if (*src == '\"') {
708 : /* Go into double quote state. */
709 511 : in_d_quote = true;
710 511 : *dest++ = *src++;
711 511 : continue;
712 : }
713 :
714 : /* Check if we need to escape the character. */
715 :
716 219810 : if (!strchr(INCLUDE_LIST, (int)*src)) {
717 13955 : *dest++ = '\\';
718 : }
719 219810 : *dest++ = *src++;
720 : }
721 1004 : *dest++ = '\0';
722 1004 : return ret;
723 : }
724 :
725 : /*
726 : * This routine improves performance for operations temporarily acting on a
727 : * full path. It is equivalent to the much more expensive
728 : *
729 : * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
730 : *
731 : * This actually does make a difference in metadata-heavy workloads (i.e. the
732 : * "standard" client.txt nbench run.
733 : */
734 :
735 4822624 : ssize_t full_path_tos(const char *dir, const char *name,
736 : char *tmpbuf, size_t tmpbuf_len,
737 : char **pdst, char **to_free)
738 : {
739 29015 : size_t dirlen, namelen, len;
740 29015 : char *dst;
741 :
742 4822624 : dirlen = strlen(dir);
743 4822624 : namelen = strlen(name);
744 4822624 : len = dirlen + namelen + 1;
745 :
746 4822624 : if (len < tmpbuf_len) {
747 4822620 : dst = tmpbuf;
748 4822620 : *to_free = NULL;
749 : } else {
750 4 : dst = talloc_array(talloc_tos(), char, len+1);
751 4 : if (dst == NULL) {
752 0 : return -1;
753 : }
754 4 : *to_free = dst;
755 : }
756 :
757 4822624 : memcpy(dst, dir, dirlen);
758 4822624 : dst[dirlen] = '/';
759 4822624 : memcpy(dst+dirlen+1, name, namelen+1);
760 4822624 : *pdst = dst;
761 4822624 : return len;
762 : }
|