Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: tools/hermetic_cygwin/MkLink/MkLink.c

Issue 1803003: Initial version of hermetic CygWin script. (Closed) Base URL: http://nativeclient.googlecode.com/svn/trunk/src/native_client/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <windows.h>
33 #include <commctrl.h>
34 #include <nsis/pluginapi.h>
35 #include <winternl.h>
36
37 enum { kLargeBuf = 1024, kSmallBuf = 256 } ;
38
39 #if defined(_MSC_VER)
40 /* Ensure these are treated as functions and not inlined as intrinsics, or disab le /Oi */
41 #pragma warning(disable:4164) /* intrinsic function not declared */
42 #pragma function(memcpy, memset, memcmp)
43 #endif
44
45 HMODULE hNrDll = NULL;
46 NTSTATUS (NTAPI *fNtCreateFile) (PHANDLE FileHandle,
47 ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes,
48 PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize,
49 ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition,
50 ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
51 NTSTATUS (NTAPI *fNtClose) (HANDLE Handle);
52
53 HMODULE hKernel32 = NULL;
54 BOOL (WINAPI *fCreateHardLink) (TCHAR * linkFileName,
55 TCHAR * existingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
56 BOOL (WINAPI *fCreateSymbolicLink) (TCHAR * linkFileName,
57 TCHAR * existingFileName, DWORD flags);
58
59 #undef CreateHardLink
60 #undef CreateSymbolicLink
61 #ifdef UNICODE
62 #define CreateHardLink "CreateHardLinkW"
63 #define CreateSymbolicLink "CreateSymbolicLinkW"
64 #else
65 #define CreateHardLink "CreateHardLinkA"
66 #define CreateSymbolicLink "CreateSymbolicLinkA"
67 #endif
68
69 BOOL MakeHardLink(TCHAR *linkFileName, TCHAR *existingFileName) {
70 if (!hKernel32)
71 hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
72 if (hKernel32) {
73 if (!fCreateHardLink)
74 fCreateHardLink = GetProcAddress(hKernel32, CreateHardLink);
75 if (fCreateHardLink)
76 return fCreateHardLink(linkFileName, existingFileName, NULL);
77 }
78 return FALSE;
79 }
80
81 BOOL MakeSymLink(TCHAR *linkFileName, TCHAR *existingFileName, BOOL dirLink) {
82 TCHAR *f1 = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
83 TCHAR *f2 = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
84 SECURITY_ATTRIBUTES sec_attr = { sizeof (SECURITY_ATTRIBUTES), NULL, FALSE};
85 OBJECT_ATTRIBUTES obj_attr;
86 IO_STATUS_BLOCK io_block;
87 TCHAR *p, *q;
88 HANDLE f;
89 BOOL status;
90 if (!f1 || !f2)
91 return FALSE;
92 lstrcpy(f1, linkFileName);
dpolukhin 2010/04/28 13:16:08 As far as I understand maximum path of 32,767 char
93 p = q = f1;
94 while (q[0]) {
95 do {
96 q++;
97 } while (q[0] && q[0] != '\\');
98 p = q;
99 }
100 if (p[0] = '\\') {
101 TCHAR c = p[1];
102 p[1] = 0;
103 status = GetVolumeInformation(f1, NULL, 0, NULL, NULL, NULL,
104 f2, sizeof(f2));
105 p[1] = c;
106 } else {
107 status = GetVolumeInformation(NULL, NULL, 0, NULL, NULL, NULL,
108 f2, sizeof(f2));
109 }
110 /* If it's NFS then we can create real symbolic link. */
111 if (!lstrcmpi(f2, _T("NFS"))) {
112 if (!hNrDll)
113 hNrDll = LoadLibrary(_T("NTDLL.DLL"));
114 if (hNrDll) {
115 if (!fNtCreateFile)
116 fNtCreateFile = GetProcAddress(hNrDll, "NtCreateFile");
117 if (!fNtClose)
118 fNtClose = GetProcAddress(hNrDll, "NtClose");
119 if (fNtCreateFile && fNtClose) {
120 struct {
121 ULONG offset;
122 UCHAR flags;
123 UCHAR nameLength;
124 USHORT valueLength;
125 CHAR name[21];
126 /* To prevent troubles with alignment */
127 CHAR value[kLargeBuf*sizeof(WCHAR)];
128 } *ea_info = HeapAlloc(GetProcessHeap(),
129 HEAP_ZERO_MEMORY,
130 sizeof(*ea_info));
131 WCHAR *fn = HeapAlloc(GetProcessHeap(),
132 0,
133 sizeof(TCHAR)*kLargeBuf);
134 UNICODE_STRING n = { lstrlen(linkFileName), kLargeBuf, fn };
135 ea_info->nameLength = 20;
136 lstrcpy(ea_info->name, "NfsSymlinkTargetName");
137 #ifdef UNICODE
138 lstrcpy(fn, linkFileName);
139 lstrcpy((LPWSTR)ea_info->value, existingFileName);
140 #else
141 MultiByteToWideChar(CP_ACP, 0, linkFileName, -1, fn, kLargeBuf);
142 MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
143 (LPWSTR)ea_info->value,
144 sizeof(ea_info->value)/sizeof(WCHAR));
145 #endif
146 ea_info->valueLength =
147 lstrlenW((LPWSTR)ea_info->value)*sizeof(WCHAR);
148 InitializeObjectAttributes(&obj_attr, &n, OBJ_CASE_INSENSITIVE,
149 NULL, NULL);
150 status = fNtCreateFile(
151 &f, FILE_WRITE_DATA | FILE_WRITE_EA | SYNCHRONIZE, &obj_attr,
152 &io_block, NULL, FILE_ATTRIBUTE_SYSTEM, FILE_SHARE_READ |
153 FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_CREATE,
154 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
155 &ea_info, 1024 * sizeof (WCHAR));
156 if (NT_SUCCESS(status)) {
157 fNtClose(f);
158 HeapFree(GetProcessHeap(), 0, fn);
159 HeapFree(GetProcessHeap(), 0, ea_info);
160 HeapFree(GetProcessHeap(), 0, f2);
161 HeapFree(GetProcessHeap(), 0, f1);
162 return TRUE;
163 }
164 HeapFree(GetProcessHeap(), 0, fn);
165 HeapFree(GetProcessHeap(), 0, ea_info);
166 }
167 }
168 }
169 lstrcpy(f2, existingFileName);
170 if (!hKernel32)
171 hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
172 if (hKernel32) {
173 if (!fCreateSymbolicLink)
174 fCreateSymbolicLink = GetProcAddress(hKernel32, CreateSymbolicLink);
175 if (fCreateSymbolicLink) {
176 for (p = f1; p[0]; p++)
177 if (p[0] == _T('/'))
178 p[0] = _T('\\');
179 for (p = f2; p[0]; p++)
180 if (p[0] == _T('/'))
181 p[0] = _T('\\');
182 if (fCreateSymbolicLink(f1, f2,
183 dirLink ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0)) {
184 HeapFree(GetProcessHeap(), 0, f2);
185 HeapFree(GetProcessHeap(), 0, f1);
186 return TRUE;
187 }
188 }
189 }
190 if (dirLink) {
191 /* Ignore errors - file may already exist */
192 CreateDirectory(linkFileName, NULL);
193 f = CreateFile(linkFileName, GENERIC_READ | GENERIC_WRITE,
194 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
195 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
196 NULL );
197 if (f != INVALID_HANDLE_VALUE) {
198 struct rp_info {
199 DWORD tag;
200 DWORD dataLength;
201 WORD reserved1;
202 WORD targetLength;
203 WORD targetMaxLength;
204 WORD reserved2;
205 WCHAR target[kLargeBuf+4];
206 } *rp_info = HeapAlloc(GetProcessHeap(),
207 HEAP_ZERO_MEMORY,
208 sizeof(*rp_info));
209 DWORD len;
210 WCHAR *startlink, *endlink;
211 rp_info->tag = IO_REPARSE_TAG_MOUNT_POINT;
212 rp_info->target[0] = L'\\';
213 rp_info->target[1] = L'?';
214 rp_info->target[2] = L'?';
215 rp_info->target[3] = L'\\';
216 if ((((existingFileName[0] == _T('\\')) ||
217 (existingFileName[0] == _T('/'))) &
218 ((existingFileName[1] == _T('\\')) ||
219 (existingFileName[1] == _T('/')))) ||
220 ((existingFileName[1] == _T(':')) &
221 ((existingFileName[2] == _T('\\')) ||
222 (existingFileName[2] == _T('/'))))) {
223 #ifdef UNICODE
224 lstrcpy(rp_info->target+4, existingFileName);
225 #else
226 MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
227 rp_info->target+4, kLargeBuf);
228 #endif
229 } else {
230 #ifdef UNICODE
231 GetFullPathNameW(linkFileName, 1024, rp_info->target+4, &startlink);
232 lstrcpy(startlink, existingFileName);
233 #else
234 MultiByteToWideChar(CP_ACP, 0, linkFileName, -1,
235 (LPWSTR)f1, kLargeBuf/sizeof(WCHAR));
236 GetFullPathNameW(f1, 1024, rp_info->target+4, &startlink);
237 MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
238 startlink, kLargeBuf+4-(startlink-rp_info->target));
239 #endif
240 }
241 /* Remove "XXX/../" and replace "/" with "\" */
242 for (startlink = endlink = rp_info->target+4;
243 endlink[0]; startlink++, endlink++) {
244 startlink[0] = endlink[0];
245 if (startlink[0] == L'/')
246 startlink[0] = L'\\';
247 if ((startlink[0] == L'\\') &&
248 (startlink[-1] == L'.') &&
249 (startlink[-2] == L'.')) {
250 for (startlink--; startlink > rp_info->target+4 &&
251 startlink[0] != L'\\'; startlink--)
252 { }
253 for (startlink--; startlink > rp_info->target+4 &&
254 startlink[0] != L'\\'; startlink--)
255 { }
256 if (startlink < rp_info->target+4)
257 startlink = rp_info->target+4;
258 }
259 }
260 startlink[0] = endlink[0];
261 rp_info->targetLength = lstrlenW(rp_info->target)*sizeof(WCHAR);
262 rp_info->targetMaxLength = rp_info->targetLength+sizeof(WCHAR);
263 rp_info->dataLength = rp_info->targetMaxLength
264 +FIELD_OFFSET(struct rp_info, target)
265 -FIELD_OFFSET(struct rp_info, reserved1)
266 +sizeof(WCHAR);
267 if (DeviceIoControl(f, 0x900A4, rp_info,
268 rp_info->dataLength
269 +FIELD_OFFSET(struct rp_info, reserved1),
270 NULL, 0, &len, NULL)) {
271 CloseHandle(f);
272 HeapFree(GetProcessHeap(), 0, rp_info);
273 HeapFree(GetProcessHeap(), 0, f2);
274 HeapFree(GetProcessHeap(), 0, f1);
275 return TRUE;
276 }
277 CloseHandle(f);
278 RemoveDirectory(linkFileName);
279 HeapFree(GetProcessHeap(), 0, rp_info);
280 }
281 }
282 for (p = f2; p[0]; p++)
283 if (p[0] == _T('\\'))
284 p[0] = _T('/');
285 f = CreateFile(linkFileName, GENERIC_READ | GENERIC_WRITE,
286 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
287 CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM, NULL);
288 if (f != INVALID_HANDLE_VALUE) {
289 struct {
290 WCHAR sig[4];
291 WCHAR value[kLargeBuf];
292 } *link_info = HeapAlloc(GetProcessHeap(),
293 HEAP_ZERO_MEMORY,
294 sizeof(*link_info));
295 DWORD towrite, written;
296 link_info->sig[0] = 0x6e49;
297 link_info->sig[1] = 0x7874;
298 link_info->sig[2] = 0x4e4c;
299 link_info->sig[3] = 0x014b;
300 #ifdef UNICODE
301 lstrcpy(link_info->value, f2);
302 #else
303 MultiByteToWideChar(CP_ACP, 0, f2, -1, link_info->value, kLargeBuf);
304 #endif
305 towrite = lstrlenW(link_info->value)*sizeof(WCHAR)+sizeof(link_info->sig);
306 WriteFile(f, link_info, towrite, &written, NULL);
307 CloseHandle(f);
308 if (written == towrite) {
309 HeapFree(GetProcessHeap(), 0, link_info);
310 HeapFree(GetProcessHeap(), 0, f2);
311 HeapFree(GetProcessHeap(), 0, f1);
312 return TRUE;
313 }
314 HeapFree(GetProcessHeap(), 0, link_info);
315 }
316 HeapFree(GetProcessHeap(), 0, f2);
317 HeapFree(GetProcessHeap(), 0, f1);
318 return FALSE;
319 }
320
321 HINSTANCE instance;
322
323 HWND parent, list;
324
325 /*
326 * Show message in NSIS details window.
327 */
328 void NSISprint(const TCHAR *str) {
329 if (list && *str) {
330 LVITEM item = {
331 /* mask */ LVIF_TEXT,
332 /* iItem */ SendMessage(list, LVM_GETITEMCOUNT, 0, 0),
333 /* iSubItem */ 0, /* state */ 0, /* stateMask */ 0,
334 /* pszText */ (TCHAR *) str, /* cchTextMax */ 0,
335 /* iImage */ 0, /* lParam */ 0, /* iIndent */ 0,
336 /* iGroupId */ 0, /* cColumns */ 0, /* puColumns */ NULL,
337 /* piColFmt */ NULL, /* iGroup */ 0};
338 ListView_InsertItem(list, &item);
339 ListView_EnsureVisible(list, item.iItem, 0);
340 }
341 }
342
343 enum linktype { HARDLINK, SOFTLINKD, SOFTLINKF };
344
345 void makelink(HWND hwndParent, int string_size, TCHAR *variables,
346 stack_t **stacktop, extra_parameters *extra, enum linktype type) {
347 TCHAR *msg = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
348 TCHAR *from = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kSmallBuf);
349 TCHAR *to = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kSmallBuf);
350 TCHAR *msgFormat =
351 type == HARDLINK ? _T("Link: \"%s\" to \"%s\"%s") :
352 type == SOFTLINKD ? _T("Symbolic Directory Link: \"%s\" to \"%s\"%s") :
353 _T("Symbolic Link: \"%s\" to \"%s\"%s");
354 BOOL res;
355 parent = hwndParent;
356 list = FindWindowEx(FindWindowEx(parent, NULL, _T("#32770"), NULL),
357 NULL, _T("SysListView32"), NULL);
358
359 EXDLL_INIT();
360
361 if (!msg || !from || !to) {
362 MessageBox(parent, _T("Fatal error: no memory for MkLink"), 0, MB_OK);
363 }
364
365 if (popstringn(from, kSmallBuf)) {
366 MessageBox(parent,
367 _T("Usage: MkLink::Hard \"to_file\" \"from_file\" "), 0, MB_OK);
368 }
369
370 if (popstringn(to, kSmallBuf)) {
371 MessageBox(parent,
372 _T("Usage: MkLink::Hard \"fo_file\" \"from_file\" "),0,MB_OK);
373 }
374
375 switch (type) {
376 case HARDLINK:
377 res = MakeHardLink(from, to);
378 break;
379 case SOFTLINKD:
380 res = MakeSymLink(from, to, TRUE);
381 break;
382 case SOFTLINKF:
383 res = MakeSymLink(from, to, FALSE);
384 break;
385 }
386 wsprintf(msg, msgFormat, to, from, res ? _T("") : _T(" - fail..."));
387 NSISprint(msg);
388
389 HeapFree(GetProcessHeap(), 0, to);
390 HeapFree(GetProcessHeap(), 0, from);
391 HeapFree(GetProcessHeap(), 0, msg);
392 }
393
394 void __declspec(dllexport) Hard(HWND hwndParent, int string_size,
395 TCHAR *variables, stack_t **stacktop,
396 extra_parameters *extra) {
397 makelink(hwndParent, string_size, variables, stacktop, extra, HARDLINK);
398 }
399
400 void __declspec(dllexport) SoftD(HWND hwndParent, int string_size,
401 TCHAR *variables, stack_t **stacktop,
402 extra_parameters *extra) {
403 makelink(hwndParent, string_size, variables, stacktop, extra, SOFTLINKD);
404 }
405
406 void __declspec(dllexport) SoftF(HWND hwndParent, int string_size,
407 TCHAR *variables, stack_t **stacktop,
408 extra_parameters *extra) {
409 makelink(hwndParent, string_size, variables, stacktop, extra, SOFTLINKF);
410 }
411
412 BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) {
413 instance = hInst;
414 return TRUE;
415 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698