add bug closure to changelog
[debian/amanda] / application-src / amstar.c
index 2f8b17c26f9f80c23c25fbdeb9398dbd610f4bb1..c351d2c3442799a920f4fb72c84b0983b47f81da 100644 (file)
@@ -40,7 +40,8 @@
  * IGNORE
  * STRANGE
  * INCLUDE-LIST                (for restore only)
- * EXCLUDE-LIST                (for restore only)
+ * EXCLUDE-FILE
+ * EXCLUDE-LIST
  * DIRECTORY
  */
 
@@ -124,12 +125,14 @@ static void amstar_validate(application_argument_t *argument);
 static GPtrArray *amstar_build_argv(application_argument_t *argument,
                                int level,
                                int command);
+static int check_device(application_argument_t *argument);
 
 static char *star_path;
 static char *star_tardumps;
 static int   star_dle_tardumps;
 static int   star_onefilesystem;
 static int   star_sparse;
+static int   star_acl;
 static char *star_directory;
 static GSList *normal_message = NULL;
 static GSList *ignore_message = NULL;
@@ -158,6 +161,8 @@ static struct option long_options[] = {
     {"exclude-list"    , 1, NULL, 20},
     {"directory"       , 1, NULL, 21},
     {"command-options" , 1, NULL, 22},
+    {"exclude-file"    , 1, NULL, 23},
+    {"acl"             , 1, NULL, 24},
     { NULL, 0, NULL, 0}
 };
 
