@@ -458,6 +458,54 @@ static void process_phantom_symlinks(void)
458458 LeaveCriticalSection (& phantom_symlinks_cs );
459459}
460460
461+ static int create_phantom_symlink (wchar_t * wtarget , wchar_t * wlink )
462+ {
463+ int len ;
464+
465+ /* create file symlink */
466+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
467+ errno = err_win_to_posix (GetLastError ());
468+ return -1 ;
469+ }
470+
471+ /* convert to directory symlink if target exists */
472+ switch (process_phantom_symlink (wtarget , wlink )) {
473+ case PHANTOM_SYMLINK_RETRY : {
474+ /* if target doesn't exist, add to phantom symlinks list */
475+ wchar_t wfullpath [MAX_LONG_PATH ];
476+ struct phantom_symlink_info * psi ;
477+
478+ /* convert to absolute path to be independent of cwd */
479+ len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
480+ if (!len || len >= MAX_LONG_PATH ) {
481+ errno = err_win_to_posix (GetLastError ());
482+ return -1 ;
483+ }
484+
485+ /* over-allocate and fill phantom_symlink_info structure */
486+ psi = xmalloc (sizeof (struct phantom_symlink_info ) +
487+ sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
488+ psi -> wlink = (wchar_t * )(psi + 1 );
489+ wcscpy (psi -> wlink , wfullpath );
490+ psi -> wtarget = psi -> wlink + len + 1 ;
491+ wcscpy (psi -> wtarget , wtarget );
492+
493+ EnterCriticalSection (& phantom_symlinks_cs );
494+ psi -> next = phantom_symlinks ;
495+ phantom_symlinks = psi ;
496+ LeaveCriticalSection (& phantom_symlinks_cs );
497+ break ;
498+ }
499+ case PHANTOM_SYMLINK_DIRECTORY :
500+ /* if we created a dir symlink, process other phantom symlinks */
501+ process_phantom_symlinks ();
502+ break ;
503+ default :
504+ break ;
505+ }
506+ return 0 ;
507+ }
508+
461509/* Normalizes NT paths as returned by some low-level APIs. */
462510static wchar_t * normalize_ntpath (wchar_t * wbuf )
463511{
@@ -2915,48 +2963,7 @@ int symlink(const char *target, const char *link)
29152963 if (wtarget [len ] == '/' )
29162964 wtarget [len ] = '\\' ;
29172965
2918- /* create file symlink */
2919- if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
2920- errno = err_win_to_posix (GetLastError ());
2921- return -1 ;
2922- }
2923-
2924- /* convert to directory symlink if target exists */
2925- switch (process_phantom_symlink (wtarget , wlink )) {
2926- case PHANTOM_SYMLINK_RETRY : {
2927- /* if target doesn't exist, add to phantom symlinks list */
2928- wchar_t wfullpath [MAX_LONG_PATH ];
2929- struct phantom_symlink_info * psi ;
2930-
2931- /* convert to absolute path to be independent of cwd */
2932- len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
2933- if (!len || len >= MAX_LONG_PATH ) {
2934- errno = err_win_to_posix (GetLastError ());
2935- return -1 ;
2936- }
2937-
2938- /* over-allocate and fill phantom_symlink_info structure */
2939- psi = xmalloc (sizeof (struct phantom_symlink_info )
2940- + sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
2941- psi -> wlink = (wchar_t * )(psi + 1 );
2942- wcscpy (psi -> wlink , wfullpath );
2943- psi -> wtarget = psi -> wlink + len + 1 ;
2944- wcscpy (psi -> wtarget , wtarget );
2945-
2946- EnterCriticalSection (& phantom_symlinks_cs );
2947- psi -> next = phantom_symlinks ;
2948- phantom_symlinks = psi ;
2949- LeaveCriticalSection (& phantom_symlinks_cs );
2950- break ;
2951- }
2952- case PHANTOM_SYMLINK_DIRECTORY :
2953- /* if we created a dir symlink, process other phantom symlinks */
2954- process_phantom_symlinks ();
2955- break ;
2956- default :
2957- break ;
2958- }
2959- return 0 ;
2966+ return create_phantom_symlink (wtarget , wlink );
29602967}
29612968
29622969#ifndef _WINNT_H
0 commit comments