0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bug.h>
0009 #include <linux/kernel.h>
0010 #include <linux/math64.h>
0011 #include <linux/export.h>
0012 #include <linux/ctype.h>
0013 #include <linux/device.h>
0014 #include <linux/errno.h>
0015 #include <linux/fs.h>
0016 #include <linux/limits.h>
0017 #include <linux/mm.h>
0018 #include <linux/slab.h>
0019 #include <linux/string.h>
0020 #include <linux/string_helpers.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
0036 char *buf, int len)
0037 {
0038 static const char *const units_10[] = {
0039 "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
0040 };
0041 static const char *const units_2[] = {
0042 "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
0043 };
0044 static const char *const *const units_str[] = {
0045 [STRING_UNITS_10] = units_10,
0046 [STRING_UNITS_2] = units_2,
0047 };
0048 static const unsigned int divisor[] = {
0049 [STRING_UNITS_10] = 1000,
0050 [STRING_UNITS_2] = 1024,
0051 };
0052 static const unsigned int rounding[] = { 500, 50, 5 };
0053 int i = 0, j;
0054 u32 remainder = 0, sf_cap;
0055 char tmp[8];
0056 const char *unit;
0057
0058 tmp[0] = '\0';
0059
0060 if (blk_size == 0)
0061 size = 0;
0062 if (size == 0)
0063 goto out;
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 while (blk_size >> 32) {
0077 do_div(blk_size, divisor[units]);
0078 i++;
0079 }
0080
0081 while (size >> 32) {
0082 do_div(size, divisor[units]);
0083 i++;
0084 }
0085
0086
0087
0088 size *= blk_size;
0089
0090
0091 while (size >= divisor[units]) {
0092 remainder = do_div(size, divisor[units]);
0093 i++;
0094 }
0095
0096
0097
0098 sf_cap = size;
0099 for (j = 0; sf_cap*10 < 1000; j++)
0100 sf_cap *= 10;
0101
0102 if (units == STRING_UNITS_2) {
0103
0104
0105
0106 remainder *= 1000;
0107 remainder >>= 10;
0108 }
0109
0110
0111
0112 remainder += rounding[j];
0113 if (remainder >= 1000) {
0114 remainder -= 1000;
0115 size += 1;
0116 }
0117
0118 if (j) {
0119 snprintf(tmp, sizeof(tmp), ".%03u", remainder);
0120 tmp[j+1] = '\0';
0121 }
0122
0123 out:
0124 if (i >= ARRAY_SIZE(units_2))
0125 unit = "UNK";
0126 else
0127 unit = units_str[units][i];
0128
0129 snprintf(buf, len, "%u%s %s", (u32)size,
0130 tmp, unit);
0131 }
0132 EXPORT_SYMBOL(string_get_size);
0133
0134 static bool unescape_space(char **src, char **dst)
0135 {
0136 char *p = *dst, *q = *src;
0137
0138 switch (*q) {
0139 case 'n':
0140 *p = '\n';
0141 break;
0142 case 'r':
0143 *p = '\r';
0144 break;
0145 case 't':
0146 *p = '\t';
0147 break;
0148 case 'v':
0149 *p = '\v';
0150 break;
0151 case 'f':
0152 *p = '\f';
0153 break;
0154 default:
0155 return false;
0156 }
0157 *dst += 1;
0158 *src += 1;
0159 return true;
0160 }
0161
0162 static bool unescape_octal(char **src, char **dst)
0163 {
0164 char *p = *dst, *q = *src;
0165 u8 num;
0166
0167 if (isodigit(*q) == 0)
0168 return false;
0169
0170 num = (*q++) & 7;
0171 while (num < 32 && isodigit(*q) && (q - *src < 3)) {
0172 num <<= 3;
0173 num += (*q++) & 7;
0174 }
0175 *p = num;
0176 *dst += 1;
0177 *src = q;
0178 return true;
0179 }
0180
0181 static bool unescape_hex(char **src, char **dst)
0182 {
0183 char *p = *dst, *q = *src;
0184 int digit;
0185 u8 num;
0186
0187 if (*q++ != 'x')
0188 return false;
0189
0190 num = digit = hex_to_bin(*q++);
0191 if (digit < 0)
0192 return false;
0193
0194 digit = hex_to_bin(*q);
0195 if (digit >= 0) {
0196 q++;
0197 num = (num << 4) | digit;
0198 }
0199 *p = num;
0200 *dst += 1;
0201 *src = q;
0202 return true;
0203 }
0204
0205 static bool unescape_special(char **src, char **dst)
0206 {
0207 char *p = *dst, *q = *src;
0208
0209 switch (*q) {
0210 case '\"':
0211 *p = '\"';
0212 break;
0213 case '\\':
0214 *p = '\\';
0215 break;
0216 case 'a':
0217 *p = '\a';
0218 break;
0219 case 'e':
0220 *p = '\e';
0221 break;
0222 default:
0223 return false;
0224 }
0225 *dst += 1;
0226 *src += 1;
0227 return true;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
0270 {
0271 char *out = dst;
0272
0273 while (*src && --size) {
0274 if (src[0] == '\\' && src[1] != '\0' && size > 1) {
0275 src++;
0276 size--;
0277
0278 if (flags & UNESCAPE_SPACE &&
0279 unescape_space(&src, &out))
0280 continue;
0281
0282 if (flags & UNESCAPE_OCTAL &&
0283 unescape_octal(&src, &out))
0284 continue;
0285
0286 if (flags & UNESCAPE_HEX &&
0287 unescape_hex(&src, &out))
0288 continue;
0289
0290 if (flags & UNESCAPE_SPECIAL &&
0291 unescape_special(&src, &out))
0292 continue;
0293
0294 *out++ = '\\';
0295 }
0296 *out++ = *src++;
0297 }
0298 *out = '\0';
0299
0300 return out - dst;
0301 }
0302 EXPORT_SYMBOL(string_unescape);
0303
0304 static bool escape_passthrough(unsigned char c, char **dst, char *end)
0305 {
0306 char *out = *dst;
0307
0308 if (out < end)
0309 *out = c;
0310 *dst = out + 1;
0311 return true;
0312 }
0313
0314 static bool escape_space(unsigned char c, char **dst, char *end)
0315 {
0316 char *out = *dst;
0317 unsigned char to;
0318
0319 switch (c) {
0320 case '\n':
0321 to = 'n';
0322 break;
0323 case '\r':
0324 to = 'r';
0325 break;
0326 case '\t':
0327 to = 't';
0328 break;
0329 case '\v':
0330 to = 'v';
0331 break;
0332 case '\f':
0333 to = 'f';
0334 break;
0335 default:
0336 return false;
0337 }
0338
0339 if (out < end)
0340 *out = '\\';
0341 ++out;
0342 if (out < end)
0343 *out = to;
0344 ++out;
0345
0346 *dst = out;
0347 return true;
0348 }
0349
0350 static bool escape_special(unsigned char c, char **dst, char *end)
0351 {
0352 char *out = *dst;
0353 unsigned char to;
0354
0355 switch (c) {
0356 case '\\':
0357 to = '\\';
0358 break;
0359 case '\a':
0360 to = 'a';
0361 break;
0362 case '\e':
0363 to = 'e';
0364 break;
0365 case '"':
0366 to = '"';
0367 break;
0368 default:
0369 return false;
0370 }
0371
0372 if (out < end)
0373 *out = '\\';
0374 ++out;
0375 if (out < end)
0376 *out = to;
0377 ++out;
0378
0379 *dst = out;
0380 return true;
0381 }
0382
0383 static bool escape_null(unsigned char c, char **dst, char *end)
0384 {
0385 char *out = *dst;
0386
0387 if (c)
0388 return false;
0389
0390 if (out < end)
0391 *out = '\\';
0392 ++out;
0393 if (out < end)
0394 *out = '0';
0395 ++out;
0396
0397 *dst = out;
0398 return true;
0399 }
0400
0401 static bool escape_octal(unsigned char c, char **dst, char *end)
0402 {
0403 char *out = *dst;
0404
0405 if (out < end)
0406 *out = '\\';
0407 ++out;
0408 if (out < end)
0409 *out = ((c >> 6) & 0x07) + '0';
0410 ++out;
0411 if (out < end)
0412 *out = ((c >> 3) & 0x07) + '0';
0413 ++out;
0414 if (out < end)
0415 *out = ((c >> 0) & 0x07) + '0';
0416 ++out;
0417
0418 *dst = out;
0419 return true;
0420 }
0421
0422 static bool escape_hex(unsigned char c, char **dst, char *end)
0423 {
0424 char *out = *dst;
0425
0426 if (out < end)
0427 *out = '\\';
0428 ++out;
0429 if (out < end)
0430 *out = 'x';
0431 ++out;
0432 if (out < end)
0433 *out = hex_asc_hi(c);
0434 ++out;
0435 if (out < end)
0436 *out = hex_asc_lo(c);
0437 ++out;
0438
0439 *dst = out;
0440 return true;
0441 }
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
0521 unsigned int flags, const char *only)
0522 {
0523 char *p = dst;
0524 char *end = p + osz;
0525 bool is_dict = only && *only;
0526 bool is_append = flags & ESCAPE_APPEND;
0527
0528 while (isz--) {
0529 unsigned char c = *src++;
0530 bool in_dict = is_dict && strchr(only, c);
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 if (!(is_append || in_dict) && is_dict &&
0552 escape_passthrough(c, &p, end))
0553 continue;
0554
0555 if (!(is_append && in_dict) && isascii(c) && isprint(c) &&
0556 flags & ESCAPE_NAP && escape_passthrough(c, &p, end))
0557 continue;
0558
0559 if (!(is_append && in_dict) && isprint(c) &&
0560 flags & ESCAPE_NP && escape_passthrough(c, &p, end))
0561 continue;
0562
0563 if (!(is_append && in_dict) && isascii(c) &&
0564 flags & ESCAPE_NA && escape_passthrough(c, &p, end))
0565 continue;
0566
0567 if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
0568 continue;
0569
0570 if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
0571 continue;
0572
0573 if (flags & ESCAPE_NULL && escape_null(c, &p, end))
0574 continue;
0575
0576
0577 if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
0578 continue;
0579
0580 if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
0581 continue;
0582
0583 escape_passthrough(c, &p, end);
0584 }
0585
0586 return p - dst;
0587 }
0588 EXPORT_SYMBOL(string_escape_mem);
0589
0590
0591
0592
0593
0594 char *kstrdup_quotable(const char *src, gfp_t gfp)
0595 {
0596 size_t slen, dlen;
0597 char *dst;
0598 const int flags = ESCAPE_HEX;
0599 const char esc[] = "\f\n\r\t\v\a\e\\\"";
0600
0601 if (!src)
0602 return NULL;
0603 slen = strlen(src);
0604
0605 dlen = string_escape_mem(src, slen, NULL, 0, flags, esc);
0606 dst = kmalloc(dlen + 1, gfp);
0607 if (!dst)
0608 return NULL;
0609
0610 WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen);
0611 dst[dlen] = '\0';
0612
0613 return dst;
0614 }
0615 EXPORT_SYMBOL_GPL(kstrdup_quotable);
0616
0617
0618
0619
0620
0621
0622 char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp)
0623 {
0624 char *buffer, *quoted;
0625 int i, res;
0626
0627 buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
0628 if (!buffer)
0629 return NULL;
0630
0631 res = get_cmdline(task, buffer, PAGE_SIZE - 1);
0632 buffer[res] = '\0';
0633
0634
0635 while (--res >= 0 && buffer[res] == '\0')
0636 ;
0637
0638
0639 for (i = 0; i <= res; i++)
0640 if (buffer[i] == '\0')
0641 buffer[i] = ' ';
0642
0643
0644 quoted = kstrdup_quotable(buffer, gfp);
0645 kfree(buffer);
0646 return quoted;
0647 }
0648 EXPORT_SYMBOL_GPL(kstrdup_quotable_cmdline);
0649
0650
0651
0652
0653
0654
0655 char *kstrdup_quotable_file(struct file *file, gfp_t gfp)
0656 {
0657 char *temp, *pathname;
0658
0659 if (!file)
0660 return kstrdup("<unknown>", gfp);
0661
0662
0663 temp = kmalloc(PATH_MAX + 11, GFP_KERNEL);
0664 if (!temp)
0665 return kstrdup("<no_memory>", gfp);
0666
0667 pathname = file_path(file, temp, PATH_MAX + 11);
0668 if (IS_ERR(pathname))
0669 pathname = kstrdup("<too_long>", gfp);
0670 else
0671 pathname = kstrdup_quotable(pathname, gfp);
0672
0673 kfree(temp);
0674 return pathname;
0675 }
0676 EXPORT_SYMBOL_GPL(kstrdup_quotable_file);
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690 char **kasprintf_strarray(gfp_t gfp, const char *prefix, size_t n)
0691 {
0692 char **names;
0693 size_t i;
0694
0695 names = kcalloc(n + 1, sizeof(char *), gfp);
0696 if (!names)
0697 return NULL;
0698
0699 for (i = 0; i < n; i++) {
0700 names[i] = kasprintf(gfp, "%s-%zu", prefix, i);
0701 if (!names[i]) {
0702 kfree_strarray(names, i);
0703 return NULL;
0704 }
0705 }
0706
0707 return names;
0708 }
0709 EXPORT_SYMBOL_GPL(kasprintf_strarray);
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721 void kfree_strarray(char **array, size_t n)
0722 {
0723 unsigned int i;
0724
0725 if (!array)
0726 return;
0727
0728 for (i = 0; i < n; i++)
0729 kfree(array[i]);
0730 kfree(array);
0731 }
0732 EXPORT_SYMBOL_GPL(kfree_strarray);
0733
0734 struct strarray {
0735 char **array;
0736 size_t n;
0737 };
0738
0739 static void devm_kfree_strarray(struct device *dev, void *res)
0740 {
0741 struct strarray *array = res;
0742
0743 kfree_strarray(array->array, array->n);
0744 }
0745
0746 char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n)
0747 {
0748 struct strarray *ptr;
0749
0750 ptr = devres_alloc(devm_kfree_strarray, sizeof(*ptr), GFP_KERNEL);
0751 if (!ptr)
0752 return ERR_PTR(-ENOMEM);
0753
0754 ptr->array = kasprintf_strarray(GFP_KERNEL, prefix, n);
0755 if (!ptr->array) {
0756 devres_free(ptr);
0757 return ERR_PTR(-ENOMEM);
0758 }
0759
0760 ptr->n = n;
0761 devres_add(dev, ptr);
0762
0763 return ptr->array;
0764 }
0765 EXPORT_SYMBOL_GPL(devm_kasprintf_strarray);
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787 ssize_t strscpy_pad(char *dest, const char *src, size_t count)
0788 {
0789 ssize_t written;
0790
0791 written = strscpy(dest, src, count);
0792 if (written < 0 || written == count - 1)
0793 return written;
0794
0795 memset(dest + written + 1, 0, count - written - 1);
0796
0797 return written;
0798 }
0799 EXPORT_SYMBOL(strscpy_pad);
0800
0801
0802
0803
0804
0805
0806
0807 char *skip_spaces(const char *str)
0808 {
0809 while (isspace(*str))
0810 ++str;
0811 return (char *)str;
0812 }
0813 EXPORT_SYMBOL(skip_spaces);
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823 char *strim(char *s)
0824 {
0825 size_t size;
0826 char *end;
0827
0828 size = strlen(s);
0829 if (!size)
0830 return s;
0831
0832 end = s + size - 1;
0833 while (end >= s && isspace(*end))
0834 end--;
0835 *(end + 1) = '\0';
0836
0837 return skip_spaces(s);
0838 }
0839 EXPORT_SYMBOL(strim);
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851 bool sysfs_streq(const char *s1, const char *s2)
0852 {
0853 while (*s1 && *s1 == *s2) {
0854 s1++;
0855 s2++;
0856 }
0857
0858 if (*s1 == *s2)
0859 return true;
0860 if (!*s1 && *s2 == '\n' && !s2[1])
0861 return true;
0862 if (*s1 == '\n' && !s1[1] && !*s2)
0863 return true;
0864 return false;
0865 }
0866 EXPORT_SYMBOL(sysfs_streq);
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885 int match_string(const char * const *array, size_t n, const char *string)
0886 {
0887 int index;
0888 const char *item;
0889
0890 for (index = 0; index < n; index++) {
0891 item = array[index];
0892 if (!item)
0893 break;
0894 if (!strcmp(item, string))
0895 return index;
0896 }
0897
0898 return -EINVAL;
0899 }
0900 EXPORT_SYMBOL(match_string);
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919 int __sysfs_match_string(const char * const *array, size_t n, const char *str)
0920 {
0921 const char *item;
0922 int index;
0923
0924 for (index = 0; index < n; index++) {
0925 item = array[index];
0926 if (!item)
0927 break;
0928 if (sysfs_streq(item, str))
0929 return index;
0930 }
0931
0932 return -EINVAL;
0933 }
0934 EXPORT_SYMBOL(__sysfs_match_string);
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944 char *strreplace(char *s, char old, char new)
0945 {
0946 for (; *s; ++s)
0947 if (*s == old)
0948 *s = new;
0949 return s;
0950 }
0951 EXPORT_SYMBOL(strreplace);
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961 void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
0962 int pad)
0963 {
0964 if (dest_len > count) {
0965 memcpy(dest, src, count);
0966 memset(dest + count, pad, dest_len - count);
0967 } else {
0968 memcpy(dest, src, dest_len);
0969 }
0970 }
0971 EXPORT_SYMBOL(memcpy_and_pad);
0972
0973 #ifdef CONFIG_FORTIFY_SOURCE
0974
0975 void __read_overflow2_field(size_t avail, size_t wanted) { }
0976 EXPORT_SYMBOL(__read_overflow2_field);
0977 void __write_overflow_field(size_t avail, size_t wanted) { }
0978 EXPORT_SYMBOL(__write_overflow_field);
0979
0980 void fortify_panic(const char *name)
0981 {
0982 pr_emerg("detected buffer overflow in %s\n", name);
0983 BUG();
0984 }
0985 EXPORT_SYMBOL(fortify_panic);
0986 #endif