/*
Bacula® - The Network Backup Solution
- Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
+ Copyright (C) 2004-2009 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
#include "filed.h"
/*
- * List of supported OSs.
+ * List of supported OSes. Everything outside that gets stub functions.
+ * Also when ACL support is explicitly disabled.
* Not sure if all the HAVE_XYZ_OS are correct for autoconf.
* The ones that says man page, are coded according to man pages only.
*/
/*
* Send an ACL stream to the SD.
*/
-static bool send_acl_stream(JCR *jcr, int stream, int len)
+static bool send_acl_stream(JCR *jcr, int stream)
{
BSOCK *sd = jcr->store_bsock;
POOLMEM *msgsave;
Dmsg1(400, "Backing up ACL <%s>\n", jcr->acl_data);
msgsave = sd->msg;
sd->msg = jcr->acl_data;
- sd->msglen = len + 1;
+ sd->msglen = jcr->acl_data_len + 1;
if (!sd->send()) {
sd->msg = msgsave;
sd->msglen = 0;
static bool aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
char *acl_text;
- int len;
if ((acl_text = acl_get(jcr->last_fname)) != NULL) {
- len = pm_strcpy(jcr->acl_data, acl_text);
+ jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
actuallyfree(acl_text);
- return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT, len);
+ return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT);
}
return false;
return ostype;
}
+#if !defined(HAVE_DARWIN_OS)
/*
* See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
* There is no need to store those acls as we already store the stat bits too.
*/
-#if defined(HAVE_DARWIN_OS)
-static bool acl_is_trivial(acl_t acl)
-{
- /*
- * acl is trivial if it is empty.
- */
-// return (acl_entries(acl) == 0);
- return true; /* Allow to compile -- KES */
-}
-#else /* FreeBSD, IRIX, OSF1, Linux */
static bool acl_is_trivial(acl_t acl)
{
/*
}
#endif
+#if !defined(HAVE_DARWIN_OS)
/*
* Make sure this is not just a trivial ACL.
*/
- if ((acltype == BACL_TYPE_ACCESS ||
- acltype == BACL_TYPE_EXTENDED) &&
- acl_is_trivial(acl)) {
+ if (acltype == BACL_TYPE_ACCESS && acl_is_trivial(acl)) {
/*
* The ACLs simply reflect the (already known) standard permissions
* So we don't send an ACL stream to the SD.
acl_free(acl);
return 0;
}
+#endif
if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
len = pm_strcpy(jcr->acl_data, acl_text);
#if defined(HAVE_DARWIN_OS)
static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len;
-
#if defined(ACL_TYPE_EXTENDED)
/*
* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
return false;
#else
/*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
return false;
-#endif
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL))
return false;
}
+#endif
return true;
}
{
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+ case STREAM_ACL_DARWIN_ACCESS_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
}
#elif defined(HAVE_FREEBSD_OS)
static bool freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len;
-
/*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL))
return false;
}
* Directories can have default ACLs too
*/
if (ff_pkt->type == FT_DIREND) {
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL))
return false;
}
}
{
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+ case STREAM_ACL_FREEBSD_ACCESS_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
+ case STREAM_ACL_FREEBSD_DEFAULT_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
}
#elif defined(HAVE_IRIX_OS)
static bool irix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len;
-
/*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL))
return false;
}
* Directories can have default ACLs too
*/
if (ff_pkt->type == FT_DIREND) {
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL))
return false;
}
}
{
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_IRIX_ACCESS_ACL_T:
+ case STREAM_ACL_IRIX_ACCESS_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+ case STREAM_ACL_IRIX_DEFAULT_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
}
#elif defined(HAVE_LINUX_OS)
static bool linux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len;
-
/*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL))
return false;
}
* Directories can have default ACLs too
*/
if (ff_pkt->type == FT_DIREND) {
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL))
return false;
}
}
{
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_LINUX_ACCESS_ACL_T:
+ case STREAM_ACL_LINUX_ACCESS_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_LINUX_DEFAULT_ACL_T:
+ case STREAM_ACL_LINUX_DEFAULT_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
}
#elif defined(HAVE_OSF1_OS)
static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len;
-
/*
* Read access ACLs for files, dirs and links
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL))
return false;
}
* Directories can have default ACLs too
*/
if (ff_pkt->type == FT_DIREND) {
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL))
return false;
}
* See http://www.helsinki.fi/atk/unix/dec_manuals/DOC_40D/AQ0R2DTE/DOCU_018.HTM
* Section 21.5 Default ACLs
*/
- if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
+ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
return false;
- if (len > 0) {
- if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T, len))
+ if (jcr->acl_data_len > 0) {
+ if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL))
return false;
}
}
{
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_TRU64_ACCESS_ACL_T:
+ case STREAM_ACL_TRU64_ACCESS_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_TRU64_DEFAULT_ACL_T:
+ case STREAM_ACL_TRU64_DEFAULT_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
- case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+ case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
}
#endif
*/
static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int n, len;
+ int n;
struct acl_entry acls[NACLENTRIES];
char *acl_text;
}
if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
- len = pm_strcpy(jcr->acl_data, acl_text);
+ jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
actuallyfree(acl_text);
- return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY, len);
+ return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY);
}
berrno be;
*/
static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int len, flags;
+ int acl_enabled, flags;
acl_t *aclp;
char *acl_text;
bool stream_status = false;
+ berrno be;
+
+ /*
+ * See if filesystem supports acls.
+ */
+ acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
+ switch (acl_enabled) {
+ case 0:
+ pm_strcpy(jcr->acl_data, "");
+
+ return true;
+ case -1:
+ Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
+ jcr->last_fname, be.bstrerror());
+ Dmsg2(100, "pathconf error file=%s ERR=%s\n",
+ jcr->last_fname, be.bstrerror());
+
+ return false;
+ default:
+ break;
+ }
/*
* Get ACL info: don't bother allocating space if there is only a trivial ACL.
*/
if (acl_get(jcr->last_fname, ACL_NO_TRIVIAL, &aclp) != 0) {
- switch (errno) {
-#if defined(BACL_ENOTSUP)
- case BACL_ENOTSUP:
- /*
- * Not supported, just pretend there is nothing to see
- */
- pm_strcpy(jcr->acl_data, "");
- return true;
-#endif
- default:
- Jmsg2(jcr, M_ERROR, 0, _("acl_get error on file \"%s\": ERR=%s\n"),
- jcr->last_fname, acl_strerror(errno));
- Dmsg2(100, "acl_get error file=%s ERR=%s\n",
- jcr->last_fname, acl_strerror(errno));
+ Jmsg2(jcr, M_ERROR, 0, _("acl_get error on file \"%s\": ERR=%s\n"),
+ jcr->last_fname, acl_strerror(errno));
+ Dmsg2(100, "acl_get error file=%s ERR=%s\n",
+ jcr->last_fname, acl_strerror(errno));
- return false;
- }
+ return false;
}
- if (aclp == NULL) {
+ if (!aclp) {
/*
* The ACLs simply reflect the (already known) standard permissions
* So we don't send an ACL stream to the SD.
#endif /* ACL_SID_FMT */
if ((acl_text = acl_totext(aclp, flags)) != NULL) {
- len = pm_strcpy(jcr->acl_data, acl_text);
+ jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
actuallyfree(acl_text);
switch (acl_type(aclp)) {
case ACLENT_T:
- stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT_T, len);
+ stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
break;
case ACE_T:
- stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE_T, len);
+ stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE);
break;
default:
break;
static bool solaris_parse_acl_stream(JCR *jcr, int stream)
{
acl_t *aclp;
- int error;
+ int acl_enabled, error;
+ berrno be;
switch (stream) {
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_SOLARIS_ACLENT_T:
- case STREAM_ACL_SOLARIS_ACE_T:
+ case STREAM_ACL_SOLARIS_ACLENT:
+ case STREAM_ACL_SOLARIS_ACE:
+ /*
+ * First make sure the filesystem supports acls.
+ */
+ acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
+ switch (acl_enabled) {
+ case 0:
+ Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"),
+ jcr->last_fname);
+
+ return false;
+ case -1:
+ Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
+ jcr->last_fname, be.bstrerror());
+ Dmsg3(100, "pathconf error acl=%s file=%s ERR=%s\n",
+ jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+ return false;
+ default:
+ /*
+ * On a filesystem with ACL support make sure this particilar ACL type can be restored.
+ */
+ switch (stream) {
+ case STREAM_ACL_SOLARIS_ACLENT:
+ /*
+ * An aclent can be restored on filesystems with _ACL_ACLENT_ENABLED or _ACL_ACE_ENABLED support.
+ */
+ if ((acl_enabled & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED)) == 0) {
+ Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without aclent acl support\n"),
+ jcr->last_fname);
+ return false;
+ }
+ break;
+ case STREAM_ACL_SOLARIS_ACE:
+ /*
+ * An ace can only be restored on a filesystem with _ACL_ACE_ENABLED support.
+ */
+ if ((acl_enabled & _ACL_ACE_ENABLED) == 0) {
+ Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"),
+ jcr->last_fname);
+ return false;
+ }
+ break;
+ default:
+ /*
+ * Stream id which doesn't describe the type of acl which is encoded.
+ */
+ break;
+ }
+ break;
+ }
+
if ((error = acl_fromtext(jcr->acl_data, &aclp)) != 0) {
Jmsg2(jcr, M_ERROR, 0, _("acl_fromtext error on file \"%s\": ERR=%s\n"),
jcr->last_fname, acl_strerror(error));
* Validate that the conversion gave us the correct acl type.
*/
switch (stream) {
- case STREAM_ACL_SOLARIS_ACLENT_T:
+ case STREAM_ACL_SOLARIS_ACLENT:
if (acl_type(aclp) != ACLENT_T) {
Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
jcr->last_fname);
return false;
}
- case STREAM_ACL_SOLARIS_ACE_T:
+ break;
+ case STREAM_ACL_SOLARIS_ACE:
if (acl_type(aclp) != ACE_T) {
Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
jcr->last_fname);
return false;
}
+ break;
default:
/*
* Stream id which doesn't describe the type of acl which is encoded.
*/
static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
{
- int n, len;
+ int n;
aclent_t *acls;
char *acl_text;
n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
- if (n < MIN_ACL_ENTRIES) {
+ if (n < MIN_ACL_ENTRIES)
return false;
acls = (aclent_t *)malloc(n * sizeof(aclent_t));
}
if ((acl_text = acltotext(acls, n)) != NULL) {
- len = pm_strcpy(jcr->acl_data, acl_text);
+ jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
actuallyfree(acl_text);
free(acls);
- return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT_T, len);
+ return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
}
berrno be;
return aix_parse_acl_stream(jcr, stream);
#elif defined(HAVE_DARWIN_OS)
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+ case STREAM_ACL_DARWIN_ACCESS_ACL:
return darwin_parse_acl_stream(jcr, stream);
#elif defined(HAVE_FREEBSD_OS)
case STREAM_UNIX_ACCESS_ACL:
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
- case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+ case STREAM_ACL_FREEBSD_DEFAULT_ACL:
+ case STREAM_ACL_FREEBSD_ACCESS_ACL:
return freebsd_parse_acl_stream(jcr, stream);
#elif defined(HAVE_HPUX_OS)
case STREAM_UNIX_ACCESS_ACL:
#elif defined(HAVE_IRIX_OS)
case STREAM_UNIX_ACCESS_ACL:
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_IRIX_DEFAULT_ACL_T:
- case STREAM_ACL_IRIX_ACCESS_ACL_T:
+ case STREAM_ACL_IRIX_DEFAULT_ACL:
+ case STREAM_ACL_IRIX_ACCESS_ACL:
return irix_parse_acl_stream(jcr, stream);
#elif defined(HAVE_LINUX_OS)
case STREAM_UNIX_ACCESS_ACL:
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_LINUX_DEFAULT_ACL_T:
- case STREAM_ACL_LINUX_ACCESS_ACL_T:
+ case STREAM_ACL_LINUX_DEFAULT_ACL:
+ case STREAM_ACL_LINUX_ACCESS_ACL:
return linux_parse_acl_stream(jcr, stream);
#elif defined(HAVE_OSF1_OS)
case STREAM_UNIX_ACCESS_ACL:
case STREAM_UNIX_DEFAULT_ACL:
- case STREAM_ACL_TRU64_DEFAULT_ACL_T:
- case STREAM_ACL_TRU64_ACCESS_ACL_T:
- case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+ case STREAM_ACL_TRU64_DEFAULT_ACL:
+ case STREAM_ACL_TRU64_ACCESS_ACL:
+ case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
return tru64_parse_acl_stream(jcr, stream);
#elif defined(HAVE_SUN_OS)
case STREAM_UNIX_ACCESS_ACL:
- case STREAM_ACL_SOLARIS_ACLENT_T:
+ case STREAM_ACL_SOLARIS_ACLENT:
#if defined(HAVE_EXTENDED_ACL)
- case STREAM_ACL_SOLARIS_ACE_T:
+ case STREAM_ACL_SOLARIS_ACE:
#endif
return solaris_parse_acl_stream(jcr, stream);
#endif