ReactOS  0.4.12-dev-43-g63b00d8
readdir.c File Reference
#include <windows.h>
#include <strsafe.h>
#include <stdlib.h>
#include "from_kernel.h"
#include "nfs41_ops.h"
#include "daemon_debug.h"
#include "upcall.h"
#include "util.h"
Include dependency graph for readdir.c:

Go to the source code of this file.

Classes

union  _FILE_DIR_INFO_UNION
 

Macros

#define FILTER_STAR   '*'
 
#define FILTER_QM   '>'
 
#define COOKIE_DOT   ((uint64_t)-2)
 
#define COOKIE_DOTDOT   ((uint64_t)-1)
 

Typedefs

typedef union _FILE_DIR_INFO_UNION FILE_DIR_INFO_UNION
 
typedef union _FILE_DIR_INFO_UNIONPFILE_DIR_INFO_UNION
 

Functions

static int parse_readdir (unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
 
static __inline const charskip_stars (const char *filter)
 
static int readdir_filter (const char *filter, const char *name)
 
static uint32_t readdir_size_for_entry (IN int query_class, IN uint32_t wname_size)
 
static void readdir_copy_dir_info (IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
 
static void readdir_copy_shortname (IN LPCWSTR name, OUT LPWSTR name_out, OUT CCHAR *name_size_out)
 
static void readdir_copy_full_dir_info (IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
 
static void readdir_copy_both_dir_info (IN nfs41_readdir_entry *entry, IN LPWSTR wname, IN PFILE_DIR_INFO_UNION info)
 
static void readdir_copy_filename (IN LPCWSTR name, IN uint32_t name_size, OUT LPWSTR name_out, OUT ULONG *name_size_out)
 
static int format_abs_path (IN const nfs41_abs_path *path, IN const nfs41_component *name, OUT nfs41_abs_path *path_out)
 
static int lookup_entry (IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *parent, OUT nfs41_readdir_entry *entry)
 
static int lookup_symlink (IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *parent, IN const nfs41_component *name, OUT nfs41_file_info *info_out)
 
static int readdir_copy_entry (IN readdir_upcall_args *args, IN nfs41_readdir_entry *entry, IN OUT unsigned char **dst_pos, IN OUT uint32_t *dst_len)
 
static int readdir_add_dots (IN readdir_upcall_args *args, IN OUT unsigned char *entry_buf, IN uint32_t entry_buf_len, OUT uint32_t *len_out, OUT uint32_t **last_offset)
 
static int handle_readdir (nfs41_upcall *upcall)
 
static int marshall_readdir (unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
 

Variables

const nfs41_upcall_op nfs41_op_readdir
 

Macro Definition Documentation

◆ COOKIE_DOT

#define COOKIE_DOT   ((uint64_t)-2)

Definition at line 363 of file readdir.c.

Referenced by readdir_add_dots().

◆ COOKIE_DOTDOT

#define COOKIE_DOTDOT   ((uint64_t)-1)

Definition at line 364 of file readdir.c.

Referenced by readdir_add_dots().

◆ FILTER_QM

#define FILTER_QM   '>'

Definition at line 75 of file readdir.c.

Referenced by handle_readdir(), and readdir_filter().

◆ FILTER_STAR

#define FILTER_STAR   '*'

Definition at line 74 of file readdir.c.

Referenced by handle_readdir(), readdir_filter(), and skip_stars().

Typedef Documentation

◆ FILE_DIR_INFO_UNION

◆ PFILE_DIR_INFO_UNION

Function Documentation

◆ format_abs_path()

static int format_abs_path ( IN const nfs41_abs_path path,
IN const nfs41_component name,
OUT nfs41_abs_path path_out 
)
static

Definition at line 207 of file readdir.c.

Referenced by lookup_entry(), and lookup_symlink().

211 {
212  /* format an absolute path 'parent\name' */
213  int status = NO_ERROR;
214 
215  InitializeSRWLock(&path_out->lock);
216  abs_path_copy(path_out, path);
217  if (FAILED(StringCchPrintfA(path_out->path + path_out->len,
218  NFS41_MAX_PATH_LEN - path_out->len, "\\%s", name->name))) {
220  goto out;
221  }
222  path_out->len += name->len + 1;
223 out:
224  return status;
225 }
#define NO_ERROR
Definition: dderror.h:5
#define NFS41_MAX_PATH_LEN
Definition: nfs41_const.h:46
void abs_path_copy(OUT nfs41_abs_path *dst, IN const nfs41_abs_path *src)
Definition: util.c:338
STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat,...)
Definition: strsafe.h:520
static FILE * out
Definition: regtests2xml.c:44
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
Definition: services.c:325
Definition: name.c:36
static SERVICE_STATUS status
Definition: service.c:31
WCHAR * name
Definition: name.c:40
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
Definition: ps.c:97

◆ handle_readdir()

static int handle_readdir ( nfs41_upcall upcall)
static

Definition at line 451 of file readdir.c.

452 {
453  int status;
454  readdir_upcall_args *args = &upcall->args.readdir;
455  nfs41_open_state *state = upcall->state_ref;
456  unsigned char *entry_buf = NULL;
457  uint32_t entry_buf_len;
458  bitmap4 attr_request;
459  bool_t eof;
460  /* make sure we allocate enough space for one nfs41_readdir_entry */
461  const uint32_t max_buf_len = max(args->buf_len,
463 
464  dprintf(1, "-> handle_nfs41_dirquery(%s,%d,%d,%d)\n",
465  args->filter, args->initial, args->restart, args->single);
466 
467  args->query_reply_len = 0;
468 
469  if (args->initial || args->restart) {
470  ZeroMemory(&state->cookie, sizeof(nfs41_readdir_cookie));
471  if (!state->cookie.cookie)
472  dprintf(1, "initializing the 1st readdir cookie\n");
473  else if (args->restart)
474  dprintf(1, "restarting; clearing previous cookie %llu\n",
475  state->cookie.cookie);
476  else if (args->initial)
477  dprintf(1, "*** initial; clearing previous cookie %llu!\n",
478  state->cookie.cookie);
479  } else if (!state->cookie.cookie) {
480  dprintf(1, "handle_nfs41_readdir: EOF\n");
481  status = ERROR_NO_MORE_FILES;
482  goto out;
483  }
484 
485  entry_buf = calloc(max_buf_len, sizeof(unsigned char));
486  if (entry_buf == NULL) {
487  status = GetLastError();
488  goto out_free_cookie;
489  }
490 fetch_entries:
491  entry_buf_len = max_buf_len;
492 
493  nfs41_superblock_getattr_mask(state->file.fh.superblock, &attr_request);
494  attr_request.arr[0] |= FATTR4_WORD0_RDATTR_ERROR;
495 
496  if (strchr(args->filter, FILTER_STAR) || strchr(args->filter, FILTER_QM)) {
497  /* use READDIR for wildcards */
498 
499  uint32_t dots_len = 0;
500  uint32_t *dots_next_offset = NULL;
501 
502  if (args->filter[0] == '*' && args->filter[1] == '\0') {
503  status = readdir_add_dots(args, entry_buf,
504  entry_buf_len, &dots_len, &dots_next_offset);
505  if (status)
506  goto out_free_cookie;
507  entry_buf_len -= dots_len;
508  }
509 
510  if (dots_len && args->single) {
511  dprintf(2, "skipping nfs41_readdir because the single query "
512  "will use . or ..\n");
513  entry_buf_len = 0;
514  eof = 0;
515  } else {
516  dprintf(2, "calling nfs41_readdir with cookie %llu\n",
517  state->cookie.cookie);
518  status = nfs41_readdir(state->session, &state->file,
519  &attr_request, &state->cookie, entry_buf + dots_len,
520  &entry_buf_len, &eof);
521  if (status) {
522  dprintf(1, "nfs41_readdir failed with %s\n",
523  nfs_error_string(status));
524  status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
525  goto out_free_cookie;
526  }
527  }
528 
529  if (!entry_buf_len && dots_next_offset)
530  *dots_next_offset = 0;
531  entry_buf_len += dots_len;
532  } else {
533  /* use LOOKUP for single files */
535  entry->cookie = 0;
536  entry->name_len = (uint32_t)strlen(args->filter) + 1;
537  StringCbCopyA(entry->name, entry->name_len, args->filter);
538  entry->next_entry_offset = 0;
539 
540  status = lookup_entry(upcall->root_ref,
541  state->session, &state->file, entry);
542  if (status) {
543  dprintf(1, "single_lookup failed with %d\n", status);
544  goto out_free_cookie;
545  }
546  entry_buf_len = entry->name_len +
548 
549  eof = 1;
550  }
551 
553 
554  if (entry_buf_len) {
555  unsigned char *entry_pos = entry_buf;
556  unsigned char *dst_pos = args->kbuf;
557  uint32_t dst_len = args->buf_len;
559  PULONG offset, last_offset = NULL;
560 
561  for (;;) {
562  entry = (nfs41_readdir_entry*)entry_pos;
563  offset = (PULONG)dst_pos; /* ULONG NextEntryOffset */
564 
565  dprintf(2, "filter %s looking at %s with cookie %d\n",
566  args->filter, entry->name, entry->cookie);
567  if (readdir_filter((const char*)args->filter, entry->name)) {
568  if (readdir_copy_entry(args, entry, &dst_pos, &dst_len)) {
569  eof = 0;
570  dprintf(2, "not enough space to copy entry %s (cookie %d)\n",
571  entry->name, entry->cookie);
572  break;
573  }
574  last_offset = offset;
575  status = NO_ERROR;
576  }
577  state->cookie.cookie = entry->cookie;
578 
579  /* last entry we got from the server */
580  if (!entry->next_entry_offset)
581  break;
582 
583  /* we found our single entry, but the server has more */
584  if (args->single && last_offset) {
585  eof = 0;
586  break;
587  }
588  entry_pos += entry->next_entry_offset;
589  }
590  args->query_reply_len = args->buf_len - dst_len;
591  if (last_offset) {
592  *last_offset = 0;
593  } else if (!eof) {
594  dprintf(1, "no entries matched; fetch more\n");
595  goto fetch_entries;
596  }
597  }
598 
599  if (eof) {
600  dprintf(1, "we don't need to save a cookie\n");
601  goto out_free_cookie;
602  } else
603  dprintf(1, "saving cookie %llu\n", state->cookie.cookie);
604 
605 out_free_entry:
606  free(entry_buf);
607 out:
608  dprintf(1, "<- handle_nfs41_dirquery(%s,%d,%d,%d) returning ",
609  args->filter, args->initial, args->restart, args->single);
610  if (status) {
611  switch (status) {
613  dprintf(1, "ERROR_FILE_NOT_FOUND.\n");
614  break;
615  case ERROR_NO_MORE_FILES:
616  dprintf(1, "ERROR_NO_MORE_FILES.\n");
617  break;
619  upcall->last_error = status;
620  status = ERROR_SUCCESS;
621  break;
622  default:
623  dprintf(1, "error code %d.\n", status);
624  break;
625  }
626  } else {
627  dprintf(1, "success!\n");
628  }
629  return status;
630 out_free_cookie:
631  state->cookie.cookie = 0;
632  goto out_free_entry;
633 }
int nfs_to_windows_error(int status, int default_error)
Definition: util.c:235
#define max(a, b)
Definition: svc.c:63
#define ERROR_SUCCESS
Definition: deptool.c:10
Definition: nfs41_ops.h:710
struct __nfs41_superblock * superblock
Definition: nfs41_types.h:56
#define NFS41_MAX_COMPONENT_LEN
Definition: nfs41_const.h:45
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int32_t bool_t
Definition: types.h:101
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
#define free
Definition: debug_ros.c:5
uint8_t entry
Definition: isohybrid.c:63
GLintptr offset
Definition: glext.h:5920
nfs41_readdir_cookie cookie
Definition: nfs41.h:131
int nfs41_readdir(IN nfs41_session *session, IN nfs41_path_fh *file, IN bitmap4 *attr_request, IN nfs41_readdir_cookie *cookie, OUT unsigned char *entries, IN OUT uint32_t *entries_len, OUT bool_t *eof_out)
Definition: nfs41_ops.c:1010
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
uint64_t cookie
Definition: nfs41_ops.h:711
#define NO_ERROR
Definition: dderror.h:5
uint32_t arr[3]
Definition: nfs41_types.h:97
Definition: match.c:390
struct __nfs41_session * session
Definition: nfs41.h:132
static int readdir_add_dots(IN readdir_upcall_args *args, IN OUT unsigned char *entry_buf, IN uint32_t entry_buf_len, OUT uint32_t *len_out, OUT uint32_t **last_offset)
Definition: readdir.c:366
#define ERROR_BAD_NET_RESP
Definition: winerror.h:150
nfs41_root * root_ref
Definition: upcall.h:206
#define FILTER_QM
Definition: readdir.c:75
nfs41_open_state * state_ref
Definition: upcall.h:207
#define dprintf
Definition: regdump.c:33
smooth NULL
Definition: ftsmooth.c:416
char name[1]
Definition: nfs41_ops.h:715
STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest, size_t cbDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:161
uint32_t next_entry_offset
Definition: nfs41_ops.h:713
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
readdir_upcall_args readdir
Definition: upcall.h:186
static int lookup_entry(IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *parent, OUT nfs41_readdir_entry *entry)
Definition: readdir.c:227
upcall_args args
Definition: upcall.h:198
static FILE * out
Definition: regtests2xml.c:44
const char * filter
Definition: upcall.h:134
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
unsigned char * kbuf
Definition: upcall.h:143
static int state
Definition: maze.c:121
uint32_t name_len
Definition: nfs41_ops.h:712
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
nfs41_path_fh file
Definition: nfs41.h:130
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
uint32_t last_error
Definition: upcall.h:197
unsigned int * PULONG
Definition: retypes.h:1
static int readdir_copy_entry(IN readdir_upcall_args *args, IN nfs41_readdir_entry *entry, IN OUT unsigned char **dst_pos, IN OUT uint32_t *dst_len)
Definition: readdir.c:279
static __inline void nfs41_superblock_getattr_mask(IN const nfs41_superblock *superblock, OUT bitmap4 *attrs)
Definition: nfs41.h:448
UINT32 uint32_t
Definition: types.h:75
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static int readdir_filter(const char *filter, const char *name)
Definition: readdir.c:85
Definition: name.c:36
#define calloc
Definition: rosglue.h:14
#define uint32_t
Definition: nsiface.idl:61
static SERVICE_STATUS status
Definition: service.c:31
#define FILTER_STAR
Definition: readdir.c:74

◆ lookup_entry()

static int lookup_entry ( IN nfs41_root root,
IN nfs41_session session,
IN nfs41_path_fh parent,
OUT nfs41_readdir_entry entry 
)
static

Definition at line 227 of file readdir.c.

Referenced by handle_readdir(), and readdir_copy_entry().

232 {
235  int status;
236 
237  name.name = entry->name;
238  name.len = (unsigned short)entry->name_len - 1;
239 
240  status = format_abs_path(parent->path, &name, &path);
241  if (status) goto out;
242 
243  status = nfs41_lookup(root, session, &path,
244  NULL, NULL, &entry->attr_info, NULL);
245  if (status) goto out;
246 out:
247  return status;
248 }
GLsizei const GLchar ** path
Definition: glext.h:7234
uint8_t entry
Definition: isohybrid.c:63
static int format_abs_path(IN const nfs41_abs_path *path, IN const nfs41_component *name, OUT nfs41_abs_path *path_out)
Definition: readdir.c:207
int nfs41_lookup(IN nfs41_root *root, IN nfs41_session *session, IN OUT nfs41_abs_path *path_inout, OUT OPTIONAL nfs41_path_fh *parent_out, OUT OPTIONAL nfs41_path_fh *target_out, OUT OPTIONAL nfs41_file_info *info_out, OUT nfs41_session **session_out)
Definition: lookup.c:424
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:91
smooth NULL
Definition: ftsmooth.c:416
const char * name
Definition: nfs41_types.h:48
r parent
Definition: btrfs.c:2644
static FILE * out
Definition: regtests2xml.c:44
unsigned short len
Definition: nfs41_types.h:49
static SERVICE_STATUS status
Definition: service.c:31
GLuint const GLchar * name
Definition: glext.h:6031

◆ lookup_symlink()

static int lookup_symlink ( IN nfs41_root root,
IN nfs41_session session,
IN nfs41_path_fh parent,
IN const nfs41_component name,
OUT nfs41_file_info info_out 
)
static

Definition at line 250 of file readdir.c.

Referenced by readdir_copy_entry().

256 {
260  int status;
261 
262  status = format_abs_path(parent->path, name, &path);
263  if (status) goto out;
264 
265  file.path = &path;
266  status = nfs41_lookup(root, session, &path, NULL, &file, &info, &session);
267  if (status) goto out;
268 
269  last_component(path.path, path.path + path.len, &file.name);
270 
271  status = nfs41_symlink_follow(root, session, &file, &info);
272  if (status) goto out;
273 
274  info_out->symlink_dir = info.type == NF4DIR;
275 out:
276  return status;
277 }
int nfs41_symlink_follow(IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *symlink, OUT nfs41_file_info *info)
Definition: symlink.c:146
GLsizei const GLchar ** path
Definition: glext.h:7234
static int format_abs_path(IN const nfs41_abs_path *path, IN const nfs41_component *name, OUT nfs41_abs_path *path_out)
Definition: readdir.c:207
int nfs41_lookup(IN nfs41_root *root, IN nfs41_session *session, IN OUT nfs41_abs_path *path_inout, OUT OPTIONAL nfs41_path_fh *parent_out, OUT OPTIONAL nfs41_path_fh *target_out, OUT OPTIONAL nfs41_file_info *info_out, OUT nfs41_session **session_out)
Definition: lookup.c:424
bool_t last_component(IN const char *path, IN const char *path_end, OUT nfs41_component *component)
Definition: util.c:317
struct _test_info info[]
Definition: SetCursorPos.c:19
smooth NULL
Definition: ftsmooth.c:416
nfs41_abs_path * path
Definition: nfs41_types.h:60
r parent
Definition: btrfs.c:2644
unsigned short len
Definition: nfs41_types.h:43
const char file[]
Definition: icontest.c:11
static FILE * out
Definition: regtests2xml.c:44
nfs41_component name
Definition: nfs41_types.h:61
Definition: name.c:36
char path[NFS41_MAX_PATH_LEN]
Definition: nfs41_types.h:42
static SERVICE_STATUS status
Definition: service.c:31

◆ marshall_readdir()

static int marshall_readdir ( unsigned char buffer,
uint32_t length,
nfs41_upcall upcall 
)
static

Definition at line 635 of file readdir.c.

636 {
637  int status;
638  readdir_upcall_args *args = &upcall->args.readdir;
639 
640  status = safe_write(&buffer, length, &args->query_reply_len, sizeof(args->query_reply_len));
641  return status;
642 }
GLuint buffer
Definition: glext.h:5915
Definition: match.c:390
readdir_upcall_args readdir
Definition: upcall.h:186
upcall_args args
Definition: upcall.h:198
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
int safe_write(unsigned char **pos, uint32_t *remaining, void *src, uint32_t src_len)
Definition: util.c:44
static SERVICE_STATUS status
Definition: service.c:31

◆ parse_readdir()

static int parse_readdir ( unsigned char buffer,
uint32_t  length,
nfs41_upcall upcall 
)
static

Definition at line 44 of file readdir.c.

45 {
46  int status;
48 
49  status = safe_read(&buffer, &length, &args->query_class, sizeof(args->query_class));
50  if (status) goto out;
51  status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
52  if (status) goto out;
53  status = get_name(&buffer, &length, &args->filter);
54  if (status) goto out;
55  status = safe_read(&buffer, &length, &args->initial, sizeof(args->initial));
56  if (status) goto out;
57  status = safe_read(&buffer, &length, &args->restart, sizeof(args->restart));
58  if (status) goto out;
59  status = safe_read(&buffer, &length, &args->single, sizeof(args->single));
60  if (status) goto out;
61  status = safe_read(&buffer, &length, &args->kbuf, sizeof(args->kbuf));
62  if (status) goto out;
63  args->root = upcall->root_ref;
64  args->state = upcall->state_ref;
65 
66  dprintf(1, "parsing NFS41_DIR_QUERY: info_class=%d buf_len=%d "
67  "filter='%s'\n\tInitial\\Restart\\Single %d\\%d\\%d buf=%p\n",
68  args->query_class, args->buf_len, args->filter,
69  args->initial, args->restart, args->single, args->kbuf);
70 out:
71  return status;
72 }
GLuint buffer
Definition: glext.h:5915
Definition: match.c:390
nfs41_root * root_ref
Definition: upcall.h:206
nfs41_open_state * state_ref
Definition: upcall.h:207
#define dprintf
Definition: regdump.c:33
int get_name(unsigned char **pos, uint32_t *remaining, const char **out_name)
Definition: util.c:55
readdir_upcall_args readdir
Definition: upcall.h:186
upcall_args args
Definition: upcall.h:198
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static FILE * out
Definition: regtests2xml.c:44
const char * filter
Definition: upcall.h:134
unsigned char * kbuf
Definition: upcall.h:143
nfs41_open_state * state
Definition: upcall.h:136
int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len)
Definition: util.c:33
nfs41_root * root
Definition: upcall.h:135
static SERVICE_STATUS status
Definition: service.c:31

◆ readdir_add_dots()

static int readdir_add_dots ( IN readdir_upcall_args args,
IN OUT unsigned char entry_buf,
IN uint32_t  entry_buf_len,
OUT uint32_t len_out,
OUT uint32_t **  last_offset 
)
static

Definition at line 366 of file readdir.c.

Referenced by handle_readdir().

372 {
373  int status = 0;
376  nfs41_open_state *state = args->state;
377 
378  *len_out = 0;
379  *last_offset = NULL;
380  switch (state->cookie.cookie) {
381  case 0:
382  if (entry_buf_len < entry_len + 2) {
383  status = ERROR_BUFFER_OVERFLOW;
384  dprintf(1, "not enough room for '.' entry. received %d need %d\n",
385  entry_buf_len, entry_len + 2);
386  args->query_reply_len = entry_len + 2;
387  goto out;
388  }
389 
390  entry = (nfs41_readdir_entry*)entry_buf;
391  ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
392 
393  status = nfs41_cached_getattr(state->session,
394  &state->file, &entry->attr_info);
395  if (status) {
396  dprintf(1, "failed to add '.' entry.\n");
397  goto out;
398  }
399  entry->cookie = COOKIE_DOT;
400  entry->name_len = 2;
401  StringCbCopyA(entry->name, entry->name_len, ".");
402  entry->next_entry_offset = entry_len + entry->name_len;
403 
404  entry_buf += entry->next_entry_offset;
405  entry_buf_len -= entry->next_entry_offset;
406  *len_out += entry->next_entry_offset;
407  *last_offset = &entry->next_entry_offset;
408  if (args->single)
409  break;
410  /* else no break! */
411  case COOKIE_DOT:
412  if (entry_buf_len < entry_len + 3) {
413  status = ERROR_BUFFER_OVERFLOW;
414  dprintf(1, "not enough room for '..' entry. received %d need %d\n",
415  entry_buf_len, entry_len);
416  args->query_reply_len = entry_len + 2;
417  goto out;
418  }
419  /* XXX: this skips '..' when listing root fh */
420  if (state->file.name.len == 0)
421  break;
422 
423  entry = (nfs41_readdir_entry*)entry_buf;
424  ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
425 
426  status = nfs41_cached_getattr(state->session,
427  &state->parent, &entry->attr_info);
428  if (status) {
429  status = ERROR_FILE_NOT_FOUND;
430  dprintf(1, "failed to add '..' entry.\n");
431  goto out;
432  }
433  entry->cookie = COOKIE_DOTDOT;
434  entry->name_len = 3;
435  StringCbCopyA(entry->name, entry->name_len, "..");
436  entry->next_entry_offset = entry_len + entry->name_len;
437 
438  entry_buf += entry->next_entry_offset;
439  entry_buf_len -= entry->next_entry_offset;
440  *len_out += entry->next_entry_offset;
441  *last_offset = &entry->next_entry_offset;
442  break;
443  }
444  if (state->cookie.cookie == COOKIE_DOTDOT ||
445  state->cookie.cookie == COOKIE_DOT)
446  ZeroMemory(&state->cookie, sizeof(nfs41_readdir_cookie));
447 out:
448  return status;
449 }
int nfs41_cached_getattr(IN nfs41_session *session, IN nfs41_path_fh *file, OUT nfs41_file_info *info)
Definition: getattr.c:32
Definition: nfs41_ops.h:710
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
uint8_t entry
Definition: isohybrid.c:63
nfs41_readdir_cookie cookie
Definition: nfs41.h:131
#define ZeroMemory
Definition: winbase.h:1635
uint64_t cookie
Definition: nfs41_ops.h:711
Definition: match.c:390
struct __nfs41_session * session
Definition: nfs41.h:132
#define dprintf
Definition: regdump.c:33
smooth NULL
Definition: ftsmooth.c:416
char name[1]
Definition: nfs41_ops.h:715
STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest, size_t cbDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:161
uint32_t next_entry_offset
Definition: nfs41_ops.h:713
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define COOKIE_DOT
Definition: readdir.c:363
nfs41_file_info attr_info
Definition: nfs41_ops.h:714
static FILE * out
Definition: regtests2xml.c:44
static int state
Definition: maze.c:121
nfs41_path_fh parent
Definition: nfs41.h:129
uint32_t name_len
Definition: nfs41_ops.h:712
nfs41_path_fh file
Definition: nfs41.h:130
nfs41_component name
Definition: nfs41_types.h:61
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
UINT32 uint32_t
Definition: types.h:75
Definition: name.c:36
#define COOKIE_DOTDOT
Definition: readdir.c:364
#define uint32_t
Definition: nsiface.idl:61
unsigned short len
Definition: nfs41_types.h:49
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ readdir_copy_both_dir_info()

static void readdir_copy_both_dir_info ( IN nfs41_readdir_entry entry,
IN LPWSTR  wname,
IN PFILE_DIR_INFO_UNION  info 
)
static

Definition at line 187 of file readdir.c.

Referenced by readdir_copy_entry().

191 {
193  readdir_copy_shortname(wname, info->fbdi.ShortName,
194  &info->fbdi.ShortNameLength);
195 }
uint8_t entry
Definition: isohybrid.c:63
static void readdir_copy_shortname(IN LPCWSTR name, OUT LPWSTR name_out, OUT CCHAR *name_size_out)
Definition: readdir.c:160
static void readdir_copy_full_dir_info(IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
Definition: readdir.c:173

◆ readdir_copy_dir_info()

static void readdir_copy_dir_info ( IN nfs41_readdir_entry entry,
IN PFILE_DIR_INFO_UNION  info 
)
static

Definition at line 139 of file readdir.c.

Referenced by readdir_copy_entry(), and readdir_copy_full_dir_info().

142 {
143  info->fdi.FileIndex = (ULONG)entry->attr_info.fileid;
144  nfs_time_to_file_time(&entry->attr_info.time_create,
145  &info->fdi.CreationTime);
146  nfs_time_to_file_time(&entry->attr_info.time_access,
147  &info->fdi.LastAccessTime);
148  nfs_time_to_file_time(&entry->attr_info.time_modify,
149  &info->fdi.LastWriteTime);
150  /* XXX: was using 'change' attr, but that wasn't giving a time */
151  nfs_time_to_file_time(&entry->attr_info.time_modify,
152  &info->fdi.ChangeTime);
153  info->fdi.EndOfFile.QuadPart =
154  info->fdi.AllocationSize.QuadPart =
155  entry->attr_info.size;
156  info->fdi.FileAttributes = nfs_file_info_to_attributes(
157  &entry->attr_info);
158 }
uint8_t entry
Definition: isohybrid.c:63
static __inline void nfs_time_to_file_time(IN const nfstime4 *nfs_time, OUT PLARGE_INTEGER file_time)
Definition: util.h:125
ULONG nfs_file_info_to_attributes(IN const nfs41_file_info *info)
Definition: util.c:137
unsigned int ULONG
Definition: retypes.h:1

◆ readdir_copy_entry()

static int readdir_copy_entry ( IN readdir_upcall_args args,
IN nfs41_readdir_entry entry,
IN OUT unsigned char **  dst_pos,
IN OUT uint32_t dst_len 
)
static

Definition at line 279 of file readdir.c.

Referenced by handle_readdir().

284 {
285  int status = 0;
286  WCHAR wname[NFS4_OPAQUE_LIMIT];
287  uint32_t wname_len, wname_size, needed;
289 
290  wname_len = MultiByteToWideChar(CP_UTF8, 0,
291  entry->name, entry->name_len, wname, NFS4_OPAQUE_LIMIT);
292  wname_size = (wname_len - 1) * sizeof(WCHAR);
293 
294  needed = readdir_size_for_entry(args->query_class, wname_size);
295  if (!needed || needed > *dst_len) {
296  status = -1;
297  goto out;
298  }
299 
300  info = (PFILE_DIR_INFO_UNION)*dst_pos;
301  info->NextEntryOffset = align8(needed);
302  *dst_pos += info->NextEntryOffset;
303  *dst_len -= info->NextEntryOffset;
304 
305  if (entry->attr_info.rdattr_error == NFS4ERR_MOVED) {
306  entry->attr_info.type = NF4DIR; /* default to dir */
307  /* look up attributes for referral entries, but ignore return value;
308  * it's okay if lookup fails, we'll just write garbage attributes */
309  lookup_entry(args->root, args->state->session,
310  &args->state->file, entry);
311  } else if (entry->attr_info.type == NF4LNK) {
313  name.name = entry->name;
314  name.len = (unsigned short)entry->name_len - 1;
315  /* look up the symlink target to see whether it's a directory */
316  lookup_symlink(args->root, args->state->session,
317  &args->state->file, &name, &entry->attr_info);
318  }
319 
320  switch (args->query_class)
321  {
323  info->fni.FileIndex = 0;
324  readdir_copy_filename(wname, wname_size,
325  info->fni.FileName, &info->fni.FileNameLength);
326  break;
329  readdir_copy_filename(wname, wname_size,
330  info->fdi.FileName, &info->fdi.FileNameLength);
331  break;
334  readdir_copy_filename(wname, wname_size,
335  info->ffdi.FileName, &info->ffdi.FileNameLength);
336  break;
339  info->fibdi.FileId.QuadPart = (LONGLONG)entry->attr_info.fileid;
340  readdir_copy_filename(wname, wname_size,
341  info->fifdi.FileName, &info->fifdi.FileNameLength);
342  break;
344  readdir_copy_both_dir_info(entry, wname, info);
345  readdir_copy_filename(wname, wname_size,
346  info->fbdi.FileName, &info->fbdi.FileNameLength);
347  break;
349  readdir_copy_both_dir_info(entry, wname, info);
350  info->fibdi.FileId.QuadPart = (LONGLONG)entry->attr_info.fileid;
351  readdir_copy_filename(wname, wname_size,
352  info->fibdi.FileName, &info->fibdi.FileNameLength);
353  break;
354  default:
355  eprintf("unhandled dir query class %d\n", args->query_class);
356  status = -1;
357  break;
358  }
359 out:
360  return status;
361 }
static int lookup_symlink(IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *parent, IN const nfs41_component *name, OUT nfs41_file_info *info_out)
Definition: readdir.c:250
static uint32_t readdir_size_for_entry(IN int query_class, IN uint32_t wname_size)
Definition: readdir.c:107
__wchar_t WCHAR
Definition: xmlstorage.h:180
uint8_t entry
Definition: isohybrid.c:63
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
Definition: match.c:390
struct _test_info info[]
Definition: SetCursorPos.c:19
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:91
FILE_BOTH_DIR_INFORMATION fbdi
Definition: readdir.c:38
FILE_DIRECTORY_INFO fdi
Definition: readdir.c:35
#define CP_UTF8
Definition: nls.h:20
#define NFS4_OPAQUE_LIMIT
Definition: nfs41_const.h:31
FILE_NAMES_INFORMATION fni
Definition: readdir.c:34
__inline uint32_t align8(uint32_t offset)
Definition: util.h:191
int64_t LONGLONG
Definition: typedefs.h:66
static void readdir_copy_both_dir_info(IN nfs41_readdir_entry *entry, IN LPWSTR wname, IN PFILE_DIR_INFO_UNION info)
Definition: readdir.c:187
static int lookup_entry(IN nfs41_root *root, IN nfs41_session *session, IN nfs41_path_fh *parent, OUT nfs41_readdir_entry *entry)
Definition: readdir.c:227
static void readdir_copy_filename(IN LPCWSTR name, IN uint32_t name_size, OUT LPWSTR name_out, OUT ULONG *name_size_out)
Definition: readdir.c:197
const char * name
Definition: nfs41_types.h:48
static FILE * out
Definition: regtests2xml.c:44
union _FILE_DIR_INFO_UNION * PFILE_DIR_INFO_UNION
FILE_FULL_DIR_INFO ffdi
Definition: readdir.c:36
static void readdir_copy_dir_info(IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
Definition: readdir.c:139
ULONG NextEntryOffset
Definition: readdir.c:33
UINT32 uint32_t
Definition: types.h:75
#define MultiByteToWideChar
Definition: compat.h:100
static void readdir_copy_full_dir_info(IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
Definition: readdir.c:173
FILE_ID_FULL_DIR_INFO fifdi
Definition: readdir.c:37
FILE_ID_BOTH_DIR_INFO fibdi
Definition: readdir.c:39
unsigned short len
Definition: nfs41_types.h:49
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97
GLuint const GLchar * name
Definition: glext.h:6031

◆ readdir_copy_filename()

static void readdir_copy_filename ( IN LPCWSTR  name,
IN uint32_t  name_size,
OUT LPWSTR  name_out,
OUT ULONG name_size_out 
)
static

Definition at line 197 of file readdir.c.

Referenced by readdir_copy_entry().

202 {
203  *name_size_out = name_size;
204  memcpy(name_out, name, name_size);
205 }
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: name.c:36

◆ readdir_copy_full_dir_info()

static void readdir_copy_full_dir_info ( IN nfs41_readdir_entry entry,
IN PFILE_DIR_INFO_UNION  info 
)
static

Definition at line 173 of file readdir.c.

Referenced by readdir_copy_both_dir_info(), and readdir_copy_entry().

176 {
178  /* for files with the FILE_ATTRIBUTE_REPARSE_POINT attribute,
179  * EaSize is used instead to specify its reparse tag. this makes
180  * the 'dir' command to show files as <SYMLINK>, and triggers a
181  * FSCTL_GET_REPARSE_POINT to query the symlink target
182  */
183  info->fifdi.EaSize = entry->attr_info.type == NF4LNK ?
185 }
uint8_t entry
Definition: isohybrid.c:63
static void readdir_copy_dir_info(IN nfs41_readdir_entry *entry, IN PFILE_DIR_INFO_UNION info)
Definition: readdir.c:139
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6883

◆ readdir_copy_shortname()

static void readdir_copy_shortname ( IN LPCWSTR  name,
OUT LPWSTR  name_out,
OUT CCHAR name_size_out 
)
static

Definition at line 160 of file readdir.c.

Referenced by readdir_copy_both_dir_info().

164 {
165  /* GetShortPathName returns number of characters, not including \0 */
166  *name_size_out = (CCHAR)GetShortPathNameW(name, name_out, 12);
167  if (*name_size_out) {
168  *name_size_out++;
169  *name_size_out *= sizeof(WCHAR);
170  }
171 }
#define WCHAR
Definition: msvc.h:43
char CCHAR
Definition: typedefs.h:50
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1832
Definition: name.c:36

◆ readdir_filter()

static int readdir_filter ( const char filter,
const char name 
)
static

Definition at line 85 of file readdir.c.

Referenced by handle_readdir().

88 {
89  const char *f = filter, *n = name;
90 
91  while (*f && *n) {
92  if (*f == FILTER_STAR) {
93  f = skip_stars(f);
94  if (*f == '\0')
95  return 1;
96  while (*n && !readdir_filter(f, n))
97  n++;
98  } else if (*f == FILTER_QM || *f == *n) {
99  f++;
100  n++;
101  } else
102  return 0;
103  }
104  return *f == *n || *skip_stars(f) == '\0';
105 }
static __inline const char * skip_stars(const char *filter)
Definition: readdir.c:77
GLuint n
Definition: s_context.h:57
#define FILTER_QM
Definition: readdir.c:75
GLfloat f
Definition: glext.h:7540
static int readdir_filter(const char *filter, const char *name)
Definition: readdir.c:85
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
#define FILTER_STAR
Definition: readdir.c:74
GLuint const GLchar * name
Definition: glext.h:6031

◆ readdir_size_for_entry()

static uint32_t readdir_size_for_entry ( IN int  query_class,
IN uint32_t  wname_size 
)
static

Definition at line 107 of file readdir.c.

Referenced by readdir_copy_entry().

110 {
111  uint32_t needed = wname_size;
112  switch (query_class)
113  {
116  break;
119  break;
122  break;
124  needed += FIELD_OFFSET(FILE_ID_BOTH_DIR_INFO, FileName);
125  break;
128  break;
131  break;
132  default:
133  eprintf("unhandled dir query class %d\n", query_class);
134  return 0;
135  }
136  return needed;
137 }
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
UINT32 uint32_t
Definition: types.h:75

◆ skip_stars()

static __inline const char* skip_stars ( const char filter)
static

Definition at line 77 of file readdir.c.

Referenced by readdir_filter().

79 {
80  while (*filter == FILTER_STAR)
81  filter++;
82  return filter;
83 }
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
#define FILTER_STAR
Definition: readdir.c:74

Variable Documentation

◆ nfs41_op_readdir

const nfs41_upcall_op nfs41_op_readdir
Initial value:
= {
}
static int handle_readdir(nfs41_upcall *upcall)
Definition: readdir.c:451
static int marshall_readdir(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
Definition: readdir.c:635
static int parse_readdir(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
Definition: readdir.c:44

Definition at line 645 of file readdir.c.