X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Fvfs%2Fea_sys.c;h=5b210d81de9042d9227bbd793d7dce0de9e07eb1;hb=6d60f95c388da5f8f901d67e0018cf4896e6c6dc;hp=7c7f8e312d1372af73994e883f32c393a51286b5;hpb=585951627c4065a11506ed33b0d900440c4067bf;p=netatalk.git diff --git a/libatalk/vfs/ea_sys.c b/libatalk/vfs/ea_sys.c index 7c7f8e31..5b210d81 100644 --- a/libatalk/vfs/ea_sys.c +++ b/libatalk/vfs/ea_sys.c @@ -1,5 +1,4 @@ /* - $Id: ea_sys.c,v 1.3 2009-11-20 16:26:23 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -26,20 +25,7 @@ #include #include #include - -#if HAVE_ATTR_XATTR_H -#include -#elif HAVE_SYS_XATTR_H -#include -#endif - -#ifdef HAVE_SYS_EA_H -#include -#endif - -#ifdef HAVE_SYS_EXTATTR_H -#include -#endif +#include #include #include @@ -49,7 +35,7 @@ #include #include #include - +#include /********************************************************************************** * EA VFS funcs for storing EAs in nativa filesystem EAs @@ -90,15 +76,17 @@ int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) } if (ret == -1) { + 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; + case ENOATTR: + return AFPERR_MISC; - return AFP_OK; default: LOG(log_error, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno)); return AFPERR_MISC; @@ -162,18 +150,22 @@ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) ret = sys_getxattr(uname, attruname, rbuf +4, maxreply); } - if (ret == -1) switch(errno) { - case ELOOP: - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname); - + if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; + switch(errno) { + 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; - return AFP_OK; - default: - LOG(log_error, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); - return AFPERR_MISC; + case ENOATTR: + return AFPERR_MISC; + + default: + LOG(log_error, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); + return AFPERR_MISC; + } } /* remember where we must store length of attribute data in rbuf */ @@ -204,6 +196,8 @@ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) * * Copies names of all EAs of uname as consecutive C strings into rbuf. * Increments *rbuflen accordingly. + * We hide the adouble:ea extended attributes here, but we currently + * allow reading, writing and deleteting them. */ int sys_list_eas(VFS_FUNC_ARGS_EA_LIST) { @@ -224,37 +218,45 @@ int sys_list_eas(VFS_FUNC_ARGS_EA_LIST) } if (ret == -1) switch(errno) { - case ELOOP: + case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ ret = AFPERR_BADTYPE; + goto exit; +#ifdef HAVE_ATTROPEN /* Solaris */ + case ENOATTR: + ret = AFP_OK; + goto exit; +#endif default: LOG(log_error, logtype_afpd, "sys_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno)); ret= AFPERR_MISC; + goto exit; } ptr = buf; while (ret > 0) { len = strlen(ptr); - - /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ - if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) { - ret = AFPERR_MISC; - goto exit; - } - - LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr); - - attrbuflen += nlen + 1; - if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { - /* Next EA name could overflow, so bail out with error. - FIXME: evantually malloc/memcpy/realloc whatever. - Is it worth it ? */ - LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname); - ret = AFPERR_MISC; - goto exit; + if (NOT_NETATALK_EA(ptr)) { + /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ + if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) { + ret = AFPERR_MISC; + goto exit; + } + + LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr); + + attrbuflen += nlen + 1; + if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { + /* Next EA name could overflow, so bail out with error. + FIXME: evantually malloc/memcpy/realloc whatever. + Is it worth it ? */ + LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname); + ret = AFPERR_MISC; + goto exit; + } } - ret -= len +1; - ptr += len +1; + ret -= len + 1; + ptr += len + 1; } ret = AFP_OK; @@ -305,13 +307,22 @@ int sys_set_ea(VFS_FUNC_ARGS_EA_SET) 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); + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): encountered symlink with kXAttrNoFollow", + getcwdpath(), uname, attruname); return AFP_OK; + case EEXIST: + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists", + getcwdpath(), uname, attruname); + return AFPERR_EXIST; default: - LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno)); + LOG(log_error, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s", + getcwdpath(), uname, attruname, attrsize, + oflag & O_CREAT ? "XATTR_CREATE" : "-", + oflag & O_TRUNC ? "XATTR_REPLACE" : "-", + oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-", + strerror(errno)); return AFPERR_MISC; } } @@ -350,7 +361,7 @@ int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE) 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; @@ -366,16 +377,37 @@ int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE) 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) { @@ -397,6 +429,15 @@ int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE) 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; @@ -404,6 +445,15 @@ int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE) 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; @@ -419,6 +469,16 @@ int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE) 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++; @@ -439,6 +499,9 @@ int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE) } getout: + if (cwd != -1) + close(cwd); + free(value); free(names);