Skip to content

Commit

Permalink
Merge pull request #606 from Tarsnap/exit-2
Browse files Browse the repository at this point in the history
Exit code 2 if server-side state was modified (and there was an error)
  • Loading branch information
cperciva authored Dec 26, 2023
2 parents 1bbc926 + 1f22b5e commit 21d8ed7
Show file tree
Hide file tree
Showing 20 changed files with 152 additions and 84 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
metadata about the specified archive(s). Multiple -f options may be
specified. This option is intended for the GUI and is not needed for
command-line usage.
- If the server-side state was modified and tarsnap exits with an error, it
will now have an exit code of 2.


Tarsnap Releases
Expand Down
15 changes: 11 additions & 4 deletions recrypt/recrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ main(int argc, char **argv)
FILE *odir, *ndir;
const char * ch;
const char * missingkey = NULL;
int storage_modified = 0;

WARNP_INIT;

Expand Down Expand Up @@ -483,7 +484,8 @@ main(int argc, char **argv)
* completed, and get the current sequence # for future reference.
*/
printf("Validating new machine state...");
if (multitape_cleanstate(ncachedir, nmachinenum, 0)) {
if (multitape_cleanstate(ncachedir, nmachinenum, 0,
&storage_modified)) {
warnp("Cannot complete pending checkpoint or commit");
exit(1);
}
Expand Down Expand Up @@ -520,7 +522,8 @@ main(int argc, char **argv)
* implies PEBKAC, but safety belts are good anyway).
*/
printf("Validating old machine state...");
if (multitape_cleanstate(ocachedir, omachinenum, 1)) {
if (multitape_cleanstate(ocachedir, omachinenum, 1,
&storage_modified)) {
warnp("Cannot complete pending checkpoint or commit");
exit(1);
}
Expand Down Expand Up @@ -617,7 +620,8 @@ main(int argc, char **argv)
}

/* Commit the write transaction. */
if (multitape_commit(ncachedir, nmachinenum, nseqnum, 0)) {
if (multitape_commit(ncachedir, nmachinenum, nseqnum, 0,
&storage_modified)) {
warnp("Cannot commit write transaction");
exit(1);
}
Expand Down Expand Up @@ -681,7 +685,8 @@ main(int argc, char **argv)

/* Commit the delete transaction and delete the old chunk dir. */
printf("Committing block deletes...");
if (multitape_commit(ocachedir, omachinenum, oseqnum, 1)) {
if (multitape_commit(ocachedir, omachinenum, oseqnum, 1,
&storage_modified)) {
warnp("Cannot commit delete transaction");
exit(1);
}
Expand All @@ -701,6 +706,8 @@ main(int argc, char **argv)
if (close(ndirlock))
warnp("close");

(void)storage_modified; /* UNUSED */

/* Success! */
return (0);
}
6 changes: 5 additions & 1 deletion tar/bsdtar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1271,9 +1271,13 @@ main(int argc, char **argv)
chdir(cachedir);
#endif

if (bsdtar->return_value != 0)
if (bsdtar->return_value != 0) {
/* If we modified the storage, return 2 instead. */
if (bsdtar->storage_modified)
bsdtar->return_value = 2;
bsdtar_warnc(bsdtar, 0,
"Error exit delayed from previous errors.");
}
return (bsdtar->return_value);
}

