From b8072bd22ec6e3ccf1a6be1b19fae9de3a0fdcc9 Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Tue, 10 Dec 2013 22:56:29 +0100 Subject: add quoteShell to osproc.nim --- lib/pure/osproc.nim | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 754e34b85..7772585a9 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -41,6 +41,58 @@ type poStdErrToStdOut, ## merge stdout and stderr to the stdout stream poParentStreams ## use the parent's streams +proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = + ## Quote s, so it can be safely passed to Windows API. + ## Based on Python's subprocess.list2cmdline + ## See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx + let needQuote = {' ', '\t'} in s or s.len == 0 + + result = "" + var backslashBuff = "" + if needQuote: + result.add("\"") + + for c in s: + if c == '\\': + backslashBuff.add(c) + elif c == '\"': + result.add(backslashBuff) + result.add(backslashBuff) + backslashBuff.setLen(0) + result.add("\\\"") + else: + if backslashBuff.len != 0: + result.add(backslashBuff) + backslashBuff.setLen(0) + result.add(c) + + if needQuote: + result.add("\"") + +proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = + ## Quote s, so it can be safely passed to POSIX shell. + ## Based on Python's pipes.quote + const safeUnixChars = {'%', '+', '-', '.', '/', '_', ':', '=', '@', + '0'..'9', 'A'..'Z', 'a'..'z'} + if s.len == 0: + return "''" + + let safe = s.allCharsInSet(safeUnixChars) + + if safe: + return s + else: + return "'" & s.replace("'", "'\"'\"'") & "'" + +proc quoteShell*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = + ## Quote s, so it can be safely passed to shell. + when defined(Windows): + return quoteShellWindows(s) + elif defined(posix): + return quoteShellPosix(s) + else: + {.error:"quoteShell is not supported on your system".} + proc execProcess*(command: string, options: set[TProcessOption] = {poStdErrToStdOut, poUseShell}): TaintedString {. @@ -792,5 +844,14 @@ proc execCmdEx*(command: string, options: set[TProcessOption] = { close(p) when isMainModule: - var x = execProcess("gcc -v") - echo "ECHO ", x + assert quoteShellWindows("aaa") == "aaa" + assert quoteShellWindows("aaa\"") == "aaa\\\"" + assert quoteShellWindows("") == "\"\"" + + assert quoteShellPosix("aaa") == "aaa" + assert quoteShellPosix("aaa a") == "'aaa a'" + assert quoteShellPosix("") == "''" + assert quoteShellPosix("a'a") == "'a'\"'\"'a'" + + when defined(posix): + assert quoteShell("") == "''" -- cgit 1.4.1-2-gfad0 From c36319727558f92a47f7aa5fed1d696d63b48d65 Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Tue, 10 Dec 2013 23:00:01 +0100 Subject: Deprecate quoteIfContainsWhite in favor of osproc.quoteShell. --- lib/pure/strutils.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/pure') diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index a4aa81578..fe71cb77b 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -709,9 +709,11 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = if result != -1: return return -1 -proc quoteIfContainsWhite*(s: string): string = +proc quoteIfContainsWhite*(s: string): string {.deprecated.} = ## returns ``'"' & s & '"'`` if `s` contains a space and does not ## start with a quote, else returns `s` + ## DEPRECATED as it was confused for shell quoting function. + ## For this application use osproc.quoteShell. if find(s, {' ', '\t'}) >= 0 and s[0] != '"': result = '"' & s & '"' else: -- cgit 1.4.1-2-gfad0 From 39cabcdd2702098825eba32fcbc6737b9aa45e6e Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Wed, 11 Dec 2013 22:27:39 +0100 Subject: Use quoteShell in stdlib, where appropriate. --- compiler/extccomp.nim | 32 ++++++++++++++++---------------- compiler/nimrod.nim | 12 ++++++------ lib/pure/browsers.nim | 4 ++-- lib/pure/osproc.nim | 8 ++++---- tools/niminst/niminst.nim | 5 ++--- 5 files changed, 30 insertions(+), 31 deletions(-) (limited to 'lib/pure') diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 13eb972f6..fe1bea3ff 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -463,9 +463,9 @@ proc getCompileOptions: string = proc getLinkOptions: string = result = linkOptions for linkedLib in items(cLinkedLibs): - result.add(cc[ccompiler].linkLibCmd % linkedLib.quoteIfContainsWhite) + result.add(cc[ccompiler].linkLibCmd % linkedLib.quoteShell) for libDir in items(cLibs): - result.add([cc[ccompiler].linkDirCmd, libDir.quoteIfContainsWhite]) + result.add([cc[ccompiler].linkDirCmd, libDir.quoteShell]) proc needsExeExt(): bool {.inline.} = result = (optGenScript in gGlobalOptions and targetOS == osWindows) or @@ -485,10 +485,10 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = var includeCmd, compilePattern: string if not noAbsolutePaths(): # compute include paths: - includeCmd = cc[c].includeCmd & quoteIfContainsWhite(libpath) + includeCmd = cc[c].includeCmd & quoteShell(libpath) for includeDir in items(cIncludes): - includeCmd.add([cc[c].includeCmd, includeDir.quoteIfContainsWhite]) + includeCmd.add([cc[c].includeCmd, includeDir.quoteShell]) compilePattern = JoinPath(ccompilerpath, exe) else: @@ -501,17 +501,17 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = toObjFile(cfile) else: completeCFilePath(toObjFile(cfile)) - cfile = quoteIfContainsWhite(AddFileExt(cfile, cExt)) - objfile = quoteIfContainsWhite(objfile) - result = quoteIfContainsWhite(compilePattern % [ + cfile = quoteShell(AddFileExt(cfile, cExt)) + objfile = quoteShell(objfile) + result = quoteShell(compilePattern % [ "file", cfile, "objfile", objfile, "options", options, "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath]) add(result, ' ') addf(result, cc[c].compileTmpl, [ "file", cfile, "objfile", objfile, "options", options, "include", includeCmd, - "nimrod", quoteIfContainsWhite(getPrefixDir()), - "lib", quoteIfContainsWhite(libpath)]) + "nimrod", quoteShell(getPrefixDir()), + "lib", quoteShell(libpath)]) proc footprint(filename: string): TCrc32 = result = crcFromFile(filename) >< @@ -590,7 +590,7 @@ proc CallCCompiler*(projectfile: string) = while it != nil: let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data add(objfiles, ' ') - add(objfiles, quoteIfContainsWhite( + add(objfiles, quoteShell( addFileExt(objFile, cc[ccompiler].objExt))) it = PStrEntry(it.next) @@ -602,8 +602,8 @@ proc CallCCompiler*(projectfile: string) = var linkerExe = getConfigVar(c, ".linkerexe") if len(linkerExe) == 0: linkerExe = cc[c].linkerExe if needsExeExt(): linkerExe = addFileExt(linkerExe, "exe") - if noAbsolutePaths(): linkCmd = quoteIfContainsWhite(linkerExe) - else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe)) + if noAbsolutePaths(): linkCmd = quoteShell(linkerExe) + else: linkCmd = quoteShell(JoinPath(ccompilerpath, linkerExe)) if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui else: buildGui = "" var exefile: string @@ -617,17 +617,17 @@ proc CallCCompiler*(projectfile: string) = exefile = options.outFile if not noAbsolutePaths(): exefile = joinPath(splitFile(projectFile).dir, exefile) - exefile = quoteIfContainsWhite(exefile) + exefile = quoteShell(exefile) let linkOptions = getLinkOptions() - linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, + linkCmd = quoteShell(linkCmd % ["builddll", builddll, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]) linkCmd.add ' ' addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, - "nimrod", quoteIfContainsWhite(getPrefixDir()), - "lib", quoteIfContainsWhite(libpath)]) + "nimrod", quoteShell(getPrefixDir()), + "lib", quoteShell(libpath)]) if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd) else: linkCmd = "" diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index 2f10e32e3..8e3c0e61e 100644 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -13,9 +13,9 @@ when defined(gcc) and defined(windows): else: {.link: "icons/nimrod_icon.o".} -import - commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, - extccomp, strutils, os, platform, main, parseopt, service +import + commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, + extccomp, strutils, os, osproc, platform, main, parseopt, service when hasTinyCBackend: import tccgen @@ -23,7 +23,7 @@ when hasTinyCBackend: when defined(profiler) or defined(memProfiler): {.hint: "Profiling support is turned on!".} import nimprof - + proc prependCurDir(f: string): string = when defined(unix): if os.isAbsolute(f): result = f @@ -61,11 +61,11 @@ proc HandleCmdLine() = tccgen.run() if optRun in gGlobalOptions: if gCmd == cmdCompileToJS: - var ex = quoteIfContainsWhite( + var ex = quoteShell( completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir)) execExternalProgram("node " & ex & ' ' & service.arguments) else: - var ex = quoteIfContainsWhite( + var ex = quoteShell( changeFileExt(gProjectFull, exeExt).prependCurDir) execExternalProgram(ex & ' ' & service.arguments) diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim index 6f5bf7ddb..b44f406c5 100644 --- a/lib/pure/browsers.nim +++ b/lib/pure/browsers.nim @@ -33,10 +33,10 @@ proc openDefaultBrowser*(url: string) = else: discard ShellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL) elif defined(macosx): - discard execShellCmd("open " & quoteIfContainsWhite(url)) + discard execShellCmd("open " & quoteShell(url)) else: const attempts = ["gnome-open ", "kde-open ", "xdg-open "] - var u = quoteIfContainsWhite(url) + var u = quoteShell(url) for a in items(attempts): if execShellCmd(a & u) == 0: return for b in getEnv("BROWSER").string.split(PathSep): diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 7772585a9..61b940ce8 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -359,10 +359,10 @@ when defined(Windows) and not defined(useNimRtl): result.writeDataImpl = hsWriteData proc buildCommandLine(a: string, args: openarray[string]): cstring = - var res = quoteIfContainsWhite(a) + var res = quoteShell(a) for i in 0..high(args): res.add(' ') - res.add(quoteIfContainsWhite(args[i])) + res.add(quoteShell(args[i])) result = cast[cstring](alloc0(res.len+1)) copyMem(result, cstring(res), res.len) @@ -562,10 +562,10 @@ elif not defined(useNimRtl): writeIdx = 1 proc addCmdArgs(command: string, args: openarray[string]): string = - result = quoteIfContainsWhite(command) + result = quoteShell(command) for i in 0 .. high(args): add(result, " ") - add(result, quoteIfContainsWhite(args[i])) + add(result, quoteShell(args[i])) proc toCStringArray(b, a: openarray[string]): cstringArray = result = cast[cstringArray](alloc0((a.len + b.len + 1) * sizeof(cstring))) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index 25ec0d283..0c9717e12 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -14,7 +14,7 @@ when haveZipLib: import zipfiles import - os, strutils, parseopt, parsecfg, strtabs, streams, debcreation + os, osproc, strutils, parseopt, parsecfg, strtabs, streams, debcreation const maxOS = 20 # max number of OSes @@ -486,7 +486,7 @@ proc setupDist(c: var TConfigData) = if c.innoSetup.path.len == 0: c.innoSetup.path = "iscc.exe" var outcmd = if c.outdir.len == 0: "build" else: c.outdir - var cmd = "$# $# /O$# $#" % [quoteIfContainsWhite(c.innoSetup.path), + var cmd = "$# $# /O$# $#" % [quoteShell(c.innoSetup.path), c.innoSetup.flags, outcmd, n] echo(cmd) if execShellCmd(cmd) == 0: @@ -587,4 +587,3 @@ if actionZip in c.actions: quit("libzip is not installed") if actionDeb in c.actions: debDist(c) - -- cgit 1.4.1-2-gfad0 From ab2eb884a0d440796b0c712346a17bbe1ff54e94 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Tue, 17 Dec 2013 18:03:08 -0500 Subject: Modified os.removeFile to act correctly when deleting a file that doesn't exist. --- lib/pure/os.nim | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 71639d821..ecab692cf 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -972,15 +972,21 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", when not defined(ENOENT): var ENOENT {.importc, header: "".}: cint +when not defined(EACCES): + var EACCES {.importc, header: "".}: cint proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail ## if the file never existed in the first place. ## On Windows, ignores the read-only attribute. - when defined(Windows): - setFilePermissions(file, {fpUserWrite}) if cremove(file) != 0'i32 and errno != ENOENT: - raise newException(EOS, $strerror(errno)) + when defined(Windows): + if errno == EACCES: # Turn this into a case stmt? + setFilePermissions(file, {fpUserWrite}) # Use lower level code? + if cremove(file) != 0'i32 and errno != ENOENT: + raise newException(EOS, $strerror(errno)) + else: + raise newException(EOS, $strerror(errno)) proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", tags: [FExecIO].} = -- cgit 1.4.1-2-gfad0 From 74a63c004fe188bc710d6867e451f894c70381be Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Wed, 18 Dec 2013 18:15:39 +0100 Subject: Rework CGI error reporting. - remove 'undocumented' stackTraceNL - add 'undocumented' errorMessageWriter - make printing errors for browser optional (for security) --- lib/pure/cgi.nim | 36 +++++++++++++++++++++++++++--------- lib/system/excpt.nim | 42 ++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 29 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim index c499abdc0..29c686fd7 100644 --- a/lib/pure/cgi.nim +++ b/lib/pure/cgi.nim @@ -342,16 +342,35 @@ proc writeContentType*() = ## ## .. code-block:: Nimrod ## write(stdout, "Content-type: text/html\n\n") - ## - ## It also modifies the debug stack traces so that they contain - ## ``
`` and are easily readable in a browser. write(stdout, "Content-type: text/html\n\n") - system.stackTraceNewLine = "
\n" -proc setStackTraceNewLine*() = - ## Modifies the debug stack traces so that they contain - ## ``
`` and are easily readable in a browser. - system.stackTraceNewLine = "
\n" +proc resetForStacktrace() = + stdout.write """ + --> --> + + +""" + +proc writeErrorMessage*(data: string) = + ## Tries to reset browser state and writes `data` to stdout in + ## tag. + resetForStacktrace() + # We use <plaintext> here, instead of escaping, so stacktrace can + # be understood by human looking at source. + stdout.write("<plaintext>\n") + stdout.write(data) + +proc setStackTraceStdout*() = + ## Makes Nimrod output stacktraces to stdout, instead of server log. + errorMessageWriter = writeErrorMessage + +proc setStackTraceNewLine*() {.deprecated.} = + ## Makes Nimrod output stacktraces to stdout, instead of server log. + ## Depracated alias for setStackTraceStdout. + setStackTraceStdout() proc setCookie*(name, value: string) = ## Sets a cookie. @@ -374,4 +393,3 @@ when isMainModule: const test1 = "abc\L+def xyz" assert UrlEncode(test1) == "abc%0A%2Bdef+xyz" assert UrlDecode(UrlEncode(test1)) == test1 - diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 45ad42a60..9b6a64fb0 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -11,11 +11,10 @@ # use the heap (and nor exceptions) do not include the GC or memory allocator. var - stackTraceNewLine*: string ## undocumented feature; it is replaced by ``<br>`` - ## for CGI applications - -template stackTraceNL: expr = - (if IsNil(stackTraceNewLine): "\n" else: stackTraceNewLine) + errorMessageWriter*: (proc(msg: string): void {.tags: [FWriteIO].}) + ## Function that will be called + ## instead of stdmsg.write when printing stacktrace. + ## Unstable API. when not defined(windows) or not defined(guiapp): proc writeToStdErr(msg: CString) = write(stdmsg, msg) @@ -27,6 +26,12 @@ else: proc writeToStdErr(msg: CString) = discard MessageBoxA(0, msg, nil, 0) +proc showErrorMessage(data: cstring) = + if errorMessageWriter != nil: + errorMessageWriter($data) + else: + writeToStdErr(data) + proc chckIndx(i, a, b: int): int {.inline, compilerproc.} proc chckRange(i, a, b: int): int {.inline, compilerproc.} proc chckRangeF(x, a, b: float): float {.inline, compilerproc.} @@ -111,7 +116,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported: add(s, tempDlInfo.dli_sname) else: add(s, '?') - add(s, stackTraceNL) + add(s, "\n") else: if dlresult != 0 and tempDlInfo.dli_sname != nil and c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32: @@ -172,21 +177,18 @@ proc auxWriteStackTrace(f: PFrame, s: var string) = add(s, ')') for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ') add(s, tempFrames[j].procname) - add(s, stackTraceNL) + add(s, "\n") when hasSomeStackTrace: proc rawWriteStackTrace(s: var string) = when nimrodStackTrace: if framePtr == nil: - add(s, "No stack traceback available") - add(s, stackTraceNL) + add(s, "No stack traceback available\n") else: - add(s, "Traceback (most recent call last)") - add(s, stackTraceNL) + add(s, "Traceback (most recent call last)\n") auxWriteStackTrace(framePtr, s) elif defined(nativeStackTrace) and nativeStackTraceSupported: - add(s, "Traceback from system (most recent call last)") - add(s, stackTraceNL) + add(s, "Traceback from system (most recent call last)\n") auxWriteStackTraceWithBacktrace(s) else: add(s, "No stack traceback available\n") @@ -207,7 +209,7 @@ proc raiseExceptionAux(e: ref E_Base) = pushCurrentException(e) c_longjmp(excHandler.context, 1) elif e[] of EOutOfMemory: - writeToStdErr(e.name) + showErrorMessage(e.name) quitOrDebug() else: when hasSomeStackTrace: @@ -219,7 +221,7 @@ proc raiseExceptionAux(e: ref E_Base) = add(buf, " [") add(buf, $e.name) add(buf, "]\n") - writeToStdErr(buf) + showErrorMessage(buf) else: # ugly, but avoids heap allocations :-) template xadd(buf, s, slen: expr) = @@ -235,7 +237,7 @@ proc raiseExceptionAux(e: ref E_Base) = add(buf, " [") xadd(buf, e.name, c_strlen(e.name)) add(buf, "]\n") - writeToStdErr(buf) + showErrorMessage(buf) quitOrDebug() proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} = @@ -255,9 +257,9 @@ proc WriteStackTrace() = when hasSomeStackTrace: var s = "" rawWriteStackTrace(s) - writeToStdErr(s) + showErrorMessage(s) else: - writeToStdErr("No stack traceback available\n") + showErrorMessage("No stack traceback available\n") proc getStackTrace(): string = when hasSomeStackTrace: @@ -298,13 +300,13 @@ when not defined(noSignalHandler): var buf = newStringOfCap(2000) rawWriteStackTrace(buf) processSignal(sig, buf.add) # nice hu? currying a la nimrod :-) - writeToStdErr(buf) + showErrorMessage(buf) GC_enable() else: var msg: cstring template asgn(y: expr) = msg = y processSignal(sig, asgn) - writeToStdErr(msg) + showErrorMessage(msg) when defined(endb): dbgAborting = True quit(1) # always quit when SIGABRT -- cgit 1.4.1-2-gfad0 From c26e787e5dab153b35470ea88f71dbf373de51f7 Mon Sep 17 00:00:00 2001 From: Clay Sweetser <clay.sweetser@gmail.com> Date: Wed, 18 Dec 2013 15:32:26 -0500 Subject: os.nim - Modify removeFile to use native Windows API calls --- lib/pure/os.nim | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/os.nim b/lib/pure/os.nim index ecab692cf..a366a7965 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -972,8 +972,16 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", when not defined(ENOENT): var ENOENT {.importc, header: "<errno.h>".}: cint -when not defined(EACCES): - var EACCES {.importc, header: "<errno.h>".}: cint + +when defined(Windows): + when useWinUnicode: + template DeleteFile(file: expr): expr {.immediate.} = DeleteFileW(file) + template SetFileAttributes(file, attrs: expr): expr {.immediate.} = + SetFileAttributesW(file, attrs) + else: + template DeleteFile(file: expr): expr {.immediate.} = DeleteFileA(file) + template SetFileAttributes(file, attrs: expr): expr {.immediate.} = + SetFileAttributesA(file, attrs) proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail @@ -981,11 +989,18 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## On Windows, ignores the read-only attribute. if cremove(file) != 0'i32 and errno != ENOENT: when defined(Windows): - if errno == EACCES: # Turn this into a case stmt? - setFilePermissions(file, {fpUserWrite}) # Use lower level code? - if cremove(file) != 0'i32 and errno != ENOENT: - raise newException(EOS, $strerror(errno)) + when useWinUnicode: + let f = newWideCString(file) else: + let f = file + if DeleteFile(f) == 0: + if GetLastError() == ERROR_ACCESS_DENIED: + if SetFileAttributes(f, FILE_ATTRIBUTE_NORMAL) == 0: + OSError(OSLastError()) + if DeleteFile(f) == 0: + OSError(OSLastError()) + else: + if cremove(file) != 0'i32 and errno != ENOENT: raise newException(EOS, $strerror(errno)) proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", -- cgit 1.4.1-2-gfad0 From 9de92522a6418b3460cea786dc363177288e02e1 Mon Sep 17 00:00:00 2001 From: Clay Sweetser <clay.sweetser@gmail.com> Date: Wed, 18 Dec 2013 16:04:43 -0500 Subject: Further fixes (stupid kdiff automerge) --- lib/pure/os.nim | 5 ++--- lib/windows/winlean.nim | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 14 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a366a7965..d74cb1fb9 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -970,7 +970,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", if crename(source, dest) != 0'i32: raise newException(EOS, $strerror(errno)) -when not defined(ENOENT): +when not defined(ENOENT) and not defined(Windows): var ENOENT {.importc, header: "<errno.h>".}: cint when defined(Windows): @@ -987,8 +987,7 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail ## if the file never existed in the first place. ## On Windows, ignores the read-only attribute. - if cremove(file) != 0'i32 and errno != ENOENT: - when defined(Windows): + when defined(Windows): when useWinUnicode: let f = newWideCString(file) else: diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 56d279db6..264285d09 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -416,17 +416,17 @@ var SOMAXCONN* {.importc, header: "Winsock2.h".}: cint INVALID_SOCKET* {.importc, header: "Winsock2.h".}: TSocketHandle SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint - SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording - SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen() - SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse - SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive - SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses - SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs - SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible - SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present - SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line - - SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint + SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording + SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen() + SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse + SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive + SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses + SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs + SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible + SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present + SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line + + SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse proc `==`*(x, y: TSocketHandle): bool {.borrow.} @@ -553,18 +553,26 @@ const FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32 +# Error Constants +const + ERROR_ACCESS_DENIED* = 5 + when useWinUnicode: proc CreateFileW*(lpFileName: widecstring, dwDesiredAccess, dwShareMode: DWORD, lpSecurityAttributes: pointer, dwCreationDisposition, dwFlagsAndAttributes: DWORD, hTemplateFile: THANDLE): THANDLE {. stdcall, dynlib: "kernel32", importc: "CreateFileW".} + proc DeleteFileW*(pathName: widecstring): int32 {. + importc: "DeleteFileW", dynlib: "kernel32", stdcall.} else: proc CreateFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD, lpSecurityAttributes: pointer, dwCreationDisposition, dwFlagsAndAttributes: DWORD, hTemplateFile: THANDLE): THANDLE {. stdcall, dynlib: "kernel32", importc: "CreateFileA".} + proc DeleteFileA*(pathName: cstring): int32 {. + importc: "DeleteFileA", dynlib: "kernel32", stdcall.} proc SetEndOfFile*(hFile: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32", importc: "SetEndOfFile".} -- cgit 1.4.1-2-gfad0 From 7a05b108d52d7d4ea2c57daf57b82b9a5cb9c37b Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz <gradha@imap.cc> Date: Sat, 21 Dec 2013 11:44:17 +0100 Subject: Renames configuration file to new pattern. Refs #720. --- lib/pure/actors.cfg | 3 --- lib/pure/actors.nimrod.cfg | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/pure/actors.cfg create mode 100644 lib/pure/actors.nimrod.cfg (limited to 'lib/pure') diff --git a/lib/pure/actors.cfg b/lib/pure/actors.cfg deleted file mode 100644 index c6bb9c545..000000000 --- a/lib/pure/actors.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# to shut up the tester: ---threads:on - diff --git a/lib/pure/actors.nimrod.cfg b/lib/pure/actors.nimrod.cfg new file mode 100644 index 000000000..c6bb9c545 --- /dev/null +++ b/lib/pure/actors.nimrod.cfg @@ -0,0 +1,3 @@ +# to shut up the tester: +--threads:on + -- cgit 1.4.1-2-gfad0