/*
- $Id: ea_sys.c,v 1.4 2009-12-04 10:26:10 franklahm Exp $
+ $Id: ea_sys.c,v 1.8 2010-04-13 08:05:06 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#include <atalk/vfs.h>
#include <atalk/util.h>
#include <atalk/unix.h>
+#include <atalk/compat.h>
#ifndef ENOATTR
#define ENOATTR ENODATA
memset(rbuf, 0, 4);
*rbuflen += 4;
switch(errno) {
- case ELOOP:
+ case OPEN_NOFOLLOW_ERRNO:
/* its a symlink and client requested O_NOFOLLOW */
LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname);
return AFP_OK;
memset(rbuf, 0, 4);
*rbuflen += 4;
switch(errno) {
- case ELOOP:
+ case OPEN_NOFOLLOW_ERRNO:
/* its a symlink and client requested O_NOFOLLOW */
LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname);
return AFP_OK;
}
if (ret == -1) switch(errno) {
- case ELOOP:
+ case OPEN_NOFOLLOW_ERRNO:
/* its a symlink and client requested O_NOFOLLOW */
ret = AFPERR_BADTYPE;
default:
if (ret == -1) {
switch(errno) {
- case ELOOP:
+ case OPEN_NOFOLLOW_ERRNO:
/* its a symlink and client requested O_NOFOLLOW */
LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): encountered symlink with kXAttrNoFollow",
uname, attruname);
return AFP_OK;
+ case EEXIST:
+ LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): EA already exists",
+ uname, attruname);
+ return AFPERR_EXIST;
default:
LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
return AFPERR_MISC;
if (ret == -1) {
switch(errno) {
- case ELOOP:
+ case OPEN_NOFOLLOW_ERRNO:
/* its a symlink and client requested O_NOFOLLOW */
LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): encountered symlink with kXAttrNoFollow", uname);
return AFP_OK;
return AFP_OK;
}
-/* ---------------------
- copy EA
-*/
+/*
+ * @brief Copy EAs
+ *
+ * @note Supports *at semantics, therfor switches back and forth between sfd and cwd
+ */
int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
{
int ret = 0;
+ int cwd = -1;
ssize_t size;
char *names = NULL, *end_names, *name, *value = NULL;
unsigned int setxattr_ENOTSUP = 0;
+ if (sfd != -1) {
+ if ((cwd = open(".", O_RDONLY)) == -1) {
+ LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant open cwd: %s",
+ strerror(errno));
+ ret = -1;
+ goto getout;
+ }
+ }
+
+ if (sfd != -1) {
+ if (fchdir(sfd) == -1) {
+ LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s",
+ strerror(errno));
+ ret = -1;
+ goto getout;
+ }
+ }
+
size = sys_listxattr(src, NULL, 0);
if (size < 0) {
if (errno != ENOSYS && errno != ENOTSUP) {
end_names = names + size;
}
+ if (sfd != -1) {
+ if (fchdir(cwd) == -1) {
+ LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s",
+ strerror(errno));
+ ret = -1;
+ goto getout;
+ }
+ }
+
for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
void *old_value;
if (!*name)
continue;
+ if (sfd != -1) {
+ if (fchdir(sfd) == -1) {
+ LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s",
+ strerror(errno));
+ ret = -1;
+ goto getout;
+ }
+ }
+
size = sys_getxattr (src, name, NULL, 0);
if (size < 0) {
ret = -1;
ret = -1;
continue;
}
+
+ if (sfd != -1) {
+ if (fchdir(cwd) == -1) {
+ LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s",
+ strerror(errno));
+ ret = -1;
+ goto getout;
+ }
+ }
+
if (sys_setxattr(dst, name, value, size, 0) != 0) {
if (errno == ENOTSUP)
setxattr_ENOTSUP++;
}
getout:
+ if (cwd != -1)
+ close(cwd);
+
free(value);
free(names);