comparison src/os/win32/ngx_files.c @ 8131: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
8130:b0a06c50c1b4 8131: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