From b6abf79d60722dbee89e6270435d0b11c0dffa91 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 30 Nov 2003 14:27:42 +0000 Subject: relase 0.3 --copy-always --sort bi-directory merges --check-md git-svn-id: file:///home/lennart/svn/public/syrep/trunk@43 07ea20a6-d2c5-0310-9e02-9ef735347d72 --- configure.ac | 19 +++++---- doc/README.html.in | 8 +++- doc/todo.txt | 8 ++-- man/man.css | 30 -------------- man/man.xsl | 120 ----------------------------------------------------- man/syrep.1.xml.in | 47 +++++++++++++++++---- man/xmltoman.css | 30 ++++++++++++++ man/xmltoman.dtd | 39 +++++++++++++++++ man/xmltoman.xsl | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cache.c | 6 ++- src/cleanup.c | 4 ++ src/context.c | 4 ++ src/dbstruct.h | 6 +-- src/dbutil.c | 15 ++++++- src/dbutil.h | 1 + src/diff.c | 4 ++ src/dump.c | 4 ++ src/extract.c | 4 ++ src/history.c | 4 ++ src/info.c | 8 +++- src/list.c | 117 ++++++++++++++++++++++++++++++++++++++++++++------- src/makepatch.c | 6 ++- src/md5.c | 4 ++ src/md5util.c | 30 +++++++++++++- src/md5util.h | 4 +- src/merge.c | 82 ++++++++++++++++++++++++++++-------- src/merge.h | 2 +- src/package.c | 4 ++ src/syrep.c | 83 +++++++++++++++++++----------------- src/syrep.ggo | 5 ++- src/update.c | 7 +++- src/util.c | 12 ++++-- test/Makefile | 2 +- 33 files changed, 579 insertions(+), 260 deletions(-) delete mode 100644 man/man.css delete mode 100644 man/man.xsl create mode 100644 man/xmltoman.css create mode 100644 man/xmltoman.dtd create mode 100644 man/xmltoman.xsl diff --git a/configure.ac b/configure.ac index b139740..b1e0fb4 100644 --- a/configure.ac +++ b/configure.ac @@ -31,8 +31,13 @@ AC_PROG_LN_S AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/syrep/]) -if test -d /usr/local/stow ; then - AC_MSG_NOTICE([*** Found /usr/local/stow: installing to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) +# If using GCC specifiy some additional parameters +if test "x$GCC" = "xyes" ; then + CFLAGS="$CFLAGS -pipe -Wall" +fi + +if type -p stow > /dev/null && test -d /usr/local/stow ; then + AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) AC_PREFIX_DEFAULT([/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}]) fi @@ -49,22 +54,20 @@ AC_CHECK_HEADER([sys/sendfile.h], sendfile=yes, sendfile=no) if test "x$sendfile" = xyes ; then AC_CHECK_LIB([c], [sendfile], sendfile=yes, sendfile=no) - CPPFLAGS="$CPPFLAGS -DUSE_SENDFILE" + AC_DEFINE([USE_SENDFILE], [1], [Use sendfile()]) fi AM_CONDITIONAL([USE_SENDFILE], [test "x$sendfile" = xyes]) - AC_C_BIGENDIAN - if test "x$ac_cv_c_bigendian" = "xyes"; then - CFLAGS="$CPPFLAGS -DARCH_IS_BIG_ENDIAN=1" + AC_DEFINE([ARCH_IS_BIG_ENDIAN], [1], [Big Endian machine]) else - CPPFLAGS="$CPPFLAGS -DARCH_IS_BIG_ENDIAN=0" + AC_DEFINE([ARCH_IS_BIG_ENDIAN], [0], [Big Endian machine]) fi # 64 Bit LFS support -CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" +AC_SYS_LARGEFILE AC_HEADER_DIRENT AC_HEADER_STDC diff --git a/doc/README.html.in b/doc/README.html.in index 3a9d750..896e28a 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -42,6 +42,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

News

+
Sun Nov 30 2003:

Version 0.3 released; Changes +include: new options --sort, --check-md, +--always-copy; implemented direct bi-directory merges, +documentation updates, build system updates, assorted fixes.

+
Tue Sep 9 2003:

Version 0.2 released; Fixes include: documentation update, --diff output improved, --merge output fixed.

@@ -221,7 +227,7 @@ L. Peter Deutsch. Thanks to him for this.


