From: <lab...@us...> - 2015-05-03 18:50:54
|
Revision: 1521 http://sourceforge.net/p/opengtoolkit/svn/1521 Author: labviewer Date: 2015-05-03 18:50:52 +0000 (Sun, 03 May 2015) Log Message: ----------- implemented the Windows side of links Modified Paths: -------------- trunk/lvzip/c_source/lvutil.c trunk/lvzip/c_source/lvutil.h Modified: trunk/lvzip/c_source/lvutil.c =================================================================== --- trunk/lvzip/c_source/lvutil.c 2015-05-03 15:20:13 UTC (rev 1520) +++ trunk/lvzip/c_source/lvutil.c 2015-05-03 18:50:52 UTC (rev 1521) @@ -168,6 +168,58 @@ return err; } +static MgErr ConvertFromPosixPath(ConstCStr posixPath, int32 len, LStrHandle *hfsPath, Boolean isDir) +{ + MgErr err = mFullErr; + CFURLRef urlRef = NULL; + CFStringRef hfsRef; + uInt32 encoding = CFStringGetSystemEncoding(); + + if (!hfsPath) + return mgArgErr; + + if (*hsfPath) + LStrLen(**hsfPath) = 0; + + urlRef = CFURLCreateFromFileSystemRepresentation(NULL, posixPath, len, false); + if (!urlRef) + { + return mFullErr; + } + hsfRef = CFURLCopyFileSystemPath(urlRef, kCFURLHFSPathStyle); + CFRelease(urlRef); + if (hfsRef) + { + CFIndex len; + CFRange range = CFRangeMake(0, CFStringGetLength(hfsRef)); + if (CFStringGetBytes(hfsRef, range, encoding, 0, false, NULL, 0, &len) > 0) + { + if (len > 0) + { + err = NumericArrayResize(uB, 1, (UHandle*)hfsPath, len + 1); + if (!err) + { + if (CFStringGetBytes(hsfRef, range, encoding, 0, false, LStrBuf(**hfsPath), len, &len) > 0) + { + LStrBuf(**hfsPath)[len] = 0; + LStrLen(**hfsPath) = len; + } + else + { + err = bogusError; + } + } + } + } + else + { + err = bogusError; + } + CFRelease(hfsRef); + } + return err; +} + static MgErr FSMakePathRef(Path path, FSRef *ref) { LStrHandle str = NULL; @@ -914,6 +966,24 @@ return err; } +LibAPI(MgErr) LVPath_FromText(CStr str, int32 len, Path *path, LVBoolean isDir) +{ + MgErr err = mgNoErr; +#if usesHFSPath + LStrHandle hsfPath = NULL; + /* Convert the posix path to an HFS path */ + err = ConvertFromPosixPath(str, len, &hfsPath, isDir); + if (!err) + { + err = FTextToPath(LStrBuf(*hfsPath), LStrLen(*hsfPath), path); + } +#else + Unused(isDir); + err = FTextToPath(str, len, path); +#endif + return err; +} + LibAPI(MgErr) LVPath_CreateLink(Path path, uInt32 flags, Path target) { MgErr err = mgNoErr; @@ -954,7 +1024,7 @@ { if (flags & kLinkDir) err = mgNotSupported; - else if (!CreateHardLinkA(LStrBuf(*src), LStrBuf(*tgt), NULL) + else if (!CreateHardLinkA(LStrBuf(*src), LStrBuf(*tgt), NULL)) { err = Win32ToLVFileErr(); } @@ -974,6 +1044,8 @@ return err; } +#define PREPARSE_DATA_BUFFER_SIZE 16*1024 + LibAPI(MgErr) LVPath_ReadLink(Path path, Path *target) { MgErr err = mgNoErr; @@ -1013,7 +1085,7 @@ } else if (retval < len) { - + err = LVPath_FromText(buf, retval, target, LV_FALSE); free(buf); break; } @@ -1021,28 +1093,64 @@ buf = realloc(buf, len); } #elif Win32 - if (GetFileAttributes(fpath) & REPARSE_FOLDER == REPARSE_FOLDER) + if ((GetFileAttributesA(LStrBuf(*src)) & REPARSE_FOLDER) == REPARSE_FOLDER) { - // Open the file correctly depending on the string type. - HANDLE handle = CreateFileA(fpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0); + PREPARSE_DATA_BUFFER buffer = NULL; + // Open the target file + HANDLE handle = CreateFileA(LStrBuf(*src), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (handle != INVALID_HANDLE_VALUE) + { + DWORD bytes; + // Maximum REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024) + buffer = (PREPARSE_DATA_BUFFER)malloc(PREPARSE_DATA_BUFFER_SIZE); + if (DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, PREPARSE_DATA_BUFFER_SIZE, &bytes, NULL)) + err = Win32ToLVFileErr(); + + if (bytes < 9) + err = fEOF; + + // Close the handle to our file so we're not locking it anymore. + CloseHandle(handle); + } + else + { + err = Win32ToLVFileErr(); + } - // MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024) - buffer = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 16*1024) - // Above will return an ugly string (byte array), so we'll need to parse it. - // But first, we'll close the handle to our file so we're not locking it anymore. - CloseHandle(handle) - - // Minimum possible length (assuming that the length of the target is bigger than 0) - if len(buffer) < 9: - return None - // Parse and return our result. - result = parse_reparse_buffer(buffer) - offset = result[SYMBOLIC_LINK]['substitute_name_offset'] - ending = offset + result[SYMBOLIC_LINK]['substitute_name_length'] - rpath = result[SYMBOLIC_LINK]['buffer'][offset:ending].replace('\x00','') - if len(rpath) > 4 and rpath[0:4] == '\\??\\': - rpath = rpath[4:] - return rpath; + if (!err) + { + PWCHAR start; + USHORT length; + int32 numBytes; + LStrHandle dest = NULL; + + switch (buffer->ReparseTag) + { + case IO_REPARSE_TAG_SYMLINK: + start = (PWCHAR)((char)buffer->SymbolicLinkReparseBuffer.PathBuffer + buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset); + length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + break; + default: + start = (PWCHAR)((char)buffer->MountPointReparseBuffer.PathBuffer + buffer->MountPointReparseBuffer.SubstituteNameOffset); + length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + break; + } + // Skip possible path prefix + if (length > 4 && !CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, start, 4, L"\\\\??\\", 4)); + start += 4; + + numBytes = WideCharToMultiByte(CP_ACP, 0, start, length, NULL, 0, NULL, NULL); + if (numBytes > 0 && numBytes <= PREPARSE_DATA_BUFFER_SIZE) + { + numBytes = WideCharToMultiByte(CP_ACP, 0, start, length, (LPSTR)buffer, numBytes, NULL, NULL); + if (numBytes > 0) + { + err = LVPath_FromText((CStr)buffer, numBytes, target, LV_FALSE); + } + } + } + if (buffer) + free(buffer); } #else err = mgNotSupported; Modified: trunk/lvzip/c_source/lvutil.h =================================================================== --- trunk/lvzip/c_source/lvutil.h 2015-05-03 15:20:13 UTC (rev 1520) +++ trunk/lvzip/c_source/lvutil.h 2015-05-03 18:50:52 UTC (rev 1521) @@ -543,6 +543,7 @@ Path FNotAPath(Path); Bool32 FIsAPath(Path path); Bool32 FIsAbsPath(Path path); +MgErr FTextToPath(UPtr str, int32 len, Path* path); MgErr FPathToText(Path path, LStrPtr lstr); MgErr FPathToPath(Path *p); Bool32 FIsAPathOfType(Path path, int32 ofType); @@ -556,6 +557,7 @@ MgErr FNewRefNum(Path path, File fd, LVRefNum* refnum); Bool32 FIsARefNum(LVRefNum); MgErr FDisposeRefNum(LVRefNum); +Bool32 FExists(ConstPath path); MgErr FRefNumToFD(LVRefNum, File*); MgErr FGetInfo(ConstPath path, FInfoPtr infop); MgErr FGetInfo64(ConstPath path, FInfo64Ptr infop, FGetInfoWhich which); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |