summaryrefslogtreecommitdiff
path: root/dev/build/windows/patches_coq/ln.c
blob: 5e02c72bb7b90b85bcda58790914a06402393220 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// (C) 2016 Intel Deutschland GmbH
// Author: Michael Soegtrop
// Released to the public under CC0
// See https://creativecommons.org/publicdomain/zero/1.0/

// Windows drop in repacement for Linux ln
// Supports command form "ln TARGET LINK_NAME"
// Supports -s and -f options
// Does not support hard links to folders (but symlinks are ok)

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

// Cygwin MinGW doesn't have this Vista++ function in windows.h
#ifdef UNICODE
    WINBASEAPI BOOLEAN APIENTRY CreateSymbolicLinkW ( LPCWSTR, LPCWSTR, DWORD );
    #define CreateSymbolicLink  CreateSymbolicLinkW
    #define CommandLineToArgv CommandLineToArgvW
#else
    WINBASEAPI BOOLEAN APIENTRY CreateSymbolicLinkA ( LPCSTR, LPCSTR, DWORD );
    #define CreateSymbolicLink  CreateSymbolicLinkA
    #define CommandLineToArgv CommandLineToArgvA
#endif
#define SYMBOLIC_LINK_FLAG_DIRECTORY 1

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLineA, int nShowCmd )
{
    int iarg;
    BOOL symbolic = FALSE;
    BOOL force = FALSE;
    BOOL folder;
    const _TCHAR *target;
    const _TCHAR *link;
    LPTSTR lpCmdLine; 
    int argc;
    LPTSTR *argv;

    // Parse command line
    // This is done explicitly here for two reasons
    // 1.) MinGW doesn't seem to support _tmain, wWinMain and the like
    // 2.) We want to make sure that CommandLineToArgv is used
    lpCmdLine = GetCommandLine();
    argv = CommandLineToArgv( lpCmdLine, &argc );
    
    // Get target and link name
    if( argc<3 )
    {
        _ftprintf( stderr, _T("Expecting at least 2 arguments, got %d\n"), argc-1 );
        return 1;
    }
    target = argv[argc-2];
    link = argv[argc-1];

    // Parse options
    // The last two arguments are interpreted as file names
    // All other arguments must be -s or -f os multi letter options like -sf
    for(iarg=1; iarg<argc-2; iarg++ )
    {
        const _TCHAR *pos = argv[iarg]; 
        if( *pos != _T('-') )
        {
            _ftprintf( stderr, _T("Command line option expected in argument %d\n"), iarg );
            return 1;
        }
        pos ++;

        while( *pos )
        {
            switch( *pos )
            {
                case _T('s') : symbolic = TRUE; break;
                case _T('f') : force = TRUE; break;
                default : 
                    _ftprintf( stderr, _T("Unknown option '%c'\n"), *pos );
                    return 1;
            }
            pos ++;
        }
    }
    
    #ifdef IGNORE_SYMBOLIC
        symbolic = FALSE;
    #endif
    
    // Check if link already exists - delete it if force is given or abort
    {
        if( GetFileAttributes(link) != INVALID_FILE_ATTRIBUTES )
        {
            if( force )
            {
                if( !DeleteFile( link ) )
                {
                    _ftprintf( stderr, _T("Error deleting file '%s'\n"), link );
                    return 1;
                }
            }
            else
            {
                _ftprintf( stderr, _T("File '%s' exists!\n"), link );
                return 1;
            }
        }
    }
    
    // Check if target is a folder
    folder = ( (GetFileAttributes(target) & FILE_ATTRIBUTE_DIRECTORY) ) != 0;
    
    // Create link
    if(symbolic)
    {
        if( !CreateSymbolicLink( link, target, folder ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ) )
        {
            _ftprintf( stderr, _T("Error creating symbolic link '%s' -> '%s'!\n"), link, target );
            return 1;
        }
    }
    else
    {
        if( folder )
        {
            _ftprintf( stderr, _T("Cannot create hard link to folder") );
            return 1;
        }
        else
        {
            if( !CreateHardLink( link, target, NULL ) )
            {
                _ftprintf( stderr, _T("Error creating hard link '%s' -> '%s'!\n"), link, target );
                return 1;
            }
        }
    }
    
    // Everything is fine
    return 0;
}