+ /* All other files should be flushed to remote storage before writing the
+ * backup descriptor below, so that it is not possible to have a backup
+ * descriptor written out depending on non-existent (not yet written)
+ * files. */
+ remote->sync();
+
+ /* Write a backup descriptor file, which says which segments are needed and
+ * where to start to restore this snapshot. The filename is based on the
+ * current time. If a signature filter program was specified, filter the
+ * data through that to give a chance to sign the descriptor contents. */
+ string desc_filename = "snapshot-";
+ if (backup_scheme.size() > 0)
+ desc_filename += backup_scheme + "-";
+ desc_filename = desc_filename + desc_buf + ".lbs";
+
+ RemoteFile *descriptor_file = remote->alloc_file(desc_filename,
+ "snapshots");
+ int descriptor_fd = descriptor_file->get_fd();
+ if (descriptor_fd < 0) {
+ fprintf(stderr, "Unable to open descriptor output file: %m\n");
+ return 1;
+ }
+ pid_t signature_pid = 0;
+ if (signature_filter.size() > 0) {
+ int new_fd = spawn_filter(descriptor_fd, signature_filter.c_str(),
+ &signature_pid);
+ close(descriptor_fd);
+ descriptor_fd = new_fd;
+ }
+ FILE *descriptor = fdopen(descriptor_fd, "w");
+
+ fprintf(descriptor, "Format: LBS Snapshot v0.8\n");
+ fprintf(descriptor, "Producer: Cumulus %s\n", cumulus_version);
+ strftime(desc_buf, sizeof(desc_buf), "%Y-%m-%d %H:%M:%S %z", &time_buf);
+ fprintf(descriptor, "Date: %s\n", desc_buf);
+ if (backup_scheme.size() > 0)
+ fprintf(descriptor, "Scheme: %s\n", backup_scheme.c_str());
+ fprintf(descriptor, "Backup-Intent: %g\n", snapshot_intent);
+ fprintf(descriptor, "Root: %s\n", backup_root.c_str());
+
+ if (csum.size() > 0) {
+ fprintf(descriptor, "Checksums: %s\n", csum.c_str());
+ }
+
+ fprintf(descriptor, "Segments:\n");
+ for (std::set<string>::iterator i = segment_list.begin();
+ i != segment_list.end(); ++i) {
+ fprintf(descriptor, " %s\n", i->c_str());
+ }
+
+ fclose(descriptor);
+
+ if (signature_pid) {
+ int status;
+ waitpid(signature_pid, &status, 0);
+
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ throw IOException("Signature filter process error");
+ }
+ }
+
+ descriptor_file->send();
+
+ remote->sync();
+ delete remote;
+
+ if (backup_script != "") {
+ if (rmdir(tmp_dir.c_str()) < 0) {
+ fprintf(stderr,
+ "Warning: Cannot delete temporary directory %s: %m\n",
+ tmp_dir.c_str());
+ }
+ }