@@ -454,6 +454,54 @@ static void process_phantom_symlinks(void)
454454 LeaveCriticalSection (& phantom_symlinks_cs );
455455}
456456
457+ static int create_phantom_symlink (wchar_t * wtarget , wchar_t * wlink )
458+ {
459+ int len ;
460+
461+ /* create file symlink */
462+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
463+ errno = err_win_to_posix (GetLastError ());
464+ return -1 ;
465+ }
466+
467+ /* convert to directory symlink if target exists */
468+ switch (process_phantom_symlink (wtarget , wlink )) {
469+ case PHANTOM_SYMLINK_RETRY : {
470+ /* if target doesn't exist, add to phantom symlinks list */
471+ wchar_t wfullpath [MAX_LONG_PATH ];
472+ struct phantom_symlink_info * psi ;
473+
474+ /* convert to absolute path to be independent of cwd */
475+ len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
476+ if (!len || len >= MAX_LONG_PATH ) {
477+ errno = err_win_to_posix (GetLastError ());
478+ return -1 ;
479+ }
480+
481+ /* over-allocate and fill phantom_symlink_info structure */
482+ psi = xmalloc (sizeof (struct phantom_symlink_info ) +
483+ sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
484+ psi -> wlink = (wchar_t * )(psi + 1 );
485+ wcscpy (psi -> wlink , wfullpath );
486+ psi -> wtarget = psi -> wlink + len + 1 ;
487+ wcscpy (psi -> wtarget , wtarget );
488+
489+ EnterCriticalSection (& phantom_symlinks_cs );
490+ psi -> next = phantom_symlinks ;
491+ phantom_symlinks = psi ;
492+ LeaveCriticalSection (& phantom_symlinks_cs );
493+ break ;
494+ }
495+ case PHANTOM_SYMLINK_DIRECTORY :
496+ /* if we created a dir symlink, process other phantom symlinks */
497+ process_phantom_symlinks ();
498+ break ;
499+ default :
500+ break ;
501+ }
502+ return 0 ;
503+ }
504+
457505/* Normalizes NT paths as returned by some low-level APIs. */
458506static wchar_t * normalize_ntpath (wchar_t * wbuf )
459507{
@@ -3128,48 +3176,7 @@ int symlink(const char *target, const char *link)
31283176 if (wtarget [len ] == '/' )
31293177 wtarget [len ] = '\\' ;
31303178
3131- /* create file symlink */
3132- if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
3133- errno = err_win_to_posix (GetLastError ());
3134- return -1 ;
3135- }
3136-
3137- /* convert to directory symlink if target exists */
3138- switch (process_phantom_symlink (wtarget , wlink )) {
3139- case PHANTOM_SYMLINK_RETRY : {
3140- /* if target doesn't exist, add to phantom symlinks list */
3141- wchar_t wfullpath [MAX_LONG_PATH ];
3142- struct phantom_symlink_info * psi ;
3143-
3144- /* convert to absolute path to be independent of cwd */
3145- len = GetFullPathNameW (wlink , MAX_LONG_PATH , wfullpath , NULL );
3146- if (!len || len >= MAX_LONG_PATH ) {
3147- errno = err_win_to_posix (GetLastError ());
3148- return -1 ;
3149- }
3150-
3151- /* over-allocate and fill phantom_symlink_info structure */
3152- psi = xmalloc (sizeof (struct phantom_symlink_info )
3153- + sizeof (wchar_t ) * (len + wcslen (wtarget ) + 2 ));
3154- psi -> wlink = (wchar_t * )(psi + 1 );
3155- wcscpy (psi -> wlink , wfullpath );
3156- psi -> wtarget = psi -> wlink + len + 1 ;
3157- wcscpy (psi -> wtarget , wtarget );
3158-
3159- EnterCriticalSection (& phantom_symlinks_cs );
3160- psi -> next = phantom_symlinks ;
3161- phantom_symlinks = psi ;
3162- LeaveCriticalSection (& phantom_symlinks_cs );
3163- break ;
3164- }
3165- case PHANTOM_SYMLINK_DIRECTORY :
3166- /* if we created a dir symlink, process other phantom symlinks */
3167- process_phantom_symlinks ();
3168- break ;
3169- default :
3170- break ;
3171- }
3172- return 0 ;
3179+ return create_phantom_symlink (wtarget , wlink );
31733180}
31743181
31753182#ifndef _WINNT_H
0 commit comments