while following symlinks on open, after we break from the loop we need to respect that nfs41_lookup could have returned some kind of error value. thus only return error_reparse if nfs41_lookup returned success or file_not_found error.
similarly in after calling nfs41_symlink_follow() only set the reparse_error if function was successful.
fixed a few cases of warning 4242: possible loss of data
wincrypt.h appears to come with windows.h in later versions of the ddk, but nfs41_client.c fails to compile in WDK 6001 without #include <wincrypt.h>
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
avoid calling map_disposition_2_nfsopen() for this, because FILE_CREATE->ERROR_FILE_EXISTS is the only case we care about
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
/* msdn: There is a maximum of 31 reparse points (and
* therefore symbolic links) allowed in a particular path. */
#define NFS41_MAX_SYMLINK_DEPTH 31
also added checks for the return value of nfs41_symlink_target() on open/link/rename
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when rename or link call nfs41_lookup() for the destination directory, they need to be able to handle ERROR_REPARSE and find the real dest dir
open now does the same thing when it sees ERROR_REPARSE; previously, it was only replacing the first symlink in the path, and could require multiple reparses on a path
modified nfs41_symlink_target() to support the case where the source and destination paths are the same (used by rename/link)
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added nfs41_file_info.symlink_dir to replace readdir's info.cansettime hack. when nfs_file_info_to_attributes() finds info.type==NF4LNK, it adds the FILE_ATTRIBUTE_DIRECTORY flag if info.symlink_dir is set
renamed nfs41_symlink_follow() to nfs41_symlink_target()
generalized lookup_symlink() into nfs41_symlink_follow(), which is called by readdir and open (also avoids an extra lookup)
added queries for symlink target type when doing normal GETATTRs (getattr.c) and opens with OPEN_REPARSE_POINT set (open.c)
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
returns symlink_embedded=TRUE when the symlink isn't the last component, which gets passed to RxPrepareToReparseSymbolicLink()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
modified nfs41_lookup() to handle NFS4ERR_SYMLINK by setting parent=symlink and returning ERROR_REPARSE
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
windows differentiates between directory and file symlinks because a file can have both FILE_ATTRIBUTE_DIRECTORY and FILE_ATTRIBUTE_REPARSE_POINT flags. nfs can only be one of NF4REG/DIR/LNK, so we have to do a readlink and look up the target file for symlinks to know whether or not to set the directory attribute flag. this is done recursively when we encounter links to links
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added check in handle_open() to avoid calling CREATE/OPEN when we're creating a symlink:
if (args->disposition == FILE_CREATE &&
args->access_mask == (FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | DELETE) &&
args->access_mode == 0 &&
args->create_opts & FILE_OPEN_REPARSE_POINT)
these are the open arguments we get from the CreateSymbolicLink() syscall. by avoiding the call to CREATE/OPEN on handle_open(), we save ourselves from having to REMOVE the file before creating the symlink
added a check to handle_symlink() in case the file was actually created on open (an application could open the file with different arguments, and send the FSCTL_SET_REPARSE_POINT manually), and removes the file first
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
driver handles FSCTL_SET_REPARSE_POINT by sending a symlink set upcall
daemon handles symlink set upcall by calling nfs41_create()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added optional symlink argument to nfs41_create(), used when type is NF4LNK
changed createttype4.u.lnk.linkdata from char[] to const char* and updated encoding in nfs41_xdr.c
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
no longer depends on nfs41_open_state or open_upcall_args
renamed to nfs41_symlink_follow() and added prototype to nfs41_ops.h
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
getattr upcall for FileAttributeTagInformation sets ReparseTag=IO_REPARSE_TAG_SYMLINK
readdir upcall sets EaSize=IO_REPARSE_TAG_SYMLINK; this makes the 'dir' command show files as <SYMLINK>, and causes a FSCTL_GET_REPARSE_POINT to query the symlink target
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when we fork a thread to handle the callback, the arguments we got from
parsing the callback operations in the callback thread are on the stack.
we need to allocate memory for same-size data structure and copy them,
not just copy the pointer.
/* we shouldn't ever see this, but a buggy server could
* send us into an infinite loop. return NFS4ERR_IO */
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added nfs41_abs_path symlink to struct open_upcall_args. we can't write the symlink target back to args->path anymore, since it's a pointer into the upcall buffer
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
in handle_mount(), the call to nfs41_lookup() requires a mutable nfs41_abs_path because it can change on referrals, so make a copy for it
removed unused fields in struct nfs41_root and related arguments to nfs41_root_create()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
because we no longer have to convert strings from unicode, we can avoid copying them out of the upcall buffer
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when open parsing fails, we were still returning upcall.status==NO_ERROR, so the driver assumed the open succeeded. other operations then sent up an open_state==NULL, and crashed the daemon. when upcall_parse() returns an error, set upcall.status to notify the driver
upcall_parse() prints a 'parsing of upcall <name> failed with <error>.' message on failure, so i removed redundant messages from the individual upcall parsing functions
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when handle_open() encounters a file of type NF4LNK and the FILE_OPEN_REPARSE_POINT flag is not present, it calls READLINK for the symlink's target path. it then calls abs_path_link() to update the filename (args->path), whether the symlink target is an absolute or relative path. abs_path_link() also takes into account the special characters . and .., though it doesn't allow traversing .. entries below the root of the server's namespace
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
on last_error == ERROR_REPARSE, the daemon converts args->path back to wchar and passes it down to the driver
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
caused memory leaks of nfs41_open_state. we have the FileDispositionInformation upcall for exactly this, so there's no need to complicate the close code path
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>