# # cpdir ver.1.5 # # coded by Kenji Arisawa (Kenar) # bug report to: arisawa@aichi-u.ac.jp # location: # http://plan9.aichi-u.ac.jp/netlib/cmd/ # This program, `cpdir' , is a direcory copy tool for Plan9. # # Usage # Usage: cpdir [-vstugRm] [-l pathlist] srcdir dstdir [path ...] Options and arguments: -v: verbose -u: copy owner info -g: copy group info -s: safe option in case of name confliction, then,not remove but just rename. -R: remove redundant files and directories in dstdir -m: merge -t: ignore mtime -l pathlist: Look "Path list file" section of this document. srcdir: source dir from which copy is made. dstdir: destination dir in which copy is made. path ... : pathes in source to be processed. path and pathlist can not co-exist. # # Function: # `cpdir' makes effort to make a copy of file in srcdir to dstdir. Those that are copied are: - contents - modified time - permissions - group if possible. (under -g option) - owner if possible. (under -u option) `cpdir' is complicated program. Because, we have many combinations: sources: file or dir destination: file or dir modified time comparison with source to destination: < or = or > Yes, we have 2*2*6=24 combination. And we have variety of options of `cpdir'... What happens if there are same path name in source and destination ? To make clear, let srcpath and dstpath be source path and destination path. case 1: srcpath is a file and dstpath is also a file Let s.mtime and d.mtime be modified time of source and destination respectively. Then `cpdir' copies: - contents (if s.mtime > d.mtime) - modified time (if s.mtime > d.mtime) - permissions (if s.mtime >= d.mtime) - group (under -g option, if s.mtime >= d.mtime) - owner if possible. (under -u option, if s.mtime >= d.mtime) case 2: srcpath is a directory and dstpath is also a directory. Then `cpdir' goes into deeper level of both directory and copying process continues. In exiting the direcory,`cpdir' copies: - modified time (if s.mtime > d.mtime) - permissions (if s.mtime >= d.mtime) - group (under -g option, if s.mtime >= d.mtime) - owner if possible. (under -u option, if s.mtime >= d.mtime) case 3: srcpath is a file and dstpath is a directory If s.mtime > d.mtime then: `cpdir' just renames dstpath adding '_' at the beginning of basename, and then create a copy of srcpath to dstpath. With uid/gid option in path list file, `cpdir' copies files with that uid/gid in dstpath. case 4: srcpath is a directory and dstpath is a file If s.mtime > d.mtime then: without any option, `cpdir' removes dstpath and then create a copy of srcpath to dstpath; with -s option, `cpdir' just renames dstpath adding '_' at the beginning of basename, and then create a copy of srcpath to dstpath. With uid/gid option in path list file, `cpdir' copies files with that uid/gid in dstpath. With -R option, `cpdir' removes files and directories in destination that are non-existent in source. # # Some usage examples # example 1: make a copy of a directory. % cpdir srcdir dstdir where srcdir is a path to the source directory and dstdir is a path to the destination directory. If dstdir is already exist, -m option is required. % cpdir -m srcdir dstdir example 2: Let's assume that we, host owner, want to have a copy (a mirror) of remote fs in local fs. We assume local fs is fossil. then: confirm remote are mounted on /n, say, /n/remote and execute: % mntgen % echo srv -APW f | con fscons % mount /srv/f /n/f % cp -x /n/remote/adm/users /n/f/adm/users % echo users -r /active/adm/users % cpdir -mvugR /n/remote /n/f WARNING: R option removes all files that are not in /n/remote. example 3: backup my remote files to local fossil confirm both remote fs and local fs are mounted on, fore example, /n/remote and /n/f, respectively and then execute: % cpdir -mvR /n/remote /n/f $home WARNING: R option removes all files that are not in /n/remote/$home from /n/f/$home. example 4: Synchronize your plan 9 system to outside.plan9.bell-labs.com If you administer your plan 9 system keeping a natural rule: change uid or gid of files that you want to be protected in updating. then you can use `cpdir' in updating your system. I am developing a smart tool to synchronize our system to /n/sources/plan9. Now testing in progress ... # # Path list file # Each line is trimmed before evaluation. Lines that begin with '#' is comment. Blank lines are simply discarded. Other lines have forms: path uid gid path uid path or ! pattern ! The former denotes the path to be processed, while the latter denotes the path pattern that should be rejected. uid and gid are optional and they can be `*' which means "any" uid and gid protect target to be copied. Created files or directories will have these uid and gid. A line path * * is equivalent to path and a line path sys * is equivalent to path sys For example, term% ls -l /lib/ndb --rw-rw-r-- M 8 sys staff 581 Dec 12 23:49 /lib/ndb/auth --rw-rw-r-- M 8 sys sys 5285 Jul 31 01:06 /lib/ndb/common --rw-rw-r-- M 8 sys sys 95 Jun 6 2000 /lib/ndb/consoledb d-rwxrwxr-x M 8 sys sys 0 May 9 2002 /lib/ndb/dhcp --rw-rw-r-- M 8 sys sys 61 Sep 15 2002 /lib/ndb/dnsdump --rw-rw-r-- M 8 sys staff 5078 Jan 8 19:47 /lib/ndb/local --rw-rw-r-- M 8 sys sys 2976 Jan 12 01:40 /lib/ndb/local.complicated --rw-rw-r-- M 8 sys staff 241 Sep 13 2002 /lib/ndb/nfs then /lib/ndb/auth,/lib/ndb/local,/lib/ndb/nfs will not be overwritten under path list description: lib sys sys Lines that begin with `!' mean the path that should not be processed. Path pattern follows `!', and the pattern is Rc style globe matching except `/' is not special. Null pattern, that is, single '!' in a line ! will terminate pattern list. (but not terminate path list.) # # sample path list file for -l option: # 386 * sys cron sys * dist sys sys rc sys lib sys sys sys sys sys acme * * mail/lib upas upas adm/timezone ! sys/log/* ! lp/* ! */tmp/* ! */_* ! * * Don't mined so much, this is merely a sample that shows syntax Last pattern denote: files that contains space. Note that tokenize is not supported in pattern. I hate file names that begin or end with spaces. And I also hate file names that contain '?' and/or '*'. cpdir does not handle these file name patterns that follow '!'. Known bug: Note: Not enough tested