diff --git a/build.vc10/daemon.vcxproj b/build.vc10/daemon.vcxproj index 0b7552f..7035e57 100644 --- a/build.vc10/daemon.vcxproj +++ b/build.vc10/daemon.vcxproj @@ -219,6 +219,7 @@ + diff --git a/build.vc10/daemon.vcxproj.filters b/build.vc10/daemon.vcxproj.filters index 0538ee1..8390631 100644 --- a/build.vc10/daemon.vcxproj.filters +++ b/build.vc10/daemon.vcxproj.filters @@ -107,6 +107,9 @@ Source Files + + Source Files + diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c index 6c017d3..e8edcc3 100644 --- a/daemon/daemon_debug.c +++ b/daemon/daemon_debug.c @@ -279,6 +279,7 @@ const char* opcode2string(DWORD opcode) case NFS41_FILE_QUERY: return "NFS41_FILE_QUERY"; case NFS41_FILE_SET: return "NFS41_FILE_SET"; case NFS41_EA_SET: return "NFS41_EA_SET"; + case NFS41_SYMLINK: return "NFS41_SYMLINK"; case NFS41_VOLUME_QUERY: return "NFS41_VOLUME_QUERY"; default: return "UNKNOWN"; } diff --git a/daemon/symlink.c b/daemon/symlink.c new file mode 100644 index 0000000..680b64f --- /dev/null +++ b/daemon/symlink.c @@ -0,0 +1,85 @@ +/* Copyright (c) 2010 + * The Regents of the University of Michigan + * All Rights Reserved + * + * Permission is granted to use, copy, create derivative works, and + * redistribute this software and such derivative works for any purpose, + * so long as the name of the University of Michigan is not used in + * any advertising or publicity pertaining to the use or distribution + * of this software without specific, written prior authorization. If + * the above copyright notice or any other identification of the + * University of Michigan is included in any copy of any portion of + * this software, then the disclaimer below must also be included. + * + * This software is provided as is, without representation or warranty + * of any kind either express or implied, including without limitation + * the implied warranties of merchantability, fitness for a particular + * purpose, or noninfringement. The Regents of the University of + * Michigan shall not be liable for any damages, including special, + * indirect, incidental, or consequential damages, with respect to any + * claim arising out of or in connection with the use of the software, + * even if it has been or is hereafter advised of the possibility of + * such damages. + */ + +#include +#include + +#include "upcall.h" +#include "util.h" +#include "daemon_debug.h" + + +/* NFS41_SYMLINK */ +int parse_symlink(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall) +{ + symlink_upcall_args *args = &upcall->args.symlink; + int status; + + status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE)); + if (status) goto out; + status = safe_read(&buffer, &length, &args->state, sizeof(nfs41_open_state *)); + if (status) goto out; + status = get_name(&buffer, &length, &args->path); + if (status) goto out; + status = safe_read(&buffer, &length, &args->set, sizeof(BOOLEAN)); + if (status) goto out; + + if (args->set) + status = get_name(&buffer, &length, &args->target_set); + else + args->target_set = NULL; + + dprintf(1, "parsing NFS41_SYMLINK: root=0x%p open_state=0x%p " + "path='%s' set=%u target='%s'\n", args->root, args->state, + args->path, args->set, args->target_set); +out: + return status; +} + +int handle_symlink(nfs41_upcall *upcall) +{ + return NO_ERROR; +} + +int marshall_symlink(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall) +{ + symlink_upcall_args *args = &upcall->args.symlink; + unsigned short len = (args->target_get.len + 1) * sizeof(WCHAR); + int status = NO_ERROR; + + if (args->set) + goto out; + + status = safe_write(&buffer, length, &len, sizeof(len)); + if (status) goto out; + + if (*length <= len || !MultiByteToWideChar(CP_UTF8, 0, + args->target_get.path, args->target_get.len, + (LPWSTR)buffer, len / sizeof(WCHAR))) { + status = ERROR_BUFFER_OVERFLOW; + goto out; + } +out: + return status; +} diff --git a/daemon/upcall.c b/daemon/upcall.c index b5168d6..316910a 100644 --- a/daemon/upcall.c +++ b/daemon/upcall.c @@ -76,6 +76,10 @@ int parse_setexattr(unsigned char*, uint32_t, nfs41_upcall*); int handle_setexattr(nfs41_upcall*); int marshall_setexattr(unsigned char*, uint32_t*, nfs41_upcall*); +int parse_symlink(unsigned char*, uint32_t, nfs41_upcall*); +int handle_symlink(nfs41_upcall*); +int marshall_symlink(unsigned char*, uint32_t*, nfs41_upcall*); + int parse_volume(unsigned char*, uint32_t, nfs41_upcall*); int handle_volume(nfs41_upcall*); int marshall_volume(unsigned char*, uint32_t*, nfs41_upcall*); @@ -93,6 +97,7 @@ static const nfs41_upcall_op g_upcall_op_table[] = { { parse_getattr, handle_getattr, marshall_getattr, NULL }, { parse_setattr, handle_setattr, marshall_setattr, NULL }, { parse_setexattr, handle_setexattr, marshall_setexattr, NULL }, + { parse_symlink, handle_symlink, marshall_symlink, NULL }, { parse_volume, handle_volume, marshall_volume, NULL }, { NULL, NULL, NULL, NULL }, /* NFS41_SHUTDOWN */ { NULL, NULL, NULL, NULL }, /* INVALID_OPCODE */ diff --git a/daemon/upcall.h b/daemon/upcall.h index e07bd91..1b45de3 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -134,6 +134,15 @@ typedef struct __readdir_upcall_args { BOOLEAN single; } readdir_upcall_args; +typedef struct __symlink_upcall_args { + nfs41_abs_path target_get; + const char *target_set; + nfs41_root *root; + nfs41_open_state *state; + const char *path; + BOOLEAN set; +} symlink_upcall_args; + typedef struct __volume_upcall_args { nfs41_root *root; FS_INFORMATION_CLASS query; @@ -157,6 +166,7 @@ typedef union __upcall_args { setattr_upcall_args setattr; setexattr_upcall_args setexattr; readdir_upcall_args readdir; + symlink_upcall_args symlink; volume_upcall_args volume; } upcall_args;