-
Lennart Poettering <@PACKAGE_BUGREPORT@>, Sep 2003
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, Nov 2003
$Id$
diff --git a/doc/todo.txt b/doc/todo.txt index 9870198..762843c 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -26,11 +26,11 @@ pre-0.1: post-0.1: - continue merge on copy failure - url/ssh merges -- bi-directory merges -- digest check before delete/replace/link +- bi-directory merges DONE +- digest check before delete/replace/link DONE - some more asserts -- PATH_MAX or PATH_MAX+1? -- add --always-copy +- PATH_MAX or PATH_MAX+1? DONE +- add --always-copy DONE - add --forget - valgrind diff --git a/man/man.css b/man/man.css deleted file mode 100644 index 37dd55f..0000000 --- a/man/man.css +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of syrep. - - syrep is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - syrep 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 syrep; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -***/ - -body { color: black; background-color: white; margin: 0.5cm; } -a:link, a:visited { color: #900000; } -h1 { text-transform:uppercase; font-size: 18pt; color: #00009F; } -p { margin-left:1cm; margin-right:1cm; } -.cmd { font-family:monospace; } -.file { font-family:monospace; } -.arg { text-transform:uppercase; font-family:monospace; font-style: italic; } -.opt { font-family:monospace; font-weight: bold; } -.manref { font-family:monospace; } -.option .optdesc { margin-left:2cm; } diff --git a/man/man.xsl b/man/man.xsl deleted file mode 100644 index 7946a76..0000000 --- a/man/man.xsl +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - - - - - - <xsl:value-of select="@name"/>(<xsl:value-of select="@section"/>) - - - - -

Name

-

- - - - -

- - - -
- - -

- -

-
- - -

- -

-
- - - - - - - - - - - - - - -
- -
-
- - -

Synopsis

- -
- - -

Synopsis

- -
- - -

Description

- -
- - -

Options

- -
- - -

- -
- - -
-
- - - - - () - - - () - - - - - - - - -
diff --git a/man/syrep.1.xml.in b/man/syrep.1.xml.in index 2b6e502..ce946b7 100644 --- a/man/syrep.1.xml.in +++ b/man/syrep.1.xml.in @@ -1,6 +1,6 @@ - - + + @@ -32,9 +32,11 @@ syrep [options...] --update DIRECTORY ... syrep [options...] --diff SNAPSHOT SNAPSHOT syrep [options...] --merge SNAPSHOT DIRECTORY + syrep [options...] --merge PATCH DIRECTORY + syrep [options...] --merge DIRECTORY DIRECTORY syrep [options...] --makepatch DIRECTORY SNAPSHOT syrep [options...] --extract SNAPSHOT ... - syrep [options...] --cleanup SNAPSHOT ... + syrep [options...] --cleanup DIRECTORY ... @@ -55,7 +57,18 @@

Syrep is able to cope with 64 bit file sizes. (LFS)

-

Syrep is optimized for speed. It may make use of a message digest cache to accelerate the calculation of digests of a whole directory hierarchy.

+

Syrep is optimized for speed. It may make use of a message + digest cache to accelerate the calculation of digests of a whole + directory hierarchy.

+ +

A syrep repository is a normal UNIX directory tree containing a + special directory .syrep with a file + current.syrep (called snapshot) which holds file + system history data. A directory is turned into a syrep repository + by running --update on it. Snapshots are used to + perform basic tasks like comparing repositories (command + --diff) or creating patches between them (command + --make-patch).

@@ -121,7 +134,7 @@ + +
@@ -184,23 +202,36 @@
-
+
+ + +
diff --git a/man/xmltoman.css b/man/xmltoman.css new file mode 100644 index 0000000..0892e4f --- /dev/null +++ b/man/xmltoman.css @@ -0,0 +1,30 @@ +/* $Id$ */ + +/*** + This file is part of ifplugd. + + ifplugd is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + ifplugd 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 ifplugd; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +***/ + +body { color: black; background-color: white; margin: 0.5cm; } +a:link, a:visited { color: #900000; } +h1 { text-transform:uppercase; font-size: 18pt; color: #00009F; } +p { margin-left:1cm; margin-right:1cm; } +.cmd { font-family:monospace; } +.file { font-family:monospace; } +.arg { text-transform:uppercase; font-family:monospace; font-style: italic; } +.opt { font-family:monospace; font-weight: bold; } +.manref { font-family:monospace; } +.option .optdesc { margin-left:2cm; } diff --git a/man/xmltoman.dtd b/man/xmltoman.dtd new file mode 100644 index 0000000..39cfa28 --- /dev/null +++ b/man/xmltoman.dtd @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/man/xmltoman.xsl b/man/xmltoman.xsl new file mode 100644 index 0000000..2048708 --- /dev/null +++ b/man/xmltoman.xsl @@ -0,0 +1,120 @@ + + + + + + + + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + + + + + + <xsl:value-of select="@name"/>(<xsl:value-of select="@section"/>) + + + + +

Name

+

+ + - + +

+ + + +
+ + +

+ +

+
+ + +

+ +

+
+ + + + + + + + + + + + + + +
+ +
+
+ + +

Synopsis

+ +
+ + +

Synopsis

+ +
+ + +

Description

+ +
+ + +

Options

+ +
+ + +

+ +
+ + +
+
+ + + + + () + + + () + + + + + + + + +
diff --git a/src/cache.c b/src/cache.c index 925cd69..6722b55 100644 --- a/src/cache.c +++ b/src/cache.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -157,7 +161,7 @@ int md_cache_get(struct syrep_md_cache *c, const char *path, uint8_t digest[16]) struct stat st; if ((fd = open(path, O_RDONLY)) < 0) { - fprintf(stderr, "open(%s): %s\n", path, strerror(errno)); + fprintf(stderr, "open(\"%s\"): %s\n", path, strerror(errno)); goto finish; } diff --git a/src/cleanup.c b/src/cleanup.c index 6f096f9..447697d 100644 --- a/src/cleanup.c +++ b/src/cleanup.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/context.c b/src/context.c index 677704d..9fe37bb 100644 --- a/src/context.c +++ b/src/context.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/dbstruct.h b/src/dbstruct.h index 74c6059..842e33d 100644 --- a/src/dbstruct.h +++ b/src/dbstruct.h @@ -59,7 +59,7 @@ struct syrep_nhash { /* name hash */ }; struct syrep_name { - char path[PATH_MAX+1]; + char path[PATH_MAX]; }; @@ -69,11 +69,11 @@ struct syrep_name { * syrep_md :: syrep_nrecno => md_nrecno (DUP) * syrep_nrecno :: syrep_md => nrecno_md (DUP) * syrep_nrecno :: syrep_md => nrecno_lastmd - * syrep_md :: syrep_nrecono => md_lastnrecno + * syrep_md :: syrep_nrecno => md_lastnrecno * * syrep_version :: syrep_timestamp => version_timestamp * - * nhash :: nrecno => nhash_nrecno (DUP) + * nhash :: nrecno => nhash_nrecno (DUP) * nrecno :: name => nrecno_name */ diff --git a/src/dbutil.c b/src/dbutil.c index d7aa319..cfa3150 100644 --- a/src/dbutil.c +++ b/src/dbutil.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -152,6 +156,14 @@ int get_current_md_by_nrecno(struct syrep_db_context *c, const struct syrep_nrec return 1; } +int get_current_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, struct syrep_md *md) { + struct syrep_nrecno nrecno; + + if (get_nrecno_by_name(c, name, &nrecno, 0) < 0) + return -1; + + return get_current_md_by_nrecno(c, &nrecno, md); +} uint32_t get_version_timestamp(struct syrep_db_context *c, uint32_t v) { DBT key, data; @@ -210,7 +222,8 @@ int get_name_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nr if (name) { memset(name, 0, sizeof(struct syrep_name)); - strncpy(name->path, data.data, MIN(PATH_MAX, data.size)); + strncpy(name->path, data.data, MIN(PATH_MAX-1, data.size)); + name->path[PATH_MAX-1] = 0; } return 1; diff --git a/src/dbutil.h b/src/dbutil.h index dd4acd2..9d9837c 100644 --- a/src/dbutil.h +++ b/src/dbutil.h @@ -27,6 +27,7 @@ int get_meta_by_nrecno_md(struct syrep_db_context *c, const struct syrep_nrecno*nrecno, const struct syrep_md *md, struct syrep_meta *meta); int get_last_md_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, struct syrep_md *md); int get_current_md_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, struct syrep_md *md); +int get_current_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, struct syrep_md *md); int get_current_nrecno_by_md(struct syrep_db_context *c, const struct syrep_md *md, struct syrep_nrecno *nrecno); uint32_t get_version_timestamp(struct syrep_db_context *c, uint32_t v); diff --git a/src/diff.c b/src/diff.c index 9a87d81..a589504 100644 --- a/src/diff.c +++ b/src/diff.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/dump.c b/src/dump.c index 289478b..5a9b721 100644 --- a/src/dump.c +++ b/src/dump.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/extract.c b/src/extract.c index ec1d8f0..2e63d14 100644 --- a/src/extract.c +++ b/src/extract.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/history.c b/src/history.c index 4da91d5..ff8532e 100644 --- a/src/history.c +++ b/src/history.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/info.c b/src/info.c index 14446c2..a35877c 100644 --- a/src/info.c +++ b/src/info.c @@ -18,16 +18,22 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include +#include #include "info.h" #include "util.h" int info(struct syrep_db_context *c) { + time_t t = (time_t) c->timestamp; assert(c); fprintf(stdout, "Origin: %s\n", c->origin); - fprintf(stdout, "Timestamp: %u; %s", c->timestamp, asctime(localtime(&c->timestamp))); + fprintf(stdout, "Timestamp: %u; %s", c->timestamp, asctime(localtime(&t))); fprintf(stdout, "Version: %u\n", c->version); fprintf(stdout, "Database nrecno_meta: "); statistics(c->db_id_meta); diff --git a/src/list.c b/src/list.c index e5fe62f..f1763eb 100644 --- a/src/list.c +++ b/src/list.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -30,17 +34,21 @@ #include "dbutil.h" #include "syrep.h" -static int handle_file(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, const struct syrep_md *md, const struct syrep_meta *meta) { +static int handle_file(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, const struct syrep_md *md, const struct syrep_meta *meta, const struct syrep_name *name) { struct syrep_meta local_meta; - struct syrep_name name; - int f; + struct syrep_name local_name; assert(c && nrecno && md); - if ((f = get_name_by_nrecno(c, nrecno, &name)) < 0) - return -1; + if (!name) { + int f; + + if ((f = get_name_by_nrecno(c, nrecno, &local_name)) < 0) + return -1; - assert(f); + assert(f); + name = &local_name; + } if (!meta) { int f; @@ -60,9 +68,9 @@ static int handle_file(struct syrep_db_context *c, const struct syrep_nrecno *nr fhex(md->digest, SYREP_DIGESTLENGTH, d); d[SYREP_DIGESTLENGTH*2] = 0; - printf("%s %s%s", d, name.path, meta->last_seen == c->version ? "\t\t" : "\t(deleted)"); + printf("%s %s%s", d, name->path, meta->last_seen == c->version ? "\t\t" : "\t(deleted)"); } else - printf("\t%s%s", name.path, meta->last_seen == c->version ? "\t\t" : "\t(deleted)"); + printf("\t%s%s", name->path, meta->last_seen == c->version ? "\t\t" : "\t(deleted)"); if (args.show_times_flag) printf( "\t(first-seen: %u; last-seen: %u)\n", meta->first_seen, meta->last_seen); @@ -73,16 +81,44 @@ static int handle_file(struct syrep_db_context *c, const struct syrep_nrecno *nr fhex(md->digest, SYREP_DIGESTLENGTH, d); d[SYREP_DIGESTLENGTH*2] = 0; - printf("\t%s", name.path); + printf("\t%s", name->path); } return 0; } +struct sort_entry { + struct syrep_nrecno nrecno; + struct syrep_md md; + struct syrep_meta meta; + struct syrep_name name; +}; + +static int sort_entry_cmp(const void *_a, const void *_b) { + const struct sort_entry *a = _a, *b = _b; + assert(a && b); + + if (a->meta.last_seen < b->meta.last_seen) + return -1; + + if (a->meta.last_seen > b->meta.last_seen) + return 1; + + if (a->meta.first_seen < b->meta.first_seen) + return -1; + + if (a->meta.first_seen > b->meta.first_seen) + return 1; + + return strncmp(a->name.path, b->name.path, PATH_MAX); +}; + int list(struct syrep_db_context *c) { int r = -1, ret; DBC *cursor = NULL; DBT key, data; + struct sort_entry *sort_array = NULL; + unsigned n_sort_array = 0, m_sort_array = 0; if (args.show_by_md_flag) { struct syrep_md previous_md; @@ -112,7 +148,7 @@ int list(struct syrep_db_context *c) { if ((ret = get_meta_by_nrecno_md(c, recno, md, &meta)) < 0) goto finish; - if (handle_file(c, recno, md, &meta) < 0) + if (handle_file(c, recno, md, &meta, NULL) < 0) fprintf(stderr, "handle_file() failed\n"); } @@ -123,7 +159,7 @@ int list(struct syrep_db_context *c) { r = 0; } else { - + if ((ret = c->db_id_meta->cursor(c->db_id_meta, NULL, &cursor, 0)) != 0) { c->db_id_meta->err(c->db_id_meta, ret, "id_meta"); goto finish; @@ -135,9 +171,59 @@ int list(struct syrep_db_context *c) { while ((ret = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) { struct syrep_id *id = (struct syrep_id*) key.data; - if (handle_file(c, &id->nrecno, &id->md, (struct syrep_meta*) data.data) < 0) - fprintf(stderr, "handle_file() failed\n"); - + if (!args.sort_flag) { + if (handle_file(c, &id->nrecno, &id->md, (struct syrep_meta*) data.data, NULL) < 0) + fprintf(stderr, "handle_file() failed\n"); + + } else { + if (n_sort_array >= m_sort_array) { + + if (!m_sort_array) { + DB_BTREE_STAT *statp; + int ret; + + if ((ret = c->db_id_meta->stat(c->db_id_meta, &statp, 0)) != 0) + break; + + m_sort_array = statp->bt_ndata; + free(statp); + } else + m_sort_array *= 2; + + sort_array = realloc(sort_array, m_sort_array * sizeof(struct sort_entry)); + } + + assert(n_sort_array < m_sort_array); + + if (get_name_by_nrecno(c, &id->nrecno, &sort_array[n_sort_array].name) != 1) + goto finish; + + memcpy(&sort_array[n_sort_array].nrecno, &id->nrecno, sizeof(struct syrep_nrecno)); + memcpy(&sort_array[n_sort_array].md, &id->md, sizeof(struct syrep_md)); + memcpy(&sort_array[n_sort_array].meta, data.data, sizeof(struct syrep_meta)); + n_sort_array++; + } + + if (interrupted) { + fprintf(stderr, "Canceled.\n"); + goto finish; + } + } + + if (args.sort_flag && sort_array) { + unsigned i; + struct sort_entry *se; + qsort(sort_array, n_sort_array, sizeof(struct sort_entry), sort_entry_cmp); + + for (i = 0, se = sort_array; i < n_sort_array; i++, se++) { + if ((handle_file(c, &se->nrecno, &se->md, &se->meta, &se->name)) < 0) + fprintf(stderr, "handle_file() failed\n"); + + if (interrupted) { + fprintf(stderr, "Canceled.\n"); + goto finish; + } + } } if (ret != DB_NOTFOUND) { @@ -153,5 +239,8 @@ finish: if (cursor) cursor->c_close(cursor); + if (sort_array) + free(sort_array); + return r; } diff --git a/src/makepatch.c b/src/makepatch.c index 3de8860..bbce369 100644 --- a/src/makepatch.c +++ b/src/makepatch.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -38,7 +42,7 @@ static int cb(DB *ddb, struct syrep_name *name, struct diff_entry *de, void *p) struct cb_info *cb_info = p; struct syrep_md md; struct syrep_nrecno nrecno; - char path[PATH_MAX+1]; + char path[PATH_MAX]; char d[SYREP_DIGESTLENGTH*2+1]; int f, k; diff --git a/src/md5.c b/src/md5.c index 2c9c2fc..f294588 100644 --- a/src/md5.c +++ b/src/md5.c @@ -51,6 +51,10 @@ 1999-05-03 lpd Original version. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "md5.h" #include diff --git a/src/md5util.c b/src/md5util.c index 6b9a1e2..27c6dd3 100644 --- a/src/md5util.c +++ b/src/md5util.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -25,12 +29,13 @@ #include #include #include +#include #include "md5util.h" #include "md5.h" #include "syrep.h" -void fhex(const unsigned char *bin,int len, char *txt) { +void fhex(const unsigned char *bin, int len, char *txt) { const static char hex[] = "0123456789abcdef"; int i; @@ -43,7 +48,7 @@ void fhex(const unsigned char *bin,int len, char *txt) { #define MMAPSIZE (100*1024*1024) #define BUFSIZE (1024*1024) -int fdmd5(int fd, size_t l, char *md) { +int fdmd5(int fd, off_t l, char *md) { void *d; off_t o = 0; size_t m; @@ -59,6 +64,9 @@ int fdmd5(int fd, size_t l, char *md) { goto finish; } + if (l == (off_t) -1) + l = pre.st_size; + if (l > BUFSIZE) { m = l < MMAPSIZE ? l : MMAPSIZE; @@ -127,3 +135,21 @@ finish: return r; } + +int fmd5(const char *fn, char *md) { + int fd = -1, r = -1; + + if ((fd = open(fn, O_RDONLY)) < 0) { + fprintf(stderr, "open(\"%s\"): %s\n", fn, strerror(errno)); + goto finish; + } + + r = fdmd5(fd, (off_t) -1, md); + +finish: + + if (fd >= 0) + close(fd); + + return r; +} diff --git a/src/md5util.h b/src/md5util.h index f5a342a..373d0b8 100644 --- a/src/md5util.h +++ b/src/md5util.h @@ -26,6 +26,8 @@ void fhex(const unsigned char *bin, int len, char *txt); #define fhex_md5(bin,txt) fhex((bin),16,(txt)) -int fdmd5(int fd, size_t l, char *md); +int fdmd5(int fd, off_t l, char *md); + +int fmd5(const char *fn, char *md); #endif diff --git a/src/merge.c b/src/merge.c index 5741d83..c095f1f 100644 --- a/src/merge.c +++ b/src/merge.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -35,10 +39,11 @@ #include "util.h" struct cb_info { - struct syrep_db_context *c1; - struct syrep_db_context *c2; - const char *root; - char trash_dir[PATH_MAX+1]; + struct syrep_db_context *c1; /* remote */ + struct syrep_db_context *c2; /* local */ + const char *root; /* directory wherein to merge files */ + const char *sroot; /* An optional source directory for bi-directory merges */ + char trash_dir[PATH_MAX]; }; static int conflict_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, void *p) { @@ -47,7 +52,7 @@ static int conflict_phase(DB *ddb, struct syrep_name *name, struct diff_entry *d struct syrep_nrecno nrecno1, nrecno2; int writeback = 0; int f1, f2; - char path[PATH_MAX+1]; + char path[PATH_MAX]; assert(ddb && name && de && p); @@ -172,10 +177,13 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v struct syrep_name name2; struct syrep_nrecno nrecno, nrecno2; struct syrep_md md; - char path[PATH_MAX+1]; + char path[PATH_MAX]; int f; char d[SYREP_DIGESTLENGTH*2+1]; + int (*copy_proc) (const char *, const char*, int c) = args.always_copy_flag ? copy_file : copy_or_link_file; + + assert(ddb && name && de && p); if (de->action != DIFF_COPY && de->action != DIFF_REPLACE) @@ -209,7 +217,7 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v return -1; if (f) { - char path2[PATH_MAX+1]; + char path2[PATH_MAX]; snprintf(path2, sizeof(path2), "%s/%s", cb_info->root, name2.path); if (args.verbose_flag) @@ -219,7 +227,7 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v return -1; if (!access(path2, R_OK)) { - if (copy_or_link_file(path2, path, 0) < 0) + if (copy_proc(path2, path, 0) < 0) return -1; } else { unsigned l; @@ -229,27 +237,39 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v escape_path(name2.path, path2+l, sizeof(path2)-l); if (!access(path2, R_OK)) { - if (copy_or_link_file(path2, path, de->action == DIFF_REPLACE) < 0) + if (copy_proc(path2, path, de->action == DIFF_REPLACE) < 0) return -1; } else fprintf(stderr, "COPY: Local file <%s> vanished. Snapshot not up to date.\n", name2.path); } } else { + char spath[PATH_MAX]; const char* a; + const char* t; int k; if ((k = package_get_item(cb_info->c1->package, d, 0, &a)) < 0) return -1; + t = "patch"; + + if (!k && cb_info->sroot) { + snprintf(spath, sizeof(spath), "%s/%s", cb_info->sroot, name->path); + a = spath; + + if ((k = (access(spath, R_OK) == 0))) + t = "tree"; + } + if (k) { if (args.verbose_flag) - fprintf(stderr, "COPY: Copying file <%s> from patch.\n", name->path); + fprintf(stderr, "COPY: Copying file <%s> from %s.\n", name->path, t); if (makeprefixpath(path, 0777) < 0) return -1; - if (copy_or_link_file(a, path, de->action == DIFF_REPLACE) < 0) + if (copy_proc(a, path, de->action == DIFF_REPLACE) < 0) return -1; } else if (args.verbose_flag) @@ -261,17 +281,43 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v static int delete_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, void *p) { struct cb_info *cb_info = p; - char path[PATH_MAX+1], target[PATH_MAX+1]; + char path[PATH_MAX], target[PATH_MAX]; unsigned l; assert(ddb && name && de && p); - if (de->action != DIFF_DELETE) + if (de->action != DIFF_DELETE && de->action != DIFF_REPLACE) + return 0; + + if (de->action == DIFF_DELETE && de->repository == cb_info->c1) return 0; - if (de->repository == cb_info->c1) + if (de->action == DIFF_REPLACE && de->repository == cb_info->c2) return 0; + snprintf(path, sizeof(path), "%s/%s", cb_info->root, name->path); + + if (args.check_md_flag) { + uint8_t digest[16]; + struct syrep_md md; + + if (fmd5(path, digest) < 0) { + fprintf(stderr, "Unable to calculate message digest sum on '%s'\n", name->path); + return -1; + } + + if (get_current_md_by_name(cb_info->c2, + name, &md) < 0) { + fprintf(stderr, "Failed to get current MD by name of '%s'\n", name->path); + return -1; + } + + if (memcmp(md.digest, digest, 16) != 0) { + fprintf(stderr, "Message digest of file to delete doesn't match snapshot data for '%s'.\n", name->path); + return -1; + } + } + if (args.question_flag) { char text[256]; int q; @@ -285,8 +331,6 @@ static int delete_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, return 0; } - snprintf(path, sizeof(path), "%s/%s", cb_info->root, name->path); - snprintf(target, sizeof(target), "%s/", cb_info->trash_dir); l = strlen(target); escape_path(name->path, target+l, sizeof(target)-l); @@ -303,8 +347,9 @@ static int delete_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, return 0; } -/* Merges c1 into c2 in directory "root" */ -int merge(struct syrep_db_context *c1, struct syrep_db_context *c2, const char* root) { +/* Merges c1 into c2 in directory "root" + * sroot is an optional source directory, only used on bi-directory merges */ +int merge(struct syrep_db_context *c1, struct syrep_db_context *c2, const char* root, const char* sroot) { struct cb_info cb_info; DB *ddb = NULL; int r = -1; @@ -313,6 +358,7 @@ int merge(struct syrep_db_context *c1, struct syrep_db_context *c2, const char* cb_info.c1 = c1; cb_info.c2 = c2; cb_info.root = root; + cb_info.sroot = sroot; snprintf(cb_info.trash_dir, sizeof(cb_info.trash_dir), "%s/.syrep/trash", root); mkdir_p(cb_info.trash_dir, 0777); diff --git a/src/merge.h b/src/merge.h index 02c1a9e..33acf11 100644 --- a/src/merge.h +++ b/src/merge.h @@ -23,7 +23,7 @@ #include "context.h" -int merge(struct syrep_db_context *c1, struct syrep_db_context *c2, const char* root); +int merge(struct syrep_db_context *c1, struct syrep_db_context *c2, const char* root, const char* sroot); int empty_trash(const char *trash); #endif diff --git a/src/package.c b/src/package.c index 9496742..c2841ad 100644 --- a/src/package.c +++ b/src/package.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/syrep.c b/src/syrep.c index e65dc1c..e063072 100644 --- a/src/syrep.c +++ b/src/syrep.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -53,10 +57,6 @@ #include "makepatch.h" #include "cleanup.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "svn-revision.h" volatile int interrupted = 0; @@ -165,7 +165,7 @@ static int do_merge(void) { if (db_context_origin_warn(c2)) goto finish; - if (merge(c1, c2, args.inputs[1]) < 0) + if (merge(c1, c2, args.inputs[1], isdirectory(args.inputs[0]) > 0 ? args.inputs[0] : NULL) < 0) goto finish; r = 0; @@ -478,53 +478,58 @@ static int help(const char *argv0) { "Usage: %s [options...] [arguments...]\n\n" "General options:\n" - " -v --verbose Enable verbose operation\n" - " -T --local-temp Use temporary directory inside repository\n" - " --ignore-origin Don't warn if snapshot not local in update, merge, makepatch\n" - " -z --compress Compress snapshots or patches\n" - " -p --progress Show progress\n\n" + " -v --verbose Enable verbose operation\n" + " -T --local-temp Use temporary directory inside repository\n" + " --ignore-origin Don't warn if snapshot not local in update, merge, makepatch\n" + " -z --compress Compress snapshots or patches\n" + " -p --progress Show progress\n\n" "General commands:\n" - " -h --help Print help and exit\n" - " -V --version Print version and exit\n\n" + " -h --help Print help and exit\n" + " -V --version Print version and exit\n\n" "Specific commands:\n" - " --list List a repository snapshot\n" - " --show-deleted Show deleted entries of repository snapshot\n" - " --show-by-md Show files by message digests\n" - " --show-times Show first and last seen times\n\n" + " --list SNAPSHOT List a repository snapshot\n" + " --show-deleted Show deleted entries of repository snapshot\n" + " --show-by-md Show files by message digests\n" + " --show-times Show first and last seen times\n" + " --sort Sort chronologically\n\n" - " --info Show information about a repository or snapshot\n\n" + " --info SNAPSHOT Show information about a repository or snapshot\n\n" - " --history Show history of a repository or snapshot\n\n" + " --history SNAPSHOT Show history of a repository or snapshot\n\n" - " --dump Show a structure dump of a repository or snapshot\n\n" + " --dump SNAPSHOT Show a structure dump of a repository or snapshot\n\n" - " --update Update a repository snapshot\n" - " -SSTRING --snapshot=STRING Use the specified snapshot file instead of the one contained in the repository\n" - " -CSTRING --cache=STRING Use the specified cache file instead of the one contained in the repository\n" - " --no-cache Don't use a message digest cache\n" - " --no-purge Don't purge obsolete entries from cache after update run\n" - " --ro-cache Use read only cache\n\n" + " --update DIRECTORY Update (or create) a repository snapshot\n" + " -SSTRING --snapshot=STRING Use the specified snapshot file instead of the one contained in the repository\n" + " -CSTRING --cache=STRING Use the specified cache file instead of the one contained in the repository\n" + " --no-cache Don't use a message digest cache\n" + " --no-purge Don't purge obsolete entries from cache after update run\n" + " --ro-cache Use read only cache\n\n" - " --diff Show difference between two repositories or snapshots\n\n" + " --diff SNAPSHOT SNAPSHOT Show difference between two repositories or snapshots\n\n" - " --merge Merge a snapshot or a patch into a repository\n" - " -q --question Ask a question before each action\n" - " --prune-empty Prune empty directories\n" - " --keep-trash Don't empty trash\n\n" + " --merge SNAPSHOT DIRECTORY Merge a snapshot into a repository (perform deletes, renames only)\n" + " --merge PATCH DIRECTORY Merge a patch into a repository\n" + " --merge DIRECTORY DIRECTORY Merge a repository into a repository\n" + " -q --question Ask a question before each action\n" + " -P --prune-empty Prune empty directories\n" + " --keep-trash Don't empty trash\n" + " --check-md Check message digest of files prior to deletion or replacement\n" + " --always-copy Always copy instead of hard link\n\n" - " --makepatch Make a patch against the specified repository\n" - " -oSTRING --output-file=STRING Write output to specified file instead of STDOUT\n" - " --include-all Include files in patch which do exist on the other side under a different name\n\n" + " --makepatch DIRECTORY SNAPSHOT Make a patch against the specified repository\n" + " -oSTRING --output-file=STRING Write output to specified file instead of STDOUT\n" + " --include-all Include files in patch which do exist on the other side under a different name\n\n" - " --extract Extract the contents of a snapshot or patch\n" - " -DSTRING --output-directory=STRING Write output to specified directory\n\n" + " --extract SNAPSHOT Extract the contents of a snapshot or patch\n" + " -DSTRING --output-directory=STRING Write output to specified directory\n\n" - " --cleanup Remove syrep info from repository\n" - " -lINT --cleanup-level=INT 1 - just remove temporary data and trash (default)\n" - " 2 - remove MD cache as well\n" - " 3 - remove all syrep data\n", + " --cleanup DIRECTORY Remove syrep info from repository\n" + " -lINT --cleanup-level=INT 1 - just remove temporary data and trash (default)\n" + " 2 - remove MD cache as well\n" + " 3 - remove all syrep data\n", argv0, argv0); return 0; diff --git a/src/syrep.ggo b/src/syrep.ggo index fea530c..5156944 100644 --- a/src/syrep.ggo +++ b/src/syrep.ggo @@ -29,6 +29,7 @@ option "list" - "List a repository snapshot" flag off option "show-deleted" - "list: Show deleted entries of repository snapshot" flag off option "show-by-md" - "list: Show files by message digests" flag off option "show-times" - "list: Show first and last seen times" flag off + option "sort" - "list: sort chronologically" flag off option "info" - "Show information about a repository or snapshot" flag off option "history" - "Show history of a repository or snapshot" flag off @@ -46,8 +47,10 @@ option "diff" - "Show difference between two repositories or snapshots" flag off option "merge" - "Merge a snapshot or a repository into a repository" flag off option "question" q "merge: Ask a question before each action" flag off - option "prune-empty" - "merge: Prune empty directories" flag off + option "prune-empty" P "merge: Prune empty directories" flag off option "keep-trash" - "merge: Don't empty trash" flag off + option "check-md" - "merge: Check message digest of file before deleting or replacing" flag off + option "always-copy" - "merge: Always copy instead of hard linking" flag off option "makepatch" - "Make a patch against the specified repository" flag off option "output-file" o "makepatch: Write output to specified file instead of STDOUT" string no diff --git a/src/update.c b/src/update.c index 06986f9..6fc2d06 100644 --- a/src/update.c +++ b/src/update.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -104,7 +108,8 @@ static int handle_file(struct syrep_db_context *c, uint32_t version, const char struct syrep_nrecno nrecno; memset(&name, 0, sizeof(name)); - strncpy(name.path, path, PATH_MAX); + strncpy(name.path, path, PATH_MAX-1); + name.path[PATH_MAX-1] = 0; if ((r = get_nrecno_by_name(c, &name, &nrecno, 0)) < 0) return -1; diff --git a/src/util.c b/src/util.c index ffc5dc3..5361e70 100644 --- a/src/util.c +++ b/src/util.c @@ -18,6 +18,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -499,11 +503,11 @@ int prune_empty_directories(const char *path, const char *root) { char rroot[PATH_MAX], rpath[PATH_MAX]; - strncpy(rroot, root, PATH_MAX); + strncpy(rroot, root, PATH_MAX-1); rroot[PATH_MAX-1] = 0; normalize_path(rroot); - strncpy(rpath, path, PATH_MAX); + strncpy(rpath, path, PATH_MAX-1); rpath[PATH_MAX-1] = 0; normalize_path(rpath); @@ -545,7 +549,7 @@ int mkdir_p(const char *path, mode_t m) { char *e, *b; int quit = 0; - strncpy(tmp, path, PATH_MAX); + strncpy(tmp, path, PATH_MAX-1); tmp[PATH_MAX-1] = 0; normalize_path(tmp); @@ -582,7 +586,7 @@ int mkdir_p(const char *path, mode_t m) { int makeprefixpath(const char *path, mode_t m) { char tmp[PATH_MAX], *e; - strncpy(tmp, path, PATH_MAX); + strncpy(tmp, path, PATH_MAX-1); tmp[PATH_MAX-1] = 0; normalize_path(tmp); diff --git a/test/Makefile b/test/Makefile index 39c51ae..54e8d32 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ ifdef VERBOSE VERBOSE=-v endif -ARGS+=-z -T --output-directory=extract -opatch --show-deleted --show-times --prune-empty +ARGS+=--sort --check-md -z -T --output-directory=extract -opatch --show-deleted --show-times --prune-empty %: @mkdir -p rep1 rep2 -- cgit