@@ -180,6 +185,7 @@ main(
     star_dle_tardumps = 0;
     star_onefilesystem = 1;
     star_sparse = 1;
+    star_acl = 1;
     star_directory = NULL;
 
     /* initialize */
@@ -240,6 +246,7 @@ main(
     argument.level      = NULL;
     argument.command_options = NULL;
     init_dle(&argument.dle);
+    argument.dle.record = 0;
 
     opterr = 0;
     while (1) {
@@ -319,6 +326,18 @@ main(
        case 22: argument.command_options =
                        g_slist_append(argument.command_options,
                                       stralloc(optarg));
+                break;
+       case 23: if (optarg)
+                    argument.dle.exclude_file =
+                        append_sl(argument.dle.exclude_file, optarg);
+                break;
+       case 24: if (optarg && strcasecmp(optarg, "NO") == 0)
+                    star_acl = 0;
+                else if (optarg && strcasecmp(optarg, "YES") == 0)
+                    star_acl = 1;
+                else if (strcasecmp(command, "selfcheck") == 0)
+                    printf(_("ERROR [%s: bad ACL property value (%s)]\n"), get_pname(), optarg);
+                break;
        case ':':
        case '?':
                break;
@@ -395,12 +414,15 @@ static void
 amstar_selfcheck(
     application_argument_t *argument)
 {
-    fprintf(stdout, "OK amstar\n");
     if (argument->dle.disk) {
        char *qdisk = quote_string(argument->dle.disk);
-       fprintf(stdout, "OK %s\n", qdisk);
+       fprintf(stdout, "OK disk %s\n", qdisk);
        amfree(qdisk);
     }
+
+    fprintf(stdout, "OK amstar version %s\n", VERSION);
+    fprintf(stdout, "OK amstar\n");
+
     if (argument->dle.device) {
        char *qdevice = quote_string(argument->dle.device);
        fprintf(stdout, "OK %s\n", qdevice);
@@ -416,15 +438,33 @@ amstar_selfcheck(
        argument->dle.include_list->nb_element >= 0) {
        fprintf(stdout, "ERROR include-list not supported for backup\n");
     }
-    if (argument->dle.exclude_list &&
-       argument->dle.exclude_list->nb_element >= 0) {
-       fprintf(stdout, "ERROR exclude-list not supported for backup\n");
-    }
 
     if (!star_path) {
        fprintf(stdout, "ERROR STAR-PATH not defined\n");
     } else {
-       check_file(star_path, X_OK);
+       if (check_file(star_path, X_OK)) {
+           char *star_version;
+           GPtrArray *argv_ptr = g_ptr_array_new();
+
+           g_ptr_array_add(argv_ptr, star_path);
+           g_ptr_array_add(argv_ptr, "--version");
+           g_ptr_array_add(argv_ptr, NULL);
+
+           star_version = get_first_line(argv_ptr);
+
+           if (star_version) {
+               char *sv, *sv1;
+               for (sv = star_version; *sv && !g_ascii_isdigit(*sv); sv++);
+               for (sv1 = sv; *sv1 && *sv1 != ' '; sv1++);
+               *sv1 = '\0';
+               printf("OK amstar star-version %s\n", sv);
+           } else {
+               printf(_("ERROR [Can't get %s version]\n"), star_path);
+           }
+           g_ptr_array_free(argv_ptr, TRUE);
+           amfree(star_version);
+
+       }
     }
 
     if (argument->calcsize) {
@@ -440,6 +480,11 @@ amstar_selfcheck(
        check_file(amandates_file, R_OK|W_OK);
     }
 
+    set_root_privs(1);
+    if (argument->dle.device) {
+       check_dir(argument->dle.device, R_OK);
+    }
+    set_root_privs(0);
 }
 
 static void
@@ -480,9 +525,9 @@ amstar_estimate(
        argument->dle.include_list->nb_element >= 0) {
        fprintf(stderr, "ERROR include-list not supported for backup\n");
     }
-    if (argument->dle.exclude_list &&
-       argument->dle.exclude_list->nb_element >= 0) {
-       fprintf(stderr, "ERROR exclude-list not supported for backup\n");
+
+    if (check_device(argument) == 0) {
+       return;
     }
 
     qdisk = quote_string(argument->dle.disk);
@@ -490,9 +535,9 @@ amstar_estimate(
        char *dirname;
 
        if (star_directory) {
-           dirname = amname_to_dirname(star_directory);
+           dirname = star_directory;
        } else {
-           dirname = amname_to_dirname(argument->dle.device);
+           dirname = argument->dle.device;
        }
        run_calcsize(argument->config, "STAR", argument->dle.disk, dirname,
                     argument->level, NULL, NULL);
@@ -665,10 +710,6 @@ amstar_backup(
        argument->dle.include_list->nb_element >= 0) {
        fprintf(mesgstream, "? include-list not supported for backup\n");
     }
-    if (argument->dle.exclude_list &&
-       argument->dle.exclude_list->nb_element >= 0) {
-       fprintf(mesgstream, "? exclude-list not supported for backup\n");
-    }
 
     level = GPOINTER_TO_INT(argument->level->data);
 
@@ -717,7 +758,7 @@ amstar_backup(
 
        if (regexec(&regex_dir, line, 3, regmatch, 0) == 0) {
            if (argument->dle.create_index && regmatch[1].rm_so == 2) {
-               line[regmatch[1].rm_eo+1]='\0';
+               line[regmatch[1].rm_eo]='\0';
                fprintf(indexstream, "/%s\n", &line[regmatch[1].rm_so]);
            }
            continue;
@@ -740,7 +781,7 @@ amstar_backup(
            }
        }
        if (rp->typ == DMP_SIZE) {
-           dump_size = (long)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0);
+           dump_size = (off_t)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0);
        }
        switch (rp->typ) {
            case DMP_IGNORE:
@@ -845,12 +886,23 @@ amstar_restore(
 
     if (argument->dle.include_list &&
        argument->dle.include_list->nb_element == 1) {
-       g_ptr_array_add(argv_ptr,
-                       stralloc2("list=",
-                                 argument->dle.include_list->first->name));
+       FILE *include_list = fopen(argument->dle.include_list->first->name, "r");
+       char  line[2*PATH_MAX+2];
+       while (fgets(line, 2*PATH_MAX, include_list)) {
+           line[strlen(line)-1] = '\0'; /* remove '\n' */
+           if (strncmp(line, "./", 2) == 0)
+               g_ptr_array_add(argv_ptr, stralloc(line+2)); /* remove ./ */
+           else if (strcmp(line, ".") != 0)
+               g_ptr_array_add(argv_ptr, stralloc(line));
+       }
+       fclose(include_list);
+    }
+    for (j=1; j< argument->argc; j++) {
+       if (strncmp(argument->argv[j], "./", 2) == 0)
+           g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]+2));/*remove ./ */
+       else if (strcmp(argument->argv[j], ".") != 0)
+           g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]));
     }
-    for (j=1; j< argument->argc; j++)
-       g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]+2));/*remove ./ */
     g_ptr_array_add(argv_ptr, NULL);
 
     debug_executing(argv_ptr);
