1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include "nfs41_ops.h"
27 #include "name_cache.h"
29 #include "daemon_debug.h"
32 int nfs41_cached_getattr(
33 IN nfs41_session
*session
,
34 IN nfs41_path_fh
*file
,
35 OUT nfs41_file_info
*info
)
39 /* first look for cached attributes */
40 status
= nfs41_attr_cache_lookup(session_name_cache(session
),
41 file
->fh
.fileid
, info
);
44 /* fetch attributes from the server */
46 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
48 status
= nfs41_getattr(session
, file
, &attr_request
, info
);
50 eprintf("nfs41_getattr() failed with %s\n",
51 nfs_error_string(status
));
52 status
= nfs_to_windows_error(status
, ERROR_BAD_NET_RESP
);
58 /* NFS41_FILE_QUERY */
59 static int parse_getattr(unsigned char *buffer
, uint32_t length
, nfs41_upcall
*upcall
)
62 getattr_upcall_args
*args
= &upcall
->args
.getattr
;
64 status
= safe_read(&buffer
, &length
, &args
->query_class
, sizeof(args
->query_class
));
66 status
= safe_read(&buffer
, &length
, &args
->buf_len
, sizeof(args
->buf_len
));
69 dprintf(1, "parsing NFS41_FILE_QUERY: info_class=%d buf_len=%d file=%.*s\n",
70 args
->query_class
, args
->buf_len
, upcall
->state_ref
->path
.len
,
71 upcall
->state_ref
->path
.path
);
76 static int handle_getattr(nfs41_upcall
*upcall
)
79 getattr_upcall_args
*args
= &upcall
->args
.getattr
;
80 nfs41_open_state
*state
= upcall
->state_ref
;
81 nfs41_file_info info
= { 0 };
83 status
= nfs41_cached_getattr(state
->session
, &state
->file
, &info
);
85 eprintf("nfs41_cached_getattr() failed with %d\n", status
);
89 if (info
.type
== NF4LNK
) {
90 nfs41_file_info target_info
;
91 int target_status
= nfs41_symlink_follow(upcall
->root_ref
,
92 state
->session
, &state
->file
, &target_info
);
93 if (target_status
== NO_ERROR
&& target_info
.type
== NF4DIR
)
94 info
.symlink_dir
= TRUE
;
97 switch (args
->query_class
) {
98 case FileBasicInformation
:
99 nfs_to_basic_info(&info
, &args
->basic_info
);
100 args
->ctime
= info
.change
;
102 case FileStandardInformation
:
103 nfs_to_standard_info(&info
, &args
->std_info
);
105 case FileAttributeTagInformation
:
106 args
->tag_info
.FileAttributes
= nfs_file_info_to_attributes(&info
);
107 args
->tag_info
.ReparseTag
= info
.type
== NF4LNK
?
108 IO_REPARSE_TAG_SYMLINK
: 0;
110 case FileInternalInformation
:
111 args
->intr_info
.IndexNumber
.QuadPart
= info
.fileid
;
113 case FileNetworkOpenInformation
:
114 nfs_to_network_openinfo(&info
, &args
->network_info
);
117 eprintf("unhandled file query class %d\n", args
->query_class
);
118 status
= ERROR_INVALID_PARAMETER
;
125 static int marshall_getattr(unsigned char *buffer
, uint32_t *length
, nfs41_upcall
*upcall
)
128 getattr_upcall_args
*args
= &upcall
->args
.getattr
;
131 switch (args
->query_class
) {
132 case FileBasicInformation
:
133 info_len
= sizeof(args
->basic_info
);
134 status
= safe_write(&buffer
, length
, &info_len
, sizeof(info_len
));
135 if (status
) goto out
;
136 status
= safe_write(&buffer
, length
, &args
->basic_info
, info_len
);
137 if (status
) goto out
;
139 case FileStandardInformation
:
140 info_len
= sizeof(args
->std_info
);
141 status
= safe_write(&buffer
, length
, &info_len
, sizeof(info_len
));
142 if (status
) goto out
;
143 status
= safe_write(&buffer
, length
, &args
->std_info
, info_len
);
144 if (status
) goto out
;
146 case FileAttributeTagInformation
:
147 info_len
= sizeof(args
->tag_info
);
148 status
= safe_write(&buffer
, length
, &info_len
, sizeof(info_len
));
149 if (status
) goto out
;
150 status
= safe_write(&buffer
, length
, &args
->tag_info
, info_len
);
151 if (status
) goto out
;
153 case FileInternalInformation
:
154 info_len
= sizeof(args
->intr_info
);
155 status
= safe_write(&buffer
, length
, &info_len
, sizeof(info_len
));
156 if (status
) goto out
;
157 status
= safe_write(&buffer
, length
, &args
->intr_info
, info_len
);
158 if (status
) goto out
;
160 case FileNetworkOpenInformation
:
161 info_len
= sizeof(args
->network_info
);
162 status
= safe_write(&buffer
, length
, &info_len
, sizeof(info_len
));
163 if (status
) goto out
;
164 status
= safe_write(&buffer
, length
, &args
->network_info
, info_len
);
165 if (status
) goto out
;
168 eprintf("unknown file query class %d\n", args
->query_class
);
172 status
= safe_write(&buffer
, length
, &args
->ctime
, sizeof(args
->ctime
));
173 if (status
) goto out
;
174 dprintf(1, "NFS41_FILE_QUERY: downcall changattr=%llu\n", args
->ctime
);
180 const nfs41_upcall_op nfs41_op_getattr
= {