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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
Index: tools/hermetic_cygwin/MkLink/MkLink.c
===================================================================
--- tools/hermetic_cygwin/MkLink/MkLink.c (revision 0)
+++ tools/hermetic_cygwin/MkLink/MkLink.c (revision 0)
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include <commctrl.h>
+#include <nsis/pluginapi.h>
+#include <winternl.h>
+
+enum { kLargeBuf = 1024, kSmallBuf = 256 } ;
+
+#if defined(_MSC_VER)
+/* Ensure these are treated as functions and not inlined as intrinsics, or disable /Oi */
+#pragma warning(disable:4164) /* intrinsic function not declared */
+#pragma function(memcpy, memset, memcmp)
+#endif
+
+HMODULE hNrDll = NULL;
+NTSTATUS (NTAPI *fNtCreateFile) (PHANDLE FileHandle,
+ ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes,
+ PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize,
+ ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition,
+ ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
+NTSTATUS (NTAPI *fNtClose) (HANDLE Handle);
+
+HMODULE hKernel32 = NULL;
+BOOL (WINAPI *fCreateHardLink) (TCHAR * linkFileName,
+ TCHAR * existingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL (WINAPI *fCreateSymbolicLink) (TCHAR * linkFileName,
+ TCHAR * existingFileName, DWORD flags);
+
+#undef CreateHardLink
+#undef CreateSymbolicLink
+#ifdef UNICODE
+#define CreateHardLink "CreateHardLinkW"
+#define CreateSymbolicLink "CreateSymbolicLinkW"
+#else
+#define CreateHardLink "CreateHardLinkA"
+#define CreateSymbolicLink "CreateSymbolicLinkA"
+#endif
+
+BOOL MakeHardLink(TCHAR *linkFileName, TCHAR *existingFileName) {
+ if (!hKernel32)
+ hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
+ if (hKernel32) {
+ if (!fCreateHardLink)
+ fCreateHardLink = GetProcAddress(hKernel32, CreateHardLink);
+ if (fCreateHardLink)
+ return fCreateHardLink(linkFileName, existingFileName, NULL);
+ }
+ return FALSE;
+}
+
+BOOL MakeSymLink(TCHAR *linkFileName, TCHAR *existingFileName, BOOL dirLink) {
+ TCHAR *f1 = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
+ TCHAR *f2 = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
+ SECURITY_ATTRIBUTES sec_attr = { sizeof (SECURITY_ATTRIBUTES), NULL, FALSE};
+ OBJECT_ATTRIBUTES obj_attr;
+ IO_STATUS_BLOCK io_block;
+ TCHAR *p, *q;
+ HANDLE f;
+ BOOL status;
+ if (!f1 || !f2)
+ return FALSE;
+ lstrcpy(f1, linkFileName);
dpolukhin 2010/04/28 13:16:08 As far as I understand maximum path of 32,767 char
+ p = q = f1;
+ while (q[0]) {
+ do {
+ q++;
+ } while (q[0] && q[0] != '\\');
+ p = q;
+ }
+ if (p[0] = '\\') {
+ TCHAR c = p[1];
+ p[1] = 0;
+ status = GetVolumeInformation(f1, NULL, 0, NULL, NULL, NULL,
+ f2, sizeof(f2));
+ p[1] = c;
+ } else {
+ status = GetVolumeInformation(NULL, NULL, 0, NULL, NULL, NULL,
+ f2, sizeof(f2));
+ }
+ /* If it's NFS then we can create real symbolic link. */
+ if (!lstrcmpi(f2, _T("NFS"))) {
+ if (!hNrDll)
+ hNrDll = LoadLibrary(_T("NTDLL.DLL"));
+ if (hNrDll) {
+ if (!fNtCreateFile)
+ fNtCreateFile = GetProcAddress(hNrDll, "NtCreateFile");
+ if (!fNtClose)
+ fNtClose = GetProcAddress(hNrDll, "NtClose");
+ if (fNtCreateFile && fNtClose) {
+ struct {
+ ULONG offset;
+ UCHAR flags;
+ UCHAR nameLength;
+ USHORT valueLength;
+ CHAR name[21];
+ /* To prevent troubles with alignment */
+ CHAR value[kLargeBuf*sizeof(WCHAR)];
+ } *ea_info = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(*ea_info));
+ WCHAR *fn = HeapAlloc(GetProcessHeap(),
+ 0,
+ sizeof(TCHAR)*kLargeBuf);
+ UNICODE_STRING n = { lstrlen(linkFileName), kLargeBuf, fn };
+ ea_info->nameLength = 20;
+ lstrcpy(ea_info->name, "NfsSymlinkTargetName");
+#ifdef UNICODE
+ lstrcpy(fn, linkFileName);
+ lstrcpy((LPWSTR)ea_info->value, existingFileName);
+#else
+ MultiByteToWideChar(CP_ACP, 0, linkFileName, -1, fn, kLargeBuf);
+ MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
+ (LPWSTR)ea_info->value,
+ sizeof(ea_info->value)/sizeof(WCHAR));
+#endif
+ ea_info->valueLength =
+ lstrlenW((LPWSTR)ea_info->value)*sizeof(WCHAR);
+ InitializeObjectAttributes(&obj_attr, &n, OBJ_CASE_INSENSITIVE,
+ NULL, NULL);
+ status = fNtCreateFile(
+ &f, FILE_WRITE_DATA | FILE_WRITE_EA | SYNCHRONIZE, &obj_attr,
+ &io_block, NULL, FILE_ATTRIBUTE_SYSTEM, FILE_SHARE_READ |
+ FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_CREATE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
+ &ea_info, 1024 * sizeof (WCHAR));
+ if (NT_SUCCESS(status)) {
+ fNtClose(f);
+ HeapFree(GetProcessHeap(), 0, fn);
+ HeapFree(GetProcessHeap(), 0, ea_info);
+ HeapFree(GetProcessHeap(), 0, f2);
+ HeapFree(GetProcessHeap(), 0, f1);
+ return TRUE;
+ }
+ HeapFree(GetProcessHeap(), 0, fn);
+ HeapFree(GetProcessHeap(), 0, ea_info);
+ }
+ }
+ }
+ lstrcpy(f2, existingFileName);
+ if (!hKernel32)
+ hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
+ if (hKernel32) {
+ if (!fCreateSymbolicLink)
+ fCreateSymbolicLink = GetProcAddress(hKernel32, CreateSymbolicLink);
+ if (fCreateSymbolicLink) {
+ for (p = f1; p[0]; p++)
+ if (p[0] == _T('/'))
+ p[0] = _T('\\');
+ for (p = f2; p[0]; p++)
+ if (p[0] == _T('/'))
+ p[0] = _T('\\');
+ if (fCreateSymbolicLink(f1, f2,
+ dirLink ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0)) {
+ HeapFree(GetProcessHeap(), 0, f2);
+ HeapFree(GetProcessHeap(), 0, f1);
+ return TRUE;
+ }
+ }
+ }
+ if (dirLink) {
+ /* Ignore errors - file may already exist */
+ CreateDirectory(linkFileName, NULL);
+ f = CreateFile(linkFileName, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL );
+ if (f != INVALID_HANDLE_VALUE) {
+ struct rp_info {
+ DWORD tag;
+ DWORD dataLength;
+ WORD reserved1;
+ WORD targetLength;
+ WORD targetMaxLength;
+ WORD reserved2;
+ WCHAR target[kLargeBuf+4];
+ } *rp_info = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(*rp_info));
+ DWORD len;
+ WCHAR *startlink, *endlink;
+ rp_info->tag = IO_REPARSE_TAG_MOUNT_POINT;
+ rp_info->target[0] = L'\\';
+ rp_info->target[1] = L'?';
+ rp_info->target[2] = L'?';
+ rp_info->target[3] = L'\\';
+ if ((((existingFileName[0] == _T('\\')) ||
+ (existingFileName[0] == _T('/'))) &
+ ((existingFileName[1] == _T('\\')) ||
+ (existingFileName[1] == _T('/')))) ||
+ ((existingFileName[1] == _T(':')) &
+ ((existingFileName[2] == _T('\\')) ||
+ (existingFileName[2] == _T('/'))))) {
+#ifdef UNICODE
+ lstrcpy(rp_info->target+4, existingFileName);
+#else
+ MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
+ rp_info->target+4, kLargeBuf);
+#endif
+ } else {
+#ifdef UNICODE
+ GetFullPathNameW(linkFileName, 1024, rp_info->target+4, &startlink);
+ lstrcpy(startlink, existingFileName);
+#else
+ MultiByteToWideChar(CP_ACP, 0, linkFileName, -1,
+ (LPWSTR)f1, kLargeBuf/sizeof(WCHAR));
+ GetFullPathNameW(f1, 1024, rp_info->target+4, &startlink);
+ MultiByteToWideChar(CP_ACP, 0, existingFileName, -1,
+ startlink, kLargeBuf+4-(startlink-rp_info->target));
+#endif
+ }
+ /* Remove "XXX/../" and replace "/" with "\" */
+ for (startlink = endlink = rp_info->target+4;
+ endlink[0]; startlink++, endlink++) {
+ startlink[0] = endlink[0];
+ if (startlink[0] == L'/')
+ startlink[0] = L'\\';
+ if ((startlink[0] == L'\\') &&
+ (startlink[-1] == L'.') &&
+ (startlink[-2] == L'.')) {
+ for (startlink--; startlink > rp_info->target+4 &&
+ startlink[0] != L'\\'; startlink--)
+ { }
+ for (startlink--; startlink > rp_info->target+4 &&
+ startlink[0] != L'\\'; startlink--)
+ { }
+ if (startlink < rp_info->target+4)
+ startlink = rp_info->target+4;
+ }
+ }
+ startlink[0] = endlink[0];
+ rp_info->targetLength = lstrlenW(rp_info->target)*sizeof(WCHAR);
+ rp_info->targetMaxLength = rp_info->targetLength+sizeof(WCHAR);
+ rp_info->dataLength = rp_info->targetMaxLength
+ +FIELD_OFFSET(struct rp_info, target)
+ -FIELD_OFFSET(struct rp_info, reserved1)
+ +sizeof(WCHAR);
+ if (DeviceIoControl(f, 0x900A4, rp_info,
+ rp_info->dataLength
+ +FIELD_OFFSET(struct rp_info, reserved1),
+ NULL, 0, &len, NULL)) {
+ CloseHandle(f);
+ HeapFree(GetProcessHeap(), 0, rp_info);
+ HeapFree(GetProcessHeap(), 0, f2);
+ HeapFree(GetProcessHeap(), 0, f1);
+ return TRUE;
+ }
+ CloseHandle(f);
+ RemoveDirectory(linkFileName);
+ HeapFree(GetProcessHeap(), 0, rp_info);
+ }
+ }
+ for (p = f2; p[0]; p++)
+ if (p[0] == _T('\\'))
+ p[0] = _T('/');
+ f = CreateFile(linkFileName, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM, NULL);
+ if (f != INVALID_HANDLE_VALUE) {
+ struct {
+ WCHAR sig[4];
+ WCHAR value[kLargeBuf];
+ } *link_info = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(*link_info));
+ DWORD towrite, written;
+ link_info->sig[0] = 0x6e49;
+ link_info->sig[1] = 0x7874;
+ link_info->sig[2] = 0x4e4c;
+ link_info->sig[3] = 0x014b;
+#ifdef UNICODE
+ lstrcpy(link_info->value, f2);
+#else
+ MultiByteToWideChar(CP_ACP, 0, f2, -1, link_info->value, kLargeBuf);
+#endif
+ towrite = lstrlenW(link_info->value)*sizeof(WCHAR)+sizeof(link_info->sig);
+ WriteFile(f, link_info, towrite, &written, NULL);
+ CloseHandle(f);
+ if (written == towrite) {
+ HeapFree(GetProcessHeap(), 0, link_info);
+ HeapFree(GetProcessHeap(), 0, f2);
+ HeapFree(GetProcessHeap(), 0, f1);
+ return TRUE;
+ }
+ HeapFree(GetProcessHeap(), 0, link_info);
+ }
+ HeapFree(GetProcessHeap(), 0, f2);
+ HeapFree(GetProcessHeap(), 0, f1);
+ return FALSE;
+}
+
+HINSTANCE instance;
+
+HWND parent, list;
+
+/*
+ * Show message in NSIS details window.
+ */
+void NSISprint(const TCHAR *str) {
+ if (list && *str) {
+ LVITEM item = {
+ /* mask */ LVIF_TEXT,
+ /* iItem */ SendMessage(list, LVM_GETITEMCOUNT, 0, 0),
+ /* iSubItem */ 0, /* state */ 0, /* stateMask */ 0,
+ /* pszText */ (TCHAR *) str, /* cchTextMax */ 0,
+ /* iImage */ 0, /* lParam */ 0, /* iIndent */ 0,
+ /* iGroupId */ 0, /* cColumns */ 0, /* puColumns */ NULL,
+ /* piColFmt */ NULL, /* iGroup */ 0};
+ ListView_InsertItem(list, &item);
+ ListView_EnsureVisible(list, item.iItem, 0);
+ }
+}
+
+enum linktype { HARDLINK, SOFTLINKD, SOFTLINKF };
+
+void makelink(HWND hwndParent, int string_size, TCHAR *variables,
+ stack_t **stacktop, extra_parameters *extra, enum linktype type) {
+ TCHAR *msg = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kLargeBuf);
+ TCHAR *from = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kSmallBuf);
+ TCHAR *to = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*kSmallBuf);
+ TCHAR *msgFormat =
+ type == HARDLINK ? _T("Link: \"%s\" to \"%s\"%s") :
+ type == SOFTLINKD ? _T("Symbolic Directory Link: \"%s\" to \"%s\"%s") :
+ _T("Symbolic Link: \"%s\" to \"%s\"%s");
+ BOOL res;
+ parent = hwndParent;
+ list = FindWindowEx(FindWindowEx(parent, NULL, _T("#32770"), NULL),
+ NULL, _T("SysListView32"), NULL);
+
+ EXDLL_INIT();
+
+ if (!msg || !from || !to) {
+ MessageBox(parent, _T("Fatal error: no memory for MkLink"), 0, MB_OK);
+ }
+
+ if (popstringn(from, kSmallBuf)) {
+ MessageBox(parent,
+ _T("Usage: MkLink::Hard \"to_file\" \"from_file\" "), 0, MB_OK);
+ }
+
+ if (popstringn(to, kSmallBuf)) {
+ MessageBox(parent,
+ _T("Usage: MkLink::Hard \"fo_file\" \"from_file\" "),0,MB_OK);
+ }
+
+ switch (type) {
+ case HARDLINK:
+ res = MakeHardLink(from, to);
+ break;
+ case SOFTLINKD:
+ res = MakeSymLink(from, to, TRUE);
+ break;
+ case SOFTLINKF:
+ res = MakeSymLink(from, to, FALSE);
+ break;
+ }
+ wsprintf(msg, msgFormat, to, from, res ? _T("") : _T(" - fail..."));
+ NSISprint(msg);
+
+ HeapFree(GetProcessHeap(), 0, to);
+ HeapFree(GetProcessHeap(), 0, from);
+ HeapFree(GetProcessHeap(), 0, msg);
+}
+
+void __declspec(dllexport) Hard(HWND hwndParent, int string_size,
+ TCHAR *variables, stack_t **stacktop,
+ extra_parameters *extra) {
+ makelink(hwndParent, string_size, variables, stacktop, extra, HARDLINK);
+}
+
+void __declspec(dllexport) SoftD(HWND hwndParent, int string_size,
+ TCHAR *variables, stack_t **stacktop,
+ extra_parameters *extra) {
+ makelink(hwndParent, string_size, variables, stacktop, extra, SOFTLINKD);
+}
+
+void __declspec(dllexport) SoftF(HWND hwndParent, int string_size,
+ TCHAR *variables, stack_t **stacktop,
+ extra_parameters *extra) {
+ makelink(hwndParent, string_size, variables, stacktop, extra, SOFTLINKF);
+}
+
+BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) {
+ instance = hInst;
+ return TRUE;
+}
Property changes on: tools/hermetic_cygwin/MkLink/MkLink.c
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698