@@ -632,44 +632,119 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
632632}
633633
634634#ifdef _WIN32
635+ static char short_path_file [MAX_PATH ];
636+
637+ static void short_path_timer_cb (uv_timer_t * handle ) {
638+ ++ timer_cb_called ;
639+ touch_file (short_path_file );
640+ }
641+
642+ /* Try to create a unique watch directory that has a 8.3 short component
643+ under `parent` ("" means the cwd). If it's successful, fills `watch_dir`
644+ and `short_dir` with the long and short forms of the created directory
645+ respectively, and returns 1. Otherwise removes the directory created
646+ and returns 0. */
647+ static int short_path_make (const char * parent ,
648+ char * watch_dir , size_t watch_n ,
649+ char * short_dir , size_t short_n ) {
650+ uv_fs_t req ;
651+ char tmpl [MAX_PATH ];
652+ WCHAR watch_dirw [MAX_PATH ];
653+ WCHAR short_dirw [MAX_PATH ];
654+ WCHAR long_dirw [MAX_PATH ];
655+ size_t pathlen ;
656+ int r ;
657+
658+ if (parent [0 ] != '\0' )
659+ r = snprintf (tmpl , sizeof (tmpl ), "%s\\watch_dirXXXXXX" , parent );
660+ else
661+ r = snprintf (tmpl , sizeof (tmpl ), "watch_dirXXXXXX" );
662+ if (r < 0 || (size_t ) r >= sizeof (tmpl ))
663+ return 0 ;
664+
665+ r = uv_fs_mkdtemp (NULL , & req , tmpl , NULL );
666+ if (r != 0 ) {
667+ uv_fs_req_cleanup (& req );
668+ return 0 ;
669+ }
670+
671+ /* Copy the created path out before cleaning up the request that owns it. */
672+ pathlen = strlen (req .path );
673+ memcpy (watch_dir , req .path , pathlen + 1 );
674+ uv_fs_req_cleanup (& req );
675+
676+ /* The caller appends "\file1" to both watch_dir and short_dir. If there is
677+ no room for that suffix, skip this location. */
678+ if (pathlen + sizeof ("\\file1" ) <= watch_n &&
679+ MultiByteToWideChar (CP_UTF8 , 0 , watch_dir , -1 ,
680+ watch_dirw , ARRAY_SIZE (watch_dirw )) != 0 &&
681+ GetShortPathNameW (watch_dirw , short_dirw , ARRAY_SIZE (short_dirw )) != 0 &&
682+ GetLongPathNameW (watch_dirw , long_dirw , ARRAY_SIZE (long_dirw )) != 0 &&
683+ _wcsicmp (short_dirw , long_dirw ) != 0 &&
684+ WideCharToMultiByte (CP_UTF8 , 0 , short_dirw , -1 ,
685+ short_dir , (int ) short_n , NULL , NULL ) != 0 )
686+ return 1 ;
687+
688+ uv_fs_rmdir (NULL , & req , watch_dir , NULL );
689+ uv_fs_req_cleanup (& req );
690+ return 0 ;
691+ }
692+
635693TEST_IMPL (fs_event_watch_dir_short_path ) {
636694 uv_loop_t * loop ;
637- uv_fs_t req ;
695+ char temp_path [MAX_PATH ];
696+ char watch_dir [MAX_PATH ];
697+ char watch_file [MAX_PATH ];
698+ char short_dir [MAX_PATH ];
699+ size_t temp_len ;
638700 int has_shortnames ;
639701 int r ;
640702
641- /* Setup */
642703 loop = uv_default_loop ();
643- delete_file ("watch_dir/file1" );
644- delete_dir ("watch_dir/" );
645- create_dir ("watch_dir" );
646- create_file ("watch_dir/file1" );
647704
648- /* Newer version of Windows ship with
649- HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
650- not equal to 0. So we verify the files we created are addressable by a 8.3
651- short name */
652- has_shortnames = uv_fs_stat (NULL , & req , "watch_~1" , NULL ) != UV_ENOENT ;
705+ /* This test needs the watched directory to have an 8.3 short component. The
706+ generated "watch_dirXXXXXX" name is > 8 chars, so it gets a short alias on
707+ volumes where 8.3 name creation is enabled. For non-system volumes on
708+ newer Windows it's disabled by default (NtfsDisable8dot3NameCreation=3).
709+ The temp dir and the cwd may be on different volumes, so try each and use
710+ whichever has a short alias, and skip if neither does. */
711+ has_shortnames = 0 ;
712+ temp_len = sizeof (temp_path );
713+ if (uv_os_tmpdir (temp_path , & temp_len ) == 0 )
714+ has_shortnames = short_path_make (temp_path ,
715+ watch_dir , sizeof (watch_dir ),
716+ short_dir , sizeof (short_dir ));
717+ if (!has_shortnames )
718+ has_shortnames = short_path_make ("" ,
719+ watch_dir , sizeof (watch_dir ),
720+ short_dir , sizeof (short_dir ));
721+
653722 if (has_shortnames ) {
723+ snprintf (watch_file , sizeof (watch_file ), "%s\\file1" , watch_dir );
724+ /* short_path_file is used in the timer callback to touch the file. */
725+ snprintf (short_path_file , sizeof (short_path_file ), "%s\\file1" , short_dir );
726+ /* The directory was just created, so file1 cannot exist yet. */
727+ create_file (watch_file );
728+
654729 r = uv_fs_event_init (loop , & fs_event );
655730 ASSERT_OK (r );
656- r = uv_fs_event_start (& fs_event , fs_event_cb_dir , "watch_~1" , 0 );
731+ r = uv_fs_event_start (& fs_event , fs_event_cb_dir , short_dir , 0 );
657732 ASSERT_OK (r );
658733 r = uv_timer_init (loop , & timer );
659734 ASSERT_OK (r );
660- r = uv_timer_start (& timer , timer_cb_file , 100 , 0 );
735+ r = uv_timer_start (& timer , short_path_timer_cb , 100 , 0 );
661736 ASSERT_OK (r );
662737
663738 uv_run (loop , UV_RUN_DEFAULT );
664739
665740 ASSERT_EQ (1 , fs_event_cb_called );
666741 ASSERT_EQ (1 , timer_cb_called );
667742 ASSERT_EQ (1 , close_cb_called );
668- }
669743
670- /* Cleanup */
671- delete_file ("watch_dir/file1" );
672- delete_dir ("watch_dir/" );
744+ /* Cleanup */
745+ delete_file (watch_file );
746+ delete_dir (watch_dir );
747+ }
673748
674749 MAKE_VALGRIND_HAPPY (loop );
675750
0 commit comments