Expand Down
3 changes: 3 additions & 0 deletions tar/bsdtar.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ struct bsdtar {
/* Used for communicating with multitape code. */
void *write_cookie;

/* Used for communication with the storage layer. */
int storage_modified;

/* Chunkification cache. */
void *chunk_cache;

Expand Down
9 changes: 5 additions & 4 deletions tar/glue/archive_multitape.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,20 @@ archive_read_open_multitape(struct archive * a, uint64_t machinenum,

/**
* archive_write_open_multitape(a, machinenum, cachedir, tapename, argc,
* argv, printstats, dryrun, creationtime, csv_filename):
* argv, printstats, dryrun, creationtime, csv_filename, storage_modified):
* Open the multitape tape ${tapename} for writing and associate it with the
* archive ${a}. If ${printstats} is non-zero, print archive statistics when
* the tape is closed. If ${dryrun} is non-zero, perform a dry run.
* Record ${creationtime} as the creation time in the archive metadata.
* If ${csv_filename} is given, write statistics in CSV format.
* If ${csv_filename} is given, write statistics in CSV format. If the
* data on the server has been modified, set ${*storage_modified} to 1.
* Return a cookie which can be passed to the multitape layer.
*/
void *
archive_write_open_multitape(struct archive * a, uint64_t machinenum,
const char * cachedir, const char * tapename, int argc,
char ** argv, int printstats, int dryrun, time_t creationtime,
const char * csv_filename)
const char * csv_filename, int * storage_modified)
{
struct multitape_write_internal * d;

Expand All @@ -142,7 +143,7 @@ archive_write_open_multitape(struct archive * a, uint64_t machinenum,

if ((d = writetape_open(machinenum, cachedir, tapename,
argc, argv, printstats, dryrun, creationtime,
csv_filename)) == NULL) {
csv_filename, storage_modified)) == NULL) {
archive_set_error(a, errno, "Error creating new archive");
return (NULL);
}
Expand Down
8 changes: 5 additions & 3 deletions tar/glue/archive_multitape.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ void * archive_read_open_multitape(struct archive *, uint64_t, const char *);

/**
* archive_write_open_multitape(a, machinenum, cachedir, tapename, argc,
* argv, printstats, dryrun, creationtime, csv_filename):
* argv, printstats, dryrun, creationtime, csv_filename, storage_modified):
* Open the multitape tape ${tapename} for writing and associate it with the
* archive ${a}. If ${printstats} is non-zero, print archive statistics when
* the tape is closed. If ${dryrun} is non-zero, perform a dry run.
* Record ${creationtime} as the creation time in the archive metadata.
* If ${csv_filename} is given, write statistics in CSV format.
* If ${csv_filename} is given, write statistics in CSV format. If the
* data on the server has been modified, set ${*storage_modified} to 1.
* Return a cookie which can be passed to the multitape layer.
*/
void * archive_write_open_multitape(struct archive *, uint64_t, const char *,
const char *, int argc, char ** argv, int, int, time_t, const char *);
const char *, int argc, char ** argv, int, int, time_t, const char *,
int *);

/**
* archive_write_multitape_setmode(a, cookie, mode):
Expand Down
11 changes: 7 additions & 4 deletions tar/glue/tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ tarsnap_mode_d(struct bsdtar *bsdtar)
bsdtar->tapenames[i]);
switch (deletetape(d, bsdtar->machinenum, bsdtar->cachedir,
bsdtar->tapenames[i], bsdtar->option_print_stats,
bsdtar->ntapes > 1 ? 1 : 0, bsdtar->option_csv_filename)) {
bsdtar->ntapes > 1 ? 1 : 0, bsdtar->option_csv_filename,
&bsdtar->storage_modified)) {
case 0:
break;
case 1:
Expand Down Expand Up @@ -234,7 +235,8 @@ void
tarsnap_mode_fsck(struct bsdtar *bsdtar, int prune, int whichkey)
{

if (fscktape(bsdtar->machinenum, bsdtar->cachedir, prune, whichkey)) {
if (fscktape(bsdtar->machinenum, bsdtar->cachedir, prune, whichkey,
&bsdtar->storage_modified)) {
bsdtar_warnc(bsdtar, 0, "Error fscking archives");
goto err0;
}
Expand Down Expand Up @@ -306,7 +308,7 @@ tarsnap_mode_nuke(struct bsdtar *bsdtar)
goto err0;
}

if (nuketape(bsdtar->machinenum)) {
if (nuketape(bsdtar->machinenum, &bsdtar->storage_modified)) {
bsdtar_warnc(bsdtar, 0, "Error nuking archives");
goto err0;
}
Expand All @@ -327,7 +329,8 @@ void
tarsnap_mode_recover(struct bsdtar *bsdtar, int whichkey)
{

if (recovertape(bsdtar->machinenum, bsdtar->cachedir, whichkey))
if (recovertape(bsdtar->machinenum, bsdtar->cachedir, whichkey,
&bsdtar->storage_modified))
goto err1;

/* Success! */
Expand Down
30 changes: 17 additions & 13 deletions tar/multitape/multitape.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ int readtape_close(TAPE_R *);

/**
* writetape_open(machinenum, cachedir, tapename, argc, argv, printstats,
* dryrun, creationtime, csv_filename):
* dryrun, creationtime, csv_filename, storage_modified):
* Create a tape with the given name, and return a cookie which can be used
* for accessing it. The argument vector must be long-lived.
*/
TAPE_W * writetape_open(uint64_t, const char *, const char *, int, char **,
int, int, time_t, const char *);
int, int, time_t, const char *, int *);

