Mercurial > hg > nginx-quic
comparison src/os/win32/ngx_files.c @ 9035:751f79bd802c
Win32: non-ASCII names support in "include" with wildcards.
Notably, ngx_open_glob() now supports opening directories with non-ASCII
characters, and pathnames returned by ngx_read_glob() are converted to UTF-8.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 23 Feb 2023 20:49:41 +0300 |
parents | b0a06c50c1b4 |
children | 8ea2e052feb4 |
comparison
equal
deleted
inserted
replaced
9034:b0a06c50c1b4 | 9035:751f79bd802c |
---|---|
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 | 10 |
11 | 11 |
12 #define NGX_UTF16_BUFLEN 256 | 12 #define NGX_UTF16_BUFLEN 256 |
13 #define NGX_UTF8_BUFLEN 512 | |
13 | 14 |
14 static ngx_int_t ngx_win32_check_filename(u_char *name, u_short *u, | 15 static ngx_int_t ngx_win32_check_filename(u_char *name, u_short *u, |
15 size_t len); | 16 size_t len); |
16 static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len, | 17 static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len, |
17 size_t reserved); | 18 size_t reserved); |
545 ngx_int_t | 546 ngx_int_t |
546 ngx_open_glob(ngx_glob_t *gl) | 547 ngx_open_glob(ngx_glob_t *gl) |
547 { | 548 { |
548 u_char *p; | 549 u_char *p; |
549 size_t len; | 550 size_t len; |
551 u_short *u; | |
550 ngx_err_t err; | 552 ngx_err_t err; |
551 | 553 u_short utf16[NGX_UTF16_BUFLEN]; |
552 gl->dir = FindFirstFile((const char *) gl->pattern, &gl->finddata); | 554 |
555 len = NGX_UTF16_BUFLEN; | |
556 u = ngx_utf8_to_utf16(utf16, gl->pattern, &len, 0); | |
557 | |
558 if (u == NULL) { | |
559 return NGX_ERROR; | |
560 } | |
561 | |
562 gl->dir = FindFirstFileW(u, &gl->finddata); | |
553 | 563 |
554 if (gl->dir == INVALID_HANDLE_VALUE) { | 564 if (gl->dir == INVALID_HANDLE_VALUE) { |
555 | 565 |
556 err = ngx_errno; | 566 err = ngx_errno; |
567 | |
568 if (u != utf16) { | |
569 ngx_free(u); | |
570 } | |
557 | 571 |
558 if ((err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) | 572 if ((err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) |
559 && gl->test) | 573 && gl->test) |
560 { | 574 { |
561 gl->no_match = 1; | 575 gl->no_match = 1; |
562 return NGX_OK; | 576 return NGX_OK; |
563 } | 577 } |
564 | 578 |
579 ngx_set_errno(err); | |
580 | |
565 return NGX_ERROR; | 581 return NGX_ERROR; |
566 } | 582 } |
567 | 583 |
568 for (p = gl->pattern; *p; p++) { | 584 for (p = gl->pattern; *p; p++) { |
569 if (*p == '/') { | 585 if (*p == '/') { |
570 gl->last = p + 1 - gl->pattern; | 586 gl->last = p + 1 - gl->pattern; |
571 } | 587 } |
572 } | 588 } |
573 | 589 |
574 len = ngx_strlen(gl->finddata.cFileName); | 590 if (u != utf16) { |
575 gl->name.len = gl->last + len; | 591 ngx_free(u); |
592 } | |
593 | |
594 gl->ready = 1; | |
595 | |
596 return NGX_OK; | |
597 } | |
598 | |
599 | |
600 ngx_int_t | |
601 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name) | |
602 { | |
603 u_char *p; | |
604 size_t len; | |
605 ngx_err_t err; | |
606 u_char utf8[NGX_UTF8_BUFLEN]; | |
607 | |
608 if (gl->no_match) { | |
609 return NGX_DONE; | |
610 } | |
611 | |
612 if (gl->ready) { | |
613 gl->ready = 0; | |
614 goto convert; | |
615 } | |
616 | |
617 ngx_free(gl->name.data); | |
618 gl->name.data = NULL; | |
619 | |
620 if (FindNextFileW(gl->dir, &gl->finddata) != 0) { | |
621 goto convert; | |
622 } | |
623 | |
624 err = ngx_errno; | |
625 | |
626 if (err == NGX_ENOMOREFILES) { | |
627 return NGX_DONE; | |
628 } | |
629 | |
630 ngx_log_error(NGX_LOG_ALERT, gl->log, err, | |
631 "FindNextFile(%s) failed", gl->pattern); | |
632 | |
633 return NGX_ERROR; | |
634 | |
635 convert: | |
636 | |
637 len = NGX_UTF8_BUFLEN; | |
638 p = ngx_utf16_to_utf8(utf8, gl->finddata.cFileName, &len, NULL); | |
639 | |
640 if (p == NULL) { | |
641 return NGX_ERROR; | |
642 } | |
643 | |
644 gl->name.len = gl->last + len - 1; | |
576 | 645 |
577 gl->name.data = ngx_alloc(gl->name.len + 1, gl->log); | 646 gl->name.data = ngx_alloc(gl->name.len + 1, gl->log); |
578 if (gl->name.data == NULL) { | 647 if (gl->name.data == NULL) { |
579 return NGX_ERROR; | 648 goto failed; |
580 } | 649 } |
581 | 650 |
582 ngx_memcpy(gl->name.data, gl->pattern, gl->last); | 651 ngx_memcpy(gl->name.data, gl->pattern, gl->last); |
583 ngx_cpystrn(gl->name.data + gl->last, (u_char *) gl->finddata.cFileName, | 652 ngx_cpystrn(gl->name.data + gl->last, p, len); |
584 len + 1); | 653 |
585 | 654 if (p != utf8) { |
586 gl->ready = 1; | 655 ngx_free(p); |
656 } | |
657 | |
658 *name = gl->name; | |
587 | 659 |
588 return NGX_OK; | 660 return NGX_OK; |
589 } | 661 |
590 | 662 failed: |
591 | 663 |
592 ngx_int_t | 664 if (p != utf8) { |
593 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name) | 665 err = ngx_errno; |
594 { | 666 ngx_free(p); |
595 size_t len; | 667 ngx_set_errno(err); |
596 ngx_err_t err; | 668 } |
597 | |
598 if (gl->no_match) { | |
599 return NGX_DONE; | |
600 } | |
601 | |
602 if (gl->ready) { | |
603 *name = gl->name; | |
604 | |
605 gl->ready = 0; | |
606 return NGX_OK; | |
607 } | |
608 | |
609 ngx_free(gl->name.data); | |
610 gl->name.data = NULL; | |
611 | |
612 if (FindNextFile(gl->dir, &gl->finddata) != 0) { | |
613 | |
614 len = ngx_strlen(gl->finddata.cFileName); | |
615 gl->name.len = gl->last + len; | |
616 | |
617 gl->name.data = ngx_alloc(gl->name.len + 1, gl->log); | |
618 if (gl->name.data == NULL) { | |
619 return NGX_ERROR; | |
620 } | |
621 | |
622 ngx_memcpy(gl->name.data, gl->pattern, gl->last); | |
623 ngx_cpystrn(gl->name.data + gl->last, (u_char *) gl->finddata.cFileName, | |
624 len + 1); | |
625 | |
626 *name = gl->name; | |
627 | |
628 return NGX_OK; | |
629 } | |
630 | |
631 err = ngx_errno; | |
632 | |
633 if (err == NGX_ENOMOREFILES) { | |
634 return NGX_DONE; | |
635 } | |
636 | |
637 ngx_log_error(NGX_LOG_ALERT, gl->log, err, | |
638 "FindNextFile(%s) failed", gl->pattern); | |
639 | 669 |
640 return NGX_ERROR; | 670 return NGX_ERROR; |
641 } | 671 } |
642 | 672 |
643 | 673 |