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 102592 : bool strnequal(const char *s1,const char *s2,size_t n)
46 : {
47 102592 : if (s1 == s2)
48 0 : return(true);
49 102592 : if (!s1 || !s2 || !n)
50 0 : return(false);
51 :
52 102592 : 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 321 : char *skip_string(const char *base, size_t len, char *buf)
62 : {
63 321 : const char *end_ptr = base + len;
64 :
65 321 : if (end_ptr < base || !base || !buf || buf >= end_ptr) {
66 0 : return NULL;
67 : }
68 :
69 : /* Skip the string */
70 5092 : while (*buf) {
71 4575 : buf++;
72 4575 : if (buf >= end_ptr) {
73 0 : return NULL;
74 : }
75 : }
76 : /* Skip the '\0' */
77 321 : buf++;
78 321 : 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 2 : size_t str_charnum(const char *s)
88 : {
89 : size_t ret, converted_size;
90 2 : smb_ucs2_t *tmpbuf2 = NULL;
91 2 : if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
92 0 : return 0;
93 : }
94 2 : ret = strlen_w(tmpbuf2);
95 2 : TALLOC_FREE(tmpbuf2);
96 2 : return ret;
97 : }
98 :
99 340856 : bool trim_char(char *s,char cfront,char cback)
100 : {
101 340856 : bool ret = false;
102 : char *ep;
103 340856 : char *fp = s;
104 :
105 : /* Ignore null or empty strings. */
106 340856 : if (!s || (s[0] == '\0'))
107 132120 : return false;
108 :
109 208736 : if (cfront) {
110 347154 : while (*fp && *fp == cfront)
111 1651 : fp++;
112 207772 : if (!*fp) {
113 : /* We ate the string. */
114 0 : s[0] = '\0';
115 0 : return true;
116 : }
117 207772 : if (fp != s)
118 1651 : ret = true;
119 : }
120 :
121 208736 : ep = fp + strlen(fp) - 1;
122 208736 : if (cback) {
123 : /* Attempt ascii only. Bail for mb strings. */
124 352727 : while ((ep >= fp) && (*ep == cback)) {
125 5759 : ret = true;
126 5759 : if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
127 : /* Could be mb... bail back to tim_string. */
128 : 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 5759 : ep--;
138 : }
139 : }
140 208736 : if (ep < fp) {
141 : /* We ate the string. */
142 0 : s[0] = '\0';
143 0 : return true;
144 : }
145 : }
146 :
147 208736 : ep[1] = '\0';
148 208736 : memmove(s, fp, ep-fp+2);
149 208736 : return ret;
150 : }
151 :
152 : /**
153 : Check if a string is part of a list.
154 : **/
155 :
156 4687 : bool in_list(const char *s, const char *list, bool casesensitive)
157 : {
158 4687 : char *tok = NULL;
159 4687 : bool ret = false;
160 : TALLOC_CTX *frame;
161 :
162 4687 : if (!list) {
163 400 : return false;
164 : }
165 :
166 4287 : frame = talloc_stackframe();
167 4287 : 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 4287 : TALLOC_FREE(frame);
181 4287 : return ret;
182 : }
183 :
184 : /**
185 : Write an octal as a string.
186 : **/
187 :
188 0 : char *octal_string(int i)
189 : {
190 : char *result;
191 0 : if (i == -1) {
192 0 : result = talloc_strdup(talloc_tos(), "-1");
193 : }
194 : else {
195 0 : result = talloc_asprintf(talloc_tos(), "0%o", i);
196 : }
197 0 : SMB_ASSERT(result != NULL);
198 0 : return result;
199 : }
200 :
201 :
202 : /**
203 : Truncate a string at a specified length.
204 : **/
205 :
206 167 : char *string_truncate(char *s, unsigned int length)
207 : {
208 167 : if (s && strlen(s) > length)
209 0 : s[length] = 0;
210 167 : return s;
211 : }
212 :
213 :
214 : /***********************************************************************
215 : Return the equivalent of doing strrchr 'n' times - always going
216 : backwards.
217 : ***********************************************************************/
218 :
219 0 : char *strnrchr_m(const char *s, char c, unsigned int n)
220 : {
221 0 : smb_ucs2_t *ws = NULL;
222 0 : char *s2 = NULL;
223 : smb_ucs2_t *p;
224 : char *ret;
225 : size_t converted_size;
226 :
227 0 : if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
228 : /* Too hard to try and get right. */
229 0 : return NULL;
230 : }
231 0 : p = strnrchr_w(ws, UCS2_CHAR(c), n);
232 0 : if (!p) {
233 0 : TALLOC_FREE(ws);
234 0 : return NULL;
235 : }
236 0 : *p = 0;
237 0 : if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
238 0 : TALLOC_FREE(ws);
239 : /* Too hard to try and get right. */
240 0 : return NULL;
241 : }
242 0 : ret = discard_const_p(char, (s+strlen(s2)));
243 0 : TALLOC_FREE(ws);
244 0 : TALLOC_FREE(s2);
245 0 : return ret;
246 : }
247 :
248 0 : static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
249 : {
250 : size_t size;
251 0 : smb_ucs2_t *buffer = NULL;
252 : bool ret;
253 :
254 0 : if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
255 : (void **)(void *)&buffer, &size))
256 : {
257 0 : return false;
258 : }
259 0 : if (!strlower_w(buffer) && (dest == src)) {
260 0 : TALLOC_FREE(buffer);
261 0 : return true;
262 : }
263 0 : ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
264 0 : TALLOC_FREE(buffer);
265 0 : return ret;
266 : }
267 :
268 : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
269 :
270 : /**
271 : Convert a string to lower case.
272 : **/
273 : _PUBLIC_ void strlower_m(char *s)
274 : {
275 : char *d;
276 : struct smb_iconv_handle *iconv_handle;
277 :
278 : iconv_handle = get_iconv_handle();
279 :
280 : d = s;
281 :
282 : while (*s) {
283 : size_t c_size, c_size2;
284 : codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
285 : c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
286 : if (c_size2 > c_size) {
287 : DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
288 : c, tolower_m(c), (int)c_size, (int)c_size2));
289 : smb_panic("codepoint expansion in strlower_m\n");
290 : }
291 : s += c_size;
292 : d += c_size2;
293 : }
294 : *d = 0;
295 : }
296 :
297 : #endif
298 :
299 : /**
300 : Convert a string to lower case.
301 : **/
302 :
303 383185 : bool strlower_m(char *s)
304 : {
305 : size_t len;
306 : int errno_save;
307 383185 : bool ret = false;
308 :
309 : /* this is quite a common operation, so we want it to be
310 : fast. We optimise for the ascii case, knowing that all our
311 : supported multi-byte character sets are ascii-compatible
312 : (ie. they match for the first 128 chars) */
313 :
314 4880343 : while (*s && !(((unsigned char)s[0]) & 0x80)) {
315 4279404 : *s = tolower_m((unsigned char)*s);
316 4279404 : s++;
317 : }
318 :
319 383185 : if (!*s)
320 383185 : return true;
321 :
322 : /* I assume that lowercased string takes the same number of bytes
323 : * as source string even in UTF-8 encoding. (VIV) */
324 0 : len = strlen(s) + 1;
325 0 : errno_save = errno;
326 0 : errno = 0;
327 0 : ret = unix_strlower(s,len,s,len);
328 : /* Catch mb conversion errors that may not terminate. */
329 0 : if (errno) {
330 0 : s[len-1] = '\0';
331 : }
332 0 : errno = errno_save;
333 0 : return ret;
334 : }
335 :
336 8 : static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
337 : {
338 : size_t size;
339 : smb_ucs2_t *buffer;
340 : bool ret;
341 :
342 8 : if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
343 8 : return false;
344 : }
345 :
346 0 : if (!strupper_w(buffer) && (dest == src)) {
347 0 : TALLOC_FREE(buffer);
348 0 : return true;
349 : }
350 :
351 0 : ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
352 0 : TALLOC_FREE(buffer);
353 0 : return ret;
354 : }
355 :
356 : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
357 :
358 : /**
359 : Convert a string to UPPER case.
360 : **/
361 : _PUBLIC_ void strupper_m(char *s)
362 : {
363 : char *d;
364 : struct smb_iconv_handle *iconv_handle;
365 :
366 : iconv_handle = get_iconv_handle();
367 :
368 : d = s;
369 :
370 : while (*s) {
371 : size_t c_size, c_size2;
372 : codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
373 : c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
374 : if (c_size2 > c_size) {
375 : DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
376 : c, toupper_m(c), (int)c_size, (int)c_size2));
377 : smb_panic("codepoint expansion in strupper_m\n");
378 : }
379 : s += c_size;
380 : d += c_size2;
381 : }
382 : *d = 0;
383 : }
384 :
385 : #endif
386 :
387 : /**
388 : Convert a string to upper case.
389 : **/
390 :
391 503282 : bool strupper_m(char *s)
392 : {
393 : size_t len;
394 503282 : bool ret = false;
395 :
396 : /* this is quite a common operation, so we want it to be
397 : fast. We optimise for the ascii case, knowing that all our
398 : supported multi-byte character sets are ascii-compatible
399 : (ie. they match for the first 128 chars) */
400 :
401 19872786 : while (*s && !(((unsigned char)s[0]) & 0x80)) {
402 19070286 : *s = toupper_ascii_fast_table[(unsigned char)s[0]];
403 19070286 : s++;
404 : }
405 :
406 503282 : if (!*s)
407 503274 : return true;
408 :
409 : /* I assume that uppercased string takes the same number of bytes
410 : * as source string even in multibyte encoding. (VIV) */
411 8 : len = strlen(s) + 1;
412 8 : ret = unix_strupper(s,len,s,len);
413 : /* Catch mb conversion errors that may not terminate. */
414 8 : if (!ret) {
415 8 : s[len-1] = '\0';
416 : }
417 8 : return ret;
418 : }
419 :
420 : /**
421 : Just a typesafety wrapper for snprintf into a fstring.
422 : **/
423 :
424 108477 : int fstr_sprintf(fstring s, const char *fmt, ...)
425 : {
426 : va_list ap;
427 : int ret;
428 :
429 108477 : va_start(ap, fmt);
430 108477 : ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
431 108477 : va_end(ap);
432 108477 : return ret;
433 : }
434 :
435 : /* read a SMB_BIG_UINT from a string */
436 0 : uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
437 : {
438 :
439 0 : uint64_t val = (uint64_t)-1;
440 0 : const char *p = nptr;
441 :
442 0 : if (!p) {
443 0 : if (entptr) {
444 0 : *entptr = p;
445 : }
446 0 : return val;
447 : }
448 :
449 0 : while (*p && isspace(*p))
450 0 : p++;
451 :
452 0 : sscanf(p,"%"SCNu64,&val);
453 0 : if (entptr) {
454 0 : while (*p && isdigit(*p))
455 0 : p++;
456 0 : *entptr = p;
457 : }
458 :
459 0 : return val;
460 : }
461 :
462 : /* Convert a size specification to a count of bytes. We accept the following
463 : * suffixes:
464 : * bytes if there is no suffix
465 : * kK kibibytes
466 : * mM mebibytes
467 : * gG gibibytes
468 : * tT tibibytes
469 : * pP whatever the ISO name for petabytes is
470 : *
471 : * Returns 0 if the string can't be converted.
472 : */
473 0 : uint64_t conv_str_size(const char * str)
474 : {
475 : uint64_t lval;
476 : char *end;
477 0 : int error = 0;
478 :
479 0 : if (str == NULL || *str == '\0') {
480 0 : return 0;
481 : }
482 :
483 0 : lval = smb_strtoull(str, &end, 10, &error, SMB_STR_STANDARD);
484 :
485 0 : if (error != 0) {
486 0 : return 0;
487 : }
488 :
489 0 : if (*end == '\0') {
490 0 : return lval;
491 : }
492 :
493 0 : if (strwicmp(end, "K") == 0) {
494 0 : lval *= 1024ULL;
495 0 : } else if (strwicmp(end, "M") == 0) {
496 0 : lval *= (1024ULL * 1024ULL);
497 0 : } else if (strwicmp(end, "G") == 0) {
498 0 : lval *= (1024ULL * 1024ULL *
499 : 1024ULL);
500 0 : } else if (strwicmp(end, "T") == 0) {
501 0 : lval *= (1024ULL * 1024ULL *
502 : 1024ULL * 1024ULL);
503 0 : } else if (strwicmp(end, "P") == 0) {
504 0 : lval *= (1024ULL * 1024ULL *
505 : 1024ULL * 1024ULL *
506 : 1024ULL);
507 : } else {
508 0 : return 0;
509 : }
510 :
511 0 : return lval;
512 : }
513 :
514 26410 : char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
515 : {
516 : va_list ap;
517 : char *ret;
518 :
519 26410 : va_start(ap, fmt);
520 26410 : ret = talloc_vasprintf(t, fmt, ap);
521 26410 : va_end(ap);
522 :
523 26410 : if (ret == NULL) {
524 0 : return NULL;
525 : }
526 26410 : if (!strupper_m(ret)) {
527 0 : TALLOC_FREE(ret);
528 0 : return NULL;
529 : }
530 26410 : return ret;
531 : }
532 :
533 0 : char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
534 : {
535 : va_list ap;
536 : char *ret;
537 :
538 0 : va_start(ap, fmt);
539 0 : ret = talloc_vasprintf(t, fmt, ap);
540 0 : va_end(ap);
541 :
542 0 : if (ret == NULL) {
543 0 : return NULL;
544 : }
545 0 : if (!strlower_m(ret)) {
546 0 : TALLOC_FREE(ret);
547 0 : return NULL;
548 : }
549 0 : return ret;
550 : }
551 :
552 :
553 : /********************************************************************
554 : Check a string for any occurrences of a specified list of invalid
555 : characters.
556 : ********************************************************************/
557 :
558 382 : bool validate_net_name( const char *name,
559 : const char *invalid_chars,
560 : int max_len)
561 : {
562 : int i;
563 :
564 382 : if (!name) {
565 0 : return false;
566 : }
567 :
568 17106 : for ( i=0; i<max_len && name[i]; i++ ) {
569 : /* fail if strchr_m() finds one of the invalid characters */
570 16780 : if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
571 56 : return false;
572 : }
573 : }
574 :
575 326 : return true;
576 : }
577 :
578 :
579 : /*******************************************************************
580 : Add a shell escape character '\' to any character not in a known list
581 : of characters. UNIX charset format.
582 : *******************************************************************/
583 :
584 : #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
585 : #define INSIDE_DQUOTE_LIST "$`\n\"\\"
586 :
587 12 : char *escape_shell_string(const char *src)
588 : {
589 12 : size_t srclen = strlen(src);
590 12 : char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
591 12 : char *dest = ret;
592 12 : bool in_s_quote = false;
593 12 : bool in_d_quote = false;
594 12 : bool next_escaped = false;
595 :
596 12 : if (!ret) {
597 0 : return NULL;
598 : }
599 :
600 2640 : while (*src) {
601 : size_t c_size;
602 2620 : codepoint_t c = next_codepoint(src, &c_size);
603 :
604 2620 : if (c == INVALID_CODEPOINT) {
605 0 : SAFE_FREE(ret);
606 0 : return NULL;
607 : }
608 :
609 2620 : if (c_size > 1) {
610 0 : memcpy(dest, src, c_size);
611 0 : src += c_size;
612 0 : dest += c_size;
613 0 : next_escaped = false;
614 425 : continue;
615 : }
616 :
617 : /*
618 : * Deal with backslash escaped state.
619 : * This only lasts for one character.
620 : */
621 :
622 2620 : if (next_escaped) {
623 0 : *dest++ = *src++;
624 0 : next_escaped = false;
625 0 : continue;
626 : }
627 :
628 : /*
629 : * Deal with single quote state. The
630 : * only thing we care about is exiting
631 : * this state.
632 : */
633 :
634 2620 : if (in_s_quote) {
635 0 : if (*src == '\'') {
636 0 : in_s_quote = false;
637 : }
638 0 : *dest++ = *src++;
639 0 : continue;
640 : }
641 :
642 : /*
643 : * Deal with double quote state. The most
644 : * complex state. We must cope with \, meaning
645 : * possibly escape next char (depending what it
646 : * is), ", meaning exit this state, and possibly
647 : * add an \ escape to any unprotected character
648 : * (listed in INSIDE_DQUOTE_LIST).
649 : */
650 :
651 2620 : if (in_d_quote) {
652 414 : if (*src == '\\') {
653 : /*
654 : * Next character might be escaped.
655 : * We have to peek. Inside double
656 : * quotes only INSIDE_DQUOTE_LIST
657 : * characters are escaped by a \.
658 : */
659 :
660 : char nextchar;
661 :
662 0 : c = next_codepoint(&src[1], &c_size);
663 0 : if (c == INVALID_CODEPOINT) {
664 0 : SAFE_FREE(ret);
665 0 : return NULL;
666 : }
667 0 : if (c_size > 1) {
668 : /*
669 : * Don't escape the next char.
670 : * Just copy the \.
671 : */
672 0 : *dest++ = *src++;
673 0 : continue;
674 : }
675 :
676 0 : nextchar = src[1];
677 :
678 0 : if (nextchar && strchr(INSIDE_DQUOTE_LIST,
679 : (int)nextchar)) {
680 0 : next_escaped = true;
681 : }
682 0 : *dest++ = *src++;
683 0 : continue;
684 : }
685 :
686 414 : if (*src == '\"') {
687 : /* Exit double quote state. */
688 11 : in_d_quote = false;
689 11 : *dest++ = *src++;
690 11 : continue;
691 : }
692 :
693 : /*
694 : * We know the character isn't \ or ",
695 : * so escape it if it's any of the other
696 : * possible unprotected characters.
697 : */
698 :
699 403 : if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
700 0 : *dest++ = '\\';
701 : }
702 403 : *dest++ = *src++;
703 403 : continue;
704 : }
705 :
706 : /*
707 : * From here to the end of the loop we're
708 : * not in the single or double quote state.
709 : */
710 :
711 2206 : if (*src == '\\') {
712 : /* Next character must be escaped. */
713 0 : next_escaped = true;
714 0 : *dest++ = *src++;
715 0 : continue;
716 : }
717 :
718 2206 : if (*src == '\'') {
719 : /* Go into single quote state. */
720 0 : in_s_quote = true;
721 0 : *dest++ = *src++;
722 0 : continue;
723 : }
724 :
725 2206 : if (*src == '\"') {
726 : /* Go into double quote state. */
727 11 : in_d_quote = true;
728 11 : *dest++ = *src++;
729 11 : continue;
730 : }
731 :
732 : /* Check if we need to escape the character. */
733 :
734 2195 : if (!strchr(INCLUDE_LIST, (int)*src)) {
735 137 : *dest++ = '\\';
736 : }
737 2195 : *dest++ = *src++;
738 : }
739 12 : *dest++ = '\0';
740 12 : return ret;
741 : }
742 :
743 : /*
744 : * This routine improves performance for operations temporarily acting on a
745 : * full path. It is equivalent to the much more expensive
746 : *
747 : * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
748 : *
749 : * This actually does make a difference in metadata-heavy workloads (i.e. the
750 : * "standard" client.txt nbench run.
751 : */
752 :
753 93865 : ssize_t full_path_tos(const char *dir, const char *name,
754 : char *tmpbuf, size_t tmpbuf_len,
755 : char **pdst, char **to_free)
756 : {
757 : size_t dirlen, namelen, len;
758 : char *dst;
759 :
760 93865 : dirlen = strlen(dir);
761 93865 : namelen = strlen(name);
762 93865 : len = dirlen + namelen + 1;
763 :
764 93865 : if (len < tmpbuf_len) {
765 93865 : dst = tmpbuf;
766 93865 : *to_free = NULL;
767 : } else {
768 0 : dst = talloc_array(talloc_tos(), char, len+1);
769 0 : if (dst == NULL) {
770 0 : return -1;
771 : }
772 0 : *to_free = dst;
773 : }
774 :
775 93865 : memcpy(dst, dir, dirlen);
776 93865 : dst[dirlen] = '/';
777 93865 : memcpy(dst+dirlen+1, name, namelen+1);
778 93865 : *pdst = dst;
779 93865 : return len;
780 : }
|