/**
* writetape_setcallbacks(d, callback_chunk, callback_trailer,
Expand Down Expand Up @@ -133,15 +133,16 @@ TAPE_D * deletetape_init(uint64_t);

/**
* deletetape(d, machinenum, cachedir, tapename, printstats, withname,
* csv_filename):
* csv_filename, storage_modified):
* Delete the specified tape, and print statistics to stderr if requested.
* If ${withname} is non-zero, print statistics with the archive name, not
* just as "This archive". Return 0 on success, 1 if the tape does not exist,
* or -1 on other errors. If ${csv_filename} is specified, output in CSV
* format instead of to stderr.
* format instead of to stderr. If the data on the server has been modified,
* set ${*storage_modified} to 1.
*/
int deletetape(TAPE_D *, uint64_t, const char *, const char *, int, int,
const char *);
const char *, int *);

/**
* deletetape_free(d):
Expand Down Expand Up @@ -211,14 +212,15 @@ int statstape_print(TAPE_S *, const char *, const char *);
int statstape_close(TAPE_S *);

/**
* fscktape(machinenum, cachedir, prune, whichkey):
* fscktape(machinenum, cachedir, prune, whichkey, storage_modified):
* Correct any inconsistencies in the archive set (by removing orphaned or
* corrupt files) and reconstruct the chunk directory in ${cachedir}. If
* ${prune} is zero, don't correct inconsistencies; instead, exit with an
* error. If ${whichkey} is zero, use the write key (for non-pruning fsck
* only); otherwise, use the delete key.
* only); otherwise, use the delete key. If the data on the server has been
* modified, set ${*storage_modified} to 1.
*/
int fscktape(uint64_t, const char *, int, int);
int fscktape(uint64_t, const char *, int, int, int *);

/**
* statstape_initialize(machinenum, cachedir):
Expand All @@ -229,17 +231,19 @@ int fscktape(uint64_t, const char *, int, int);
int statstape_initialize(uint64_t, const char *);

/**
* recovertape(machinenum, cachedir, whichkey):
* recovertape(machinenum, cachedir, whichkey, storage_modified):
* Complete any pending checkpoint or commit, including a checkpoint in a
* write transaction being performed by a different machine (if any). If
* ${whichkey} is zero, use the write key; otherwise, use the delete key.
* If the data on the server has been modified, set ${*storage_modified} to 1.
*/
int recovertape(uint64_t, const char *, int);
int recovertape(uint64_t, const char *, int, int *);

/**
* nuketape(machinenum):
* Delete all files in the archive set.
* nuketape(machinenum, storage_modified):
* Delete all files in the archive set. If the data on the server has been
* modified, set ${*storage_modified} to 1.
*/
int nuketape(uint64_t);
int nuketape(uint64_t, int *);

#endif /* !MULTITAPE_H_ */
11 changes: 6 additions & 5 deletions tar/multitape/multitape_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,18 @@ deletetape_init(uint64_t machinenum)

