Forum OpenACS Development: Re: NaviServer on Windows: [ns_logroll] returns "Permission denied"

Hi,

We were just discussing this with Brian. Windows and its permissions policies are causing this issue, the issue is in the call to the C rename function. We patched our AOLServer for Windows long time ago by writing an ugly custom workaround that creates a custom Rename function.

The Ns_RollFile calls CustomRename defined below.

Here is our workaround if you find it useful: https://gist.github.com/anonymous/aa3cf1f864c96c252d650f40f80aa4db

Dear Enrique,

many thanks for sharing the code. ... which is somewhat weird, since the custom "rename" performs actually a copy operation. This indicates, that the actual user of NaviServer/AOLserver has "create" permissions but not "rename" permissions - which are under windows essentially "delete" permissions (as i found though googling).

Stupid question: if this is the case, isn't it easier to give the user the delete permissions for this folder instead of patching the code?

all the best
-g

Thanks for your reply Gustaf.

Back then, We tried all possible combinations of Windows permissions, including Full Admin/Full Control and even granted ownership. It never worked.

So, we decided to give 'CopyFile' a go and it worked. Our feeling was that there was some sort of lock that the standard 'rename'/'copy' didn't like and we didn't have the chance to do more investigation than just using what worked for us back then.

Super duper Enrique! TVM
Dear Enrique,
I have implemented the following changes into my Windows-OpenACS distribution:

static int
Rename(const char *from, const char *to)
{
int err;
Tcl_Obj *fromObj, *toObj;

NS_NONNULL_ASSERT(from != NULL);
NS_NONNULL_ASSERT(to != NULL);

fromObj = Tcl_NewStringObj(from, -1);
Tcl_IncrRefCount(fromObj);

toObj = Tcl_NewStringObj(to, -1);
Tcl_IncrRefCount(toObj);

#ifdef WIN32
err != CopyFile(from, to, FALSE);
if (err == 0) {
DeleteFile(from);
}
#else
err = Tcl_FSRenameFile(fromObj, toObj);
#endif
Tcl_DecrRefCount(fromObj);
Tcl_DecrRefCount(toObj);
if (err != 0) {
Ns_Log(Error, "rollfile: failed to rename file '%s' to '%s': '%s'",
from, to, strerror(Tcl_GetErrno()));
}

return err;
}

with this change the rolling of the log files works also on Windows.

Once again thank you,
Maurizio

I did find the following piece of text inside TCL's code:

"The many functions in this structure are broken down into three
categories: infrastructure functions (almost all of which must be
implemented), operational functions (which must be implemented if a
complete filesystem is provided), and efficiency functions (which need
only be implemented if they can be done so efficiently, or if they have
side-effects which are required by the filesystem; Tcl has less
efficient emulations it can fall back on). It is important to note
that, in the current version of Tcl, most of these fallbacks are only
used to handle commands initiated in Tcl, not in C. What this means is,
that if a "file rename" command is issued in Tcl, and the relevant
filesystem(s) do not implement their "Tcl_FSRenameFileProc", Tcl's
core will instead fallback on a combination of other filesystem
functions (it will use "Tcl_FSCopyFileProc" followed by
"Tcl_FSDeleteFileProc", and if "Tcl_FSCopyFileProc\"is not
implemented there is a further fallback). However, if a
"Tcl_FSRenameFileProc" command is issued at the C level, no such
fallbacks occur
.
[...]
"

Hi!

Just to let you know that the latest changes in NaviServer did not fix the ns_logroll issue. I can now execute, the command, but the result is not what is expected. Here is the output after executing "ns_logroll" a few times in the /ds/shell:

-rwxrwx---+ 1 Administratoren SYSTEM 2299588 26. Jun 22:52 error.log
-rwxrwx---+ 1 Administratoren SYSTEM 2216752 26. Jun 22:48 error.log.000
-rwxrwx---+ 1 Administratoren SYSTEM 2216752 26. Jun 22:48 error.log.001
-rwxrwx---+ 1 Administratoren SYSTEM 2216752 26. Jun 22:48 error.log.002
-rwxrwx---+ 1 Administratoren SYSTEM 2216752 26. Jun 22:48 error.log.003

ns_logroll seems to perform a copy operation. But it doesn't start over with an empty error.log...

Cheers,
Frank

Thank you Frank for spotting this.
I've just uploaded version 3.3.2 of my installer/distribution that should fix it:

static int
Rename(const char *from, const char *to)
{
int err;
Tcl_Obj *fromObj, *toObj;

NS_NONNULL_ASSERT(from != NULL);
NS_NONNULL_ASSERT(to != NULL);

fromObj = Tcl_NewStringObj(from, -1);
Tcl_IncrRefCount(fromObj);

toObj = Tcl_NewStringObj(to, -1);
Tcl_IncrRefCount(toObj);

#ifdef WIN32
err != CopyFile(from, to, FALSE);
if (err == 0) {
File * fw = (FILE *)NULL;
if ((fw = fopen(from, "w")) != (FILE *)NULL) {
fprintf(fw, "");
fflush(fw);
fclose(fw);
}
}
#else
err = Tcl_FSRenameFile(fromObj, toObj);
#endif
Tcl_DecrRefCount(fromObj);
Tcl_DecrRefCount(toObj);
if (err != 0) {
Ns_Log(Error, "rollfile: failed to rename file '%s' to '%s': '%s'",
from, to, strerror(Tcl_GetErrno()));
}

return err;
}

Thank you,
Maurizio

Dear Frank, could you double check that in your config you have

ns_param logroll on

?

TIA,
Maurizio