diff -ruNU 20 ../coreutils-4.5.6.orig/man/cp.1 ./man/cp.1 --- ../coreutils-4.5.6.orig/man/cp.1 2003-02-03 14:59:06.000000000 +0100 +++ ./man/cp.1 2003-02-12 18:37:01.000000000 +0100 @@ -78,40 +78,43 @@ .TP \fB\-\-reply=\fR{yes,no,query} specify how to handle the prompt about an existing destination file .TP \fB\-\-sparse\fR=\fIWHEN\fR control creation of sparse files .TP \fB\-\-strip\-trailing\-slashes\fR remove any trailing slashes from each SOURCE argument .TP \fB\-s\fR, \fB\-\-symbolic\-link\fR make symbolic links instead of copying .TP \fB\-S\fR, \fB\-\-suffix\fR=\fISUFFIX\fR override the usual backup suffix .TP \fB\-\-target\-directory\fR=\fIDIRECTORY\fR move all SOURCE arguments into DIRECTORY .TP +\fB\-t\fR, \fB\-\-throughput\fR=\fIRATE\fR +limit the write throughput to RATE kB/s. +.TP \fB\-u\fR, \fB\-\-update\fR copy only when the SOURCE file is newer than the destination file or when the destination file is missing .TP \fB\-v\fR, \fB\-\-verbose\fR explain what is being done .TP \fB\-x\fR, \fB\-\-one\-file\-system\fR stay on this file system .TP \fB\-\-help\fR display this help and exit .TP \fB\-\-version\fR output version information and exit .PP By default, sparse SOURCE files are detected by a crude heuristic and the corresponding DEST file is made sparse as well. That is the behavior selected by \fB\-\-sparse\fR=\fIauto\fR. Specify \fB\-\-sparse\fR=\fIalways\fR to create a sparse DEST diff -ruNU 20 ../coreutils-4.5.6.orig/man/install.1 ./man/install.1 --- ../coreutils-4.5.6.orig/man/install.1 2003-02-03 14:59:09.000000000 +0100 +++ ./man/install.1 2003-02-12 18:37:36.000000000 +0100 @@ -37,40 +37,43 @@ then copy SOURCE to DEST; useful in the 1st format .TP \fB\-g\fR, \fB\-\-group\fR=\fIGROUP\fR set group ownership, instead of process' current group .TP \fB\-m\fR, \fB\-\-mode\fR=\fIMODE\fR set permission mode (as in chmod), instead of rwxr-xr-x .TP \fB\-o\fR, \fB\-\-owner\fR=\fIOWNER\fR set ownership (super-user only) .TP \fB\-p\fR, \fB\-\-preserve\-timestamps\fR apply access/modification times of SOURCE files to corresponding destination files .TP \fB\-s\fR, \fB\-\-strip\fR strip symbol tables, only for 1st and 2nd formats .HP \fB\-S\fR, \fB\-\-suffix\fR=\fISUFFIX\fR override the usual backup suffix .TP +\fB\-t\fR, \fB\-\-throughput\fR=\fIRATE\fR +limit the write throughput to RATE kB/s. +.TP \fB\-v\fR, \fB\-\-verbose\fR print the name of each directory as it is created .TP \fB\-\-help\fR display this help and exit .TP \fB\-\-version\fR output version information and exit .PP The backup suffix is `~', unless set with \fB\-\-suffix\fR or SIMPLE_BACKUP_SUFFIX. The version control method may be selected via the \fB\-\-backup\fR option or through the VERSION_CONTROL environment variable. Here are the values: .TP none, off never make backups (even if \fB\-\-backup\fR is given) .TP numbered, t make numbered backups .TP existing, nil diff -ruNU 20 ../coreutils-4.5.6.orig/man/mv.1 ./man/mv.1 --- ../coreutils-4.5.6.orig/man/mv.1 2003-02-03 14:59:10.000000000 +0100 +++ ./man/mv.1 2003-02-12 18:37:23.000000000 +0100 @@ -28,40 +28,43 @@ do not prompt before overwriting equivalent to \fB\-\-reply\fR=\fIyes\fR .TP \fB\-i\fR, \fB\-\-interactive\fR prompt before overwrite equivalent to \fB\-\-reply\fR=\fIquery\fR .TP \fB\-\-reply=\fR{yes,no,query} specify how to handle the prompt about an existing destination file .TP \fB\-\-strip\-trailing\-slashes\fR remove any trailing slashes from each SOURCE argument .TP \fB\-S\fR, \fB\-\-suffix\fR=\fISUFFIX\fR override the usual backup suffix .TP \fB\-\-target\-directory\fR=\fIDIRECTORY\fR move all SOURCE arguments into DIRECTORY .TP +\fB\-t\fR, \fB\-\-throughput\fR=\fIRATE\fR +limit the write throughput to RATE kB/s. +.TP \fB\-u\fR, \fB\-\-update\fR move only when the SOURCE file is newer than the destination file or when the destination file is missing .TP \fB\-v\fR, \fB\-\-verbose\fR explain what is being done .TP \fB\-\-help\fR display this help and exit .TP \fB\-\-version\fR output version information and exit .PP The backup suffix is `~', unless set with \fB\-\-suffix\fR or SIMPLE_BACKUP_SUFFIX. The version control method may be selected via the \fB\-\-backup\fR option or through the VERSION_CONTROL environment variable. Here are the values: .TP none, off never make backups (even if \fB\-\-backup\fR is given) diff -ruNU 20 ../coreutils-4.5.6.orig/src/copy.c ./src/copy.c --- ../coreutils-4.5.6.orig/src/copy.c 2003-02-10 14:33:28.000000000 +0100 +++ ./src/copy.c 2003-02-12 18:32:24.000000000 +0100 @@ -8,40 +8,41 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Extracted from cp.c and librarified by Jim Meyering. */ #ifdef _AIX #pragma alloca #endif #include #include #include #include +#include #if HAVE_HURD_H # include #endif #include "system.h" #include "error.h" #include "backupfile.h" #include "savedir.h" #include "copy.h" #include "cp-hash.h" #include "hash.h" #include "hash-pjw.h" #include "same.h" #include "dirname.h" #include "full-write.h" #include "path-concat.h" #include "quote.h" #include "same.h" #include "xreadlink.h" @@ -176,40 +177,50 @@ If the source file contains holes, copies holes and blocks of zeros in the source file as holes in the destination file. (Holes are read as zeroes by the `read' system call.) Use DST_MODE as the 3rd argument in the call to open. X provides many option settings. Return 0 if successful, -1 if an error occurred. *NEW_DST is as in copy_internal. SRC_SB is the result of calling xstat (aka stat in this case) on SRC_PATH. */ static int copy_reg (const char *src_path, const char *dst_path, const struct cp_options *x, mode_t dst_mode, int *new_dst, struct stat const *src_sb) { char *buf; int buf_size; int dest_desc; int source_desc; struct stat sb; struct stat src_open_sb; +/* For throughput limiting only: */ + struct timespec bwlimit_tv; + struct timeval old_bwlimit_time; + struct timeval new_bwlimit_time; + int bwlimit_time_elapsed_usec; + int bwlimit_delay_usec; + int bwlimit_fixed_delay_usec; + int bwlimit_delay_correction_usec; +#define BWLIMIT_DELAY_THRESHOLD 20 +/* End throughput limiting */ char *cp; int *ip; int return_val = 0; off_t n_read_total = 0; int last_write_made_hole = 0; int make_holes = (x->sparse_mode == SPARSE_ALWAYS); source_desc = open (src_path, O_RDONLY); if (source_desc < 0) { error (0, errno, _("cannot open %s for reading"), quote (src_path)); return -1; } if (fstat (source_desc, &src_open_sb)) { error (0, errno, _("cannot fstat %s"), quote (src_path)); return_val = -1; goto close_src_desc; } @@ -279,40 +290,50 @@ if (fstat (source_desc, &sb)) { error (0, errno, _("cannot fstat %s"), quote (src_path)); return_val = -1; goto close_src_and_dst_desc; } /* If the file has fewer blocks than would normally be needed for a file of its size, then at least one of the blocks in the file is a hole. */ if (S_ISREG (sb.st_mode) && sb.st_size / ST_NBLOCKSIZE > ST_NBLOCKS (sb)) make_holes = 1; } #endif /* Make a buffer with space for a sentinel at the end. */ buf = (char *) alloca (buf_size + sizeof (int)); + /* Initialize throughput data */ + if(x->bwlimit) + { + gettimeofday(&old_bwlimit_time,NULL); + bwlimit_fixed_delay_usec = ( buf_size * 960 ) / + ( x->bwlimit ); + bwlimit_delay_usec = 0; + bwlimit_delay_correction_usec = 0; + } + for (;;) { ssize_t n_read = read (source_desc, buf, buf_size); if (n_read < 0) { #ifdef EINTR if (errno == EINTR) continue; #endif error (0, errno, _("reading %s"), quote (src_path)); return_val = -1; goto close_src_and_dst_desc; } if (n_read == 0) break; n_read_total += n_read; ip = 0; if (make_holes) @@ -335,40 +356,86 @@ and we can make a hole. */ if (cp > buf + n_read) { /* 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; } else /* Clear to indicate that a normal write is needed. */ ip = 0; } if (ip == 0) { size_t n = n_read; + + if(x->bwlimit && n > 0) + { + gettimeofday(&new_bwlimit_time, NULL); + bwlimit_time_elapsed_usec = + ( ( new_bwlimit_time.tv_sec - old_bwlimit_time.tv_sec ) + * 1000000 ) + + new_bwlimit_time.tv_usec - old_bwlimit_time.tv_usec; + + old_bwlimit_time.tv_sec = new_bwlimit_time.tv_sec; + old_bwlimit_time.tv_usec = new_bwlimit_time.tv_usec; + + + /* Got another amount of data than intended? */ + + if (n != buf_size) + { + bwlimit_fixed_delay_usec = ( buf_size * 960 ) / + ( x->bwlimit ); + bwlimit_delay_usec = bwlimit_fixed_delay_usec; + bwlimit_delay_correction_usec = 0; + } + + /* check gap */ + + bwlimit_delay_correction_usec = bwlimit_fixed_delay_usec - + bwlimit_time_elapsed_usec; + + bwlimit_delay_correction_usec = + bwlimit_delay_correction_usec >> 1; + bwlimit_delay_usec += bwlimit_delay_correction_usec; + + + if ( bwlimit_delay_usec > BWLIMIT_DELAY_THRESHOLD ) + { + bwlimit_tv.tv_sec = 0; + bwlimit_tv.tv_nsec = 1000 * bwlimit_delay_usec ; + while ( bwlimit_tv.tv_nsec > 1000000000 ) + { + bwlimit_tv.tv_sec++; + bwlimit_tv.tv_nsec -= 1000000000; + } + nanosleep(&bwlimit_tv, NULL); + } + } + if (full_write (dest_desc, buf, n) != n) { error (0, errno, _("writing %s"), quote (dst_path)); return_val = -1; goto close_src_and_dst_desc; } last_write_made_hole = 0; } } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. */ if (last_write_made_hole) { #if HAVE_FTRUNCATE /* Write a null character and truncate it again. */ if (full_write (dest_desc, "", 1) != 1 || ftruncate (dest_desc, n_read_total) < 0) diff -ruNU 20 ../coreutils-4.5.6.orig/src/copy.h ./src/copy.h --- ../coreutils-4.5.6.orig/src/copy.h 2003-02-10 14:33:28.000000000 +0100 +++ ./src/copy.h 2003-02-10 17:18:08.000000000 +0100 @@ -122,40 +122,44 @@ /* If nonzero, copy directories recursively and copy special files as themselves rather than copying their contents. */ int recursive; /* If nonzero, set file mode to value of MODE. Otherwise, set it based on current umask modified by UMASK_KILL. */ int set_mode; /* Set the mode of the destination file to exactly this value if USE_MODE is nonzero. */ mode_t mode; /* Control creation of sparse files. */ enum Sparse_type sparse_mode; /* If nonzero, create symbolic links instead of copying files. Create destination directories as usual. */ int symbolic_link; + /* If nonzero, sleep between read()-write() cycles to limit bandwidth + usage. Argument given as kB/s */ + int bwlimit; + /* If nonzero, do not copy a nondirectory that has an existing destination with the same or newer modification time. */ int update; /* If nonzero, display the names of the files before copying them. */ int verbose; /* A pointer to either lstat or stat, depending on whether the copy should dereference symlinks. */ int (*xstat) (); /* If nonzero, stdin is a tty. */ int stdin_tty; /* This is a set of destination name/inode/dev triples. Each such triple represents a file we have created corresponding to a source file name that was specified on the command line. Use it to avoid clobbering source files in commands like this: rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c For now, it protects only regular files when copying (i.e. not renaming). diff -ruNU 20 ../coreutils-4.5.6.orig/src/cp.c ./src/cp.c --- ../coreutils-4.5.6.orig/src/cp.c 2003-02-10 14:33:28.000000000 +0100 +++ ./src/cp.c 2003-02-10 17:15:10.000000000 +0100 @@ -128,40 +128,41 @@ {"archive", no_argument, NULL, 'a'}, {"backup", optional_argument, NULL, 'b'}, {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION}, {"dereference", no_argument, NULL, 'L'}, {"force", no_argument, NULL, 'f'}, {"interactive", no_argument, NULL, 'i'}, {"link", no_argument, NULL, 'l'}, {"no-dereference", no_argument, NULL, 'P'}, {"no-preserve", required_argument, NULL, NO_PRESERVE_ATTRIBUTES_OPTION}, {"one-file-system", no_argument, NULL, 'x'}, {"parents", no_argument, NULL, PARENTS_OPTION}, {"path", no_argument, NULL, PARENTS_OPTION}, /* Deprecated. */ {"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION}, {"recursive", no_argument, NULL, 'R'}, {"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING}, {"reply", required_argument, NULL, REPLY_OPTION}, {"sparse", required_argument, NULL, SPARSE_OPTION}, {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION}, {"suffix", required_argument, NULL, 'S'}, {"symbolic-link", no_argument, NULL, 's'}, + {"throughput", required_argument, NULL, 't'}, {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION}, {"update", no_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */ {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} }; void usage (int status) { if (status != 0) fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else { printf (_("\ Usage: %s [OPTION]... SOURCE DEST\n\ or: %s [OPTION]... SOURCE... DIRECTORY\n\ @@ -200,40 +201,41 @@ fputs (_("\ --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ --parents append source path to DIRECTORY\n\ -P same as `--no-dereference'\n\ "), stdout); fputs (_("\ -R, -r, --recursive copy directories recursively\n\ --remove-destination remove each existing destination file before\n\ attempting to open it (contrast with --force)\n\ "), stdout); fputs (_("\ --reply={yes,no,query} specify how to handle the prompt about an\n\ existing destination file\n\ --sparse=WHEN control creation of sparse files\n\ --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ argument\n\ "), stdout); fputs (_("\ -s, --symbolic-link make symbolic links instead of copying\n\ -S, --suffix=SUFFIX override the usual backup suffix\n\ + -t, --throughput=rate limit throughput to rate kBytes per second\n\ --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\ "), stdout); fputs (_("\ -u, --update copy only when the SOURCE file is newer\n\ than the destination file or when the\n\ destination file is missing\n\ -v, --verbose explain what is being done\n\ -x, --one-file-system stay on this file system\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\ \n\ By default, sparse SOURCE files are detected by a crude heuristic and the\n\ corresponding DEST file is made sparse as well. That is the behavior\n\ selected by --sparse=auto. Specify --sparse=always to create a sparse DEST\n\ file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\ Use --sparse=never to inhibit creation of sparse files.\n\ \n\ "), stdout); @@ -766,40 +768,41 @@ { x->copy_as_regular = 1; x->dereference = DEREF_UNDEFINED; x->unlink_dest_before_opening = 0; x->unlink_dest_after_failed_open = 0; x->hard_link = 0; x->interactive = I_UNSPECIFIED; x->myeuid = geteuid (); x->move_mode = 0; x->one_file_system = 0; x->preserve_ownership = 0; x->preserve_links = 0; x->preserve_mode = 0; x->preserve_timestamps = 0; x->require_preserve = 0; x->recursive = 0; x->sparse_mode = SPARSE_AUTO; x->symbolic_link = 0; + x->bwlimit = 0; x->set_mode = 0; x->mode = 0; /* Not used. */ x->stdin_tty = 0; x->update = 0; x->verbose = 0; x->dest_info = NULL; x->src_info = NULL; } /* Given a string, ARG, containing a comma-separated list of arguments to the --preserve option, set the appropriate fields of X to ON_OFF. */ static void decode_preserve_arg (char const *arg, struct cp_options *x, int on_off) { enum File_attribute { PRESERVE_MODE, @@ -877,41 +880,41 @@ int make_backups = 0; char *backup_suffix_string; char *version_control_string = NULL; struct cp_options x; int copy_contents = 0; char *target_directory = NULL; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); cp_option_init (&x); /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless 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, "abdfHilLprsuvxPRS:t:V:", long_opts, NULL)) != -1) { switch (c) { case 0: break; case SPARSE_OPTION: x.sparse_mode = XARGMATCH ("--sparse", optarg, sparse_type_string, sparse_type); break; case 'a': /* Like -dpPR. */ x.dereference = DEREF_NEVER; x.preserve_links = 1; x.preserve_ownership = 1; x.preserve_mode = 1; x.preserve_timestamps = 1; x.require_preserve = 1; x.recursive = 1; @@ -1000,40 +1003,49 @@ reply_args, reply_vals); break; case UNLINK_DEST_BEFORE_OPENING: x.unlink_dest_before_opening = 1; break; case STRIP_TRAILING_SLASHES_OPTION: remove_trailing_slashes = 1; break; case 's': #ifdef S_ISLNK x.symbolic_link = 1; #else error (EXIT_FAILURE, 0, _("symbolic links are not supported on this system")); #endif break; + case 't': + x.bwlimit = atoi(optarg); + if ( x.bwlimit < 0 ) + { + error (EXIT_FAILURE, 0, + _("Can't limit to negative bandwidth")); + } + break; + case TARGET_DIRECTORY_OPTION: target_directory = optarg; break; case 'u': x.update = 1; break; case 'v': x.verbose = 1; break; case 'x': x.one_file_system = 1; break; case 'S': make_backups = 1; backup_suffix_string = optarg; break; diff -ruNU 20 ../coreutils-4.5.6.orig/src/install.c ./src/install.c --- ../coreutils-4.5.6.orig/src/install.c 2003-02-10 14:33:39.000000000 +0100 +++ ./src/install.c 2003-02-10 18:07:58.000000000 +0100 @@ -139,40 +139,41 @@ static void cp_option_init (struct cp_options *x) { x->copy_as_regular = 1; x->dereference = DEREF_ALWAYS; x->unlink_dest_before_opening = 1; x->unlink_dest_after_failed_open = 0; x->hard_link = 0; x->interactive = I_UNSPECIFIED; x->move_mode = 0; x->myeuid = geteuid (); x->one_file_system = 0; x->preserve_ownership = 0; x->preserve_links = 0; x->preserve_mode = 0; x->preserve_timestamps = 0; x->require_preserve = 0; x->recursive = 0; x->sparse_mode = SPARSE_AUTO; x->symbolic_link = 0; + x->bwlimit = 0; x->backup_type = none; /* Create destination files initially writable so we can run strip on them. Although GNU strip works fine on read-only files, some others would fail. */ x->set_mode = 1; x->mode = S_IRUSR | S_IWUSR; x->stdin_tty = 0; x->update = 0; x->verbose = 0; x->xstat = stat; x->dest_info = NULL; x->src_info = NULL; } int main (int argc, char **argv) { int optc; diff -ruNU 20 ../coreutils-4.5.6.orig/src/mv.c ./src/mv.c --- ../coreutils-4.5.6.orig/src/mv.c 2003-02-10 14:33:28.000000000 +0100 +++ ./src/mv.c 2003-02-10 18:15:59.000000000 +0100 @@ -73,40 +73,41 @@ "yes", "no", "query", 0 }; /* The values that correspond to the above strings. */ static int const reply_vals[] = { I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER }; static struct option const long_options[] = { {"backup", optional_argument, NULL, 'b'}, {"force", no_argument, NULL, 'f'}, {"interactive", no_argument, NULL, 'i'}, {"reply", required_argument, NULL, REPLY_OPTION}, {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION}, {"suffix", required_argument, NULL, 'S'}, {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION}, {"update", no_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, + {"throughput", required_argument, NULL, 't'}, {"version-control", required_argument, NULL, 'V'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} }; static void rm_option_init (struct rm_options *x) { x->unlink_dirs = 0; x->ignore_missing_files = 0; x->recursive = 1; /* Should we prompt for removal, too? No. Prompting for the `move' part is enough. It implies removal. */ x->interactive = 0; x->stdin_tty = 0; @@ -116,40 +117,41 @@ static void cp_option_init (struct cp_options *x) { x->copy_as_regular = 0; /* FIXME: maybe make this an option */ x->dereference = DEREF_NEVER; x->unlink_dest_before_opening = 0; x->unlink_dest_after_failed_open = 0; x->hard_link = 0; x->interactive = I_UNSPECIFIED; x->move_mode = 1; x->myeuid = geteuid (); x->one_file_system = 0; x->preserve_ownership = 1; x->preserve_links = 1; x->preserve_mode = 1; x->preserve_timestamps = 1; x->require_preserve = 0; /* FIXME: maybe make this an option */ x->recursive = 1; x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ x->symbolic_link = 0; + x->bwlimit = 0; x->set_mode = 0; x->mode = 0; x->stdin_tty = isatty (STDIN_FILENO); x->update = 0; x->verbose = 0; x->xstat = lstat; x->dest_info = NULL; x->src_info = NULL; } /* If PATH is an existing directory, return nonzero, else 0. */ static int is_real_dir (const char *path) { struct stat stats; return lstat (path, &stats) == 0 && S_ISDIR (stats.st_mode); } @@ -312,40 +314,41 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\ \n\ "), stdout); fputs (_("\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ --backup[=CONTROL] make a backup of each existing destination file\n\ -b like --backup but does not accept an argument\n\ -f, --force do not prompt before overwriting\n\ equivalent to --reply=yes\n\ -i, --interactive prompt before overwrite\n\ equivalent to --reply=query\n\ "), stdout); fputs (_("\ --reply={yes,no,query} specify how to handle the prompt about an\n\ existing destination file\n\ --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ argument\n\ -S, --suffix=SUFFIX override the usual backup suffix\n\ + -t, --throughput=rate limit throughput to rate kBytes per second\n\ "), stdout); fputs (_("\ --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\ -u, --update move only when the SOURCE file is newer\n\ than the destination file or when the\n\ destination file is missing\n\ -v, --verbose explain what is being done\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\ \n\ The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\ The version control method may be selected via the --backup option or through\n\ the VERSION_CONTROL environment variable. Here are the values:\n\ \n\ "), stdout); fputs (_("\ none, off never make backups (even if --backup is given)\n\ numbered, t make numbered backups\n\ @@ -370,65 +373,73 @@ char *target_directory = NULL; int target_directory_specified; unsigned int n_files; char **file; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); cp_option_init (&x); /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); errors = 0; - while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1) + while ((c = getopt_long (argc, argv, "bfiuvS:t:V:", long_options, NULL)) != -1) { switch (c) { case 0: break; case 'V': /* FIXME: this is deprecated. Remove it in 2001. */ error (0, 0, _("warning: --version-control (-V) is obsolete; support for\ it\nwill be removed in some future release. Use --backup=%s instead." ), optarg); /* Fall through. */ case 'b': make_backups = 1; if (optarg) version_control_string = optarg; break; case 'f': x.interactive = I_ALWAYS_YES; break; case 'i': x.interactive = I_ASK_USER; break; + case 't': + x.bwlimit = atoi(optarg); + if ( x.bwlimit < 0 ) + { + error (EXIT_FAILURE, 0, + _("Can't limit to negative bandwidth")); + } + break; case REPLY_OPTION: x.interactive = XARGMATCH ("--reply", optarg, reply_args, reply_vals); break; case STRIP_TRAILING_SLASHES_OPTION: remove_trailing_slashes = 1; break; case TARGET_DIRECTORY_OPTION: target_directory = optarg; break; case 'u': x.update = 1; break; case 'v': x.verbose = 1; break; case 'S': make_backups = 1; backup_suffix_string = optarg; break;