ReactOS 0.4.15-dev-7674-gc0b4db1
ea.c File Reference
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#include "from_kernel.h"
#include "nfs41_ops.h"
#include "delegation.h"
#include "upcall.h"
#include "daemon_debug.h"
Include dependency graph for ea.c:

Go to the source code of this file.

Macros

#define EALVL   2 /* dprintf level for extended attribute logging */
 
#define NEXT_ENTRY(ea)   ((PBYTE)(ea) + (ea)->NextEntryOffset)
 
#define READDIR_LEN_INITIAL   8192
 
#define READDIR_LEN_MIN   2048
 
#define ALIGNED_EASIZE(len)   (align4(sizeof(FILE_GET_EA_INFORMATION) + len))
 

Functions

static int set_ea_value (IN nfs41_session *session, IN nfs41_path_fh *parent, IN state_owner4 *owner, IN PFILE_FULL_EA_INFORMATION ea)
 
static int is_cygwin_ea (PFILE_FULL_EA_INFORMATION ea)
 
int nfs41_ea_set (IN nfs41_open_state *state, IN PFILE_FULL_EA_INFORMATION ea)
 
static int parse_setexattr (unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
 
static int handle_setexattr (nfs41_upcall *upcall)
 
static int marshall_setexattr (unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
 
static int parse_getexattr (unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
 
static int read_entire_dir (IN nfs41_session *session, IN nfs41_path_fh *eadir, OUT unsigned char **buffer_out, OUT uint32_t *length_out)
 
static uint32_t calculate_ea_list_length (IN const unsigned char *position, IN uint32_t remaining)
 
static void populate_ea_list (IN const unsigned char *position, OUT PFILE_GET_EA_INFORMATION ea_list)
 
static int get_ea_list (IN OUT nfs41_open_state *state, IN nfs41_path_fh *eadir, OUT PFILE_GET_EA_INFORMATION *ealist_out, OUT uint32_t *eaindex_out)
 
static int get_ea_value (IN nfs41_session *session, IN nfs41_path_fh *parent, IN state_owner4 *owner, OUT PFILE_FULL_EA_INFORMATION ea, IN uint32_t length, OUT uint32_t *needed)
 
static int empty_ea_error (IN uint32_t index, IN BOOLEAN restart)
 
static int overflow_error (IN OUT getexattr_upcall_args *args, IN PFILE_FULL_EA_INFORMATION prev, IN uint32_t needed)
 
static int handle_getexattr (nfs41_upcall *upcall)
 
static int marshall_getexattr (unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
 

Variables

const nfs41_upcall_op nfs41_op_setexattr
 
const nfs41_upcall_op nfs41_op_getexattr
 

Macro Definition Documentation

◆ ALIGNED_EASIZE

#define ALIGNED_EASIZE (   len)    (align4(sizeof(FILE_GET_EA_INFORMATION) + len))

Definition at line 320 of file ea.c.

◆ EALVL

#define EALVL   2 /* dprintf level for extended attribute logging */

Definition at line 33 of file ea.c.

◆ NEXT_ENTRY

#define NEXT_ENTRY (   ea)    ((PBYTE)(ea) + (ea)->NextEntryOffset)

Definition at line 114 of file ea.c.

◆ READDIR_LEN_INITIAL

#define READDIR_LEN_INITIAL   8192

Definition at line 235 of file ea.c.

◆ READDIR_LEN_MIN

#define READDIR_LEN_MIN   2048

Definition at line 236 of file ea.c.

Function Documentation

◆ calculate_ea_list_length()

static uint32_t calculate_ea_list_length ( IN const unsigned char position,
IN uint32_t  remaining 
)
static

Definition at line 322 of file ea.c.

325{
327 uint32_t length = 0;
328
329 while (remaining) {
330 entry = (const nfs41_readdir_entry*)position;
331 length += ALIGNED_EASIZE(entry->name_len);
332
333 if (!entry->next_entry_offset)
334 break;
335
336 position += entry->next_entry_offset;
337 remaining -= entry->next_entry_offset;
338 }
339 return length;
340}
#define ALIGNED_EASIZE(len)
Definition: ea.c:320
UINT32 uint32_t
Definition: types.h:75
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
uint32_t entry
Definition: isohybrid.c:63
Definition: nfs41_ops.h:710

Referenced by get_ea_list().

◆ empty_ea_error()

static int empty_ea_error ( IN uint32_t  index,
IN BOOLEAN  restart 
)
static

Definition at line 496 of file ea.c.

499{
500 /* choose an error value depending on the arguments */
501 if (index)
503
504 if (!restart)
505 return ERROR_NO_MORE_FILES; /* -> STATUS_NO_MORE_EAS */
506
507 return ERROR_FILE_NOT_FOUND; /* -> STATUS_NO_EAS_ON_FILE */
508}
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
GLuint index
Definition: glext.h:6031
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define ERROR_INVALID_EA_HANDLE
Definition: winerror.h:299
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121

◆ get_ea_list()

static int get_ea_list ( IN OUT nfs41_open_state state,
IN nfs41_path_fh eadir,
OUT PFILE_GET_EA_INFORMATION ealist_out,
OUT uint32_t eaindex_out 
)
static

Definition at line 366 of file ea.c.

371{
372 unsigned char *entry_list;
374 uint32_t entry_len, ea_size;
375 int status = NO_ERROR;
376
377 EnterCriticalSection(&state->ea.lock);
378
379 if (state->ea.list != INVALID_HANDLE_VALUE) {
380 /* use cached ea names */
381 *ealist_out = state->ea.list;
382 *eaindex_out = state->ea.index;
383 goto out;
384 }
385
386 /* read the entire directory into a nfs41_readdir_entry buffer */
387 status = read_entire_dir(state->session, eadir, &entry_list, &entry_len);
388 if (status)
389 goto out;
390
391 ea_size = calculate_ea_list_length(entry_list, entry_len);
392 if (ea_size == 0) {
393 *ealist_out = state->ea.list = NULL;
394 goto out_free;
395 }
396 ea_list = calloc(1, ea_size);
397 if (ea_list == NULL) {
399 goto out_free;
400 }
401
402 populate_ea_list(entry_list, ea_list);
403
404 *ealist_out = state->ea.list = ea_list;
405 *eaindex_out = state->ea.index;
406out_free:
407 free(entry_list); /* allocated by read_entire_dir() */
408out:
409 LeaveCriticalSection(&state->ea.lock);
410 return status;
411}
static int state
Definition: maze.c:121
static int read_entire_dir(IN nfs41_session *session, IN nfs41_path_fh *eadir, OUT unsigned char **buffer_out, OUT uint32_t *length_out)
Definition: ea.c:239
static void populate_ea_list(IN const unsigned char *position, OUT PFILE_GET_EA_INFORMATION ea_list)
Definition: ea.c:342
static uint32_t calculate_ea_list_length(IN const unsigned char *position, IN uint32_t remaining)
Definition: ea.c:322
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
Definition: ps.c:97
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)

◆ get_ea_value()

static int get_ea_value ( IN nfs41_session session,
IN nfs41_path_fh parent,
IN state_owner4 owner,
OUT PFILE_FULL_EA_INFORMATION  ea,
IN uint32_t  length,
OUT uint32_t needed 
)
static

Definition at line 413 of file ea.c.

420{
421 nfs41_path_fh file = { 0 };
422 open_claim4 claim;
423 stateid_arg stateid;
424 open_delegation4 delegation = { 0 };
426 unsigned char *buffer;
427 uint32_t diff, bytes_read;
428 bool_t eof;
429 int status;
430
431 if (parent->fh.len == 0) /* no named attribute directory */
432 goto out_empty;
433
434 claim.claim = CLAIM_NULL;
435 claim.u.null.filename = &file.name;
436 file.name.name = ea->EaName;
437 file.name.len = ea->EaNameLength;
438
439 status = nfs41_open(session, parent, &file, owner, &claim,
442 &stateid.stateid, &delegation, &info);
443 if (status) {
444 eprintf("nfs41_open() failed with %s\n", nfs_error_string(status));
445 if (status == NFS4ERR_NOENT)
446 goto out_empty;
447 goto out;
448 }
449
450 if (info.size > NFS4_EASIZE) {
452 eprintf("EA value for '%s' longer than maximum %u "
453 "(%llu bytes), returning %s\n", ea->EaName, NFS4_EASIZE,
455 goto out_close;
456 }
457
458 buffer = (unsigned char*)ea->EaName + ea->EaNameLength + 1;
459 diff = (uint32_t)(buffer - (unsigned char*)ea);
460
461 /* make sure we have room for the value */
462 if (length < diff + info.size) {
463 *needed = (uint32_t)(sizeof(FILE_FULL_EA_INFORMATION) +
464 ea->EaNameLength + info.size);
466 goto out_close;
467 }
468
469 /* read directly into the ea buffer */
470 status = nfs41_read(session, &file, &stateid,
471 0, length - diff, buffer, &bytes_read, &eof);
472 if (status) {
473 eprintf("nfs41_read() failed with %s\n", nfs_error_string(status));
474 goto out_close;
475 }
476 if (!eof) {
477 *needed = (uint32_t)(sizeof(FILE_FULL_EA_INFORMATION) +
478 ea->EaNameLength + NFS4_EASIZE);
480 goto out_close;
481 }
482
483 ea->EaValueLength = (USHORT)bytes_read;
484
485out_close:
486 nfs41_close(session, &file, &stateid);
487out:
488 return status;
489
490out_empty: /* return an empty value */
491 ea->EaValueLength = 0;
492 status = NFS4_OK;
493 goto out;
494}
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
r parent
Definition: btrfs.c:3010
GLuint buffer
Definition: glext.h:5915
#define NFS4_EASIZE
Definition: nfs41_const.h:34
@ NFS4ERR_TOOSMALL
Definition: nfs41_const.h:110
@ NFS4ERR_FBIG
Definition: nfs41_const.h:99
@ NFS4ERR_NOENT
Definition: nfs41_const.h:89
@ NFS4_OK
Definition: nfs41_const.h:87
int nfs41_open(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN state_owner4 *owner, IN open_claim4 *claim, IN uint32_t allow, IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, IN OPTIONAL nfs41_file_info *createattrs, IN bool_t try_recovery, OUT stateid4 *stateid, OUT open_delegation4 *delegation, OUT OPTIONAL nfs41_file_info *info)
Definition: nfs41_ops.c:366
int nfs41_read(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN uint64_t offset, IN uint32_t count, OUT unsigned char *data_out, OUT uint32_t *data_len_out, OUT bool_t *eof_out)
Definition: nfs41_ops.c:774
int nfs41_close(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid)
Definition: nfs41_ops.c:627
@ OPEN4_SHARE_ACCESS_WANT_NO_DELEG
Definition: nfs41_ops.h:578
@ OPEN4_SHARE_DENY_WRITE
Definition: nfs41_ops.h:570
@ OPEN4_SHARE_ACCESS_READ
Definition: nfs41_ops.h:564
@ OPEN4_NOCREATE
Definition: nfs41_ops.h:553
@ UNCHECKED4
Definition: nfs41_ops.h:540
@ CLAIM_NULL
Definition: nfs41_ops.h:593
#define uint32_t
Definition: nsiface.idl:61
unsigned short USHORT
Definition: pedump.c:61
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
uint32_t claim
Definition: nfs41_ops.h:615
struct __open_claim4::@50::__open_claim_null null
union __open_claim4::@50 u
stateid4 stateid
Definition: nfs41_ops.h:284
Definition: fci.c:127
char name[1]
Definition: fci.c:135

◆ handle_getexattr()

static int handle_getexattr ( nfs41_upcall upcall)
static

Definition at line 530 of file ea.c.

531{
532 getexattr_upcall_args *args = &upcall->args.getexattr;
535 nfs41_open_state *state = upcall->state_ref;
536 nfs41_path_fh parent = { 0 };
537 uint32_t remaining, needed, index = 0;
538 int status;
539
540 status = nfs41_rpc_openattr(state->session, &state->file, FALSE, &parent.fh);
541 if (status == NFS4ERR_NOENT) { /* no named attribute directory */
542 dprintf(EALVL, "no named attribute directory for '%s'\n", args->path);
543 if (query == NULL) {
544 status = empty_ea_error(args->eaindex, args->restart);
545 goto out;
546 }
547 } else if (status) {
548 eprintf("nfs41_rpc_openattr() failed with %s\n",
551 goto out;
552 }
553
554 if (query == NULL) {
555 /* if no names are queried, use READDIR to list them all */
556 uint32_t i;
558 if (status)
559 goto out;
560
561 if (query == NULL) { /* the file has no EAs */
562 dprintf(EALVL, "empty named attribute directory for '%s'\n",
563 args->path);
564 status = empty_ea_error(args->eaindex, args->restart);
565 goto out;
566 }
567
568 if (args->eaindex)
569 index = args->eaindex - 1; /* convert to zero-based index */
570 else if (args->restart)
571 index = 0;
572
573 /* advance the list to the specified index */
574 for (i = 0; i < index; i++) {
575 if (query->NextEntryOffset == 0) {
576 if (args->eaindex)
578 else
579 status = ERROR_NO_MORE_FILES; /* STATUS_NO_MORE_EAS */
580 goto out;
581 }
583 }
584 }
585
586 /* returned ea information can't exceed the downcall buffer size */
587 if (args->buf_len > UPCALL_BUF_SIZE - 2 * sizeof(uint32_t))
588 args->buf_len = UPCALL_BUF_SIZE - 2 * sizeof(uint32_t);
589
590 args->buf = malloc(args->buf_len);
591 if (args->buf == NULL) {
593 goto out;
594 }
595
597 remaining = args->buf_len;
598
599 for (;;) {
600 /* make sure we have room for at least the name */
601 needed = sizeof(FILE_FULL_EA_INFORMATION) + query->EaNameLength;
602 if (needed > remaining) {
603 status = overflow_error(args, prev, needed + NFS4_EASIZE);
604 goto out;
605 }
606
607 ea->EaNameLength = query->EaNameLength;
608 StringCchCopy(ea->EaName, ea->EaNameLength + 1, query->EaName);
609 ea->Flags = 0;
610
611 /* read the value from file */
612 status = get_ea_value(state->session, &parent,
613 &state->owner, ea, remaining, &needed);
614 if (status == NFS4ERR_TOOSMALL) {
615 status = overflow_error(args, prev, needed);
616 goto out;
617 }
618 if (status) {
620 goto out_free;
621 }
622
624 ea->EaNameLength + 1 + ea->EaValueLength);
625
626 if (remaining < needed) {
627 /* align4 may push NextEntryOffset past our buffer, but we
628 * were still able to fit the ea value. set remaining = 0
629 * so we'll fail on the next ea (if any) */
630 remaining = 0;
631 } else
632 remaining -= needed;
633
634 index++;
635 if (query->NextEntryOffset == 0 || args->single)
636 break;
637
638 prev = ea;
639 ea->NextEntryOffset = needed;
642 }
643
644 ea->NextEntryOffset = 0;
645 args->buf_len -= remaining;
646out:
647 if (args->ealist == NULL) { /* update the ea index */
648 EnterCriticalSection(&state->ea.lock);
649 state->ea.index = index;
650 if (status == NO_ERROR && !args->overflow && !args->single) {
651 /* listing was completed, free the cache */
652 free(state->ea.list);
653 state->ea.list = INVALID_HANDLE_VALUE;
654 }
655 LeaveCriticalSection(&state->ea.lock);
656 }
657 return status;
658
659out_free:
660 free(args->buf);
661 goto out;
662}
#define index(s, c)
Definition: various.h:29
#define NEXT_ENTRY(ea)
Definition: ea.c:114
static int get_ea_list(IN OUT nfs41_open_state *state, IN nfs41_path_fh *eadir, OUT PFILE_GET_EA_INFORMATION *ealist_out, OUT uint32_t *eaindex_out)
Definition: ea.c:366
static int empty_ea_error(IN uint32_t index, IN BOOLEAN restart)
Definition: ea.c:496
#define EALVL
Definition: ea.c:33
static int get_ea_value(IN nfs41_session *session, IN nfs41_path_fh *parent, IN state_owner4 *owner, OUT PFILE_FULL_EA_INFORMATION ea, IN uint32_t length, OUT uint32_t *needed)
Definition: ea.c:413
int nfs_to_windows_error(int status, int default_error)
Definition: util.c:235
__inline uint32_t align4(uint32_t offset)
Definition: util.h:198
#define malloc
Definition: debug_ros.c:4
#define FALSE
Definition: types.h:117
struct _FILE_FULL_EA_INFORMATION * PFILE_FULL_EA_INFORMATION
struct _FILE_GET_EA_INFORMATION * PFILE_GET_EA_INFORMATION
struct _FILE_FULL_EA_INFORMATION FILE_FULL_EA_INFORMATION
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
if(dx< 0)
Definition: linetemp.h:194
#define for
Definition: utility.h:88
#define UPCALL_BUF_SIZE
Definition: nfs41_const.h:42
nfs41_updowncall_list upcall
Definition: nfs41_driver.c:273
enum nfsstat4 nfs41_rpc_openattr(IN nfs41_session *session, IN nfs41_path_fh *file, IN bool_t createdir, OUT nfs41_fh *fh_out)
Definition: nfs41_ops.c:2145
#define dprintf
Definition: regdump.c:33
#define StringCchCopy
Definition: strsafe.h:139
Definition: match.c:390
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define ERROR_EA_FILE_CORRUPT
Definition: winerror.h:297
#define ERROR_EAS_NOT_SUPPORTED
Definition: winerror.h:300

◆ handle_setexattr()

static int handle_setexattr ( nfs41_upcall upcall)
static

Definition at line 162 of file ea.c.

163{
164 int status;
165 setexattr_upcall_args *args = &upcall->args.setexattr;
166 nfs41_open_state *state = upcall->state_ref;
169
170 /* break read delegations before SETATTR */
171 nfs41_delegation_return(state->session, &state->file,
173
174 if (strncmp("NfsV3Attributes", ea->EaName, ea->EaNameLength) == 0
175 && sizeof("NfsV3Attributes")-1 == ea->EaNameLength) {
177 stateid_arg stateid;
178
179 nfs41_open_stateid_arg(state, &stateid);
180
181 info.mode = args->mode;
182 info.attrmask.arr[0] = 0;
183 info.attrmask.arr[1] = FATTR4_WORD1_MODE;
184 info.attrmask.count = 2;
185
186 status = nfs41_setattr(state->session, &state->file, &stateid, &info);
187 if (status) {
188 dprintf(1, "nfs41_setattr() failed with error %s.\n",
190 goto out;
191 }
192
193 args->ctime = info.change;
194 goto out;
195 }
196
198out:
200}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
int nfs41_ea_set(IN nfs41_open_state *state, IN PFILE_FULL_EA_INFORMATION ea)
Definition: ea.c:116
int nfs41_delegation_return(IN nfs41_session *session, IN nfs41_path_fh *file, IN enum open_delegation_type4 access, IN bool_t truncate)
Definition: delegation.c:629
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
void nfs41_open_stateid_arg(IN nfs41_open_state *state, OUT struct __stateid_arg *arg)
@ FATTR4_WORD1_MODE
Definition: nfs41_const.h:245
int nfs41_setattr(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN nfs41_file_info *info)
Definition: nfs41_ops.c:1351
@ OPEN_DELEGATE_READ
Definition: nfs41_ops.h:587
unsigned int count
Definition: notification.c:64

◆ is_cygwin_ea()

static int is_cygwin_ea ( PFILE_FULL_EA_INFORMATION  ea)
static

Definition at line 103 of file ea.c.

105{
106 return (strncmp("NfsV3Attributes", ea->EaName, ea->EaNameLength) == 0
107 && sizeof("NfsV3Attributes")-1 == ea->EaNameLength)
108 || (strncmp("NfsActOnLink", ea->EaName, ea->EaNameLength) == 0
109 && sizeof("NfsActOnLink")-1 == ea->EaNameLength)
110 || (strncmp("NfsSymlinkTargetName", ea->EaName, ea->EaNameLength) == 0
111 && sizeof("NfsSymlinkTargetName")-1 == ea->EaNameLength);
112}

Referenced by nfs41_ea_set().

◆ marshall_getexattr()

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

Definition at line 664 of file ea.c.

665{
666 int status = NO_ERROR;
667 getexattr_upcall_args *args = &upcall->args.getexattr;
668
669 status = safe_write(&buffer, length, &args->overflow, sizeof(args->overflow));
670 if (status) goto out;
671 status = safe_write(&buffer, length, &args->buf_len, sizeof(args->buf_len));
672 if (status) goto out;
673 if (args->overflow == ERROR_INSUFFICIENT_BUFFER)
674 goto out;
675 status = safe_write(&buffer, length, args->buf, args->buf_len);
676 if (status) goto out;
677out:
678 free(args->buf);
679 return status;
680}
int safe_write(unsigned char **pos, uint32_t *remaining, void *src, uint32_t src_len)
Definition: util.c:44
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10

◆ marshall_setexattr()

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

Definition at line 202 of file ea.c.

203{
204 setexattr_upcall_args *args = &upcall->args.setexattr;
205 return safe_write(&buffer, length, &args->ctime, sizeof(args->ctime));
206}

◆ nfs41_ea_set()

int nfs41_ea_set ( IN nfs41_open_state state,
IN PFILE_FULL_EA_INFORMATION  ea 
)

Definition at line 116 of file ea.c.

119{
120 nfs41_path_fh attrdir = { 0 };
121 int status;
122
123 status = nfs41_rpc_openattr(state->session, &state->file, TRUE, &attrdir.fh);
124 if (status) {
125 eprintf("nfs41_rpc_openattr() failed with error %s\n",
127 goto out;
128 }
129
130 while (status == NFS4_OK) {
131 if (!is_cygwin_ea(ea))
132 status = set_ea_value(state->session, &attrdir, &state->owner, ea);
133
134 if (ea->NextEntryOffset == 0)
135 break;
137 }
138out:
139 return status;
140}
static int is_cygwin_ea(PFILE_FULL_EA_INFORMATION ea)
Definition: ea.c:103
static int set_ea_value(IN nfs41_session *session, IN nfs41_path_fh *parent, IN state_owner4 *owner, IN PFILE_FULL_EA_INFORMATION ea)
Definition: ea.c:36

Referenced by handle_open(), and handle_setexattr().

◆ overflow_error()

static int overflow_error ( IN OUT getexattr_upcall_args args,
IN PFILE_FULL_EA_INFORMATION  prev,
IN uint32_t  needed 
)
static

Definition at line 510 of file ea.c.

514{
515 if (prev) {
516 /* unlink the overflowing entry, but copy the entries that fit */
517 prev->NextEntryOffset = 0;
518 args->overflow = ERROR_BUFFER_OVERFLOW;
519 } else {
520 /* no entries fit; return only the length needed */
521 args->buf_len = needed;
523 }
524
525 /* in either case, the upcall must return NO_ERROR so we
526 * can copy this information down to the driver */
527 return NO_ERROR;
528}
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185

◆ parse_getexattr()

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

Definition at line 210 of file ea.c.

211{
212 int status;
213 getexattr_upcall_args *args = &upcall->args.getexattr;
214
215 status = get_name(&buffer, &length, &args->path);
216 if (status) goto out;
217 status = safe_read(&buffer, &length, &args->eaindex, sizeof(args->eaindex));
218 if (status) goto out;
219 status = safe_read(&buffer, &length, &args->restart, sizeof(args->restart));
220 if (status) goto out;
221 status = safe_read(&buffer, &length, &args->single, sizeof(args->single));
222 if (status) goto out;
223 status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
224 if (status) goto out;
225 status = safe_read(&buffer, &length, &args->ealist_len, sizeof(args->ealist_len));
226 if (status) goto out;
227 args->ealist = args->ealist_len ? buffer : NULL;
228
229 dprintf(1, "parsing NFS41_EA_GET: buf_len=%d Index %d Restart %d "
230 "Single %d\n", args->buf_len,args->eaindex, args->restart, args->single);
231out:
232 return status;
233}
int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len)
Definition: util.c:33
int get_name(unsigned char **pos, uint32_t *remaining, const char **out_name)
Definition: util.c:55

◆ parse_setexattr()

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

Definition at line 144 of file ea.c.

145{
146 int status;
147 setexattr_upcall_args *args = &upcall->args.setexattr;
148
149 status = get_name(&buffer, &length, &args->path);
150 if (status) goto out;
151 status = safe_read(&buffer, &length, &args->mode, sizeof(args->mode));
152 if (status) goto out;
153 status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
154 if (status) goto out;
155 args->buf = buffer;
156
157 dprintf(1, "parsing NFS41_EA_SET: mode=%o\n", args->mode);
158out:
159 return status;
160}

◆ populate_ea_list()

static void populate_ea_list ( IN const unsigned char position,
OUT PFILE_GET_EA_INFORMATION  ea_list 
)
static

Definition at line 342 of file ea.c.

345{
347 PFILE_GET_EA_INFORMATION ea = ea_list, prev = NULL;
348
349 for (;;) {
350 entry = (const nfs41_readdir_entry*)position;
351 StringCchCopyA(ea->EaName, entry->name_len, entry->name);
352 ea->EaNameLength = (UCHAR)entry->name_len - 1;
353
354 if (!entry->next_entry_offset) {
355 ea->NextEntryOffset = 0;
356 break;
357 }
358
359 prev = ea;
362 position += entry->next_entry_offset;
363 }
364}
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by get_ea_list().

◆ read_entire_dir()

static int read_entire_dir ( IN nfs41_session session,
IN nfs41_path_fh eadir,
OUT unsigned char **  buffer_out,
OUT uint32_t length_out 
)
static

Definition at line 239 of file ea.c.

244{
246 bitmap4 attr_request;
247 nfs41_readdir_entry *last_entry;
248 unsigned char *buffer;
249 uint32_t buffer_len, len, total_len;
250 bool_t eof;
251 int status = NO_ERROR;
252
253 attr_request.count = 0; /* don't request attributes */
254
255 /* allocate the buffer for readdir entries */
256 buffer_len = READDIR_LEN_INITIAL;
257 buffer = calloc(1, buffer_len);
258 if (buffer == NULL) {
260 goto out;
261 }
262
263 last_entry = NULL;
264 total_len = 0;
265 eof = FALSE;
266
267 while (!eof) {
268 len = buffer_len - total_len;
269 if (len < READDIR_LEN_MIN) {
270 const ptrdiff_t diff = (unsigned char*)last_entry - buffer;
271 /* realloc the buffer to fit more entries */
272 unsigned char *tmp = realloc(buffer, buffer_len * 2);
273 if (tmp == NULL) {
275 goto out_free;
276 }
277
278 if (last_entry) /* fix last_entry pointer */
279 last_entry = (nfs41_readdir_entry*)(tmp + diff);
280 buffer = tmp;
281 buffer_len *= 2;
282 len = buffer_len - total_len;
283 }
284
285 /* fetch the next group of entries */
286 status = nfs41_readdir(session, eadir, &attr_request,
287 &cookie, buffer + total_len, &len, &eof);
288 if (status)
289 goto out_free;
290
291 if (last_entry == NULL) {
292 /* initialize last_entry to the front of the list */
293 last_entry = (nfs41_readdir_entry*)(buffer + total_len);
294 } else if (len) {
295 /* link the previous list to the new one */
297 nfs41_readdir_entry, name) + last_entry->name_len;
298 }
299
300 /* find the new last entry */
301 while (last_entry->next_entry_offset) {
302 last_entry = (nfs41_readdir_entry*)((char*)last_entry +
303 last_entry->next_entry_offset);
304 }
305
306 cookie.cookie = last_entry->cookie;
307 total_len += len;
308 }
309
310 *buffer_out = buffer;
311 *length_out = total_len;
312out:
313 return status;
314
315out_free:
316 free(buffer);
317 goto out;
318}
#define READDIR_LEN_INITIAL
Definition: ea.c:235
#define READDIR_LEN_MIN
Definition: ea.c:236
#define realloc
Definition: debug_ros.c:6
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
GLenum GLsizei len
Definition: glext.h:6722
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
uint32_t count
Definition: nfs41_types.h:96
uint32_t name_len
Definition: nfs41_ops.h:712
uint32_t next_entry_offset
Definition: nfs41_ops.h:713
uint64_t cookie
Definition: nfs41_ops.h:711
Definition: cookie.c:34
Definition: name.c:39

Referenced by get_ea_list().

◆ set_ea_value()

static int set_ea_value ( IN nfs41_session session,
IN nfs41_path_fh parent,
IN state_owner4 owner,
IN PFILE_FULL_EA_INFORMATION  ea 
)
static

Definition at line 36 of file ea.c.

41{
42 nfs41_path_fh file = { 0 };
43 nfs41_file_info createattrs;
44 open_claim4 claim;
45 stateid_arg stateid;
46 open_delegation4 delegation = { 0 };
48 uint32_t bytes_written;
49 int status;
50
51 /* don't allow values larger than NFS4_EASIZE */
52 if (ea->EaValueLength > NFS4_EASIZE) {
53 eprintf("trying to write extended attribute value of size %d, "
54 "max allowed %d\n", ea->EaValueLength, NFS4_EASIZE);
56 goto out;
57 }
58 /* remove the file on empty value */
59 if (ea->EaValueLength == 0) {
61 name.name = ea->EaName;
62 name.len = ea->EaNameLength;
65 goto out;
66 }
67
68 claim.claim = CLAIM_NULL;
69 claim.u.null.filename = &file.name;
70 file.name.name = ea->EaName;
71 file.name.len = ea->EaNameLength;
72
73 createattrs.attrmask.count = 2;
74 createattrs.attrmask.arr[0] = FATTR4_WORD0_SIZE;
75 createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE;
76 createattrs.size = 0;
77 createattrs.mode = 0664;
78
79 status = nfs41_open(session, parent, &file, owner, &claim,
82 &createattrs, TRUE, &stateid.stateid, &delegation, NULL);
83 if (status) {
84 eprintf("nfs41_open() failed with %s\n", nfs_error_string(status));
85 goto out;
86 }
87
88 status = nfs41_write(session, &file, &stateid,
89 (unsigned char*)ea->EaName + ea->EaNameLength + 1,
90 ea->EaValueLength, 0, FILE_SYNC4, &bytes_written,
91 &verf, NULL);
92 if (status) {
93 eprintf("nfs41_write() failed with %s\n", nfs_error_string(status));
94 goto out_close;
95 }
96
97out_close:
98 nfs41_close(session, &file, &stateid);
99out:
100 return status;
101}
@ FATTR4_WORD0_SIZE
Definition: nfs41_const.h:211
int nfs41_remove(IN nfs41_session *session, IN nfs41_path_fh *parent, IN const nfs41_component *target, IN uint64_t fileid)
Definition: nfs41_ops.c:1180
int nfs41_write(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN unsigned char *data, IN uint32_t data_len, IN uint64_t offset, IN enum stable_how4 stable, OUT uint32_t *bytes_written, OUT nfs41_write_verf *verf, OUT nfs41_file_info *cinfo)
Definition: nfs41_ops.c:685
@ OPEN4_SHARE_ACCESS_WRITE
Definition: nfs41_ops.h:565
@ OPEN4_SHARE_DENY_BOTH
Definition: nfs41_ops.h:571
@ FILE_SYNC4
Definition: nfs41_ops.h:838
@ OPEN4_CREATE
Definition: nfs41_ops.h:554
uint32_t arr[3]
Definition: nfs41_types.h:97
WCHAR * name
Definition: name.c:42

Referenced by nfs41_ea_set().

Variable Documentation

◆ nfs41_op_getexattr

const nfs41_upcall_op nfs41_op_getexattr
Initial value:
= {
}
static int handle_getexattr(nfs41_upcall *upcall)
Definition: ea.c:530
static int marshall_getexattr(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
Definition: ea.c:664
static int parse_getexattr(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
Definition: ea.c:210

Definition at line 689 of file ea.c.

◆ nfs41_op_setexattr

const nfs41_upcall_op nfs41_op_setexattr
Initial value:
= {
}
static int parse_setexattr(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
Definition: ea.c:144
static int marshall_setexattr(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
Definition: ea.c:202
static int handle_setexattr(nfs41_upcall *upcall)
Definition: ea.c:162

Definition at line 683 of file ea.c.