Removing file in haskell - windows

I am trying to delete a text file in haskell while working in winhugs with help of removeFile function.But it is giving an error that
Program error: price.txt: Directory.removeFile: permission denied
What can be the reason?

According to the Hackage Docs for removeFile, the operation may fail with:
isPermissionError / PermissionDenied The process has insufficient privileges to perform the operation. [EROFS, EACCES, EPERM]
Also, according to the source code there, removeFile is just a thin wrapper around deleteFile in the Win32 API:
removeFile :: FilePath -> IO ()
removeFile path =
#if mingw32_HOST_OS
Win32.deleteFile path
#else
Posix.removeLink path
#endif
Update
After digging around the source code for winhugs, it seems the Windows API function unlink is actually being used to delete a file in Hugs:
primFun(primRemoveFile) { /* remove a file */
int rc;
String s = evalName(IOArg(1));
if (!s) {
IOFail(mkIOError(NULL,
nameIllegal,
"Directory.removeFile",
"illegal file name",
&IOArg(1)));
}
rc = unlink(s);
if (rc != 0)
throwErrno("Directory.removeFile", TRUE, NO_HANDLE, &IOArg(1));
IOReturn(nameUnit);
}
In any case, the previous answer is going to hold up in the sense that any permissions constraint is not introduced by Haskell. Rather, any permissions error would be due to the underlying OS environment (user accounts, open files, permissions, etc).

Related

requesting `root` access from user to update `/etc/paths.d`

my app installer uses the standard open DMG, drag to 'Applications' for installation, but I want to update $PATH so my app can be used from the command line.
I think the right way to do this is to call a script on the first time my application runs that creates a file myapp in /etc/paths.d with the text /Applications/myapp/bin followed by a newline(ascii 13):
rm /etc/paths.d/myapp
echo "/Applications/myapp/bin" > /etc/paths.d/myapp
currently I'm getting errors;
rm: /etc/paths.d/myapp: No such file or directory
./myapp.sh: line 2: /etc/paths.d/myapp: Permission denied
I need to trigger a request for the user to type the admin password but I'm not sure how to do that in a way this clearly inform the user what changes I am making to their system and why. (I can add it to the manual but who reads that)
Any suggestions?
PS I need to do the same on linux(hopefully similar) and Windows, but if I can get MacOS sorted hopefully I'll know where to start.
AuthorizationExecuteWithPrivileges is deprecated for a long time, but still present and working in macOS 11 (Big Sur / 10.16). STPrivilegedTask demonstrates how to call the function in a "safe" manner - that is, to properly handle the case where the function might be removed in a future version of the OS.
Usage is something like this (error checking etc is omitted for brevity). This will create a symlink of your executable in /usr/local/bin with the name "my-app":
AuthorizationRef authorizationRef;
OSStatus err;
const char* tool = "/bin/ln";
char *args[] = {
"-sf",
[[[NSBundle mainBundle] executablePath] UTF8String],
"/usr/local/bin/my-app",
nil
};
AuthorizationCreate(nil, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
err = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, nil);
switch (err)
{
case errAuthorizationCanceled:
// user cancelled prompt
break;
case errAuthorizationSuccess:
// success
break;
default:
// an error occurred
break;
}
AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
How you use that, is up to you - you could place it behind a menu item ("Install Command Line Tools") like cmake does. If you want to install this at launch time, I'd suggest prompting the user first (and allowing them the option to "don't ask me again").

How to resolve case-aware paths in node.js or io.js?

While path.resolve (myPath) resolves myPath against cwd, is there a way to get the case-aware path using fs (.stat etc.) for Windows?
Actual path casing on file-system:
C:\\myProjectX\\aBc\\function.js
change dir to c:\myprojectx, then in REPL:
process.chdir('c:\\MYprojectx\\abc')
console.log(process.cwd(), path.resolve('c:\\myprojectx\\abc'))
Printsc:\\MYprojectx\\abc c:\\myprojectx\\abc.
Probably something like what this answer suggests for .NET. Note that the other answer on same thread suggests making win32 API call to SHGetFileInfo stuct, which eventually leads to this solution.
This gives problem when generating data with relative paths, which is supposed to be shared cross-platform.
Use true-case-path
const trueCasePathSync = require('true-case-path')
trueCasePathSync('/users/guest') // OSX: -> '/Users/Guest'
trueCasePathSync('c:\\users\\all users') // Windows: -> 'c:\Users\All Users'
From Node 9.2.0 you can use fs.realpath.native() or fs.realpathSync.native()
const fs = require('fs');
fs.realpathSync.native('c:\\users') // Windows10: C:\\Users
fs.realpathSync.native('c:\\users\\all users') // Windows10: C:\\ProgramData

