From owner-freebsd-ports-bugs@FreeBSD.ORG Thu May 22 19:00:01 2014 Return-Path: Delivered-To: freebsd-ports-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DEBBFF52 for ; Thu, 22 May 2014 19:00:01 +0000 (UTC) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B9F76202C for ; Thu, 22 May 2014 19:00:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.8/8.14.8) with ESMTP id s4MJ01wG011346 for ; Thu, 22 May 2014 19:00:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.8/8.14.8/Submit) id s4MJ01vF011345; Thu, 22 May 2014 19:00:01 GMT (envelope-from gnats) Resent-Date: Thu, 22 May 2014 19:00:01 GMT Resent-Message-Id: <201405221900.s4MJ01vF011345@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-ports-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Michael Graziano Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 4DB58DF2 for ; Thu, 22 May 2014 18:54:23 +0000 (UTC) Received: from cgiserv.freebsd.org (cgiserv.freebsd.org [IPv6:2001:1900:2254:206a::50:4]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 390722FFA for ; Thu, 22 May 2014 18:54:23 +0000 (UTC) Received: from cgiserv.freebsd.org ([127.0.1.6]) by cgiserv.freebsd.org (8.14.8/8.14.8) with ESMTP id s4MIsM21029313 for ; Thu, 22 May 2014 18:54:22 GMT (envelope-from nobody@cgiserv.freebsd.org) Received: (from nobody@localhost) by cgiserv.freebsd.org (8.14.8/8.14.8/Submit) id s4MIsM88029312; Thu, 22 May 2014 18:54:22 GMT (envelope-from nobody) Message-Id: <201405221854.s4MIsM88029312@cgiserv.freebsd.org> Date: Thu, 22 May 2014 18:54:22 GMT From: Michael Graziano To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: ports/190120: Staging (and other misc. updates) for sysutils/radmind X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 May 2014 19:00:02 -0000 >Number: 190120 >Category: ports >Synopsis: Staging (and other misc. updates) for sysutils/radmind >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: maintainer-update >Submitter-Id: current-users >Arrival-Date: Thu May 22 19:00:01 UTC 2014 >Closed-Date: >Last-Modified: >Originator: Michael Graziano >Release: RELENG_9_1 >Organization: >Environment: FreeBSD SYSBUILDER.dev.premierheart.com 9.1-RELEASE-p12 FreeBSD 9.1-RELEASE-p12 #3 r265198: Thu May 1 17:14:50 EDT 2014 root@SYSBUILDER.dev.premierheart.com:/usr/obj/usr/src/sys/ph-amd64 amd64 >Description: The attached patch converts sysutils/radmind for staging. Staging QA tests pass and packaging appears to be working correctly for both root and non-root users. This patch also removes the "ignore timestamps" option (subtly broken and no longer used in my environment so I can't validate it) and adds upstream bug fixes through 2012-05-22 which are not currently in the distfiles. Recommend applying this patch with "patch -E" to remove dead items from the files directory which are now contained in the rollup patch. >How-To-Repeat: >Fix: Patch attached Patch attached with submission follows: diff -ruN ./Makefile ./Makefile --- ./Makefile 2014-05-22 14:34:26.000000000 -0400 +++ ./Makefile 2014-05-22 14:23:44.000000000 -0400 @@ -3,7 +3,7 @@ PORTNAME= radmind PORTVERSION= 1.14.1 -PORTREVISION= 2012032001 +PORTREVISION= 2014052201 CATEGORIES= sysutils MASTER_SITES= SF MASTER_SITE_SUBDIR=${PORTNAME}/${PORTNAME}/${PORTNAME}-${PORTVERSION} @@ -27,35 +27,33 @@ PLIST_SUB= RADMIND_BASE_DIR=${RADMIND_BASE_DIR} RADMINUSER=${RADMINUSER} SUB_FILES+= pkg-install pkg-message -MAN1= fsdiff.1 ktcheck.1 lapply.1 lcksum.1 lcreate.1 lfdiff.1 \ - lmerge.1 lsort.1 twhich.1 rash.1 repo.1 -MAN5= applefile.5 -MAN8= radmind.8 DOCS= COPYRIGHT README SPEC -OPTIONS_DEFINE= IGNORE_TIMESTAMPS DOCS +OPTIONS_DEFINE= DOCS IGNORE_TIMESTAMPS_DESC= Add '-t' option to fsdiff -NO_STAGE= yes .include -.if ${PORT_OPTIONS:MIGNORE_TIMESTAMPS} -EXTRA_PATCHES+= ${FILESDIR}/optpatch-ignore_timestamps -.endif - post-install: -# Ugly hack to remove generated man pages + # Ugly hack to remove generated man pages ${RM} -rf ${WRKSRC}/tmp -.if ${PORT_OPTIONS:MDOCS} - ${MKDIR} ${DOCSDIR} - cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${DOCSDIR} -.endif - ${CP} ${FILESDIR}/config.sample ${RADMIND_BASE_DIR}/config.sample - @if [ ! -f ${RADMIND_BASE_DIR}/config ]; then \ - ${CP} -p ${RADMIND_BASE_DIR}/config.sample ${RADMIND_BASE_DIR}/config ; \ - fi - @${CHOWN} -R ${RADMINUSER}:${RADMINUSER} ${RADMIND_BASE_DIR} - @${CAT} ${PKGMESSAGE} + # Port's Docs (Copyright & wire protocol info) + ${MKDIR} ${STAGEDIR}${DOCSDIR} + cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${STAGEDIR}${DOCSDIR} + + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR} + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/cert + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/client + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/command + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/file + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/postapply + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/preapply + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/special + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/file + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/transcript + ${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/transcript + ${CP} ${FILESDIR}/config.sample ${STAGEDIR}${RADMIND_BASE_DIR}/config.sample .include diff -ruN ./files/optpatch-ignore_timestamps ./files/optpatch-ignore_timestamps --- ./files/optpatch-ignore_timestamps 2014-05-22 14:34:26.000000000 -0400 +++ ./files/optpatch-ignore_timestamps 1969-12-31 19:00:00.000000000 -0500 @@ -1,94 +0,0 @@ ---- fsdiff.c.orig -+++ fsdiff.c -@@ -33,6 +33,7 @@ int dotfd; - int lastpercent = -1; - int case_sensitive = 1; - int tran_format = -1; -+int ignore_timestamps = 0; - extern int exclude_warnings; - const EVP_MD *md; - -@@ -266,7 +267,7 @@ main( int argc, char **argv ) - cksum = 0; - outtran = stdout; - -- while (( c = getopt( argc, argv, "%1ACc:IK:o:VvW" )) != EOF ) { -+ while (( c = getopt( argc, argv, "%1ACc:IK:o:tVvW" )) != EOF ) { - switch( c ) { - case '%': - case 'v': -@@ -320,6 +321,10 @@ main( int argc, char **argv ) - exclude_warnings = 1; - break; - -+ case 't': /* ignore files for which only the time has changed */ -+ ignore_timestamps = 1; -+ break; -+ - case '?': - printf( "bad %c\n", c ); - errflag++; - ---- man/fsdiff.1.orig -+++ man/fsdiff.1 -@@ -11,7 +11,7 @@ - | - .B -1 - } [ --.BI -IVW -+.BI -IVWt - ] [ - .BI \-K\ command - ] [ -@@ -312,6 +312,9 @@ order of preference and then exits. - prints a warning to the standard error when encountering an object - matching an exclude pattern. - .sp -+.TP 19 -+.B \-t -+ignores files where only the timestamp has changed. - .SH FILES - .TP 19 - .B _RADMIND_COMMANDFILE - ---- transcript.c.orig -+++ transcript.c -@@ -38,6 +38,7 @@ static struct transcript *prev_tran = NULL; - extern int edit_path; - extern int case_sensitive; - extern int tran_format; -+extern int ignore_timestamps; - static char *kdir; - static struct list *kfile_list; - struct list *special_list; -@@ -45,6 +46,7 @@ struct list *exclude_list; - - char *path_prefix = NULL; - int edit_path; -+int ignore_timestamps; - int skip; - int cksum; - int fs_minus; -@@ -544,14 +546,16 @@ t_compare( struct pathinfo *fs, struct transcript *tran ) - t_print( fs, tran, PR_DOWNLOAD ); - break; - } -- } else if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) { -- t_print( fs, tran, PR_DOWNLOAD ); -- break; -+ } else if ( ignore_timestamps == 0 && -+ fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime) { -+ t_print( fs, tran, PR_DOWNLOAD ); -+ break; - } - -- if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) { -- t_print( fs, tran, PR_STATUS ); -- break; -+ if ( ignore_timestamps == 0 && -+ fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) { -+ t_print( fs, tran, PR_STATUS ); -+ break; - } - } - diff -ruN ./files/patch-.gitignore ./files/patch-.gitignore --- ./files/patch-.gitignore 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-.gitignore 1969-12-31 19:00:00.000000000 -0500 @@ -1,17 +0,0 @@ ---- ./.gitignore.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./.gitignore 2012-03-20 14:37:54.000000000 -0400 -@@ -10,12 +10,8 @@ - config.log - config.status - --# External Libraries # --###################### --libsnet -- --# Comiled Files # --################# -+# Compiled Files # -+################## - *.o - fsdiff - ktcheck diff -ruN ./files/patch-20140522 ./files/patch-20140522 --- ./files/patch-20140522 1969-12-31 19:00:00.000000000 -0500 +++ ./files/patch-20140522 2014-05-22 14:34:49.000000000 -0400 @@ -0,0 +1,1412 @@ +diff --git a/.gitignore b/.gitignore +index fc33886..dc49f11 100644 +--- ./.gitignore ++++ ./.gitignore +@@ -10,12 +10,8 @@ config.h + config.log + config.status + +-# External Libraries # +-###################### +-libsnet +- +-# Comiled Files # +-################# ++# Compiled Files # ++################## + *.o + fsdiff + ktcheck +diff --git a/.gitmodules b/.gitmodules +new file mode 100644 +index 0000000..3ebdb4a +--- /dev/null ++++ ./.gitmodules +@@ -0,0 +1,3 @@ ++[submodule "libsnet"] ++ path = libsnet ++ url = git://libsnet.git.sourceforge.net/gitroot/libsnet/libsnet +diff --git a/Makefile.in b/Makefile.in +index e45ecfd..8b0bef8 100644 +--- ./Makefile.in ++++ ./Makefile.in +@@ -204,37 +204,37 @@ tls.o : tls.c + radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile + ${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS} + +-fsdiff : ${FSDIFF_OBJ} ++fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ} + ${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS} + +-ktcheck: ${KTCHECK_OBJ} ++ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ} + ${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS} + +-lapply: ${LAPPLY_OBJ} ++lapply: libsnet/libsnet.la ${LAPPLY_OBJ} + ${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS} + +-lcksum: ${LCKSUM_OBJ} ++lcksum: libsnet/libsnet.la ${LCKSUM_OBJ} + ${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS} + +-lcreate: ${LCREATE_OBJ} ++lcreate: libsnet/libsnet.la ${LCREATE_OBJ} + ${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS} + +-lmerge: ${LMERGE_OBJ} ++lmerge: libsnet/libsnet.la ${LMERGE_OBJ} + ${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS} + +-lfdiff: ${LFDIFF_OBJ} ++lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ} + ${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS} + +-repo : ${REPO_OBJ} ++repo: libsnet/libsnet.la ${REPO_OBJ} + ${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS} + + t2pkg: ${T2PKG_OBJ} + ${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS} + +-twhich: ${TWHICH_OBJ} ++twhich: libsnet/libsnet.la ${TWHICH_OBJ} + ${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS} + +-lsort: ${LSORT_OBJ} ++lsort: libsnet/libsnet.la ${LSORT_OBJ} + ${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS} + + FRC : +diff --git a/README b/README +index bc034ca..4e7e03b 100644 +--- ./README ++++ ./README +@@ -72,25 +72,25 @@ for the kerberos header files: + % "env CPPFLAGS=-I/usr/kerberos/include ./configure" + + ----------------- +-Building from CVS ++Building from git + ----------------- + The Radmind Development Team occasionally asks for help testing a new feature + or bug fix. The best way to assist is to download the source code from the +-CVS repository and build it manually. The following steps will result in +-a build from CVS. ++git repository and build it manually. The following steps will result in ++a build from git. + +-1) Download the source from CVS: ++1) Download the source from git: + +-cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \ +- checkout radmind ++ git clone git://radmind.git.sourceforge.net/gitroot/radmind/radmind + + 2) Move into the new radmind directory: + +-cd radmind ++ cd radmind + +-3) Download libsnet[1], the network library Radmind uses: ++3) Checkout all required submodules [1]: + +-sh bin/getsnet ++ git submodule init ++ git submodule update + + 4) Follow steps 2 and 3 from "More detailed instructions" for building, above. + +@@ -115,4 +115,7 @@ for details on how to join. + ---------- + References + ---------- +-[1]: http://sourceforge.net/projects/libsnet ++[1]: Current submodules: ++ ++ * libsnet, a networking library with TLS support ++ http://sourceforge.net/projects/libsnet +diff --git a/aclocal.m4 b/aclocal.m4 +index 24b1b0f..0b7d456 100644 +--- ./aclocal.m4 ++++ ./aclocal.m4 +@@ -105,16 +105,11 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES], + arches="-arch i386 -arch ppc" + ;; + +- darwin9*) ++ darwin9*|darwin10*|darwin11*) + dep_target="-mmacosx-version-min=10.4" + macosx_sdk="MacOSX10.5.sdk" + arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64" +- ;; +- +- darwin10*) +- dep_target="-mmacosx-version-min=10.4" +- macosx_sdk="MacOSX10.6.sdk" +- arches="-arch i386 -arch x86_64 -arch ppc" ++ LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib" + ;; + + *) +@@ -129,3 +124,20 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES], + fi + ]) + ++AC_DEFUN([MACOSX_MUTE_DEPRECATION_WARNINGS], ++[ ++ dnl Lion deprecates a system-provided OpenSSL. Build output ++ dnl is cluttered with useless deprecation warnings. ++ ++ AS_IF([test x"$CC" = x"gcc"], [ ++ case "${host_os}" in ++ darwin11*) ++ AC_MSG_NOTICE([muting deprecation warnings from compiler]) ++ OPTOPTS="$OPTOPTS -Wno-deprecated-declarations" ++ ;; ++ ++ *) ++ ;; ++ esac ++ ]) ++]) +diff --git a/argcargv.c b/argcargv.c +index 44111af..d78ca47 100644 +--- ./argcargv.c ++++ ./argcargv.c +@@ -48,7 +48,9 @@ acav_parse( ACAV *acav, char *line, char **argv[] ) + + if ( acav == NULL ) { + if ( acavg == NULL ) { +- acavg = acav_alloc(); ++ if (( acavg = acav_alloc()) == NULL ) { ++ return( -1 ); ++ } + } + acav = acavg; + } +diff --git a/bin/getsnet b/bin/getsnet +deleted file mode 100755 +index 1136f54..0000000 +--- ./bin/getsnet ++++ /dev/null +@@ -1,16 +0,0 @@ +-#! /bin/sh +- +-# getsnet: download libsnet source code from SF.net +- +-proj="libsnet" +-rev="1.0.1" +-gitroot="git://${proj}.git.sourceforge.net/gitroot/${proj}/${proj}" +- +-[ -e "${proj}" ] && echo "${proj} already retrieved" && exit 1 +-[ ! -e "${proj}" ] \ +- && git clone ${gitroot} \ +- && (cd "${proj}" \ +- && git checkout -b "${proj}-${rev}-branch" "${proj}-${rev}" \ +- && autoconf) +- +-exit $? +diff --git a/command.c b/command.c +index 9cf6510..5dc0a54 100644 +--- ./command.c ++++ ./command.c +@@ -477,38 +477,90 @@ f_retr( SNET *sn, int ac, char **av ) + + /* looks for special file info in transcripts */ + char ** +-special_t( char *transcript, char *epath ) ++special_t( char *sp_path, char *remote_path ) + { +- FILE *fs; +- int ac, len; +- char **av; ++ FILE *fs = NULL; ++ int i, ac, len, ln; ++ char **av = NULL; ++ char *paths[ 4 ] = { NULL }; ++ char *p; ++ char sp_t[ MAXPATHLEN ]; + static char line[ MAXPATHLEN ]; + +- if (( fs = fopen( transcript, "r" )) == NULL ) { +- return( NULL ); +- } +- +- while ( fgets( line, MAXPATHLEN, fs ) != NULL ) { +- len = strlen( line ); +- if (( line[ len - 1 ] ) != '\n' ) { +- syslog( LOG_ERR, "special_t: %s: line too long", transcript ); +- break; ++ /* ++ * in order, we look for special file transcript lines in the ++ * following locations: ++ * ++ * - A transcript in the same directory and with the same name ++ * as the special file, but with a ".T" extension. ++ * ++ * - A transcript named ".T" in the same directory as ++ * the client's special file directory root. ++ * ++ * - /var/radmind/transcript/special.T ++ * ++ * if no matching transcript line is found, default metadata is ++ * returned to the client (type: f; mode: 0444; owner: 0; group: 0). ++ */ ++ paths[ 0 ] = sp_path; ++ paths[ 1 ] = special_dir; ++ paths[ 2 ] = "transcript/special.T"; ++ paths[ 3 ] = NULL; ++ ++ for ( i = 0; paths[ i ] != NULL; i++ ) { ++ if (( p = strrchr( paths[ i ], '.' )) != NULL ++ && strcmp( p, ".T" ) == 0 ) { ++ if ( strlen( paths[ i ] ) >= MAXPATHLEN ) { ++ syslog( LOG_WARNING, "special_t: path \"%s\" too long", ++ paths[ i ] ); ++ continue; ++ } ++ strcpy( sp_t, paths[ i ] ); ++ } else if ( snprintf( sp_t, MAXPATHLEN, "%s.T", ++ paths[ i ] ) >= MAXPATHLEN ) { ++ syslog( LOG_WARNING, "special_t: path \"%s.T\" too long", sp_path ); ++ continue; + } + +- if (( ac = argcargv( line, &av )) != 8 ) { ++ if (( fs = fopen( sp_t, "r" )) == NULL ) { + continue; + } +- if (( *av[ 0 ] != 'f' ) && ( *av[ 0 ] != 'a' )) { +- continue; ++ ++ ln = 0; ++ while ( fgets( line, MAXPATHLEN, fs ) != NULL ) { ++ ln++; ++ len = strlen( line ); ++ if (( line[ len - 1 ] ) != '\n' ) { ++ syslog( LOG_ERR, "special_t: %s: line %d too long", sp_t, ln ); ++ break; ++ } ++ ++ /* only files and applefiles allowed */ ++ if ( strncmp( line, "f ", strlen( "f " )) != 0 && ++ strncmp( line, "a ", strlen( "a " )) != 0 ) { ++ continue; ++ } ++ if (( ac = argcargv( line, &av )) != 8 ) { ++ syslog( LOG_WARNING, "special_t: %s: line %d: " ++ "bad transcript line", sp_t, ln ); ++ continue; ++ } ++ ++ if ( strcmp( av[ 1 ], remote_path ) == 0 ) { ++ (void)fclose( fs ); ++ return( av ); ++ } + } + +- if ( strcmp( av[ 1 ], epath ) == 0 ) { +- (void)fclose( fs ); +- return( av ); ++ if ( fclose( fs ) != 0 ) { ++ syslog( LOG_WARNING, "special_t: fclose %s: %m", sp_t ); + } ++ fs = NULL; + } +- +- (void)fclose( fs ); ++ if ( fs != NULL ) { ++ (void)fclose( fs ); ++ } ++ + return( NULL ); + } + +@@ -624,11 +676,11 @@ f_stat( SNET *sn, int ac, char *av[] ) + switch ( key ) { + case K_COMMAND: + if ( ac == 2 ) { +- snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n", ++ snet_writef( sn, RADMIND_STAT_FMT, + "f", "command", DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, + st.st_mtime, st.st_size, cksum_b64 ); + } else { +- snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n", ++ snet_writef( sn, RADMIND_STAT_FMT, + "f", av[ 2 ], DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, + st.st_mtime, st.st_size, cksum_b64 ); + } +@@ -636,61 +688,33 @@ f_stat( SNET *sn, int ac, char *av[] ) + + + case K_TRANSCRIPT: +- snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n", ++ snet_writef( sn, RADMIND_STAT_FMT, + "f", av[ 2 ], + DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, + st.st_mtime, st.st_size, cksum_b64 ); + return( 0 ); + + case K_SPECIAL: +- /* status on a special file comes from 1 of three cases: +- * 1. A transcript in the special file directory +- * 2. A transcript in the Transcript dir with .T appended +- * 3. No transcript is found, and constants are returned +- */ +- +- /* look for transcript containing the information */ +- if ( ( strlen( path ) + 2 ) > MAXPATHLEN ) { +- syslog( LOG_WARNING, +- "f_stat: transcript path longer than MAXPATHLEN" ); +- +- /* return constants */ +- snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n", +- "f", av[ 2 ], +- DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, +- st.st_mtime, st.st_size, cksum_b64 ); +- return( 0 ); +- } +- +- /* if allowable, check for transcript in the special file directory */ +- +- strcat( path, ".T" ); +- +- /* store value of av[ 2 ], because argcargv will be called ++ /* ++ * store value of av[ 2 ], because argcargv will be called + * from special_t(), and that will blow away the current values +- * for av[ 2 ] +- * +- * Could just use new argvargc API... XXX Notice how we never free +- * env_file... ++ * for av[ 2 ]. + */ +- + if (( enc_file = strdup( av[ 2 ] )) == NULL ) { + syslog( LOG_ERR, "f_stat: strdup: %s %m", av[ 2 ] ); + return( -1 ); + } + + if (( av = special_t( path, enc_file )) == NULL ) { +- if (( av = special_t( "transcript/special.T", enc_file )) +- == NULL ) { +- snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n", +- "f", enc_file, +- DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, +- st.st_mtime, st.st_size, cksum_b64 ); +- free( enc_file ); +- return( 0 ); +- } ++ /* no special transcript match found, return defaults. */ ++ snet_writef( sn, RADMIND_STAT_FMT, ++ "f", enc_file, ++ DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, ++ st.st_mtime, st.st_size, cksum_b64 ); ++ free( enc_file ); ++ return( 0 ); + } +- snet_writef( sn, "%s %s %s %s %s %d %" PRIofft "d %s\r\n", ++ snet_writef( sn, RADMIND_STAT_FMT, + av[ 0 ], enc_file, + av[ 2 ], av[ 3 ], av[ 4 ], + st.st_mtime, st.st_size, cksum_b64 ); +@@ -1261,8 +1285,7 @@ command_k( char *path_config, int depth ) + continue; + } + if ( strcmp( av[ 0 ], "@include" ) == 0 ) { +- depth++; +- if ( depth > RADMIND_MAX_INCLUDE_DEPTH ) { ++ if ( depth >= RADMIND_MAX_INCLUDE_DEPTH ) { + syslog( LOG_ERR, "%s: line %d: include %s exceeds max depth", + path_config, linenum, av[ 1 ] ); + goto command_k_done; +@@ -1277,7 +1300,7 @@ command_k( char *path_config, int depth ) + continue; + } + } +- if ( command_k( av[ 1 ], depth ) != 0 ) { ++ if ( command_k( av[ 1 ], depth + 1 ) != 0 ) { + continue; + } + +@@ -1325,7 +1348,8 @@ command_k( char *path_config, int depth ) + + /* If we get here, the host that connected is not in the config + file. So screw him. */ +- syslog( LOG_ERR, "host not in config file: %s", remote_host ); ++ syslog( LOG_ERR, "host %s not in config file %s", ++ remote_host, path_config ); + + command_k_done: + snet_close( sn ); +diff --git a/command.h b/command.h +index b0ea9f5..e0ee775 100644 +--- ./command.h ++++ ./command.h +@@ -13,3 +13,5 @@ struct command { + char *c_name; + int (*c_func)( SNET *, int, char *[] ); + }; ++ ++#define RADMIND_STAT_FMT "%s %s %o %d %d %" PRItimet "d %" PRIofft "d %s\r\n" +diff --git a/configure.ac b/configure.ac +index 43a243c..e724f32 100644 +--- ./configure.ac ++++ ./configure.ac +@@ -44,25 +44,36 @@ AC_SYS_LARGEFILE + + # Check sizes + AC_CHECK_SIZEOF(off_t) ++AC_CHECK_SIZEOF(time_t) ++ ++# check early to make any required changes to environment for following tests. ++CHECK_UNIVERSAL_BINARIES ++ ++# mute Mac OS X's helpful notices that using dylib OpenSSL ++MACOSX_MUTE_DEPRECATION_WARNINGS + + # Checks for libraries. + AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) + if test x$libc_inet_aton != xyes; then + AC_CHECK_LIB(resolv, inet_aton) + fi +-AC_CHECK_LIB(c, lchown) +-AC_CHECK_LIB(c, lchmod) ++if test x$host_vendor = xapply; then ++ AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], []) ++ AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], []) ++fi + AC_CHECK_LIB(nsl, gethostbyaddr) + AC_CHECK_LIB([socket], [socket]) + AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL]) + AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file + is required for this software. You may be running RedHat 9. If so, see the FAQ or the README for further instructions.])]) + AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL]) +-AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], []) ++AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], []) + + # PAM +-AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes) ++AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr) + if test x_"$with_pam" != x_no; then ++ CPPFLAGS="${CPPFLAGS} -I$with_pam/include" ++ LDFLAGS="${LDFLAGS} -L$with_pam/lib" + AC_CHECK_LIB([pam], [pam_start], + [ + AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)]) +@@ -75,7 +86,6 @@ AC_CHECK_HEADER([dns_sd.h], [AC_DEFINE(HAVE_DNSSD)], [], []) + AC_CHECK_LIB(dns_sd, DNSServiceRegister) + + CHECK_ZLIB +-CHECK_UNIVERSAL_BINARIES + + # HPUX lacks wait4 and strtoll + AC_CHECK_FUNCS(wait4 strtoll) +diff --git a/contrib/specialist b/contrib/specialist +new file mode 100755 +index 0000000..ee796ac +--- /dev/null ++++ ./contrib/specialist +@@ -0,0 +1,79 @@ ++#! /bin/sh ++ ++# specialist: assist creation of special files. ++ ++PATH=/bin:/usr/bin:/usr/local/bin; export PATH ++ ++SCRIPT=`basename "$0"` ++INPUT_FORMAT=${INPUT_FORMAT:=path} ++ ++usage() { ++ echo "usage: ${SCRIPT} [ -T ]" 1>&2 ++ exit 1 ++} ++ ++die() { ++ msg=$* ++ ++ echo "${msg}" 1>&2 ++ exit 2 ++} ++ ++# create a special transcript line for the given path. ++specialize() { ++ local path="$1" ++ ++ [ -n "${path}" -a -f "${path}" ] || die "Invalid path: ${path}" ++ ++ fsdiff -1 -c sha1 "${path}" ++ return $? ++} ++ ++specialize_transcript() { ++ local path="" ++ status=0 ++ ++ while read type path remainder; do ++ if [ x"${type}" != x"f" ]; then ++ continue ++ fi ++ ++ specialize "${path}" ++ done ++} ++ ++specialize_paths() { ++ local path="" ++ status=0 ++ ++ while read path; do ++ specialize "${path}" ++ if [ $? -ne 0 ]; then ++ status=1 ++ fi ++ done ++ ++ return "${status}" ++} ++ ++while getopts T opt; do ++ case $opt in ++ T) ++ INPUT_FORMAT="transcript" ++ ;; ++ ++ *) ++ usage ++ ;; ++ ++ esac ++done ++shift $((OPTIND - 1)) ++ ++if [ x"${INPUT_FORMAT}" = x"transcript" ]; then ++ specialize_transcript ++else ++ specialize_paths ++fi ++ ++exit $? +diff --git a/fsdiff.c b/fsdiff.c +index 61fbb03..57d3ff0 100644 +--- ./fsdiff.c ++++ ./fsdiff.c +@@ -249,6 +249,144 @@ fs_walk( char *path, struct stat *st, char *type, struct applefileinfo *afinfo, + return; + } + ++ static char * ++canonicalized_path( char *path ) ++{ ++ int len; ++ static char cpath[ MAXPATHLEN ]; ++ ++ if ( path == NULL ) { ++ return( NULL ); ++ } ++ ++ len = strlen( path ); ++ if ( len >= sizeof( cpath )) { ++ fprintf( stderr, "fsdiff: path too long: %s\n", path ); ++ exit( 2 ); ++ } ++ strcpy( cpath, path ); ++ ++ /* Clip trailing '/' */ ++ if (( len > 1 ) && ( cpath[ len - 1 ] == '/' )) { ++ cpath[ len - 1 ] = '\0'; ++ len--; ++ } ++ ++ /* ++ * If prefix doesn't contain a directory, canonicalize it by prepending a ++ * "./". This allow paths to be dynamically converted between relative and ++ * absolute paths without breaking sort order. ++ */ ++ switch( cpath[ 0 ] ) { ++ case '/': ++ break; ++ ++ case '.': ++ /* Don't rewrite '.' or paths starting with './' */ ++ if ( len == 1 || cpath[ 1 ] == '/' ) { ++ break; ++ } ++ ++ default: ++ if ( len + 2 >= sizeof( cpath )) { ++ fprintf( stderr, "fsdiff: path too long: ./%s\n", cpath ); ++ exit( 2 ); ++ } ++ memmove( cpath + 2, cpath, len ); ++ cpath[ 0 ] = '.'; cpath[ 1 ] = '/'; ++ ++ break; ++ } ++ ++ /* ++ * Determine if called with relative or absolute pathing. Path is relative ++ * if it's just '.' or starts with './'. File names that start with a '.' ++ * are absolute. ++ */ ++ if ( cpath[ 0 ] == '.' ) { ++ if ( len == 1 ) { ++ tran_format = T_RELATIVE; ++ } else if ( cpath[ 1 ] == '/' ) { ++ tran_format = T_RELATIVE; ++ } else { ++ tran_format = T_ABSOLUTE; ++ } ++ } else { ++ tran_format = T_ABSOLUTE; ++ } ++ ++ return( cpath ); ++} ++ ++ static void ++fsdiff( char *path, char *kfile, int start, int finish, int pdel ) ++{ ++ struct applefileinfo afinfo; ++ struct stat st; ++ char type; ++ char lpath[ MAXPATHLEN ]; ++ int len; ++ ++ if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) { ++ perror( "OOPS!" ); ++ exit( 2 ); ++ } ++ ++ if ( skip && strcmp( path, "-" ) == 0 ) { ++ /* leave excludes in place */ ++ skip = skip & ~T_SKIP_EXCLUDES; ++ ++ path_prefix = "/"; ++ transcript_init( kfile, K_CLIENT ); ++ ++ /* run -1 against every line we get from stdin */ ++ while ( fgets( lpath, sizeof( lpath ), stdin ) != NULL ) { ++ len = strlen( lpath ); ++ if ( lpath[ len - 1 ] != '\n' ) { ++ fprintf( stderr, "fsdiff: fgets: line too long\n" ); ++ exit( 2 ); ++ } ++ lpath[ len - 1 ] = '\0'; ++ path = canonicalized_path( lpath ); ++ ++ if ( radstat( path, &st, &type, &afinfo ) != 0 ) { ++ if ( errno != ENOENT ) { ++ perror( lpath ); ++ exit( 2 ); ++ } ++ ++ fprintf( stderr, "Warning: %s: %s\n", path, strerror( errno )); ++ continue; ++ } ++ (void)transcript( path, &st, &type, &afinfo, pdel ); ++ } ++ if ( ferror( stdin )) { ++ perror( "fgets" ); ++ exit( 2 ); ++ } ++ } else { ++ path_prefix = canonicalized_path( path ); ++ ++ /* initialize the transcripts */ ++ transcript_init( kfile, K_CLIENT ); ++ ++ if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) { ++ perror( path_prefix ); ++ exit( 2 ); ++ } ++ ++ fs_walk( path_prefix, &st, &type, &afinfo, start, finish, pdel ); ++ } ++ ++ if ( finish > 0 ) { ++ printf( "%%%d\n", ( int )finish ); ++ } ++ ++ /* free the transcripts */ ++ transcript_free( ); ++ hardlink_free( ); ++} ++ + int + main( int argc, char **argv ) + { +@@ -258,9 +396,6 @@ main( int argc, char **argv ) + int c, len, edit_path_change = 0; + int errflag = 0, use_outfile = 0; + int finish = 0; +- struct stat st; +- char type, buf[ MAXPATHLEN ]; +- struct applefileinfo afinfo; + + edit_path = CREATABLE; + cksum = 0; +@@ -300,7 +435,7 @@ main( int argc, char **argv ) + break; + + case '1': +- skip = 1; ++ skip = T_SKIP_ALL; + case 'C': + edit_path_change++; + edit_path = CREATABLE; +@@ -347,82 +482,13 @@ main( int argc, char **argv ) + } + + if ( errflag || ( argc - optind != 1 )) { +- fprintf( stderr, "usage: %s { -C | -A | -1 } [ -IVW ] ", argv[ 0 ] ); ++ fprintf( stderr, "usage: %s { -C | -A | -1 } " "[ -IVW ] ", argv[ 0 ] ); + fprintf( stderr, "[ -K command ] " ); + fprintf( stderr, "[ -c checksum ] [ -o file [ -%% ] ] path\n" ); + exit ( 2 ); + } + +- path_prefix = argv[ optind ]; +- len = strlen( path_prefix ); +- +- /* Clip trailing '/' */ +- if (( len > 1 ) && ( path_prefix[ len - 1 ] == '/' )) { +- path_prefix[ len - 1 ] = '\0'; +- len--; +- } +- +- /* If path_prefix doesn't contain a directory, canonicalize it by +- * prepending a "./". This allow paths to be dynamically converted between +- * relative and absolute paths without breaking sort order. +- */ +- switch( path_prefix[ 0 ] ) { +- case '/': +- break; +- +- case '.': +- /* Don't rewrite '.' or paths starting with './' */ +- if (( len == 1 ) || ( path_prefix[ 1 ] == '/' )) { +- break; +- } +- default: +- if ( snprintf( buf, sizeof( buf ), "./%s", +- path_prefix ) >= MAXPATHLEN ) { +- fprintf( stderr, "path too long\n" ); +- exit( 2 ); +- } +- path_prefix = buf; +- break; +- } +- +- /* Determine if called with relative or absolute pathing. Path is relative +- * if it's just '.' or starts with './'. File names that start with a '.' +- * are absolute. +- */ +- if ( path_prefix[ 0 ] == '.' ) { +- if ( len == 1 ) { +- tran_format = T_RELATIVE; +- } else if ( path_prefix[ 1 ] == '/' ) { +- tran_format = T_RELATIVE; +- } else { +- tran_format = T_ABSOLUTE; +- } +- } else { +- tran_format = T_ABSOLUTE; +- } +- +- if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) { +- perror( path_prefix ); +- exit( 2 ); +- } +- +- if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) { +- perror( "OOPS!" ); +- exit( 2 ); +- } +- +- /* initialize the transcripts */ +- transcript_init( kfile, K_CLIENT ); +- +- fs_walk( path_prefix, &st, &type, &afinfo, 0, finish, 0 ); +- +- if ( finish > 0 ) { +- printf( "%%%d\n", ( int )finish ); +- } +- +- /* free the transcripts */ +- transcript_free( ); +- hardlink_free( ); ++ fsdiff( argv[ optind ], kfile, 0, finish, 0 ); + + /* close the output file */ + fclose( outtran ); +diff --git a/ktcheck.c b/ktcheck.c +index 567a555..9d1f41d 100644 +--- ./ktcheck.c ++++ ./ktcheck.c +@@ -459,7 +459,7 @@ check( SNET *sn, char *type, char *file ) + perror( "Incorrect number of arguments\n" ); + return( 2 ); + } +- times.modtime = atoi( targv[ 5 ] ); ++ times.modtime = strtotimet( targv[ 5 ], NULL, 10 ); + times.actime = time( NULL ); + + if (( stat( path, &st )) != 0 ) { +@@ -506,7 +506,7 @@ check( SNET *sn, char *type, char *file ) + needupdate = 1; + } + } else { +- if ( atoi( targv[ 5 ] ) != (int)st.st_mtime ) { ++ if ( strtotimet( targv[ 5 ], NULL, 10 ) != st.st_mtime ) { + needupdate = 1; + } + } +diff --git a/lapply.c b/lapply.c +index c13ad9e..3749617 100644 +--- ./lapply.c ++++ ./lapply.c +@@ -651,27 +651,37 @@ dirchecklist: + filechecklist: + if ( head == NULL ) { + if ( unlink( path ) != 0 ) { +- perror( path ); +- goto error2; +- } +- if ( !quiet && !showprogress ) { +- printf( "%s: deleted\n", path ); +- } +- if ( showprogress ) { +- progressupdate( PROGRESSUNIT, path ); +- } +- } else { +- if ( ischildcase( path, head->path, case_sensitive )) { +- if ( unlink( path ) != 0 ) { ++ if ( !force || errno != ENOENT ) { + perror( path ); + goto error2; + } ++ fprintf( stderr, "Warning: failed to remove %s: %s\n", ++ path, strerror( errno )); ++ } else { + if ( !quiet && !showprogress ) { + printf( "%s: deleted\n", path ); + } + if ( showprogress ) { + progressupdate( PROGRESSUNIT, path ); + } ++ } ++ } else { ++ if ( ischildcase( path, head->path, case_sensitive )) { ++ if ( unlink( path ) != 0 ) { ++ if ( !force || errno != ENOENT ) { ++ perror( path ); ++ goto error2; ++ } ++ fprintf( stderr, "Warning: failed to remove %s: " ++ "%s\n", path, strerror( errno )); ++ } else { ++ if ( !quiet && !showprogress ) { ++ printf( "%s: deleted\n", path ); ++ } ++ if ( showprogress ) { ++ progressupdate( PROGRESSUNIT, path ); ++ } ++ } + } else { + /* remove head */ + if ( rmdir( head->path ) != 0 ) { +diff --git a/largefile.h b/largefile.h +index 4a11d3b..3a09ce9 100644 +--- ./largefile.h ++++ ./largefile.h +@@ -18,3 +18,15 @@ + #define strtoofft(x,y,z) (strtol((x),(y),(z))) + #define PRIofft "l" + #endif ++ ++#if SIZEOF_TIME_T == 8 ++ #ifdef HAVE_STRTOLL ++ #define strtotimet(x,y,z) (strtoll((x),(y),(z))) ++ #else /* !HAVE_STRTOLL */ ++ #define strtotimet(x,y,z) (strtol((x),(y),(z))) ++ #endif /* HAVE_STRTOLL */ ++ #define PRItimet "ll" ++#else /* SIZEOF_TIME_T != 8 */ ++ #define strtotimet(x,y,z) (strtol((x),(y),(z))) ++ #define PRItimet "l" ++#endif /* SIZEOF_TIME_T */ +diff --git a/lcksum.c b/lcksum.c +index 40d3c1e..cc09f8c 100644 +--- ./lcksum.c ++++ ./lcksum.c +@@ -434,7 +434,7 @@ do_lcksum( char *tpath ) + /* Check to see if checksum is listed in transcript */ + if ( strcmp( targv[ 7 ], "-" ) != 0) { + /* use mtime from server */ +- fprintf( ufs, "%s %-37s %4s %5s %5s %9ld " ++ fprintf( ufs, "%s %-37s %4s %5s %5s %9" PRItimet "d " + "%7" PRIofft "d %s\n", + targv[ 0 ], targv[ 1 ], targv[ 2 ], targv[ 3 ], + targv[ 4 ], st.st_mtime, st.st_size, lcksum ); +@@ -457,6 +457,12 @@ done: + } + free( line ); + } ++ if ( fclose( f ) != 0 ) { ++ fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno )); ++ cleanup( updatetran, upath ); ++ exit( 2 ); ++ } ++ + if ( showprogress ) { + progressupdate( bytes, "" ); + } +@@ -496,6 +502,10 @@ done: + badline: + exitval = 1; + ++ if ( fclose( f ) != 0 ) { ++ fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno )); ++ } ++ + if ( checkall ) { + goto done; + } else { +diff --git a/man/lcreate.1 b/man/lcreate.1 +index 64bdcc2..658c1fc 100644 +--- ./man/lcreate.1 ++++ ./man/lcreate.1 +@@ -45,12 +45,6 @@ will store the file on the server and give a warning. + .sp + If the -n option is given, no files or transcripts are uploaded. Instead, + .B lcreate +-verifies that all files exist in the filesystem and have +-the same size as listed in the transcript. If used with the -c option, +-checksums are also verified. +-.sp +-If the -n option is given, no files or transcripts are uploaded. Instead, +-.B lcreate + uses + .BR access (2) + to verify that all files in the transcript exist in the +diff --git a/man/rash.1 b/man/rash.1 +index 92c77d3..52fc6f0 100644 +--- ./man/rash.1 ++++ ./man/rash.1 +@@ -11,6 +11,10 @@ + | + .B -q + ] [ ++.BR \-C\ "generate" ++| ++.BI \-C\ checksum ++] [ + .B \-D + .I workingdir + ] [ +@@ -120,6 +124,24 @@ to use percentage done progress output. + .B \-c + use sha1 checksums. + .TP 19 ++.BR \-C\ "generate" ++Print a sha1 checksum of the difference transcript of applied changes. For use with ++.IR auto , ++.IR force ++or ++.IR update . ++.TP 19 ++.BI \-C\ checksum ++In ++.I auto ++mode, exit with an error if the checksum of the difference transcript to be applied does not match ++.IR checksum . ++In ++.I update ++or ++.I force ++mode, warn if the two do not match. ++.TP 19 + .BI \-D\ workingdir + change to + .I workingdir +diff --git a/mkdirs.c b/mkdirs.c +index 3839432..65ddeba 100644 +--- ./mkdirs.c ++++ ./mkdirs.c +@@ -37,7 +37,9 @@ mkdirs( char *path ) + if ( mkdir( path, 0777 ) == 0 ) { + break; + } +- if ( errno != ENOENT ) { ++ if ( errno == EEXIST ) { ++ break; ++ } else if ( errno != ENOENT ) { + return( -1 ); + } + q = p; +diff --git a/ra.sh b/ra.sh +index 8ee8dd4..4152d27 100755 +--- ./ra.sh ++++ ./ra.sh +@@ -91,7 +91,7 @@ checkedout() { + } + + usage() { +- $ECHO "Usage: $0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2 ++ $ECHO "Usage: $0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2 + exit 1 + } + +@@ -128,6 +128,38 @@ dopostapply() { + fi + } + ++cksum_generate() { ++ if [ -n "$FSDIFF_CHECKSUM" ]; then ++ FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'` ++ fi ++} ++ ++cksum_compare() { ++ if [ -n "$FSDIFF_CHECKSUM" -a \ ++ "$FSDIFF_CHECKSUM" != "generate" -a \ ++ "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then ++ return 1 ++ fi ++ ++ return 0 ++} ++ ++cksum_print() { ++ if [ -n "$FSDIFF_CHECKSUM" ]; then ++ $ECHO "Difference transcript checksum: $FTMP_CHECKSUM" ++ fi ++} ++ ++cksum_mismatch() { ++ if [ -n "$FSDIFF_CHECKSUM" ]; then ++ $ECHO ++ $ECHO "**** Difference transcript checksum mismatch!" ++ $ECHO "**** Expected: $FSDIFF_CHECKSUM" ++ $ECHO "**** Actual: $FTMP_CHECKSUM" ++ #ECHO ++ fi ++} ++ + update() { + opt="$1" + kopt= +@@ -211,6 +243,11 @@ update() { + fi + if [ x"${opt}" = x"interactive" ]; then + while [ 1 ]; do ++ cksum_generate ++ if ! cksum_compare; then ++ cksum_mismatch ++ fi ++ + if [ x"${can_edit}" = x"yes" ]; then + $ECHO -n "(e)dit difference transcript, " + fi +@@ -248,7 +285,8 @@ update() { + + lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP} + case "$?" in +- 0) ;; ++ 0) cksum_print ++ ;; + + *) if [ x"$opt" = x"hook" ]; then + $ECHO -n "Applying changes failed, trying again " +@@ -284,7 +322,7 @@ if [ -f "${DEFAULTS}" ]; then + . "${DEFAULTS}" + fi + +-while getopts %cD:h:Ilp:qr:tU:Vw: opt; do ++while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do + case $opt in + %) PROGRESS="-%" + FPROGRESS="-%" +@@ -293,6 +331,13 @@ while getopts %cD:h:Ilp:qr:tU:Vw: opt; do + q) PROGRESS="-q" + ;; + ++ C) FSDIFF_CHECKSUM="$OPTARG" ++ if ! type openssl >/dev/null 2>&1; then ++ $ECHO "-C requires openssl, but no openssl found in PATH $PATH" ++ cleanup_and_exit ++ fi ++ ;; ++ + c) CHECKSUM="-csha1" + ;; + +@@ -524,6 +569,14 @@ auto) + cleanup + exit 1 + fi ++ ++ cksum_generate ++ if ! cksum_compare; then ++ $ECHO "Auto failure: `hostname`: difference cksum mismatch" ++ cksum_mismatch ++ cleanup_and_exit ++ fi ++ + dopreapply ${FTMP} + if [ -s ${FTMP} ]; then + lapply ${NETOPTS} ${CASE} ${PROGRESS} \ +@@ -532,6 +585,7 @@ auto) + 0) + $ECHO Auto update: `hostname` + cat ${FTMP} ++ cksum_print + dopostapply ${FTMP} + cleanup + break +@@ -588,14 +642,17 @@ force) + exit 0 + fi + ++ cksum_generate ++ cksum_compare || cksum_mismatch + dopreapply ${FTMP} + lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP} + case "$?" in +- 0) ;; ++ 0) cksum_print ++ ;; + + *) cleanup +- exit $? +- ;; ++ exit $? ++ ;; + esac + dopostapply ${FTMP} + +diff --git a/t2pkg.c b/t2pkg.c +index ad43135..a75e8de 100644 +--- ./t2pkg.c ++++ ./t2pkg.c +@@ -38,6 +38,7 @@ extern int showprogress; + extern off_t lsize; + extern char *version; + ++int tran_format = -1; + int cksum = 0; + int force = 0; + int case_sensitive = 1; +@@ -718,31 +719,23 @@ main( int ac, char *av[] ) + } + + /* create the destination path */ +- if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name ) ++ if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name ) + >= MAXPATHLEN ) { + fprintf( stderr, "%s/%s: path too long\n", dstdir, + t->t_pinfo.pi_name ); + exit( 2 ); + } +- if ( mkdirs( tmp ) < 0 ) { +- fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno )); +- } +- if ( realpath( tmp, dst ) == NULL ) { +- fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno )); +- exit( 2 ); ++ if ( mkdirs( dst ) < 0 ) { ++ fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno )); + } + + /* and the source path */ +- if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name ) ++ if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name ) + >= MAXPATHLEN ) { + fprintf( stderr, "%s/%s: path too long\n", dstdir, + t->t_pinfo.pi_name ); + exit( 2 ); + } +- if ( realpath( tmp, src ) == NULL ) { +- fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno )); +- exit( 2 ); +- } + + if ( local_update( t, dst, src, where ) != 0 ) { + /* XXX is this really a good idea? */ +diff --git a/transcript.c b/transcript.c +index cad8d50..94e21ca 100644 +--- ./transcript.c ++++ ./transcript.c +@@ -45,7 +45,7 @@ struct list *exclude_list; + + char *path_prefix = NULL; + int edit_path; +-int skip; ++int skip = 0; + int cksum; + int fs_minus; + int exclude_warnings = 0; +@@ -271,7 +271,7 @@ transcript_parse( struct transcript *tran ) + tran->t_pinfo.pi_stat.st_mode = strtol( argv[ 2 ], NULL, 8 ); + tran->t_pinfo.pi_stat.st_uid = atoi( argv[ 3 ] ); + tran->t_pinfo.pi_stat.st_gid = atoi( argv[ 4 ] ); +- tran->t_pinfo.pi_stat.st_mtime = atoi( argv[ 5 ] ); ++ tran->t_pinfo.pi_stat.st_mtime = strtotimet( argv[ 5 ], NULL, 10 ); + tran->t_pinfo.pi_stat.st_size = strtoofft( argv[ 6 ], NULL, 10 ); + if ( tran->t_type != T_NEGATIVE ) { + if (( cksum ) && ( strcmp( "-", argv [ 7 ] ) == 0 )) { +@@ -436,12 +436,13 @@ t_print( struct pathinfo *fs, struct transcript *tran, int flag ) + * but the corresponding transcript is negative, hence, retain + * the file system's mtime. Woof! + */ +- fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9d %7" PRIofft "d %s\n", ++ fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9" PRItimet "d " ++ "%7" PRIofft "d %s\n", + cur->pi_type, epath, + (unsigned long)( T_MODE & cur->pi_stat.st_mode ), + (int)cur->pi_stat.st_uid, (int)cur->pi_stat.st_gid, + ( flag == PR_STATUS_NEG ) ? +- (int)fs->pi_stat.st_mtime : (int)cur->pi_stat.st_mtime, ++ fs->pi_stat.st_mtime : cur->pi_stat.st_mtime, + cur->pi_stat.st_size, cur->pi_cksum_b64 ); + break; + +@@ -723,7 +724,7 @@ transcript_select( void ) + if ( begin_tran->t_type != T_SPECIAL && + t_exclude( begin_tran->t_pinfo.pi_name )) { + if ( exclude_warnings ) { +- fprintf( stderr, "Warning: excluding %s\n", ++ printf( "#! Warning: excluding %s\n", + begin_tran->t_pinfo.pi_name ); + } + transcript_parse( begin_tran ); +@@ -769,7 +770,7 @@ transcript( char *path, struct stat *st, char *type, + if ( list_size( special_list ) <= 0 + || list_check( special_list, path ) == 0 ) { + if ( exclude_warnings ) { +- fprintf( stderr, "Warning: excluding %s\n", path ); ++ printf( "#! Warning: excluding %s\n", path ); + } + + /* move the transcripts ahead */ +@@ -949,7 +950,7 @@ transcript_init( char *kfile, int location ) + */ + t_new( T_NULL, NULL, NULL, NULL ); + +- if ( skip ) { ++ if ( skip == T_SKIP_ALL ) { + return; + } + +@@ -985,15 +986,17 @@ transcript_init( char *kfile, int location ) + exit( 2 ); + } + +- if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) { +- /* open the special transcript if there were any special files */ +- if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) { +- fprintf( stderr, +- "special path too long: %s%s\n", kdir, special ); +- exit( 2 ); ++ if ( !( skip & T_SKIP_SPECIAL )) { ++ if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) { ++ /* open the special transcript if there were any special files */ ++ if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) { ++ fprintf( stderr, ++ "special path too long: %s%s\n", kdir, special ); ++ exit( 2 ); ++ } ++ sprintf( fullpath, "%s%s", kdir, special ); ++ t_new( T_SPECIAL, fullpath, special, "special" ); + } +- sprintf( fullpath, "%s%s", kdir, special ); +- t_new( T_SPECIAL, fullpath, special, "special" ); + } + + if ( tran_head->t_type == T_NULL && edit_path == APPLICABLE ) { +@@ -1108,6 +1111,10 @@ read_kfile( char *kfile, int location ) + break; + + case 'n': /* negative */ ++ if ( skip & T_SKIP_NEGATIVE ) { ++ break; ++ } ++ + if ( minus ) { + t_remove( T_NEGATIVE, av[ 1 ] ); + } else { +@@ -1116,6 +1123,10 @@ read_kfile( char *kfile, int location ) + break; + + case 'p': /* positive */ ++ if ( skip & T_SKIP_POSITIVE ) { ++ break; ++ } ++ + if ( minus ) { + t_remove( T_POSITIVE, av[ 1 ] ); + } else { +@@ -1124,6 +1135,10 @@ read_kfile( char *kfile, int location ) + break; + + case 'x': /* exclude */ ++ if ( skip & T_SKIP_EXCLUDES ) { ++ break; ++ } ++ + if (( d_pattern = decode( av[ 1 ] )) == NULL ) { + fprintf( stderr, "%s: line %d: decode buffer too small\n", + kfile, linenum ); +@@ -1149,6 +1164,10 @@ read_kfile( char *kfile, int location ) + break; + + case 's': /* special */ ++ if ( skip & T_SKIP_SPECIAL ) { ++ break; ++ } ++ + path = av[ 1 ]; + + /* Convert path to match transcript type */ +diff --git a/transcript.h b/transcript.h +index 29ae3cf..f4453ca 100644 +--- ./transcript.h ++++ ./transcript.h +@@ -39,6 +39,14 @@ extern int fs_minus; + extern FILE *outtran; + extern char *path_prefix; + ++ ++#define T_SKIP_POSITIVE (1 << 1) ++#define T_SKIP_NEGATIVE (1 << 2) ++#define T_SKIP_SPECIAL (1 << 3) ++#define T_SKIP_EXCLUDES (1 << 4) ++#define T_SKIP_ALL (T_SKIP_POSITIVE | T_SKIP_NEGATIVE | \ ++ T_SKIP_SPECIAL | T_SKIP_EXCLUDES) ++ + struct pathinfo { + char pi_type; + int pi_minus; +diff --git a/update.c b/update.c +index fa4227d..47911cc 100644 +--- ./update.c ++++ ./update.c +@@ -26,6 +26,7 @@ + #include "update.h" + #include "code.h" + #include "radstat.h" ++#include "largefile.h" + #include "transcript.h" + #include "progress.h" + #include "mkdirs.h" +@@ -73,7 +74,7 @@ update( char *path, char *displaypath, int present, int newfile, + + mode = strtol( targv[ 2 ], (char **)NULL, 8 ); + +- times.modtime = atoi( targv[ 5 ] ); ++ times.modtime = strtotimet( targv[ 5 ], NULL, 10 ); + if ( times.modtime != st->st_mtime ) { + times.actime = st->st_atime; + if ( utime( path, × ) != 0 ) { diff -ruN ./files/patch-Makefile.in ./files/patch-Makefile.in --- ./files/patch-Makefile.in 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-Makefile.in 1969-12-31 19:00:00.000000000 -0500 @@ -1,50 +0,0 @@ ---- ./Makefile.in.orig 2010-12-12 22:43:49.000000000 -0500 -+++ ./Makefile.in 2012-03-20 14:37:54.000000000 -0400 -@@ -204,37 +204,37 @@ - radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile - ${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS} - --fsdiff : ${FSDIFF_OBJ} -+fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ} - ${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS} - --ktcheck: ${KTCHECK_OBJ} -+ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ} - ${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS} - --lapply: ${LAPPLY_OBJ} -+lapply: libsnet/libsnet.la ${LAPPLY_OBJ} - ${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS} - --lcksum: ${LCKSUM_OBJ} -+lcksum: libsnet/libsnet.la ${LCKSUM_OBJ} - ${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS} - --lcreate: ${LCREATE_OBJ} -+lcreate: libsnet/libsnet.la ${LCREATE_OBJ} - ${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS} - --lmerge: ${LMERGE_OBJ} -+lmerge: libsnet/libsnet.la ${LMERGE_OBJ} - ${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS} - --lfdiff: ${LFDIFF_OBJ} -+lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ} - ${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS} - --repo : ${REPO_OBJ} -+repo: libsnet/libsnet.la ${REPO_OBJ} - ${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS} - - t2pkg: ${T2PKG_OBJ} - ${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS} - --twhich: ${TWHICH_OBJ} -+twhich: libsnet/libsnet.la ${TWHICH_OBJ} - ${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS} - --lsort: ${LSORT_OBJ} -+lsort: libsnet/libsnet.la ${LSORT_OBJ} - ${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS} - - FRC : diff -ruN ./files/patch-README ./files/patch-README --- ./files/patch-README 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-README 1969-12-31 19:00:00.000000000 -0500 @@ -1,46 +0,0 @@ ---- ./README.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./README 2012-03-20 14:37:54.000000000 -0400 -@@ -72,25 +72,25 @@ - % "env CPPFLAGS=-I/usr/kerberos/include ./configure" - - ----------------- --Building from CVS -+Building from git - ----------------- - The Radmind Development Team occasionally asks for help testing a new feature - or bug fix. The best way to assist is to download the source code from the --CVS repository and build it manually. The following steps will result in --a build from CVS. -+git repository and build it manually. The following steps will result in -+a build from git. - --1) Download the source from CVS: -+1) Download the source from git: - --cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \ -- checkout radmind -+ git clone git://radmind.git.sourceforge.net/gitroot/gradmind - - 2) Move into the new radmind directory: - --cd radmind -+ cd radmind - --3) Download libsnet[1], the network library Radmind uses: -+3) Checkout all required submodules [1]: - --sh bin/getsnet -+ git submodule init -+ git submodule update - - 4) Follow steps 2 and 3 from "More detailed instructions" for building, above. - -@@ -115,4 +115,7 @@ - ---------- - References - ---------- --[1]: http://sourceforge.net/projects/libsnet -+[1]: Current submodules: -+ -+ * libsnet, a networking library with TLS support -+ http://sourceforge.net/projects/libsnet diff -ruN ./files/patch-aclocal.m4 ./files/patch-aclocal.m4 --- ./files/patch-aclocal.m4 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-aclocal.m4 1969-12-31 19:00:00.000000000 -0500 @@ -1,21 +0,0 @@ ---- ./aclocal.m4.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./aclocal.m4 2012-03-20 14:37:54.000000000 -0400 -@@ -105,16 +105,11 @@ - arches="-arch i386 -arch ppc" - ;; - -- darwin9*) -+ darwin9*|darwin10*|darwin11*) - dep_target="-mmacosx-version-min=10.4" - macosx_sdk="MacOSX10.5.sdk" - arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64" -- ;; -- -- darwin10*) -- dep_target="-mmacosx-version-min=10.4" -- macosx_sdk="MacOSX10.6.sdk" -- arches="-arch i386 -arch x86_64 -arch ppc" -+ LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib" - ;; - - *) diff -ruN ./files/patch-configure.ac ./files/patch-configure.ac --- ./files/patch-configure.ac 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-configure.ac 1969-12-31 19:00:00.000000000 -0500 @@ -1,44 +0,0 @@ ---- ./configure.ac.orig 2010-12-12 22:43:38.000000000 -0500 -+++ ./configure.ac 2012-03-20 14:37:54.000000000 -0400 -@@ -45,24 +45,29 @@ - # Check sizes - AC_CHECK_SIZEOF(off_t) - -+# check early to make any required changes to environment for following tests. -+CHECK_UNIVERSAL_BINARIES -+ - # Checks for libraries. - AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) - if test x$libc_inet_aton != xyes; then - AC_CHECK_LIB(resolv, inet_aton) - fi --AC_CHECK_LIB(c, lchown) --AC_CHECK_LIB(c, lchmod) -+AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], []) -+AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], []) - AC_CHECK_LIB(nsl, gethostbyaddr) - AC_CHECK_LIB([socket], [socket]) - AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL]) - AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file - is required for this software. You may be running RedHat 9. If so, see the FAQ or the README for further instructions.])]) - AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL]) --AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], []) -+AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], []) - - # PAM --AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes) -+AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr) - if test x_"$with_pam" != x_no; then -+ CPPFLAGS="${CPPFLAGS} -I$with_pam/include" -+ LDFLAGS="${LDFLAGS} -L$with_pam/lib" - AC_CHECK_LIB([pam], [pam_start], - [ - AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)]) -@@ -75,7 +80,6 @@ - AC_CHECK_LIB(dns_sd, DNSServiceRegister) - - CHECK_ZLIB --CHECK_UNIVERSAL_BINARIES - - # HPUX lacks wait4 and strtoll - AC_CHECK_FUNCS(wait4 strtoll) diff -ruN ./files/patch-lapply.c ./files/patch-lapply.c --- ./files/patch-lapply.c 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-lapply.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,52 +0,0 @@ ---- ./lapply.c.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./lapply.c 2012-03-20 14:37:54.000000000 -0400 -@@ -651,27 +651,37 @@ - filechecklist: - if ( head == NULL ) { - if ( unlink( path ) != 0 ) { -- perror( path ); -- goto error2; -- } -- if ( !quiet && !showprogress ) { -- printf( "%s: deleted\n", path ); -- } -- if ( showprogress ) { -- progressupdate( PROGRESSUNIT, path ); -- } -- } else { -- if ( ischildcase( path, head->path, case_sensitive )) { -- if ( unlink( path ) != 0 ) { -+ if ( !force || errno != ENOENT ) { - perror( path ); - goto error2; - } -+ fprintf( stderr, "Warning: failed to remove %s: %s\n", -+ path, strerror( errno )); -+ } else { - if ( !quiet && !showprogress ) { - printf( "%s: deleted\n", path ); - } - if ( showprogress ) { - progressupdate( PROGRESSUNIT, path ); - } -+ } -+ } else { -+ if ( ischildcase( path, head->path, case_sensitive )) { -+ if ( unlink( path ) != 0 ) { -+ if ( !force || errno != ENOENT ) { -+ perror( path ); -+ goto error2; -+ } -+ fprintf( stderr, "Warning: failed to remove %s: " -+ "%s\n", path, strerror( errno )); -+ } else { -+ if ( !quiet && !showprogress ) { -+ printf( "%s: deleted\n", path ); -+ } -+ if ( showprogress ) { -+ progressupdate( PROGRESSUNIT, path ); -+ } -+ } - } else { - /* remove head */ - if ( rmdir( head->path ) != 0 ) { diff -ruN ./files/patch-man__lcreate.1 ./files/patch-man__lcreate.1 --- ./files/patch-man__lcreate.1 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-man__lcreate.1 1969-12-31 19:00:00.000000000 -0500 @@ -1,15 +0,0 @@ ---- ./man/lcreate.1.orig 2010-12-12 22:50:53.000000000 -0500 -+++ ./man/lcreate.1 2012-03-20 14:38:03.000000000 -0400 -@@ -45,12 +45,6 @@ - .sp - If the -n option is given, no files or transcripts are uploaded. Instead, - .B lcreate --verifies that all files exist in the filesystem and have --the same size as listed in the transcript. If used with the -c option, --checksums are also verified. --.sp --If the -n option is given, no files or transcripts are uploaded. Instead, --.B lcreate - uses - .BR access (2) - to verify that all files in the transcript exist in the diff -ruN ./files/patch-man__rash.1 ./files/patch-man__rash.1 --- ./files/patch-man__rash.1 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-man__rash.1 1969-12-31 19:00:00.000000000 -0500 @@ -1,38 +0,0 @@ ---- ./man/rash.1.orig 2010-12-12 22:50:53.000000000 -0500 -+++ ./man/rash.1 2012-03-20 14:38:08.000000000 -0400 -@@ -11,6 +11,10 @@ - | - .B -q - ] [ -+.BR \-C\ "generate" -+| -+.BI \-C\ checksum -+] [ - .B \-D - .I workingdir - ] [ -@@ -120,6 +124,24 @@ - .B \-c - use sha1 checksums. - .TP 19 -+.BR \-C\ "generate" -+Print a sha1 checksum of the difference transcript of applied changes. For use with -+.IR auto , -+.IR force -+or -+.IR update . -+.TP 19 -+.BI \-C\ checksum -+In -+.I auto -+mode, exit with an error if the checksum of the difference transcript to be applied does not match -+.IR checksum . -+In -+.I update -+or -+.I force -+mode, warn if the two do not match. -+.TP 19 - .BI \-D\ workingdir - change to - .I workingdir diff -ruN ./files/patch-mkdirs.c ./files/patch-mkdirs.c --- ./files/patch-mkdirs.c 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-mkdirs.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,13 +0,0 @@ ---- ./mkdirs.c.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./mkdirs.c 2012-03-20 14:38:08.000000000 -0400 -@@ -37,7 +37,9 @@ - if ( mkdir( path, 0777 ) == 0 ) { - break; - } -- if ( errno != ENOENT ) { -+ if ( errno == EEXIST ) { -+ break; -+ } else if ( errno != ENOENT ) { - return( -1 ); - } - q = p; diff -ruN ./files/patch-ra.sh ./files/patch-ra.sh --- ./files/patch-ra.sh 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-ra.sh 1969-12-31 19:00:00.000000000 -0500 @@ -1,139 +0,0 @@ ---- ./ra.sh.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./ra.sh 2012-03-20 14:38:08.000000000 -0400 -@@ -91,7 +91,7 @@ - } - - usage() { -- $ECHO "Usage: $0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2 -+ $ECHO "Usage: $0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2 - exit 1 - } - -@@ -128,6 +128,38 @@ - fi - } - -+cksum_generate() { -+ if [ -n "$FSDIFF_CHECKSUM" ]; then -+ FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'` -+ fi -+} -+ -+cksum_compare() { -+ if [ -n "$FSDIFF_CHECKSUM" -a \ -+ "$FSDIFF_CHECKSUM" != "generate" -a \ -+ "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then -+ return 1 -+ fi -+ -+ return 0 -+} -+ -+cksum_print() { -+ if [ -n "$FSDIFF_CHECKSUM" ]; then -+ $ECHO "Difference transcript checksum: $FTMP_CHECKSUM" -+ fi -+} -+ -+cksum_mismatch() { -+ if [ -n "$FSDIFF_CHECKSUM" ]; then -+ $ECHO -+ $ECHO "**** Difference transcript checksum mismatch!" -+ $ECHO "**** Expected: $FSDIFF_CHECKSUM" -+ $ECHO "**** Actual: $FTMP_CHECKSUM" -+ #ECHO -+ fi -+} -+ - update() { - opt="$1" - kopt= -@@ -211,6 +243,11 @@ - fi - if [ x"${opt}" = x"interactive" ]; then - while [ 1 ]; do -+ cksum_generate -+ if ! cksum_compare; then -+ cksum_mismatch -+ fi -+ - if [ x"${can_edit}" = x"yes" ]; then - $ECHO -n "(e)dit difference transcript, " - fi -@@ -248,7 +285,8 @@ - - lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP} - case "$?" in -- 0) ;; -+ 0) cksum_print -+ ;; - - *) if [ x"$opt" = x"hook" ]; then - $ECHO -n "Applying changes failed, trying again " -@@ -284,7 +322,7 @@ - . "${DEFAULTS}" - fi - --while getopts %cD:h:Ilp:qr:tU:Vw: opt; do -+while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do - case $opt in - %) PROGRESS="-%" - FPROGRESS="-%" -@@ -293,6 +331,13 @@ - q) PROGRESS="-q" - ;; - -+ C) FSDIFF_CHECKSUM="$OPTARG" -+ if ! type openssl >/dev/null 2>&1; then -+ $ECHO "-C requires openssl, but no openssl found in PATH $PATH" -+ cleanup_and_exit -+ fi -+ ;; -+ - c) CHECKSUM="-csha1" - ;; - -@@ -524,6 +569,14 @@ - cleanup - exit 1 - fi -+ -+ cksum_generate -+ if ! cksum_compare; then -+ $ECHO "Auto failure: `hostname`: difference cksum mismatch" -+ cksum_mismatch -+ cleanup_and_exit -+ fi -+ - dopreapply ${FTMP} - if [ -s ${FTMP} ]; then - lapply ${NETOPTS} ${CASE} ${PROGRESS} \ -@@ -532,6 +585,7 @@ - 0) - $ECHO Auto update: `hostname` - cat ${FTMP} -+ cksum_print - dopostapply ${FTMP} - cleanup - break -@@ -588,14 +642,17 @@ - exit 0 - fi - -+ cksum_generate -+ cksum_compare || cksum_mismatch - dopreapply ${FTMP} - lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP} - case "$?" in -- 0) ;; -+ 0) cksum_print -+ ;; - - *) cleanup -- exit $? -- ;; -+ exit $? -+ ;; - esac - dopostapply ${FTMP} - diff -ruN ./files/patch-t2pkg.c ./files/patch-t2pkg.c --- ./files/patch-t2pkg.c 2014-05-22 14:34:26.000000000 -0400 +++ ./files/patch-t2pkg.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,46 +0,0 @@ ---- ./t2pkg.c.orig 2010-12-12 22:42:49.000000000 -0500 -+++ ./t2pkg.c 2012-03-20 14:38:08.000000000 -0400 -@@ -38,6 +38,7 @@ - extern off_t lsize; - extern char *version; - -+int tran_format = -1; - int cksum = 0; - int force = 0; - int case_sensitive = 1; -@@ -718,31 +719,23 @@ - } - - /* create the destination path */ -- if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name ) -+ if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name ) - >= MAXPATHLEN ) { - fprintf( stderr, "%s/%s: path too long\n", dstdir, - t->t_pinfo.pi_name ); - exit( 2 ); - } -- if ( mkdirs( tmp ) < 0 ) { -- fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno )); -- } -- if ( realpath( tmp, dst ) == NULL ) { -- fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno )); -- exit( 2 ); -+ if ( mkdirs( dst ) < 0 ) { -+ fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno )); - } - - /* and the source path */ -- if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name ) -+ if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name ) - >= MAXPATHLEN ) { - fprintf( stderr, "%s/%s: path too long\n", dstdir, - t->t_pinfo.pi_name ); - exit( 2 ); - } -- if ( realpath( tmp, src ) == NULL ) { -- fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno )); -- exit( 2 ); -- } - - if ( local_update( t, dst, src, where ) != 0 ) { - /* XXX is this really a good idea? */ diff -ruN ./pkg-descr ./pkg-descr --- ./pkg-descr 2014-05-22 14:34:26.000000000 -0400 +++ ./pkg-descr 2014-05-22 14:17:53.000000000 -0400 @@ -3,4 +3,6 @@ of hosts at the filesystem level. It can also act as an intelligent tripwire. -WWW: http://rsug.itd.umich.edu/software/radmind/ +This port contains security and functionality patches through May 22, 2014. + +WWW: http://sourceforge.net/projects/radmind/ diff -ruN ./pkg-plist ./pkg-plist --- ./pkg-plist 2014-05-22 14:34:26.000000000 -0400 +++ ./pkg-plist 2014-05-22 13:11:03.000000000 -0400 @@ -10,18 +10,30 @@ bin/repo bin/twhich sbin/radmind +man/man1/fsdiff.1.gz +man/man1/ktcheck.1.gz +man/man1/lapply.1.gz +man/man1/lcksum.1.gz +man/man1/lcreate.1.gz +man/man1/lfdiff.1.gz +man/man1/lmerge.1.gz +man/man1/lsort.1.gz +man/man1/rash.1.gz +man/man1/repo.1.gz +man/man1/twhich.1.gz +man/man5/applefile.5.gz +man/man8/radmind.8.gz %%PORTDOCS%%%%DOCSDIR%%/COPYRIGHT %%PORTDOCS%%%%DOCSDIR%%/README %%PORTDOCS%%%%DOCSDIR%%/SPEC -%%PORTDOCS%%@dirrm %%DOCSDIR%% -@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%% -@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/cert -@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/client -@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/preapply -@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/postapply -@exec chown -R %%RADMINUSER%%:%%RADMINUSER%% %%RADMIND_BASE_DIR%% -@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi +%%PORTDOCS%% +@mode 700 %%RADMIND_BASE_DIR%%/config.sample +@mode +@exec chown -R %%RADMINUSER%% %%RADMIND_BASE_DIR%% +@exec chgrp -R %%RADMINUSER%% %%RADMIND_BASE_DIR%% + +@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi @dirrmtry %%RADMIND_BASE_DIR%%/transcript @dirrmtry %%RADMIND_BASE_DIR%%/tmp/transcript @dirrmtry %%RADMIND_BASE_DIR%%/tmp/file >Release-Note: >Audit-Trail: >Unformatted: