@@ -451,6 +451,54 @@ static void process_phantom_symlinks(void)
451451 LeaveCriticalSection (& phantom_symlinks_cs );
452452}
453453
454+ static int create_phantom_symlink (wchar_t * wtarget , wchar_t * wlink )
455+ {
456+ int len ;
457+
458+ /* create file symlink */
459+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
460+ errno = err_win_to_posix (GetLastError ());
461+ return -1 ;
462+ }
463+
464+ /* convert to directory symlink if target exists */
465+ switch (process_phantom_symlink (wtarget , wlink )) {
466+ case PHANTOM_SYMLINK_RETRY : {
467+ /* if target doesn't exist, add to phantom symlinks list */
468+ wchar_t wfullpath [MAX_LONG_PATH ];
469+ struct phantom_symlink_info * psi ;
470+
471+ /* convert to absolute path to be independent of cwd */
472+ len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
473+ if (!len || len >= MAX_LONG_PATH ) {
474+ errno = err_win_to_posix (GetLastError ());
475+ return -1 ;
476+ }
477+
478+ /* over-allocate and fill phantom_symlink_info structure */
479+ psi = xmalloc (sizeof (struct phantom_symlink_info ) +
480+ sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
481+ psi -> wlink = (wchar_t * )(psi + 1 );
482+ wcscpy (psi -> wlink , wfullpath );
483+ psi -> wtarget = psi -> wlink + len + 1 ;
484+ wcscpy (psi -> wtarget , wtarget );
485+
486+ EnterCriticalSection (& phantom_symlinks_cs );
487+ psi -> next = phantom_symlinks ;
488+ phantom_symlinks = psi ;
489+ LeaveCriticalSection (& phantom_symlinks_cs );
490+ break ;
491+ }
492+ case PHANTOM_SYMLINK_DIRECTORY :
493+ /* if we created a dir symlink, process other phantom symlinks */
494+ process_phantom_symlinks ();
495+ break ;
496+ default :
497+ break ;
498+ }
499+ return 0 ;
500+ }
501+
454502/* Normalizes NT paths as returned by some low-level APIs. */
455503static wchar_t * normalize_ntpath (wchar_t * wbuf )
456504{
@@ -3093,48 +3141,7 @@ int symlink(const char *target, const char *link)
30933141 if (wtarget [len ] == '/' )
30943142 wtarget [len ] = '\\' ;
30953143
3096- /* create file symlink */
3097- if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
3098- errno = err_win_to_posix (GetLastError ());
3099- return -1 ;
3100- }
3101-
3102- /* convert to directory symlink if target exists */
3103- switch (process_phantom_symlink (wtarget , wlink )) {
3104- case PHANTOM_SYMLINK_RETRY : {
3105- /* if target doesn't exist, add to phantom symlinks list */
3106- wchar_t wfullpath [MAX_LONG_PATH ];
3107- struct phantom_symlink_info * psi ;
3108-
3109- /* convert to absolute path to be independent of cwd */
3110- len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
3111- if (!len || len >= MAX_LONG_PATH ) {
3112- errno = err_win_to_posix (GetLastError ());
3113- return -1 ;
3114- }
3115-
3116- /* over-allocate and fill phantom_symlink_info structure */
3117- psi = xmalloc (sizeof (struct phantom_symlink_info )
3118- + sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
3119- psi -> wlink = (wchar_t * )(psi + 1 );
3120- wcscpy (psi -> wlink , wfullpath );
3121- psi -> wtarget = psi -> wlink + len + 1 ;
3122- wcscpy (psi -> wtarget , wtarget );
3123-
3124- EnterCriticalSection (& phantom_symlinks_cs );
3125- psi -> next = phantom_symlinks ;
3126- phantom_symlinks = psi ;
3127- LeaveCriticalSection (& phantom_symlinks_cs );
3128- break ;
3129- }
3130- case PHANTOM_SYMLINK_DIRECTORY :
3131- /* if we created a dir symlink, process other phantom symlinks */
3132- process_phantom_symlinks ();
3133- break ;
3134- default :
3135- break ;
3136- }
3137- return 0 ;
3144+ return create_phantom_symlink (wtarget , wlink );
31383145}
31393146
31403147#ifndef _WINNT_H
0 commit comments