void CreateLinkIfNeeded()

in dotnet/tools/common/manifest.c [164:224]


void CreateLinkIfNeeded(const char *target, const char *toCreate)
{
    BOOL result;
    DWORD error;
    DWORD flag;

    if (!PathFileExists(target))
    {
        printf("File %s does not exist\n", target);
        exit(-1);
    }

    /* The file is linked by the calling script */
    if (strstr(toCreate, "manifest_prep.exe") != NULL)
        return;

    _chmod(toCreate, _S_IREAD | _S_IWRITE);

    unlink(toCreate);

    /* Try hard linking first (except mono.exe) */
    if (strstr(toCreate, "mono.exe") == NULL)
    {
        result = CreateHardLink(toCreate, target, NULL);
        if (result)
            return;
        error = GetLastError();
        if (error == ERROR_ALREADY_EXISTS)
        {
            /*printf("%s does exist after unlink. Ignoring error. \n", toCreate);*/
            return;
        }
    }

    /* Fall back to symbolic linking */
    flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
retry:
    result = CreateSymbolicLinkA(toCreate, target, flag);
    if (!result)
    {
        error = GetLastError();
        if (error == 87 && flag != 0)
        {
            printf("SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE seems not supported\n");
            flag = 0;
            goto retry;
        }
        if (error != ERROR_ALREADY_EXISTS)
        {
            /* For uknown to me reasons, sometimes the link function failes even if long paths are enabled. */
            if (error == ERROR_PATH_NOT_FOUND && PathFileExistsA(target))
            {
                /*printf("Target file %s does exists. Ignoring error. \n", target);*/
                return;
            }
            printf("Error %d on linking %s to %s\n", error, toCreate, target);

            exit(-1);
        }
    }
}