Lua file handling error: Permission Denied (Mac OSX Yosemite)

I'm struggling with a permission error in Lua when trying to read/write from/to a text file. As you can see below, I've pulled the error message from the io.open function and I'm getting "file.txt: permission denied". If it helps at all, I'm using Mac OSX Yosemite and the Love2D engine.
function fileWrite()
outputFile, error = io.open("new.txt", "w")
if outputFile then
for k,v in pairs(clicks) do
outputFile:write(tostring(v[1]) .. "," .. tostring(v[2]) .. "\n")
end
outputFile:close()
else
errorText = error
end
end
Am I making a silly error somewhere by any chance? I've dealt with writing to files in Lua before (on Windows 7), and I've never had this problem before.
Any feedback would be greatly appreciated! :)
In LÖVE your game shouldn't be interacting directly with the file system through io. Instead uselove.filesystem.newFile so your assets will still be available within a .love (zip) file. This should also handle the permission issues your having on OS X as it will write to /Users/user/Library/Application Support/LOVE/ to which love will have write permissions.
function fileWrite()
outputFile, error = love.filesystem.newFile("new.txt")
if outputFile:open("w") then
outputFile:write("Hello World!")
outputFile:close()
else
print(error)
end
end
Check your current directory. For OS X and Linux like systems:
require "os"
print( os.getenv("PWD") )
You do not have access to the file system where the application is running.

using registry to run a prog at startup

i am trying to run a code in c++ which will result in an .exe file running at startup using registry...but the problem is that the code results fails without showing any errors...i compiled the code in devcpp...
the code is
void createkey(char *path)
{
int reg;
HKEY hkey,Hkey1;
DWORD ptr;
reg=RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"),0,KEY_SET_VALUE,&hkey);
if(reg=ERROR_SUCCESS)
cout<<"success"<<endl;
else
cout<<"failure"; //(a)
cout<<reg<<endl; //(b)
if(reg==0)
{
RegSetValueEx(hkey,TEXT("key"),0,REG_SZ,(BYTE*)path,strlen(path));
}
}
in the command line failure and 0 got printed as a result of (a) and (b)...(dont know how as the two mean completely opposite things )....the char *path passed to regsetvalueex was "c:/Dev-Cpp/bin/Untitled2.exe"...i am sure that the functions are not working as key doesnt appear in run key(i checked using regedit)...
if(reg=ERROR_SUCCESS)
That's an assignment, you need to use the == operator. Most modern compilers warn about this, be sure to update yours. You probably got an access denied error, can't write to HKLM\Software without elevation.
Standard users don't have write access to HKLM. You need to run this process elevated.

How to get R script line numbers at error?