@@ -912,9 +964,9 @@ static GPtrArray *amstar_build_argv(
     GSList    *copt;
 
     if (star_directory) {
-       dirname = amname_to_dirname(star_directory);
+       dirname = star_directory;
     } else {
-       dirname = amname_to_dirname(argument->dle.device);
+       dirname = argument->dle.device;
     }
     fsname = vstralloc("fs-name=", dirname, NULL);
     for (s = fsname; *s != '\0'; s++) {
@@ -941,6 +993,7 @@ static GPtrArray *amstar_build_argv(
        g_ptr_array_add(argv_ptr, stralloc("-"));
     }
     g_ptr_array_add(argv_ptr, stralloc("-C"));
+
 #if defined(__CYGWIN__)
     {
        char tmppath[PATH_MAX];
@@ -959,28 +1012,117 @@ static GPtrArray *amstar_build_argv(
     g_ptr_array_add(argv_ptr, stralloc2("tardumps=", tardumpfile));
     if (command == CMD_BACKUP)
        g_ptr_array_add(argv_ptr, stralloc("-wtardumps"));
+
     g_ptr_array_add(argv_ptr, stralloc("-xattr"));
-    g_ptr_array_add(argv_ptr, stralloc("-acl"));
+    if (star_acl)
+       g_ptr_array_add(argv_ptr, stralloc("-acl"));
     g_ptr_array_add(argv_ptr, stralloc("H=exustar"));
     g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|DIFF|GROW|SHRINK|SPECIALFILE|GETXATTR|BADACL *"));
     if (star_sparse)
        g_ptr_array_add(argv_ptr, stralloc("-sparse"));
     g_ptr_array_add(argv_ptr, stralloc("-dodesc"));
 
+    if (command == CMD_BACKUP && argument->dle.create_index)
+       g_ptr_array_add(argv_ptr, stralloc("-v"));
+
+    if ((argument->dle.exclude_file &&
+        argument->dle.exclude_file->nb_element >= 1) ||
+       (argument->dle.exclude_list &&
+        argument->dle.exclude_list->nb_element >= 1)) {
+       g_ptr_array_add(argv_ptr, stralloc("-match-tree"));
+       g_ptr_array_add(argv_ptr, stralloc("-not"));
+    }
+    if (argument->dle.exclude_file &&
+       argument->dle.exclude_file->nb_element >= 1) {
+       sle_t *excl;
+       for (excl = argument->dle.exclude_file->first; excl != NULL;
+            excl = excl->next) {
+           char *ex;
+           if (strcmp(excl->name, "./") == 0) {
+               ex = g_strdup_printf("pat=%s", excl->name+2);
+           } else {
+               ex = g_strdup_printf("pat=%s", excl->name);
+           }
+           g_ptr_array_add(argv_ptr, ex);
+       }
+    }
+    if (argument->dle.exclude_list &&
+       argument->dle.exclude_list->nb_element >= 1) {
+       sle_t *excl;
+       for (excl = argument->dle.exclude_list->first; excl != NULL;
+            excl = excl->next) {
+           char *exclname = fixup_relative(excl->name, argument->dle.device);
+           FILE *exclude;
+           char *aexc;
+           if ((exclude = fopen(exclname, "r")) != NULL) {
+               while ((aexc = agets(exclude)) != NULL) {
+                   if (aexc[0] != '\0') {
+                       char *ex;
+                       if (strcmp(aexc, "./") == 0) {
+                           ex = g_strdup_printf("pat=%s", aexc+2);
+                       } else {
+                           ex = g_strdup_printf("pat=%s", aexc);
+                       }
+                       g_ptr_array_add(argv_ptr, ex);
+                   }
+                   amfree(aexc);
+               }
+               fclose(exclude);
+           }
+           amfree(exclname);
+       }
+    }
+
+    /* It is best to place command_options at the and of command line.
+     * For example '-find' option requires that it is the last option used.
+     * See: http://cdrecord.berlios.de/private/man/star/star.1.html
+     */
     for (copt = argument->command_options; copt != NULL; copt = copt->next) {
        g_ptr_array_add(argv_ptr, stralloc((char *)copt->data));
     }
 
-    if (command == CMD_BACKUP && argument->dle.create_index)
-       g_ptr_array_add(argv_ptr, stralloc("-v"));
-
     g_ptr_array_add(argv_ptr, stralloc("."));
 
     g_ptr_array_add(argv_ptr, NULL);
 
     amfree(tardumpfile);
     amfree(fsname);
-    amfree(dirname);
 
     return(argv_ptr);
 }
+
+static int
+check_device(
+    application_argument_t *argument)
+{
+    char *qdevice;
+    struct stat stat_buf;
+
+    qdevice = quote_string(argument->dle.device);
+    set_root_privs(1);
+    if(!stat(argument->dle.device, &stat_buf)) { 
+       if (!S_ISDIR(stat_buf.st_mode)) {
+           set_root_privs(0);
+           g_fprintf(stderr, _("ERROR %s is not a directory\n"), qdevice);
+           amfree(qdevice);
+           return 0;
+       }
+    } else {
+       set_root_privs(0);
+       g_fprintf(stderr, _("ERROR can not stat %s: %s\n"), qdevice,
+                  strerror(errno));
+       amfree(qdevice);
+       return 0;
+    }
+    if (access(argument->dle.device, R_OK|X_OK) == -1) {
+       set_root_privs(0);
+       g_fprintf(stderr, _("ERROR can not access %s: %s\n"),
+                 argument->dle.device, strerror(errno));
+       amfree(qdevice);
+       return 0;
+    }
+    set_root_privs(0);
+    amfree(qdevice);
+    return 1;
+}
+