[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: extension of mkisofs for incremental backups



On Mon, 2003-07-21 at 19:07, Patrick Ohly wrote:
> Hello everyone,
> 
> I have updated the patch that adds -root and -old-root
> to mkisofs. It is now based on cdrtools 2.01a16,

I have updated the patch again to apply cleanly against
2.01a26pre. Patching the man page and a function prototype
caused conflicts while the rest applied still fine.

-- 
Bye, Patrick Ohly
--  
Patrick.Ohly@gmx.de
patrick@core.de (MakeCD related mails)
http://home.pages.de/~ohly/
http://makecd.core.de/ (MakeCD home page)
diff -r -c cdrtools-2.01a26pre/mkisofs/mkisofs.8 cdrtools-2.01a26pre-patched/mkisofs/mkisofs.8
*** cdrtools-2.01a26pre/mkisofs/mkisofs.8	Mon Dec 29 14:34:17 2003
--- cdrtools-2.01a26pre-patched/mkisofs/mkisofs.8	Sun Feb 15 17:08:58 2004
***************
*** 480,485 ****
--- 480,534 ----
  .I \-graft\-points
  has been specified.
  .TP
+ .BI \-root " dir
+ Moves all files and directories into
+ .I dir
+ in the image. This is essentially the
+ same as using 
+ .B -graft-points
+ and adding
+ .I dir
+ in front of every pathspec, but is easier to use.
+ 
+ .I dir
+ may actually be several levels deep. It is
+ created with the same permissions as other graft points.
+ .TP
+ .BI \-old-root " dir
+ This option is necessary when writing a multisession
+ image and the previous (or even older) session was written with
+ .BI -root " dir.
+ Using a directory name not found in the previous session
+ causes
+ .B mkisofs
+ to abort with an error.
+ 
+ Without this option,
+ .B mkisofs
+ would not be able to find unmodified files and would
+ be forced to write their data into the image once more.
+ 
+ .B \-root
+ and
+ .B \-old-root
+ are meant to be used together to do incremental backups.
+ The initial session would e.g. use:
+ mkisofs \-root backup_1 <dirs>.
+ The next incremental backup with mkisofs \-root backup_2
+ \-old-root backup_1 <dirs>
+ would take another snapshot of these directories. The first
+ snapshot would be found in backup_1, the second one in
+ backup_2, but only modified or new files need to be written
+ into the second session.
+ 
+ Without these options, new files would be added and old ones would be
+ preserved. But old ones would be overwritten if the file was
+ modified. Recovering the files by copying the whole directory back
+ from CD would also restore files that were deleted
+ intentionally. Accessing several older versions of a file requires
+ support by the operating system to choose which sessions are to be
+ mounted.
+ .TP
  .BI \-hide " glob
  Hide
  .I glob
diff -r -c cdrtools-2.01a26pre/mkisofs/mkisofs.c cdrtools-2.01a26pre-patched/mkisofs/mkisofs.c
*** cdrtools-2.01a26pre/mkisofs/mkisofs.c	Wed Jan  7 00:23:46 2004
--- cdrtools-2.01a26pre-patched/mkisofs/mkisofs.c	Sun Feb 15 17:10:08 2004
***************
*** 420,425 ****
--- 420,428 ----
  #define	OPTION_HFS_BLESS		2040
  #define	OPTION_HFS_PARMS		2041
  
+ #define OPTION_RELOC_ROOT     2042
+ #define OPTION_RELOC_OLD_ROOT 2043
+ 
  #endif	/* APPLE_HYB */
  
  static int	save_pname = 0;
***************
*** 481,486 ****
--- 484,493 ----
  	ONE_DASH},
  	{{"graft-points", no_argument, NULL, OPTION_USE_GRAFT},
  	'\0', NULL, "Allow to use graft points for filenames", ONE_DASH},
