Hi Jason, On Fri, Jan 17, 2025 at 07:01:46PM -0500, Jason Yundt wrote: > On Fri, Jan 17, 2025 at 03:14:55PM +0100, Alejandro Colomar wrote: > > Curiously, my system is also limited to 255 for tmpfs filesystems but > > yours is not? I still get longer paths rejected. > > That was my mistake. Running your program confirms that tmpfs filenames > are limited to 255 bytes as well. I had originally assumed that /tmp > was tmpfs on my system, but it was actually bcachefs which has a > _PC_NAME_MAX of 512. > > > Doesn't iconv(3) terminate its output? I've never used that API, so I > > don't know. > > I thought that at first because I hadn’t ever used iconv(3) either. I > created a test program in order to make sure that it doesn’t terminate > its output: > > $ cat iconv_termination_test.c > #include <err.h> > #include <iconv.h> > #include <langinfo.h> > #include <locale.h> > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > #include <uchar.h> > > #define NELEMS(a) (sizeof(a) / sizeof(a[0])) > > > void > display_memory(char *memory_block, size_t len) { > for (size_t i = 0; i < len; i++) { > printf("%02hhX ", memory_block[i]); > } > printf("\n"); > } > > int > main(void) > { > char32_t utf32_pathname[] = U"example"; > size_t pathname_len = NELEMS(utf32_pathname) - 1; There's no other length. You could just call it len. pathname_ just adds noise here. See the section on "Variable names" here: <https://doc.cat-v.org/bell_labs/pikestyle>. > size_t utf8_pathname_size = pathname_len * 4 + 1; > char *utf8_pathname = malloc(utf8_pathname_size); > if (utf8_pathname == NULL) { > err(EXIT_FAILURE, "calloc"); > } > memset(utf8_pathname, 0xFF, utf8_pathname_size); > printf("utf8_pathname before calling iconv: "); > display_memory(utf8_pathname, utf8_pathname_size); > > iconv_t cd = iconv_open("UTF-8", "UTF-32"); > if (cd == (iconv_t) - 1) { > err(EXIT_FAILURE, "iconv_open"); > } > char *inbuf = (char *) utf32_pathname; > size_t inbytesleft = pathname_len * (sizeof *utf32_pathname); > char *outbuf = utf8_pathname; > size_t outbytesleft = utf8_pathname_size; > size_t iconv_result; > while (inbytesleft > 0) { I don't think we need a loop. Do you? iconv(3) should convert the entire string if it is valid and there's enough room. > iconv_result = > iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); It seems you're passing a non-terminated string, and thus it's producing a non-terminated string. Why don't you pass a null-terminated string? That is, inbytesleft should include be the length + 1. Have a lovely night! Alex > if (iconv_result == -1) { > err(EXIT_FAILURE, "iconv"); > } > } > iconv_result = > iconv(cd, NULL, &inbytesleft, &outbuf, &outbytesleft); > if (iconv_result == -1) { > err(EXIT_FAILURE, "iconv"); > } > if (iconv_close(cd) == -1) { > err(EXIT_FAILURE, "iconv_close"); > } > > printf("utf8_pathname after calling iconv: "); > display_memory(utf8_pathname, utf8_pathname_size); > > free(utf8_pathname); > exit(EXIT_SUCCESS); > } > $ gcc -Wall iconv_termination_test.c > $ ./a.out > utf8_pathname before calling iconv: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF > utf8_pathname after calling iconv: 65 78 61 6D 70 6C 65 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF > $ -- <https://www.alejandro-colomar.es/>
Attachment:
signature.asc
Description: PGP signature