Code falling under the above conditions will be marked as follows:
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
for (k=0; k<fo->regex.size(); k++) {
sendit(sock, " R %s\n", fo->regex.get(k));
}
+ for (k=0; k<fo->regexdir.size(); k++) {
+ sendit(sock, " RD %s\n", fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ sendit(sock, " RF %s\n", fo->regexfile.get(k));
+ }
for (k=0; k<fo->wild.size(); k++) {
sendit(sock, " W %s\n", fo->wild.get(k));
}
+ for (k=0; k<fo->wilddir.size(); k++) {
+ sendit(sock, " WD %s\n", fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ sendit(sock, " WF %s\n", fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
sendit(sock, " B %s\n", fo->base.get(k));
}
for (int i=0; i<incexe->num_opts; i++) {
FOPTS *fopt = incexe->opts_list[i];
fopt->regex.destroy();
+ fopt->regexdir.destroy();
+ fopt->regexfile.destroy();
fopt->wild.destroy();
+ fopt->wilddir.destroy();
+ fopt->wildfile.destroy();
fopt->base.destroy();
fopt->fstype.destroy();
if (fopt->reader) {
struct FOPTS {
char opts[MAX_FOPTS]; /* options string */
alist regex; /* regex string(s) */
+ alist regexdir; /* regex string(s) for directories */
+ alist regexfile; /* regex string(s) for files */
alist wild; /* wild card strings */
+ alist wilddir; /* wild card strings for directories */
+ alist wildfile; /* wild card strings for files */
alist base; /* list of base names */
alist fstype; /* file system type limitation */
char *reader; /* reader program */
for (k=0; k<fo->regex.size(); k++) {
bnet_fsend(fd, "R %s\n", fo->regex.get(k));
}
+ for (k=0; k<fo->regexdir.size(); k++) {
+ bnet_fsend(fd, "RD %s\n", fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ bnet_fsend(fd, "RF %s\n", fo->regexfile.get(k));
+ }
for (k=0; k<fo->wild.size(); k++) {
bnet_fsend(fd, "W %s\n", fo->wild.get(k));
}
+ for (k=0; k<fo->wilddir.size(); k++) {
+ bnet_fsend(fd, "WD %s\n", fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
bnet_fsend(fd, "B %s\n", fo->base.get(k));
}
{"mtimeonly", store_opts, NULL, 0, 0, 0},
{"keepatime", store_opts, NULL, 0, 0, 0},
{"regex", store_regex, NULL, 0, 0, 0},
+ {"regexdir", store_regex, NULL, 1, 0, 0},
+ {"regexfile", store_regex, NULL, 2, 0, 0},
{"base", store_base, NULL, 0, 0, 0},
{"wild", store_wild, NULL, 0, 0, 0},
+ {"wilddir", store_wild, NULL, 1, 0, 0},
+ {"wildfile", store_wild, NULL, 2, 0, 0},
{"exclude", store_opts, NULL, 0, 0, 0},
{"aclsupport", store_opts, NULL, 0, 0, 0},
{"reader", store_reader, NULL, 0, 0, 0},
int token, rc;
regex_t preg;
char prbuf[500];
+ char *type;
+ int newsize;
token = lex_get_token(lc, T_SKIP_EOL);
if (pass == 1) {
break;
}
regfree(&preg);
- res_incexe.current_opts->regex.append(bstrdup(lc->str));
- Dmsg3(900, "set regex %p size=%d %s\n",
- res_incexe.current_opts, res_incexe.current_opts->regex.size(),lc->str);
+ if (item->code == 1) {
+ type = "regexdir";
+ res_incexe.current_opts->regexdir.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->regexdir.size();
+ } else if (item->code == 2) {
+ type = "regexfile";
+ res_incexe.current_opts->regexfile.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->regexfile.size();
+ } else {
+ type = "regex";
+ res_incexe.current_opts->regex.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->regex.size();
+ }
+ Dmsg4(900, "set %s %p size=%d %s\n",
+ type, res_incexe.current_opts, newsize, lc->str);
break;
default:
scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str);
static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
+ char *type;
+ int newsize;
token = lex_get_token(lc, T_SKIP_EOL);
if (pass == 1) {
case T_IDENTIFIER:
case T_UNQUOTED_STRING:
case T_QUOTED_STRING:
- res_incexe.current_opts->wild.append(bstrdup(lc->str));
- Dmsg3(900, "set wild %p size=%d %s\n",
- res_incexe.current_opts, res_incexe.current_opts->wild.size(),lc->str);
+ if (item->code == 1) {
+ type = "wilddir";
+ res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->wilddir.size();
+ } else if (item->code == 2) {
+ type = "wildfile";
+ res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->wildfile.size();
+ } else {
+ type = "wild";
+ res_incexe.current_opts->wild.append(bstrdup(lc->str));
+ newsize = res_incexe.current_opts->wild.size();
+ }
+ Dmsg4(9, "set %s %p size=%d %s\n",
+ type, res_incexe.current_opts, newsize, lc->str);
break;
default:
scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str);
FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
memset(fo, 0, sizeof(FOPTS));
fo->regex.init(1, true);
+ fo->regexdir.init(1, true);
+ fo->regexfile.init(1, true);
fo->wild.init(1, true);
+ fo->wilddir.init(1, true);
+ fo->wildfile.init(1, true);
fo->base.init(1, true);
fo->fstype.init(1, true);
res_incexe.current_opts = fo;
dummy:
#
-SVRSRCS = filed.c authenticate.c backup.c chksum.c estimate.c \
+SVRSRCS = filed.c authenticate.c acl.c backup.c chksum.c estimate.c \
filed_conf.c heartbeat.c job.c \
restore.c status.c verify.c verify_vol.c
-SVROBJS = filed.o authenticate.o backup.o chksum.o estimate.o \
+SVROBJS = filed.o authenticate.o acl.o backup.o chksum.o estimate.o \
filed_conf.o heartbeat.o job.o \
restore.o status.o verify.o verify_vol.o
--- /dev/null
+/*
+ * Functions to handle ACL for bacula.
+ *
+ * We handle two different typers of ACLs: access and default ACLS.
+ * Default ACLs only apply to directories.
+ *
+ * On some systems (eg. linux and FreeBSD) we must obtain the two ACLs
+ * independently, while others (eg. Solaris) provide both in one call.
+ *
+ * As for the streams to use, we have two choices:
+ *
+ * 1. Build a generic framework.
+ * With two different types of ACLs, supported differently, we
+ * probably end up encoding and decoding everything ourselves.
+ *
+ * 2. Take the easy way out.
+ * Just handle each platform individually, assuming that backups
+ * and restores are done on the same (kind of) client.
+ *
+ * Currently we take the easy way out. We use two kinds of streams, one
+ * for access ACLs and one for default ACLs. If an OS mixes the two, we
+ * send the mix in the access ACL stream.
+ *
+ * Looking at more man pages, supporting a framework seems really hard
+ * if we want to support HP-UX. Deity knows what AIX is up to.
+ *
+ * Written by Preben 'Peppe' Guldberg, December MMIV
+ *
+ * Version $Id$
+ */
+
+#ifdef xxxxxxx
+
+Remove fprintf's and actuallyfree and fix POOLMEM coding
+
+Pass errmsg buffer and a length or a POOLMEM buffer
+into subroutine rather than malloc in
+subroutine and free() in higher level routine, which causes
+memory leaks if you forget to free.
+
+#ifndef TEST_PROGRAM
+#include "bacula.h"
+#include "filed.h"
+#else
+/*
+ * Compile and set up with eg. with eg.
+ *
+ * $ cc -DTEST_PROGRAM -DHAVE_SUN_OS -lsec -o acl acl.c
+ * $ ln -s acl aclcp
+ *
+ * You can then list ACLs with acl and copy them with aclcp.
+ *
+ * For a list of compiler flags, see the list preceding the big #if below.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "acl.h"
+#define POOLMEM char
+#define bstrdup strdup
+#define actuallyfree(x) free(x)
+int aclls(char *fname);
+int aclcp(char *src, char *dst);
+#endif
+
+/*
+ * List of supported OSs.
+ * 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.
+ */
+#if !defined(HAVE_ACL) /* ACL support is required, of course */ \
+ || !( defined(HAVE_AIX_OS) /* man page -- may need flags */ \
+ || defined(HAVE_FREEBSD_OS) /* tested -- compile wihtout flags */ \
+ || defined(HAVE_IRIX_OS) /* man page -- compile without flags */ \
+ || defined(HAVE_OSF1_OS) /* man page -- may need -lpacl */ \
+ || defined(HAVE_LINUX_OS) /* tested -- compile with -lacl */ \
+ || defined(HAVE_HPUX_OS) /* man page -- may need flags */ \
+ || defined(HAVE_SUN_OS) /* tested -- compile with -lsec */ \
+ )
+POOLMEM *bacl_get(char *fname, int acltype)
+{
+ return NULL;
+}
+
+int bacl_set(char *fname, int acltype, char *acltext)
+{
+ return -1;
+}
+#elif defined(HAVE_AIX_OS)
+#include <sys/access.h>
+
+POOLMEM *bacl_get(char *fname, int acltype)
+{
+ char *tmp;
+ POOLMEM *acltext = NULL;
+
+ if ((tmp = acl_get(fname)) != NULL) {
+ acltext = bstrdup(tmp);
+ actuallyfree(tmp);
+ }
+ return acltext;
+}
+
+int bacl_set(char *fname, int acltype, char *acltext)
+{
+ if (acl_put(fname, acltext, 0) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+#elif defined(HAVE_FREEBSD_OS) \
+ || defined(HAVE_IRIX_OS) \
+ || defined(HAVE_OSF1_OS) \
+ || defined(HAVE_LINUX_OS)
+#include <sys/types.h>
+#include <sys/acl.h>
+
+/* On IRIX we can get shortened ACLs */
+#if defined(HAVE_IRIX_OS) && defined(BACL_WANT_SHORT_ACLS)
+#define acl_to_text(acl,len) acl_to_short_text((acl), (len))
+#endif
+
+/* In Linux we can get numeric and/or shorted ACLs */
+#if defined(HAVE_LINUX_OS)
+#if defined(BACL_WANT_SHORT_ACLS) && defined(BACL_WANT_NUMERIC_IDS)
+#define BACL_ALTERNATE_TEXT (TEXT_ABBREVIATE|TEXT_NUMERIC_IDS)
+#elif defined(BACL_WANT_SHORT_ACLS)
+#define BACL_ALTERNATE_TEXT TEXT_ABBREVIATE
+#elif defined(BACL_WANT_NUMERIC_IDS)
+#define BACL_ALTERNATE_TEXT TEXT_NUMERIC_IDS
+#endif
+#ifdef BACL_ALTERNATE_TEXT
+#include <acl/libacl.h>
+#define acl_to_text(acl,len) ((len), acl_to_any_text((acl), NULL, ',', BACL_ALTERNATE_TEXT))
+#endif
+#endif
+
+POOLMEM *bacl_get(char *fname, int acltype)
+{
+ acl_t acl;
+ int ostype;
+ char *tmp;
+ POOLMEM *acltext = NULL;
+
+ ostype = (acltype & BACL_TYPE_DEFAULT) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS;
+
+ acl = acl_get_file(fname, ostype);
+ if (acl) {
+ if ((tmp = acl_to_text(acl, NULL)) != NULL) {
+ acltext = bstrdup(tmp);
+ acl_free(tmp);
+ }
+ acl_free(acl);
+ }
+ return acltext;
+}
+
+int bacl_set(char *fname, int acltype, char *acltext)
+{
+ acl_t acl;
+ int ostype, stat;
+
+ ostype = (acltype & BACL_TYPE_DEFAULT) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS;
+
+ acl = acl_from_text(acltext);
+ if (acl == NULL) {
+ return -1;
+ }
+
+ /*
+ * FreeBSD always fails acl_valid() - at least on valid input...
+ * As it does the right thing, given valid input, just ignore acl_valid().
+ */
+#ifndef HAVE_FREEBSD_OS
+ if (acl_valid(acl) != 0) {
+ acl_free(acl);
+ return -1;
+ }
+#endif
+
+ stat = acl_set_file(fname, ostype, acl);
+ acl_free(acl);
+ return stat;
+}
+
+#elif defined(HAVE_HPUX_OS)
+#include <sys/acl.h>
+#include <acllib.h>
+
+POOLMEM *bacl_get(char *fname, int acltype)
+{
+ int n;
+ struct acl_entry acls[NACLENTRIES];
+ char *tmp;
+ POOLMEM *acltext = NULL;
+
+ if ((n = getacl(fname, 0, acls)) <= 0) {
+ return NULL;
+ }
+ if ((n = getacl(fname, n, acls)) > 0) {
+ if ((tmp = acltostr(n, acls, FORM_SHORT)) != NULL) {
+ acltext = bstrdup(tmp);
+ actuallyfree(tmp);
+ }
+ }
+ return acltext;
+}
+
+int bacl_set(char *fname, int acltype, char *acltext)
+{
+ int n, stat;
+ struct acl_entry acls[NACLENTRIES];
+
+ n = strtoacl(acltext, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
+ if (n <= 0) {
+ return -1;
+ }
+ if (strtoacl(acltext, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
+ return -1;
+ }
+ if (setacl(fname, n, acls) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+#elif defined(HAVE_SUN_OS)
+#include <sys/acl.h>
+
+POOLMEM *bacl_get(char *fname, int acltype)
+{
+ int n;
+ aclent_t *acls;
+ char *tmp;
+ POOLMEM *acltext = NULL;
+
+ n = acl(fname, GETACLCNT, 0, NULL);
+ if (n <= 0) {
+ return NULL;
+ }
+ if ((acls = (aclent_t *)malloc(n * sizeof(aclent_t))) == NULL) {
+ return NULL;
+ }
+ if (acl(fname, GETACL, n, acls) == n) {
+ if ((tmp = acltotext(acls, n)) != NULL) {
+ acltext = bstrdup(tmp);
+ actuallyfree(tmp);
+ }
+ }
+ actuallyfree(acls);
+ return acltext;
+}
+
+int bacl_set(char *fname, int acltype, char *acltext)
+{
+ int n, stat;
+ aclent_t *acls;
+
+ acls = aclfromtext(acltext, &n);
+ if (!acls) {
+ return -1;
+ }
+ stat = acl(fname, SETACL, n, acls);
+ actuallyfree(acls);
+ return stat;
+}
+
+#endif
+
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+ char *prgname;
+ int status = 0;
+
+ if (argc < 1) {
+ fprintf(stderr, "Cannot determine my own name\n");
+ return EXIT_FAILURE;
+ }
+
+ prgname = strrchr(argv[0], '/');
+ if (prgname == NULL || *++prgname == '\0') {
+ prgname = argv[0];
+ }
+ --argc;
+ ++argv;
+
+ /* aclcp "copies" ACLs - set ACLs on destination equal to ACLs on source */
+ if (strcmp(prgname, "aclcp") == 0) {
+ int verbose = 0;
+ if (strcmp(*argv, "-v") == 0) {
+ ++verbose;
+ --argc;
+ ++argv;
+ }
+ if (argc != 2) {
+ fprintf(stderr, "%s: wrong number of arguments\n"
+ "usage:\t%s [-v] source destination\n"
+ "\tCopies ACLs from source to destination.\n"
+ "\tSpecify -v to show ACLs after copy for verification.\n",
+ prgname, prgname);
+ return EXIT_FAILURE;
+ }
+ if (strcmp(argv[0], argv[1]) == 0) {
+ fprintf(stderr, "%s: identical source and destination.\n"
+ "usage:\t%s [-v] source destination\n"
+ "\tCopies ACLs from source to destination.\n"
+ "\tSpecify -v to show ACLs after copy for verification.\n",
+ prgname, prgname);
+ return EXIT_FAILURE;
+ }
+ if (verbose) {
+ aclls(argv[0]);
+ }
+ status = aclcp(argv[0], argv[1]);
+ if (verbose && status == 0) {
+ aclls(argv[1]);
+ }
+ return status;
+ }
+
+ /* Default: just list ACLs */
+ if (argc < 1) {
+ fprintf(stderr, "%s: missing arguments\n"
+ "usage:\t%s file ...\n"
+ "\tLists ACLs of specified files or directories.\n",
+ prgname, prgname);
+ return EXIT_FAILURE;
+ }
+ while (argc--) {
+ if (!aclls(*argv++)) {
+ status = EXIT_FAILURE;
+ }
+ }
+
+ return status;
+}
+
+int aclcp(char *src, char *dst)
+{
+ struct stat st;
+ POOLMEM *acltext;
+
+ if (lstat(dst, &st) != 0) {
+ fprintf(stderr, "aclcp: destination does not exist\n");
+ return EXIT_FAILURE;
+ }
+ if (S_ISLNK(st.st_mode)) {
+ fprintf(stderr, "aclcp: cannot set ACL on symlinks\n");
+ return EXIT_FAILURE;
+ }
+ if (lstat(src, &st) != 0) {
+ fprintf(stderr, "aclcp: source does not exist\n");
+ return EXIT_FAILURE;
+ }
+ if (S_ISLNK(st.st_mode)) {
+ fprintf(stderr, "aclcp: will not read ACL from symlinks\n");
+ return EXIT_FAILURE;
+ }
+
+ acltext = bacl_get(src, BACL_TYPE_ACCESS);
+ if (!acltext) {
+ fprintf(stderr, "aclcp: could not read ACLs for %s\n", src);
+ return EXIT_FAILURE;
+ } else {
+ if (bacl_set(dst, BACL_TYPE_ACCESS, acltext) != 0) {
+ fprintf(stderr, "aclcp: could not set ACLs on %s\n", dst);
+ actuallyfree(acltext);
+ return EXIT_FAILURE;
+ }
+ actuallyfree(acltext);
+ }
+
+ if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
+ acltext = bacl_get(src, BACL_TYPE_DEFAULT);
+ if (acltext) {
+ if (bacl_set(dst, BACL_TYPE_DEFAULT, acltext) != 0) {
+ fprintf(stderr, "aclcp: could not set default ACLs on %s\n", dst);
+ actuallyfree(acltext);
+ return EXIT_FAILURE;
+ }
+ actuallyfree(acltext);
+ }
+ }
+
+ return 0;
+}
+
+int aclls(char *fname)
+{
+ struct stat st;
+ POOLMEM *acltext;
+
+ if (lstat(fname, &st) != 0) {
+ fprintf(stderr, "acl: source does not exist\n");
+ return EXIT_FAILURE;
+ }
+ if (S_ISLNK(st.st_mode)) {
+ fprintf(stderr, "acl: will not read ACL from symlinks\n");
+ return EXIT_FAILURE;
+ }
+
+ acltext = bacl_get(fname, BACL_TYPE_ACCESS);
+ if (!acltext) {
+ fprintf(stderr, "acl: could not read ACLs for %s\n", fname);
+ return EXIT_FAILURE;
+ }
+ printf("#file: %s\n%s\n", fname, acltext);
+ actuallyfree(acltext);
+
+ if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
+ acltext = bacl_get(fname, BACL_TYPE_DEFAULT);
+ if (!acltext) {
+ fprintf(stderr, "acl: could not read default ACLs for %s\n", fname);
+ return EXIT_FAILURE;
+ }
+ printf("#file: %s [default]\n%s\n", fname, acltext);
+ actuallyfree(acltext);
+ }
+
+ return 0;
+}
+#endif
+#endif
--- /dev/null
+/*
+ * Properties we use for getting and setting ACLs.
+ */
+
+#ifndef _BACULA_ACL_
+#define _BACULA_ACL_
+
+/* If you want shorter ACL strings when possible, uncomment this */
+#define BACL_WANT_SHORT_ACLS
+
+/* If you want numeric user/group ids when possible, uncomment this */
+/* #define BACL_WANT_NUMERIC_IDS */
+
+/* We support the following types of ACLs */
+#define BACL_TYPE_NONE 0x000
+#define BACL_TYPE_ACCESS 0x001
+#define BACL_TYPE_DEFAULT 0x002
+
+#define BACL_CAP_NONE 0x000 /* No special capabilities */
+#define BACL_CAP_DEFAULTS 0x001 /* Has default ACLs for directories */
+#define BACL_CAP_DEFAULTS_DIR 0x002 /* Default ACLs must be read separately */
+
+/* Set capabilities for various OS */
+#if defined(HAVE_SUN_OS)
+#define BACL_CAP BACL_CAP_DEFAULTS
+#elif defined(HAVE_FREEBSD_OS) \
+ || defined(HAVE_IRIX_OS) \
+ || defined(HAVE_OSF1_OS) \
+ || defined(HAVE_LINUX_OS)
+#define BACL_CAP (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
+#else
+#define BACL_CAP BACL_CAP_NONE
+#endif
+
+#endif
+/*
+ * Properties we use for getting and setting ACLs.
+ */
+
+#ifndef _BACULA_ACL_
+#define _BACULA_ACL_
+
+/* If you want shorter ACL strings when possible, uncomment this */
+#define BACL_WANT_SHORT_ACLS
+
+/* If you want numeric user/group ids when possible, uncomment this */
+/* #define BACL_WANT_NUMERIC_IDS */
+
+/* We support the following types of ACLs */
+#define BACL_TYPE_NONE 0x000
+#define BACL_TYPE_ACCESS 0x001
+#define BACL_TYPE_DEFAULT 0x002
+
+#define BACL_CAP_NONE 0x000 /* No special capabilities */
+#define BACL_CAP_DEFAULTS 0x001 /* Has default ACLs for directories */
+#define BACL_CAP_DEFAULTS_DIR 0x002 /* Default ACLs must be read separately */
+
+/* Set capabilities for various OS */
+#if defined(HAVE_SUN_OS)
+#define BACL_CAP BACL_CAP_DEFAULTS
+#elif defined(HAVE_FREEBSD_OS) \
+ || defined(HAVE_IRIX_OS) \
+ || defined(HAVE_OSF1_OS) \
+ || defined(HAVE_LINUX_OS)
+#define BACL_CAP (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
+#else
+#define BACL_CAP BACL_CAP_NONE
+#endif
+
+#endif
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
static void usage()
{
- fprintf(stderr, _(
-"Copyright (C) 2000-2004 Kern Sibbald and John Walker\n"
+ Pmsg0(-1, _(
+"Copyright (C) 2000-2005 Kern Sibbald\n"
"\nVersion: " VERSION " (" BDATE ")\n\n"
"Usage: bacula-fd [-f -s] [-c config_file] [-d debug_level]\n"
" -c <file> use <file> as configuration file\n"
me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
UnlockRes();
if (!me->messages) {
- Emsg1(M_ABORT, 0, _("No Messages resource defined in %s\n"), configfile);
+ Emsg1(M_ABORT, 0, _("No Messages resource defined in %s\n"), configfile);
}
}
close_msg(NULL); /* close temp message handler */
/* Become server, and handle requests */
IPADDR *p;
foreach_dlist(p, me->FDaddrs) {
- Dmsg1(10, "filed: listening on port %d\n", p->get_port_host_order());
+ Dmsg1(10, "filed: listening on port %d\n", p->get_port_host_order());
}
bnet_thread_server(me->FDaddrs, me->MaxConcurrentJobs, &dir_workq, handle_client_request);
}
#include "chksum.h"
#include "findlib/find.h"
#include "jcr.h"
+#include "acl.h"
#include "protos.h" /* file daemon prototypes */
#ifdef HAVE_LIBZ
#include <zlib.h> /* compression headers */
regfree((regex_t *)fo->regex.get(k));
}
fo->regex.destroy();
+ fo->regexdir.destroy();
+ fo->regexfile.destroy();
fo->wild.destroy();
+ fo->wilddir.destroy();
+ fo->wildfile.destroy();
fo->base.destroy();
fo->fstype.destroy();
if (fo->reader) {
for (j=0; j<incexe->opts_list.size(); j++) {
findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
fo->regex.destroy();
+ fo->regexdir.destroy();
+ fo->regexfile.destroy();
fo->wild.destroy();
+ fo->wilddir.destroy();
+ fo->wildfile.destroy();
fo->base.destroy();
fo->fstype.destroy();
}
findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
memset(fo, 0, sizeof(findFOPTS));
fo->regex.init(1, true);
+ fo->regexdir.init(1, true);
+ fo->regexfile.init(1, true);
fo->wild.init(1, true);
+ fo->wilddir.init(1, true);
+ fo->wildfile.init(1, true);
fo->base.init(1, true);
fo->fstype.init(1, true);
incexe->current_opts = fo;
int state = fileset->state;
findFOPTS *current_opts;
+ /* Get code, optional subcode, and position item past the dividing space */
Dmsg1(100, "%s\n", item);
int code = item[0];
- if (item[1] == ' ') { /* If string follows */
- item += 2; /* point to string */
+ if (code != '\0') {
+ ++item;
+ }
+ int subcode = ' '; /* A space is always a valid subcode */
+ if (item[0] != '\0' && item[0] != ' ') {
+ subcode = item[0];
+ ++item;
+ }
+ if (*item == ' ') {
+ ++item;
}
+ /* Skip all lines we receive after an error */
if (state == state_error) {
return;
}
+
+ /*
+ * The switch tests the code for validity.
+ * The subcode is always good if it is a space, otherwise we must confirm.
+ * We set state to state_error first assuming the subcode is invalid,
+ * requiring state to be set in cases below that handle subcodes.
+ */
+ if (subcode != ' ') {
+ state = state_error;
+ }
switch (code) {
case 'I':
/* New include */
state = state_error;
break;
}
- current_opts->regex.append(preg);
state = state_options;
+ if (subcode == ' ') {
+ current_opts->regex.append(preg);
+ } else if (subcode == 'D') {
+ current_opts->regexdir.append(preg);
+ } else if (subcode == 'F') {
+ current_opts->regexfile.append(preg);
+ } else {
+ state = state_error;
+ }
break;
case 'B':
current_opts = start_options(ff);
break;
case 'W':
current_opts = start_options(ff);
- current_opts->wild.append(bstrdup(item));
state = state_options;
+ if (subcode == ' ') {
+ current_opts->wild.append(bstrdup(item));
+ } else if (subcode == 'D') {
+ current_opts->wilddir.append(bstrdup(item));
+ } else if (subcode == 'F') {
+ current_opts->wildfile.append(bstrdup(item));
+ } else {
+ state = state_error;
+ }
break;
case 'O':
current_opts = start_options(ff);
for (k=0; k<fo->regex.size(); k++) {
Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
}
- for (k=0; k<fo->wild.size(); k++) {
- Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
- }
+ for (k=0; k<fo->regexdir.size(); k++) {
+ Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
+ }
+ for (k=0; k<fo->wild.size(); k++) {
+ Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
+ }
+ for (k=0; k<fo->wilddir.size(); k++) {
+ Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
}
for (k=0; k<fo->regex.size(); k++) {
Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
}
- for (k=0; k<fo->wild.size(); k++) {
- Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
- }
+ for (k=0; k<fo->regexdir.size(); k++) {
+ Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
+ }
+ for (k=0; k<fo->wild.size(); k++) {
+ Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
+ }
+ for (k=0; k<fo->wilddir.size(); k++) {
+ Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
}
void stop_heartbeat_monitor(JCR *jcr);
void start_dir_heartbeat(JCR *jcr);
void stop_dir_heartbeat(JCR *jcr);
+
+/* From acl.c */
+POOLMEM *bacl_get(char *fname, int acltype);
+int bacl_set(char *fname, int acltype, char *acltext);
ff->writer = fo->writer;
ff->fstypes = fo->fstype;
ic = (ff->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
+ if (S_ISDIR(ff->statp.st_mode)) {
+ for (k=0; k<fo->wilddir.size(); k++) {
+ if (fnmatch((char *)fo->wilddir.get(k), ff->fname, fnmode|ic) == 0) {
+ if (ff->flags & FO_EXCLUDE) {
+ Dmsg2(100, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k),
+ ff->fname);
+ return false; /* reject file */
+ }
+ return true; /* accept file */
+ }
+ }
+ } else {
+ for (k=0; k<fo->wildfile.size(); k++) {
+ if (fnmatch((char *)fo->wildfile.get(k), ff->fname, fnmode|ic) == 0) {
+ if (ff->flags & FO_EXCLUDE) {
+ Dmsg2(100, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k),
+ ff->fname);
+ return false; /* reject file */
+ }
+ return true; /* accept file */
+ }
+ }
+ }
for (k=0; k<fo->wild.size(); k++) {
if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|ic) == 0) {
if (ff->flags & FO_EXCLUDE) {
}
}
#ifndef WIN32
+ if (S_ISDIR(ff->statp.st_mode)) {
+ for (k=0; k<fo->regexdir.size(); k++) {
+ const int nmatch = 30;
+ regmatch_t pmatch[nmatch];
+ if (regexec((regex_t *)fo->regexdir.get(k), ff->fname, nmatch, pmatch, 0) == 0) {
+ if (ff->flags & FO_EXCLUDE) {
+ return false; /* reject file */
+ }
+ return true; /* accept file */
+ }
+ }
+ } else {
+ for (k=0; k<fo->regexfile.size(); k++) {
+ const int nmatch = 30;
+ regmatch_t pmatch[nmatch];
+ if (regexec((regex_t *)fo->regexfile.get(k), ff->fname, nmatch, pmatch, 0) == 0) {
+ if (ff->flags & FO_EXCLUDE) {
+ return false; /* reject file */
+ }
+ return true; /* accept file */
+ }
+ }
+ }
for (k=0; k<fo->regex.size(); k++) {
const int nmatch = 30;
regmatch_t pmatch[nmatch];
int GZIP_level; /* GZIP level */
char VerifyOpts[MAX_FOPTS]; /* verify options */
alist regex; /* regex string(s) */
+ alist regexdir; /* regex string(s) for directories */
+ alist regexfile; /* regex string(s) for files */
alist wild; /* wild card strings */
+ alist wilddir; /* wild card strings for directories */
+ alist wildfile; /* wild card strings for files */
alist base; /* list of base names */
alist fstype; /* file system type limitation */
char *reader; /* reader program */
"HAVE_SUN_OS\n"
#define POOLMEM char
#define bstrdup strdup
-#define Dmsg0(n,s) fprintf(stderr, s "\n");
-#define Dmsg1(n,s,a1) fprintf(stderr, s "\n", a1);
-#define Dmsg2(n,s,a1,a2) fprintf(stderr, s "\n", a1, a2);
+#define Dmsg0(n,s) fprintf(stderr, s);
+#define Dmsg1(n,s,a1) fprintf(stderr, s, a1);
+#define Dmsg2(n,s,a1,a2) fprintf(stderr, s, a1, a2);
#endif
/*
if (statfs(fname, &st) == 0) {
return bstrdup(st.f_fstypename);
}
- Dmsg1(50, "statfs() failed for \"%s\"", fname);
+ Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
return NULL;
}
if (statvfs(fname, &st) == 0) {
return bstrdup(st.f_basetype);
}
- Dmsg1(50, "statfs() failed for \"%s\"", fname);
+ Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
return NULL;
}
#endif
default:
- Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".", st.f_type,
+ Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
fname);
return NULL;
}
}
- Dmsg1(50, "statfs() failed for \"%s\"", fname);
+ Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
return NULL;
}
if (lstat(fname, &st) == 0) {
return bstrdup(st.st_fstype);
}
- Dmsg1(50, "lstat() failed for \"%s\"", fname);
+ Dmsg1(50, "lstat() failed for \"%s\"\n", fname);
return NULL;
}
#else /* No recognised OS */
POOLMEM *fstype(const char *fname)
{
- Dmsg0(10, "!!! fstype() not implemented for this OS. !!!");
+ Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
#ifdef TEST_PROGRAM
Dmsg1(10, "Please define one of the following when compiling:\n\n%s\n",
SUPPORTEDOSES);
/* */
#undef VERSION
#define VERSION "1.37.1"
-#define BDATE "01 January 2005"
-#define LSMDATE "01Jan05"
+#define BDATE "06 January 2005"
+#define LSMDATE "06Jan05"
/* Debug flags */
#undef DEBUG