+ 	{{"root", required_argument, NULL, OPTION_RELOC_ROOT},
+ 	'\0', "DIR", "Set root directory for all new files and directories", ONE_DASH},
+ 	{{"old-root", required_argument, NULL, OPTION_RELOC_OLD_ROOT},
+ 	'\0', "DIR", "Set root directory in previous session that is searched for files", ONE_DASH},
  	{{"help", no_argument, NULL, OPTION_HELP},
  	'\0', NULL, "Print option help", ONE_DASH},
  	{{"hide", required_argument, NULL, OPTION_I_HIDE},
***************
*** 1145,1150 ****
--- 1152,1159 ----
  #endif
  	struct stat	statbuf;
  	char		*merge_image = NULL;
+ 	char     *reloc_root = NULL;
+ 	char     *reloc_old_root = NULL;
  	struct iso_directory_record *mrootp = NULL;
  	struct output_fragment *opnt;
  	int		longind;
***************
*** 1521,1526 ****
--- 1530,1541 ----
  		case 'M':
  			merge_image = optarg;
  			break;
+ 		case OPTION_RELOC_ROOT:
+ 			reloc_root = optarg;
+ 			break;
+ 		case OPTION_RELOC_OLD_ROOT:
+ 			reloc_old_root = optarg;
+ 			break;
  		case 'N':
  			omit_version_number++;
  			warn_violate++;
***************
*** 2647,2652 ****
--- 2662,2673 ----
  
  	memset(&de, 0, sizeof (de));
  
+ 	/*
+ 	 * PO:
+ 	 * Isn't root NULL at this time anyway?
+ 	 * I think it is created by the first call to
+ 	 * find_or_create_directory() below.
+ 	 */
  	de.filedir = root;	/* We need this to bootstrap */
  
  	if (cdrecord_data != NULL && merge_image == NULL) {
***************
*** 2764,2776 ****
  
  		short_name = NULL;
  
! 		if (node != NULL) {
  			char		*pnt;
  			char		*xpnt;
  
! 			*node = '\0';
! 			escstrcpy(graft_point, arg);
! 			*node = '=';
  
  			/*
  			 * Remove unwanted "./" & "/" sequences from start...
--- 2785,2812 ----
  
  		short_name = NULL;
  
! 		if (node != NULL || reloc_root) {
  			char		*pnt;
  			char		*xpnt;
+ 			size_t    len;
+ 
+ 			/* insert -root prefix */
+ 			if (reloc_root != NULL) {
+ 				strcpy(graft_point, reloc_root);
+ 				len = strlen(graft_point);
+ 				if (graft_point[len] != '/' ) {
+ 					graft_point[len] = '/';
+ 					len++;
+ 				}
+ 			} else {
+ 				len = 0;
+ 			}
  
! 			if (node) {
! 				*node = '\0';
! 				escstrcpy(graft_point + len, arg);
! 				*node = '=';
! 			}
  
  			/*
  			 * Remove unwanted "./" & "/" sequences from start...
***************
*** 2785,2791 ****
  				strcpy(graft_point, xpnt);
  			} while (xpnt > graft_point);
  
! 			node = escstrcpy(nodename, ++node);
  
  			graft_dir = root;
  			xpnt = graft_point;
--- 2821,2831 ----
  				strcpy(graft_point, xpnt);
  			} while (xpnt > graft_point);
  
! 			if (node) {
! 				node = escstrcpy(nodename, ++node);
! 			} else {
! 				node = arg;
! 			}
  
  			graft_dir = root;
  			xpnt = graft_point;
***************
*** 2945,2951 ****
  	 * side, since we may need to create some additional directories.
  	 */
  	if (merge_image != NULL) {
! 		if (merge_previous_session(root, mrootp) < 0) {
  #ifdef	USE_LIBSCHILY
  			comerrno(EX_BAD, "Cannot merge previous session.\n");
  #else
--- 2985,2992 ----
  	 * side, since we may need to create some additional directories.
  	 */
  	if (merge_image != NULL) {
! 		if (merge_previous_session(root, mrootp,
! 											reloc_root, reloc_old_root) < 0) {
  #ifdef	USE_LIBSCHILY
  			comerrno(EX_BAD, "Cannot merge previous session.\n");
  #else
diff -r -c cdrtools-2.01a26pre/mkisofs/mkisofs.h cdrtools-2.01a26pre-patched/mkisofs/mkisofs.h
*** cdrtools-2.01a26pre/mkisofs/mkisofs.h	Sun Dec 28 14:38:51 2003
--- cdrtools-2.01a26pre-patched/mkisofs/mkisofs.h	Sun Feb 15 17:02:57 2004
***************
*** 496,502 ****
  				struct directory_entry * dpnt));
  extern int	rr_flags	__PR((struct iso_directory_record *idr));
  extern int merge_previous_session __PR((struct directory *,
! 				struct iso_directory_record *));
  extern int get_session_start __PR((int *));
  
  /* joliet.c */
--- 496,502 ----
  				struct directory_entry * dpnt));
  extern int	rr_flags	__PR((struct iso_directory_record *idr));
  extern int merge_previous_session __PR((struct directory *,
! 				struct iso_directory_record *, char *, char *));
  extern int get_session_start __PR((int *));
  
  /* joliet.c */
diff -r -c cdrtools-2.01a26pre/mkisofs/multi.c cdrtools-2.01a26pre-patched/mkisofs/multi.c
*** cdrtools-2.01a26pre/mkisofs/multi.c	Wed Apr 30 00:18:10 2003
--- cdrtools-2.01a26pre-patched/mkisofs/multi.c	Sun Feb 15 17:02:57 2004
***************
*** 1530,1538 ****
   * directory entries, so that we can determine how large each directory is.
   */
  int
! merge_previous_session(this_dir, mrootp)
  	struct directory *this_dir;
  	struct iso_directory_record *mrootp;
  {
  	struct directory_entry **orig_contents = NULL;
  	struct directory_entry *odpnt = NULL;
--- 1530,1540 ----
   * directory entries, so that we can determine how large each directory is.
   */
  int
! merge_previous_session(this_dir, mrootp, reloc_root, reloc_old_root)
  	struct directory *this_dir;
  	struct iso_directory_record *mrootp;
+ 	char *reloc_root;
+ 	char *reloc_old_root;
  {
  	struct directory_entry **orig_contents = NULL;
  	struct directory_entry *odpnt = NULL;
***************
*** 1544,1558 ****
--- 1546,1677 ----
  			lstatbuf;
  	int		retcode;
  
+ 	/* skip leading slash */
+ 	while (reloc_old_root && reloc_old_root[0] == PATH_SEPARATOR) {
+ 		reloc_old_root++;
+ 	}
+ 	while (reloc_root && reloc_root[0] == PATH_SEPARATOR) {
+ 		reloc_root++;
+ 	}
+ 	 
  	/*
  	 * Parse the same directory in the image that we are merging for
  	 * multisession stuff.
  	 */
  	orig_contents = read_merging_directory(mrootp, &n_orig);
  	if (orig_contents == NULL) {
+ 		if (reloc_old_root) {
+ #ifdef	USE_LIBSCHILY
+ 			comerrno(EX_BAD, "Reading old session failed, cannot execute -old-root.\n");
+ #else
+ 			fprintf(stderr, "Reading old session failed, cannot execute -old-root.\n");
+ #endif
+ 			return (-1);
+ 		}
  		return (0);
  	}
  
+ 	if (reloc_old_root && reloc_old_root[0]) {
+ 		struct directory_entry **new_orig_contents = orig_contents;
+ 		int		new_n_orig = n_orig;
+ 
+ 		/* decend until we reach the original root */
+ 		while (reloc_old_root[0]) {
+ 			int i;
+ 			char *next;
+ 			int last;
+ 
+ 			for (next = reloc_old_root; *next && *next != PATH_SEPARATOR; next++);
+ 			if (*next) {
+ 				last = 0;
+ 				*next = 0;
+ 				next++;
+ 			} else {
+ 				last = 1;
+ 			}
+ 			while (*next == PATH_SEPARATOR) {
+ 				next++;
+ 			}
+ 
+ 			for (i = 0; i < new_n_orig; i++) {
+ 				struct iso_directory_record subroot;
+ 
+ 				if (new_orig_contents[i]->name != NULL
+ 					 && strcmp(new_orig_contents[i]->name, reloc_old_root) != 0) {
+ 					/* Not the same name continue */
+ 					continue;
+ 				}
+ 				/*
+ 				 * enter directory, free old one only if not the top level,
+ 				 * which is still needed
+ 				 */
+ 				subroot = new_orig_contents[i]->isorec;
+ 				if (new_orig_contents != orig_contents) {
+ 					free_mdinfo(new_orig_contents, new_n_orig);
+ 				}				
+ 				new_orig_contents = read_merging_directory(&subroot, &new_n_orig);
+ 
+ 				if (!new_orig_contents) {
+ #ifdef	USE_LIBSCHILY
+ 					comerrno(EX_BAD, "Reading directory %s in old session failed, cannot execute -old-root.\n", reloc_old_root );
+ #else
+ 					fprintf(stderr, "Reading directory %s in old session failed, cannot execute -old-root.\n", reloc_old_root );
+ #endif
+ 					return (-1);
+ 				}
+ 				
+ 				i = -1;
+ 				break;
+ 			}
+ 
+ 			if (i == new_n_orig) {
+ 				#ifdef	USE_LIBSCHILY
+ 				comerrno(EX_BAD, "-old-root (sub)directory %s not found in old session.\n", reloc_old_root );
+ #else
+ 				fprintf(stderr, "-old-root (sub)directory %s not found in old session.\n", reloc_old_root );
+ #endif
+ 				return (-1);
+ 			}
+ 
+ 			/* restore string, proceed to next sub directory */
+ 			if (!last) {
+ 				reloc_old_root[strlen(reloc_old_root)] = PATH_SEPARATOR;
+ 			}
+ 			reloc_old_root = next;
+ 		}
+ 
+ 		/*
+ 		 * preserve the old session, skipping those dirs/files that are found again
+ 		 * in the new root
+ 		 */
+ 		for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+ 			status = stat_filter(s_entry->whole_name, &statbuf);
+ 			lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
+ 
+ 			/* check_prev_session() will search for s_entry and remove it from
+ 				orig_contents if found */
+ 			retcode = check_prev_session(orig_contents, n_orig, s_entry,
+ 												  &statbuf, &lstatbuf, NULL);
+ 			if (retcode == -1)
+ 				return (-1);
+ 		}
+ 		merge_remaining_entries(this_dir, orig_contents, n_orig);
+ 
+ 		/* use new directory */
+ 		free_mdinfo(orig_contents, n_orig);
+ 		orig_contents = new_orig_contents;
+ 		n_orig = new_n_orig;		
+ 		
+ 		if (reloc_root && reloc_root[0]) {
+ 			/* also decend into new root before searching for files */
+ 			this_dir = find_or_create_directory(this_dir, reloc_root, NULL, TRUE);
+ 			if (!this_dir) {
+ 				return (-1);
+ 			}
+ 		}
+ 	}
+ 
+ 
  	/*
  	 * Now we scan the directory itself, and look at what is inside of it.
  	 */
***************
*** 1613,1619 ****
  					s_entry->whole_name,
  					s_entry, 1);
  				dflag = merge_previous_session(child,
! 					&odpnt->isorec);
  				if (dflag == -1) {
  					return (-1);
  				}
--- 1732,1739 ----
  					s_entry->whole_name,
  					s_entry, 1);
  				dflag = merge_previous_session(child,
! 					&odpnt->isorec,
! 					NULL, reloc_old_root );
  				if (dflag == -1) {
  					return (-1);
  				}
***************
*** 1623,1633 ****
  		}
  	}
  
! 	/*
! 	 * Whatever is left over, are things which are no longer in the tree on
! 	 * disk. We need to also merge these into the tree.
! 	 */
! 	merge_remaining_entries(this_dir, orig_contents, n_orig);
  	free_mdinfo(orig_contents, n_orig);
  	return (1);
  }
--- 1743,1755 ----
  		}
  	}
  
! 	if (!reloc_old_root) {
! 		/*
! 		 * Whatever is left over, are things which are no longer in the tree on
! 		 * disk. We need to also merge these into the tree.
! 		 */
! 		merge_remaining_entries(this_dir, orig_contents, n_orig);
! 	}
  	free_mdinfo(orig_contents, n_orig);
  	return (1);
  }

Reply to: