diff options
author | Araq <rumpf_a@web.de> | 2014-04-21 00:07:40 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-04-21 00:07:40 +0200 |
commit | 2c972427399da894f91d0a4bd067b63866bb20ea (patch) | |
tree | 41317db61b4c404940816989172bc1c921b7ccf0 /lib | |
parent | e3fab47508138687cdc85553440c8313606395c3 (diff) | |
parent | 5cf8c05a226ba617a6e6de8ebe7e82c19d680b98 (diff) | |
download | Nim-2c972427399da894f91d0a4bd067b63866bb20ea.tar.gz |
Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/future.nim | 15 | ||||
-rw-r--r-- | lib/pure/os.nim | 179 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 6 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 4 |
4 files changed, 176 insertions, 28 deletions
diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 2401c4f72..73c20e708 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -26,8 +26,15 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} = for i in 0 .. <p.len: let ident = p[i] var identDefs = newNimNode(nnkIdentDefs) - identDefs.add newIdentNode("i" & $i) - identDefs.add(ident) + case ident.kind + of nnkExprColonExpr: + identDefs.add ident[0] + identDefs.add ident[1] + of nnkIdent: + identDefs.add newIdentNode("i" & $i) + identDefs.add(ident) + else: + error("Incorrect type list in proc type declaration.") identDefs.add newEmptyNode() formalParams.add identDefs of nnkIdent: @@ -47,7 +54,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} = macro `=>`*(p, b: expr): expr {.immediate.} = ## Syntax sugar for anonymous procedures. ## - ## ..code-block:: nimrod + ## .. code-block:: nimrod ## ## proc passTwoAndTwo(f: (int, int) -> int): int = ## f(2, 2) @@ -98,7 +105,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} = macro `->`*(p, b: expr): expr {.immediate.} = ## Syntax sugar for procedure types. ## - ## ..code-block:: nimrod + ## .. code-block:: nimrod ## ## proc pass2(f: (float, float) -> float): float = ## f(2, 2) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 62261753f..00a33db75 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -448,6 +448,8 @@ proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} = proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} = ## Returns the `file`'s creation time. + ## Note that under posix OS's, the returned time may actually be the time at + ## which the file's attribute's were last modified. when defined(posix): var res: TStat if stat(file, res) < 0'i32: osError(osLastError()) @@ -777,6 +779,25 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} = elif defined(posix): result = path[0] == '/' +when defined(Windows): + proc openHandle(path: string, followSymlink=true): THandle = + var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL + if not followSymlink: + flags = flags or FILE_FLAG_OPEN_REPARSE_POINT + + when useWinUnicode: + result = createFileW( + newWideCString(path), 0'i32, + FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, + nil, OPEN_EXISTING, flags, 0 + ) + else: + result = createFileA( + path, 0'i32, + FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, + nil, OPEN_EXISTING, flags, 0 + ) + proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = ## Returns True if both pathname arguments refer to the same physical @@ -787,26 +808,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", ## sym-linked paths to the same file or directory. when defined(Windows): var success = true - - when useWinUnicode: - var p1 = newWideCString(path1) - var p2 = newWideCString(path2) - template openHandle(path: expr): expr = - createFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or - FILE_SHARE_WRITE, nil, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0) - - var f1 = openHandle(p1) - var f2 = openHandle(p2) - - else: - template openHandle(path: expr): expr = - createFileA(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or - FILE_SHARE_WRITE, nil, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0) - - var f1 = openHandle(path1) - var f2 = openHandle(path2) + var f1 = openHandle(path1) + var f2 = openHandle(path2) var lastErr: TOSErrorCode if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE: @@ -1747,4 +1750,140 @@ proc expandTilde*(path: string): string = else: result = path +when defined(Windows): + type + DeviceId = int32 + FileId = int64 +else: + type + DeviceId = TDev + FileId = TIno + +type + FileInfo = object + ## Contains information associated with a file object. + id: tuple[device: DeviceId, file: FileId] # Device and file id. + kind: TPathComponent # Kind of file object - directory, symlink, etc. + size: BiggestInt # Size of file. + permissions: set[TFilePermission] # File permissions + linkCount: BiggestInt # Number of hard links the file object has. + lastAccessTime: TTime # Time file was last accessed. + lastWriteTime: TTime # Time file was last modified/written to. + creationTime: TTime # Time file was created. Not supported on all systems! + +template rawToFormalFileInfo(rawInfo, formalInfo): expr = + ## Transforms the native file info structure into the one nimrod uses. + ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows, + ## or a 'TStat' structure on posix + when defined(Windows): + template toTime(e): expr = winTimeToUnixTime(rdFileTime(e)) + template merge(a, b): expr = a or (b shl 32) + formalInfo.id.device = rawInfo.dwVolumeSerialNumber + formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh) + formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh) + formalInfo.linkCount = rawInfo.nNumberOfLinks + formalInfo.lastAccessTime = toTime(rawInfo.ftLastAccessTime) + formalInfo.lastWriteTime = toTime(rawInfo.ftLastWriteTime) + formalInfo.creationTime = toTime(rawInfo.ftCreationTime) + + # Retrieve basic permissions + if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_READONLY) != 0'i32: + formalInfo.permissions = {fpUserExec, fpUserRead, fpGroupExec, + fpGroupRead, fpOthersExec, fpOthersRead} + else: + result.permissions = {fpUserExec..fpOthersRead} + + # Retrieve basic file kind + result.kind = pcFile + if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32: + formalInfo.kind = pcDir + if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32: + formalInfo.kind = succ(result.kind) + + else: + template checkAndIncludeMode(rawMode, formalMode: expr) = + if (rawInfo.st_mode and rawMode) != 0'i32: + formalInfo.permissions.incl(formalMode) + formalInfo.id = (rawInfo.st_dev, rawInfo.st_ino) + formalInfo.size = rawInfo.st_size + formalInfo.linkCount = rawInfo.st_Nlink + formalInfo.lastAccessTime = rawInfo.st_atime + formalInfo.lastWriteTime = rawInfo.st_mtime + formalInfo.creationTime = rawInfo.st_ctime + + result.permissions = {} + checkAndIncludeMode(S_IRUSR, fpUserRead) + checkAndIncludeMode(S_IWUSR, fpUserWrite) + checkAndIncludeMode(S_IXUSR, fpUserExec) + + checkAndIncludeMode(S_IRGRP, fpGroupRead) + checkAndIncludeMode(S_IWGRP, fpGroupWrite) + checkAndIncludeMode(S_IXGRP, fpGroupExec) + + checkAndIncludeMode(S_IROTH, fpOthersRead) + checkAndIncludeMode(S_IWOTH, fpOthersWrite) + checkAndIncludeMode(S_IXOTH, fpOthersExec) + + formalInfo.kind = pcFile + if S_ISDIR(rawInfo.st_mode): formalInfo.kind = pcDir + if S_ISLNK(rawInfo.st_mode): formalInfo.kind.inc() + +proc getFileInfo*(handle: TFileHandle): FileInfo = + ## Retrieves file information for the file object represented by the given + ## handle. + ## + ## If the information cannot be retrieved, such as when the file handle + ## is invalid, an error will be thrown. + # Done: ID, Kind, Size, Permissions, Link Count + when defined(Windows): + var rawInfo: TBY_HANDLE_FILE_INFORMATION + # We have to use the super special '_get_osfhandle' call (wrapped above) + # To transform the C file descripter to a native file handle. + var realHandle = get_osfhandle(handle) + if getFileInformationByHandle(realHandle, addr rawInfo) == 0: + osError(osLastError()) + rawToFormalFileInfo(rawInfo, result) + else: + var rawInfo: TStat + if fstat(handle, rawInfo) < 0'i32: + osError(osLastError()) + rawToFormalFileInfo(rawInfo, result) + +proc getFileInfo*(file: TFile): FileInfo = + result = getFileInfo(file.fileHandle()) + +proc getFileInfo*(path: string, followSymlink = true): FileInfo = + ## Retrieves file information for the file object pointed to by `path`. + ## + ## Due to intrinsic differences between operating systems, the information + ## contained by the returned `FileInfo` structure will be slightly different + ## across platforms, and in some cases, incomplete or inaccurate. + ## + ## When `followSymlink` is true, symlinks are followed and the information + ## retrieved is information related to the symlink's target. Otherwise, + ## information on the symlink itself is retrieved. + ## + ## If the information cannot be retrieved, such as when the path doesn't + ## exist, or when permission restrictions prevent the program from retrieving + ## file information, an error will be thrown. + when defined(Windows): + var + handle = openHandle(path, followSymlink) + rawInfo: TBY_HANDLE_FILE_INFORMATION + if handle == INVALID_HANDLE_VALUE: + osError(osLastError()) + if getFileInformationByHandle(handle, addr rawInfo) == 0: + osError(osLastError()) + rawToFormalFileInfo(rawInfo, result) + discard closeHandle(handle) + else: + var rawInfo: TStat + if followSymlink: + if lstat(path, rawInfo) < 0'i32: + osError(osLastError()) + else: + if stat(path, rawInfo) < 0'i32: + osError(osLastError()) + rawToFormalFileInfo(rawInfo, result) + {.pop.} diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index eb9d2000b..4244bae4c 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -252,10 +252,8 @@ proc nimIntToStr(x: int): string {.compilerRtl.} = proc nimFloatToStr(x: float): string {.compilerproc.} = var buf: array [0..59, char] - c_sprintf(buf, "%#.f", x) - result = $buf - if result[len(result)-1] == '.': - result.add("0") + c_sprintf(buf, "%#.16e", x) + return $buf proc nimInt64ToStr(x: int64): string {.compilerRtl.} = result = newString(sizeof(x)*4) diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 7024943b3..4ce2f11b4 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -581,6 +581,7 @@ const INVALID_FILE_SIZE* = -1'i32 FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32 + FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32 # Error Constants const @@ -715,3 +716,6 @@ proc WSASend*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD, bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped, completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".} + +proc get_osfhandle*(fd:TFileHandle): THandle {. + importc:"_get_osfhandle", header:"<io.h>".} |