If I am running a long R script from the command line (R --slave script.R), then how can I get it to give line numbers at errors?
I don't want to add debug commands to the script if at all possible; I just want R to behave like most other scripting languages.
This won't give you the line number, but it will tell you where the failure happens in the call stack which is very helpful:
traceback()
[Edit:] When running a script from the command line you will have to skip one or two calls, see traceback() for interactive and non-interactive R sessions
I'm not aware of another way to do this without the usual debugging suspects:
debug()
browser()
options(error=recover) [followed by options(error = NULL) to revert it]
You might want to look at this related post.
[Edit:] Sorry...just saw that you're running this from the command line. In that case I would suggest working with the options(error) functionality. Here's a simple example:
options(error = quote({dump.frames(to.file=TRUE); q()}))
You can create as elaborate a script as you want on an error condition, so you should just decide what information you need for debugging.
Otherwise, if there are specific areas you're concerned about (e.g. connecting to a database), then wrap them in a tryCatch() function.
Doing options(error=traceback) provides a little more information about the content of the lines leading up to the error. It causes a traceback to appear if there is an error, and for some errors it has the line number, prefixed by #. But it's hit or miss, many errors won't get line numbers.
Support for this will be forthcoming in R 2.10 and later. Duncan Murdoch just posted to r-devel on Sep 10 2009 about findLineNum and setBreapoint:
I've just added a couple of functions to R-devel to help with
debugging. findLineNum() finds which line of which function
corresponds to a particular line of source code; setBreakpoint() takes
the output of findLineNum, and calls trace() to set a breakpoint
there.
These rely on having source reference debug information in the code.
This is the default for code read by source(), but not for packages.
To get the source references in package code, set the environment
variable R_KEEP_PKG_SOURCE=yes, or within R, set
options(keep.source.pkgs=TRUE), then install the package from source
code. Read ?findLineNum for details on how to tell it to search
within packages, rather than limiting the search to the global
environment.
For example,
x <- " f <- function(a, b) {
if (a > b) {
a
} else {
b
}
}"
eval(parse(text=x)) # Normally you'd use source() to read a file...
findLineNum("<text>#3") # <text> is a dummy filename used by
parse(text=)
This will print
f step 2,3,2 in <environment: R_GlobalEnv>
and you can use
setBreakpoint("<text>#3")
to set a breakpoint there.
There are still some limitations (and probably bugs) in the code; I'll
be fixing thos
You do it by setting
options(show.error.locations = TRUE)
I just wonder why this setting is not a default in R? It should be, as it is in every other language.
Specifying the global R option for handling non-catastrophic errors worked for me, along with a customized workflow for retaining info about the error and examining this info after the failure. I am currently running R version 3.4.1.
Below, I've included a description of the workflow that worked for me, as well as some code I used to set the global error handling option in R.
As I have it configured, the error handling also creates an RData file containing all objects in working memory at the time of the error. This dump can be read back into R using load() and then the various environments as they existed at the time of the error can be inspected interactively using debugger(errorDump).
I will note that I was able to get line numbers in the traceback() output from any custom functions within the stack, but only if I used the keep.source=TRUE option when calling source() for any custom functions used in my script. Without this option, setting the global error handling option as below sent the full output of the traceback() to an error log named error.log, but line numbers were not available.
Here's the general steps I took in my workflow and how I was able to access the memory dump and error log after a non-interactive R failure.
I put the following at the top of the main script I was calling from the command line. This sets the global error handling option for the R session. My main script was called myMainScript.R. The various lines in the code have comments after them describing what they do. Basically, with this option, when R encounters an error that triggers stop(), it will create an RData (*.rda) dump file of working memory across all active environments in the directory ~/myUsername/directoryForDump and will also write an error log named error.log with some useful information to the same directory. You can modify this snippet to add other handling on error (e.g., add a timestamp to the dump file and error log filenames, etc.).
options(error = quote({
setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
sink(file="error.log"); # Specify sink file to redirect all output.
dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
cat('\nTraceback:');
cat('\n');
traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
sink();
q()}))
Make sure that from the main script and any subsequent function calls, anytime a function is sourced, the option keep.source=TRUE is used. That is, to source a function, you would use source('~/path/to/myFunction.R', keep.source=TRUE). This is required for the traceback() output to contain line numbers. It looks like you may also be able to set this option globally using options( keep.source=TRUE ), but I have not tested this to see if it works. If you don't need line numbers, you can omit this option.
From the terminal (outside R), call the main script in batch mode using Rscript myMainScript.R. This starts a new non-interactive R session and runs the script myMainScript.R. The code snippet given in step 1 that has been placed at the top of myMainScript.R sets the error handling option for the non-interactive R session.
Encounter an error somewhere within the execution of myMainScript.R. This may be in the main script itself, or nested several functions deep. When the error is encountered, handling will be performed as specified in step 1, and the R session will terminate.
An RData dump file named errorDump.rda and and error log named error.log are created in the directory specified by '~/myUsername/directoryForDump' in the global error handling option setting.
At your leisure, inspect error.log to review information about the error, including the error message itself and the full stack trace leading to the error. Here's an example of the log that's generated on error; note the numbers after the # character are the line numbers of the error at various points in the call stack:
Error in callNonExistFunc() : could not find function "callNonExistFunc"
Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
Traceback:
3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
1: test_multi_commodity_flow_cmd(config_file_path = config_file_path,
spot_file_path = spot_file_path, forward_file_path = forward_file_path,
data_dir = "../", user_dir = "Output", sim_type = "spot",
sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw",
nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31",
compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes,
overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime,
ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
At your leisure, you may load errorDump.rda into an interactive R session using load('~/path/to/errorDump.rda'). Once loaded, call debugger(errorDump) to browse all R objects in memory in any of the active environments. See the R help on debugger() for more info.
This workflow is enormously helpful when running R in some type of production environment where you have non-interactive R sessions being initiated at the command line and you want information retained about unexpected errors. The ability to dump memory to a file you can use to inspect working memory at the time of the error, along with having the line numbers of the error in the call stack, facilitate speedy post-mortem debugging of what caused the error.
First, options(show.error.locations = TRUE) and then traceback(). The error line number will be displayed after #

Resources