diff -ur packages/fileutils-4.1/src/copy.c build/fileutils-4.1/src/copy.c --- packages/fileutils-4.1/src/copy.c Sun Jan 14 02:49:43 2001 +++ build/fileutils-4.1/src/copy.c Wed May 16 19:01:30 2001 @@ -26,6 +26,10 @@ #include #include +#ifdef HAVE_MMAP + #include +#endif /* HAVE_MMAP */ + #include "system.h" #include "error.h" #include "backupfile.h" @@ -182,6 +186,8 @@ copy_reg (const char *src_path, const char *dst_path, const struct cp_options *x, mode_t dst_mode, int *new_dst) { + char *dest_buf; + int dest_buf_size; char *buf; int buf_size; int dest_desc; @@ -193,6 +199,8 @@ off_t n_read_total = 0; int last_write_made_hole = 0; int make_holes = (x->sparse_mode == SPARSE_ALWAYS); + int mmap_source = 0; + int mmap_dest = 0; source_desc = open (src_path, O_RDONLY); if (source_desc < 0) @@ -214,11 +222,17 @@ The if-block will be taken in move_mode. */ if (*new_dst) { - dest_desc = open (dst_path, O_WRONLY | O_CREAT, dst_mode); + if (x->mmap_mode) + dest_desc = open (dst_path, O_RDWR | O_CREAT, dst_mode); + else + dest_desc = open (dst_path, O_WRONLY | O_CREAT, dst_mode); } else { - dest_desc = open (dst_path, O_WRONLY | O_TRUNC, dst_mode); + if (x->mmap_mode) + dest_desc = open (dst_path, O_RDWR | O_TRUNC, dst_mode); + else + dest_desc = open (dst_path, O_WRONLY | O_TRUNC, dst_mode); if (dest_desc < 0 && x->unlink_dest_after_failed_open) { @@ -279,11 +293,77 @@ /* Make a buffer with space for a sentinel at the end. */ - buf = (char *) alloca (buf_size + sizeof (int)); + if (x->mmap_mode) + { +#ifdef HAVE_MMAP + if (fstat (source_desc, &sb)) + { + error (0, errno, _("cannot fstat: %s"), quote (src_path)); + return_val = -1; + goto close_src_and_dst_desc; + } + + dest_buf_size = sb.st_size; + + /* We don't care if mmap() or madvise() dont work, we use it them we can */ + /* we need PROT_WRITE for sentinel writing for the hole checking algorithm below */ + + if ((buf = mmap (NULL, dest_buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, source_desc, 0)) == (void *) -1) + { + mmap_source = 0; + } + else + { + mmap_source = 1; +#if 0 + madvise (buf, dest_buf_size, MADV_SEQUENTIAL); +#endif + } + +#if HAVE_FTRUNCATE + /* Write a null character and truncate it again. */ + if (ftruncate (dest_desc, dest_buf_size) < 0) +#else + /* Seek backwards one character and write a null. */ + if (lseek (dest_desc, (off_t) dest_buf_size, SEEK_SET) < 0L + || full_write (dest_desc, "", 1) < 0) +#endif + { + error (0, errno, _("writing %s"), quote (dst_path)); + return_val = -1; + } + + if ((dest_buf = mmap (NULL, dest_buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_desc, 0)) == (void *) -1) + { + mmap_dest = 0; + } + else + { + mmap_dest = 1; +#if 0 + madvise (dest_buf, dest_buf_size, MADV_SEQUENTIAL); +#endif + } +#endif /* HAVE_MMAP */ + } + else + { + buf = (char *) alloca (buf_size + sizeof (int)); + } for (;;) { - int n_read = read (source_desc, buf, buf_size); + int n_read; + + if (mmap_source) + { + n_read = MIN (buf_size, dest_buf_size - n_read_total); + } + else + { + n_read = read (source_desc, buf, buf_size); + } + if (n_read < 0) { #ifdef EINTR @@ -302,6 +382,9 @@ ip = 0; if (make_holes) { + char tmp; + + tmp = buf[n_read]; buf[n_read] = 1; /* Sentinel to stop loop. */ /* Find first nonzero *word*, or the word with the sentinel. */ @@ -321,26 +404,49 @@ if (cp > buf + n_read) { - /* Make a hole. */ - if (lseek (dest_desc, (off_t) n_read, SEEK_CUR) < 0L) + /* no need to do anythning if the dest is mmap()'ed */ + /* that includes any last write_made_hole handling */ + if (!mmap_dest) { - error (0, errno, _("cannot lseek %s"), quote (dst_path)); - return_val = -1; - goto close_src_and_dst_desc; + /* Make a hole. */ + if (lseek (dest_desc, (off_t) n_read, SEEK_CUR) < 0L) + { + error (0, errno, _("cannot lseek %s"), quote (dst_path)); + return_val = -1; + goto close_src_and_dst_desc; + } + last_write_made_hole = 1; } - last_write_made_hole = 1; } else /* Clear to indicate that a normal write is needed. */ ip = 0; + + buf[n_read] = tmp; } if (ip == 0) { - if (full_write (dest_desc, buf, n_read) < 0) + if (mmap_dest) { - error (0, errno, _("writing %s"), quote (dst_path)); - return_val = -1; - goto close_src_and_dst_desc; + memmove(dest_buf + n_read_total - n_read, buf + n_read_total - n_read, n_read); + } + else if (mmap_source) + { + if (full_write (dest_desc, buf + n_read_total - n_read, n_read) < 0) + { + error (0, errno, _("writing %s"), quote (dst_path)); + return_val = -1; + goto close_src_and_dst_desc; + } + } + else + { + if (full_write (dest_desc, buf, n_read) < 0) + { + error (0, errno, _("writing %s"), quote (dst_path)); + return_val = -1; + goto close_src_and_dst_desc; + } } last_write_made_hole = 0; } @@ -368,12 +474,46 @@ } close_src_and_dst_desc: +#ifdef HAVE_MMAP + if (mmap_dest) + { + /* dont care if madvise() doesnt work */ +#if 0 + madvise (dest_buf, dest_buf_size, MADV_DONTNEED); +#endif + if (dest_buf_size) + { + if (munmap (dest_buf, dest_buf_size) < 0) + { + error (0, errno, _("munmaping %s"), quote (src_path)); + return_val = -1; + } + } + } +#endif /* HAVE_MMAP */ if (close (dest_desc) < 0) { error (0, errno, _("closing %s"), quote (dst_path)); return_val = -1; } close_src_desc: +#ifdef HAVE_MMAP + if (mmap_source) + { + /* dont care if madvise() doesnt work */ +#if 0 + madvise (buf, dest_buf_size, MADV_DONTNEED); +#endif + if (dest_buf_size) + { + if (munmap (buf, dest_buf_size) < 0) + { + error (0, errno, _("munmaping %s"), quote (dst_path)); + return_val = -1; + } + } + } +#endif /* HAVE_MMAP */ if (close (source_desc) < 0) { error (0, errno, _("closing %s"), quote (src_path)); diff -ur packages/fileutils-4.1/src/copy.h build/fileutils-4.1/src/copy.h --- packages/fileutils-4.1/src/copy.h Sun Jan 14 22:03:30 2001 +++ build/fileutils-4.1/src/copy.h Tue May 15 15:34:58 2001 @@ -73,6 +73,10 @@ with regular files. */ int interactive; + /* If nonzero, use mmap() and madvise() if possible to avoid + polluting the page / buffer cache */ + int mmap_mode; + /* If nonzero, rather than copying, first attempt to use rename. If that fails, then resort to copying. */ int move_mode; diff -ur packages/fileutils-4.1/src/cp.c build/fileutils-4.1/src/cp.c --- packages/fileutils-4.1/src/cp.c Sun Feb 4 03:48:34 2001 +++ build/fileutils-4.1/src/cp.c Wed May 16 19:13:36 2001 @@ -117,6 +117,7 @@ {"sparse", required_argument, NULL, SPARSE_OPTION}, {"interactive", no_argument, NULL, 'i'}, {"link", no_argument, NULL, 'l'}, + {"mmap", no_argument, NULL, 'M'}, {"no-dereference", no_argument, NULL, 'd'}, {"one-file-system", no_argument, NULL, 'x'}, {"parents", no_argument, NULL, PARENTS_OPTION}, @@ -163,6 +164,7 @@ -H follow command-line symbolic links\n\ -l, --link link files instead of copying\n\ -L, --dereference always follow symbolic links\n\ + -M, --mmap use mmap() and madvise() to copy files\n\ -p, --preserve preserve file attributes if possible\n\ --parents append source path to DIRECTORY\n\ -P same as `--parents' for now; soon to change to\n\ @@ -672,6 +674,7 @@ x->interactive = 0; x->myeuid = geteuid (); x->move_mode = 0; + x->mmap_mode = 0; x->one_file_system = 0; x->preserve_owner_and_group = 0; @@ -719,7 +722,7 @@ we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL)) + while ((c = getopt_long (argc, argv, "abdfHilLMprsuvxPRS:V:", long_opts, NULL)) != -1) { switch (c) @@ -777,6 +780,10 @@ case 'L': x.dereference = DEREF_ALWAYS; + break; + + case 'M': + x.mmap_mode = 1; break; case 'p': diff -ur packages/fileutils-4.1/src/install.c build/fileutils-4.1/src/install.c --- packages/fileutils-4.1/src/install.c Wed May 16 18:26:27 2001 +++ build/fileutils-4.1/src/install.c Wed May 16 19:17:09 2001 @@ -155,6 +155,7 @@ x->hard_link = 0; x->interactive = 0; x->move_mode = 0; + x->mmap_mode = 0; x->myeuid = geteuid (); x->one_file_system = 0; x->preserve_owner_and_group = 0; @@ -211,7 +212,7 @@ we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pvV:S:", long_options, + while ((optc = getopt_long (argc, argv, "bcsDdg:m:Mo:pvV:S:", long_options, NULL)) != -1) { switch (optc) @@ -251,6 +252,9 @@ case 'm': specified_mode = optarg; break; + case 'M': + x.mmap_mode = 1; + break; case 'o': owner_name = optarg; break; @@ -632,6 +636,7 @@ then copy SOURCE to DEST; useful in the 1st format\n\ -g, --group=GROUP set group ownership, instead of process' current group\n\ -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\ + -M, --mmap use mmap() and madvise() to copy files\n\ -o, --owner=OWNER set ownership (super-user only)\n\ -p, --preserve-timestamps apply access/modification times of SOURCE files\n\ to corresponding destination files\n\ diff -ur packages/fileutils-4.1/src/mv.c build/fileutils-4.1/src/mv.c --- packages/fileutils-4.1/src/mv.c Sun Feb 4 03:48:34 2001 +++ build/fileutils-4.1/src/mv.c Wed May 16 19:15:32 2001 @@ -111,6 +111,7 @@ x->hard_link = 0; x->interactive = 0; x->move_mode = 1; + x->mmap_mode = 0; x->myeuid = geteuid (); x->one_file_system = 0; x->preserve_owner_and_group = 1; @@ -341,6 +342,7 @@ -i, --interactive prompt before overwrite\n\ --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ argument\n\ + -M, --mmap use mmap() and madvise() to copy files\n\ -S, --suffix=SUFFIX override the usual backup suffix\n\ --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\ -u, --update move only older or brand new non-directories\n\ @@ -394,7 +396,7 @@ errors = 0; - while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1) + while ((c = getopt_long (argc, argv, "bfiuvMS:V:", long_options, NULL)) != -1) { switch (c) { @@ -431,6 +433,9 @@ case 'v': x.verbose = 1; break; + case 'M': + x.mmap_mode = 1; + break; case 'S': make_backups = 1; backup_suffix_string = optarg;