/**
* deletetape(d, machinenum, cachedir, tapename, printstats, withname,
* csv_filename):
* csv_filename, storage_modified):
* Delete the specified tape, and print statistics to stderr if requested.
* If ${withname} is non-zero, print statistics with the archive name, not
* just as "This archive". Return 0 on success, 1 if the tape does not exist,
* or -1 on other errors. If ${csv_filename} is specified, output in CSV
* format instead of to stderr.
* format instead of to stderr. If the data on the server has been modified,
* set ${*storage_modified} to 1.
*/
int
deletetape(TAPE_D * d, uint64_t machinenum, const char * cachedir,
const char * tapename, int printstats, int withname,
const char * csv_filename)
const char * csv_filename, int * storage_modified)
{
struct tapemetadata tmd;
CHUNKS_D * C; /* Chunk layer delete cookie. */
Expand All @@ -95,7 +96,7 @@ deletetape(TAPE_D * d, uint64_t machinenum, const char * cachedir,
goto err0;

/* Make sure the lower layers are in a clean state. */
if (multitape_cleanstate(cachedir, machinenum, 1))
if (multitape_cleanstate(cachedir, machinenum, 1, storage_modified))
goto err1;

/* Get sequence number (# of last committed transaction). */
Expand Down Expand Up @@ -164,7 +165,7 @@ deletetape(TAPE_D * d, uint64_t machinenum, const char * cachedir,
goto err1;

/* Commit the transaction. */
if (multitape_commit(cachedir, machinenum, seqnum, 1))
if (multitape_commit(cachedir, machinenum, seqnum, 1, storage_modified))
goto err1;

/* Unlock the cache directory. */
Expand Down
16 changes: 10 additions & 6 deletions tar/multitape/multitape_fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,15 +446,17 @@ phase5(STORAGE_D * SD, CHUNKS_S * C)
}

/**
* fscktape(machinenum, cachedir, prune, whichkey):
* fscktape(machinenum, cachedir, prune, whichkey, storage_modified):
* Correct any inconsistencies in the archive set (by removing orphaned or
* corrupt files) and reconstruct the chunk directory in ${cachedir}. If
* ${prune} is zero, don't correct inconsistencies; instead, exit with an
* error. If ${whichkey} is zero, use the write key (for non-pruning fsck
* only); otherwise, use the delete key.
* only); otherwise, use the delete key. If the data on the server has been
* modified, set ${*storage_modified} to 1.
*/
int
fscktape(uint64_t machinenum, const char * cachedir, int prune, int whichkey)
fscktape(uint64_t machinenum, const char * cachedir, int prune, int whichkey,
int * storage_modified)
{
STORAGE_D * SD;
STORAGE_R * SR;
Expand All @@ -471,15 +473,16 @@ fscktape(uint64_t machinenum, const char * cachedir, int prune, int whichkey)
goto err0;

/* Make sure the lower layers are in a clean state. */
if (multitape_cleanstate(cachedir, machinenum, key))
if (multitape_cleanstate(cachedir, machinenum, key, storage_modified))
goto err1;

/*
* If a checkpointed archive creation was in progress on a different
* machine, we might as well commit it -- we're going to regenerate
* all of our local state anyway.
*/
if (storage_transaction_commitfromcheckpoint(machinenum, key))
if (storage_transaction_commitfromcheckpoint(machinenum, key,
storage_modified))
goto err1;

/* Start a storage-layer fsck transaction. */
Expand Down Expand Up @@ -545,7 +548,8 @@ fscktape(uint64_t machinenum, const char * cachedir, int prune, int whichkey)
goto err1;

/* Commit the transaction. */
if (multitape_commit(cachedir, machinenum, seqnum, key))
if (multitape_commit(cachedir, machinenum, seqnum, key,
storage_modified))
goto err1;

/* Unlock the cache directory. */
Expand Down
15 changes: 9 additions & 6 deletions tar/multitape/multitape_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ struct tapemetaindex {
#define MAXIFRAG MAXCHUNK

/**
* multitape_cleanstate(cachedir, machinenum, key):
* multitape_cleanstate(cachedir, machinenum, key, storage_modified):
* Complete any pending checkpoint or commit. The value ${key} should be 0
* if the write access key should be used to sign a commit request, or 1 if
* the delete access key should be used.
* the delete access key should be used. If the data on the server has been
* modified, set ${*storage_modified} to 1.
*/
int multitape_cleanstate(const char *, uint64_t, uint8_t);
int multitape_cleanstate(const char *, uint64_t, uint8_t, int *);

/**
* multitape_checkpoint(cachedir, machinenum, seqnum):
Expand All @@ -75,11 +76,13 @@ int multitape_cleanstate(const char *, uint64_t, uint8_t);
int multitape_checkpoint(const char *, uint64_t, const uint8_t[32]);

/**
* multitape_commit(cachedir, machinenum, seqnum, key):
* multitape_commit(cachedir, machinenum, seqnum, key, storage_modified):
* Commit the most recent transaction. The value ${key} is defined as in
* multitape_cleanstate.
* multitape_cleanstate. If the data on the server has been modified, set
* ${*storage_modified} to 1.
*/
int multitape_commit(const char *, uint64_t, const uint8_t[32], uint8_t);
int multitape_commit(const char *, uint64_t, const uint8_t[32], uint8_t,
int *);

/**
* multitape_chunkiter_tmd(S, C, tmd, func, cookie, quiet):
Expand Down
Loading

0 comments on commit 21d8ed7

Please sign in to comment.