View | Details | Raw Unified | Return to bug 190120 | Differences between
and this patch

Collapse All | Expand All

(-)./Makefile (-22 / +20 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	radmind
4
PORTNAME=	radmind
5
PORTVERSION=	1.14.1
5
PORTVERSION=	1.14.1
6
PORTREVISION=	2012032001
6
PORTREVISION=	2014052201
7
CATEGORIES=	sysutils
7
CATEGORIES=	sysutils
8
MASTER_SITES=	SF
8
MASTER_SITES=	SF
9
MASTER_SITE_SUBDIR=${PORTNAME}/${PORTNAME}/${PORTNAME}-${PORTVERSION}
9
MASTER_SITE_SUBDIR=${PORTNAME}/${PORTNAME}/${PORTNAME}-${PORTVERSION}
Lines 27-61 Link Here
27
PLIST_SUB=	RADMIND_BASE_DIR=${RADMIND_BASE_DIR} RADMINUSER=${RADMINUSER}
27
PLIST_SUB=	RADMIND_BASE_DIR=${RADMIND_BASE_DIR} RADMINUSER=${RADMINUSER}
28
SUB_FILES+=	pkg-install pkg-message
28
SUB_FILES+=	pkg-install pkg-message
29
29
30
MAN1=		fsdiff.1 ktcheck.1 lapply.1 lcksum.1 lcreate.1 lfdiff.1 \
31
		lmerge.1 lsort.1 twhich.1 rash.1 repo.1
32
MAN5=		applefile.5
33
MAN8=		radmind.8
34
DOCS=		COPYRIGHT README SPEC
30
DOCS=		COPYRIGHT README SPEC
35
31
36
OPTIONS_DEFINE=	IGNORE_TIMESTAMPS DOCS
32
OPTIONS_DEFINE=	DOCS
37
IGNORE_TIMESTAMPS_DESC=	Add '-t' option to fsdiff
33
IGNORE_TIMESTAMPS_DESC=	Add '-t' option to fsdiff
38
34
39
NO_STAGE=	yes
40
.include <bsd.port.options.mk>
35
.include <bsd.port.options.mk>
41
36
42
.if ${PORT_OPTIONS:MIGNORE_TIMESTAMPS}
43
EXTRA_PATCHES+=	${FILESDIR}/optpatch-ignore_timestamps
44
.endif
45
46
post-install:
37
post-install:
47
# Ugly hack to remove generated man pages
38
	# Ugly hack to remove generated man pages
48
	${RM} -rf ${WRKSRC}/tmp
39
	${RM} -rf ${WRKSRC}/tmp
49
40
50
.if ${PORT_OPTIONS:MDOCS}
41
	# Port's Docs (Copyright & wire protocol info) 
51
	${MKDIR} ${DOCSDIR}
42
	${MKDIR} ${STAGEDIR}${DOCSDIR}
52
	cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${DOCSDIR}
43
	cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${STAGEDIR}${DOCSDIR}
53
.endif
44
54
	${CP} ${FILESDIR}/config.sample ${RADMIND_BASE_DIR}/config.sample
45
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}
55
	@if [ ! -f ${RADMIND_BASE_DIR}/config ]; then \
46
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/cert
56
		${CP} -p ${RADMIND_BASE_DIR}/config.sample ${RADMIND_BASE_DIR}/config ; \
47
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/client
57
	fi
48
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/command
58
	@${CHOWN} -R ${RADMINUSER}:${RADMINUSER} ${RADMIND_BASE_DIR}
49
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/file
59
	@${CAT} ${PKGMESSAGE}
50
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/postapply
51
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/preapply
52
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/special
53
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp
54
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/file
55
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/transcript
56
	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/transcript
57
	${CP}    ${FILESDIR}/config.sample ${STAGEDIR}${RADMIND_BASE_DIR}/config.sample
60
58
61
.include <bsd.port.mk>
59
.include <bsd.port.mk>
(-)./files/optpatch-ignore_timestamps (-94 lines)
Lines 1-94 Link Here
1
--- fsdiff.c.orig
2
+++ fsdiff.c
3
@@ -33,6 +33,7 @@ int		dotfd;
4
 int		lastpercent = -1;
5
 int		case_sensitive = 1;
6
 int		tran_format = -1; 
7
+int		ignore_timestamps = 0;
8
 extern int	exclude_warnings;
9
 const EVP_MD    *md;
10
 
11
@@ -266,7 +267,7 @@ main( int argc, char **argv )
12
     cksum = 0;
13
     outtran = stdout;
14
 
15
-    while (( c = getopt( argc, argv, "%1ACc:IK:o:VvW" )) != EOF ) {
16
+    while (( c = getopt( argc, argv, "%1ACc:IK:o:tVvW" )) != EOF ) {
17
 	switch( c ) {
18
 	case '%':
19
 	case 'v':
20
@@ -320,6 +321,10 @@ main( int argc, char **argv )
21
 	    exclude_warnings = 1;
22
 	    break;
23
 
24
+	case 't':		/* ignore files for which only the time has changed */
25
+	    ignore_timestamps = 1;
26
+	break;
27
+
28
 	case '?':
29
 	    printf( "bad %c\n", c );
30
 	    errflag++;
31
32
--- man/fsdiff.1.orig
33
+++ man/fsdiff.1
34
@@ -11,7 +11,7 @@
35
 |
36
 .B -1
37
 } [
38
-.BI -IVW
39
+.BI -IVWt
40
 ] [
41
 .BI \-K\  command
42
 ] [
43
@@ -312,6 +312,9 @@ order of preference and then exits.
44
 prints a warning to the standard error when encountering an object
45
 matching an exclude pattern.
46
 .sp
47
+.TP 19
48
+.B \-t
49
+ignores files where only the timestamp has changed.
50
 .SH FILES
51
 .TP 19
52
 .B _RADMIND_COMMANDFILE
53
54
--- transcript.c.orig
55
+++ transcript.c
56
@@ -38,6 +38,7 @@ static struct transcript	*prev_tran = NULL;
57
 extern int			edit_path;
58
 extern int			case_sensitive;
59
 extern int			tran_format;
60
+extern int			ignore_timestamps;
61
 static char			*kdir;
62
 static struct list		*kfile_list;
63
 struct list			*special_list;
64
@@ -45,6 +46,7 @@ struct list			*exclude_list;
65
 
66
 char				*path_prefix = NULL;
67
 int				edit_path;
68
+int				ignore_timestamps;
69
 int				skip;
70
 int				cksum;
71
 int				fs_minus;
72
@@ -544,14 +546,16 @@ t_compare( struct pathinfo *fs, struct transcript *tran )
73
 		    t_print( fs, tran, PR_DOWNLOAD );
74
 		    break;
75
 		}
76
-	    } else if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
77
-		t_print( fs, tran, PR_DOWNLOAD );
78
-		break;
79
+	    } else if ( ignore_timestamps == 0 &&
80
+			fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime) {
81
+		    t_print( fs, tran, PR_DOWNLOAD );
82
+		    break;
83
 	    }
84
 
85
-	    if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
86
-		t_print( fs, tran, PR_STATUS );
87
-		break;
88
+	    if ( ignore_timestamps == 0 &&
89
+		 fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
90
+		    t_print( fs, tran, PR_STATUS );
91
+		    break;
92
 	    }
93
 	}
94
 
(-)./files/patch-.gitignore (-17 lines)
Lines 1-17 Link Here
1
--- ./.gitignore.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./.gitignore	2012-03-20 14:37:54.000000000 -0400
3
@@ -10,12 +10,8 @@
4
 config.log
5
 config.status
6
 
7
-# External Libraries #
8
-######################
9
-libsnet
10
-
11
-# Comiled Files #
12
-#################
13
+# Compiled Files #
14
+##################
15
 *.o
16
 fsdiff
17
 ktcheck
(-)./files/patch-20140522 (+1412 lines)
Line 0 Link Here
1
diff --git a/.gitignore b/.gitignore
2
index fc33886..dc49f11 100644
3
--- ./.gitignore
4
+++ ./.gitignore
5
@@ -10,12 +10,8 @@ config.h
6
 config.log
7
 config.status
8
 
9
-# External Libraries #
10
-######################
11
-libsnet
12
-
13
-# Comiled Files #
14
-#################
15
+# Compiled Files #
16
+##################
17
 *.o
18
 fsdiff
19
 ktcheck
20
diff --git a/.gitmodules b/.gitmodules
21
new file mode 100644
22
index 0000000..3ebdb4a
23
--- /dev/null
24
+++ ./.gitmodules
25
@@ -0,0 +1,3 @@
26
+[submodule "libsnet"]
27
+	path = libsnet
28
+	url = git://libsnet.git.sourceforge.net/gitroot/libsnet/libsnet
29
diff --git a/Makefile.in b/Makefile.in
30
index e45ecfd..8b0bef8 100644
31
--- ./Makefile.in
32
+++ ./Makefile.in
33
@@ -204,37 +204,37 @@ tls.o : tls.c
34
 radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile
35
 	${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS}
36
 
37
-fsdiff : ${FSDIFF_OBJ}
38
+fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ}
39
 	${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS}
40
 
41
-ktcheck: ${KTCHECK_OBJ}
42
+ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ}
43
 	${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS}
44
 
45
-lapply: ${LAPPLY_OBJ}
46
+lapply: libsnet/libsnet.la ${LAPPLY_OBJ}
47
 	${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS}
48
 
49
-lcksum: ${LCKSUM_OBJ}
50
+lcksum: libsnet/libsnet.la ${LCKSUM_OBJ}
51
 	${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS}
52
 
53
-lcreate: ${LCREATE_OBJ}
54
+lcreate: libsnet/libsnet.la ${LCREATE_OBJ}
55
 	${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS}
56
 
57
-lmerge: ${LMERGE_OBJ}
58
+lmerge: libsnet/libsnet.la ${LMERGE_OBJ}
59
 	${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS}
60
 
61
-lfdiff: ${LFDIFF_OBJ}
62
+lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ}
63
 	${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS}
64
 
65
-repo : ${REPO_OBJ}
66
+repo: libsnet/libsnet.la ${REPO_OBJ}
67
 	${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS}
68
 
69
 t2pkg: ${T2PKG_OBJ}
70
 	${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS}
71
 
72
-twhich: ${TWHICH_OBJ}
73
+twhich: libsnet/libsnet.la ${TWHICH_OBJ}
74
 	${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS}
75
 
76
-lsort: ${LSORT_OBJ}
77
+lsort: libsnet/libsnet.la ${LSORT_OBJ}
78
 	${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS}
79
 
80
 FRC :
81
diff --git a/README b/README
82
index bc034ca..4e7e03b 100644
83
--- ./README
84
+++ ./README
85
@@ -72,25 +72,25 @@ for the kerberos header files:
86
   % "env CPPFLAGS=-I/usr/kerberos/include ./configure"
87
 
88
 -----------------
89
-Building from CVS
90
+Building from git
91
 -----------------
92
 The Radmind Development Team occasionally asks for help testing a new feature
93
 or bug fix. The best way to assist is to download the source code from the
94
-CVS repository and build it manually. The following steps will result in
95
-a build from CVS.
96
+git repository and build it manually. The following steps will result in
97
+a build from git.
98
 
99
-1) Download the source from CVS:
100
+1) Download the source from git:
101
 
102
-cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \
103
-	checkout radmind
104
+    git clone git://radmind.git.sourceforge.net/gitroot/radmind/radmind
105
 
106
 2) Move into the new radmind directory:
107
 
108
-cd radmind
109
+    cd radmind
110
 
111
-3) Download libsnet[1], the network library Radmind uses:
112
+3) Checkout all required submodules [1]:
113
 
114
-sh bin/getsnet
115
+    git submodule init
116
+    git submodule update
117
 
118
 4) Follow steps 2 and 3 from "More detailed instructions" for building, above.
119
 
120
@@ -115,4 +115,7 @@ for details on how to join.
121
 ----------
122
 References
123
 ----------
124
-[1]: http://sourceforge.net/projects/libsnet
125
+[1]: Current submodules:
126
+
127
+    * libsnet, a networking library with TLS support
128
+	http://sourceforge.net/projects/libsnet
129
diff --git a/aclocal.m4 b/aclocal.m4
130
index 24b1b0f..0b7d456 100644
131
--- ./aclocal.m4
132
+++ ./aclocal.m4
133
@@ -105,16 +105,11 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES],
134
 	    arches="-arch i386 -arch ppc"
135
 	    ;;
136
 
137
-	  darwin9*)
138
+	  darwin9*|darwin10*|darwin11*)
139
 	    dep_target="-mmacosx-version-min=10.4"
140
 	    macosx_sdk="MacOSX10.5.sdk"
141
 	    arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64"
142
-	    ;;
143
-
144
-	  darwin10*)
145
-	    dep_target="-mmacosx-version-min=10.4"
146
-	    macosx_sdk="MacOSX10.6.sdk"
147
-	    arches="-arch i386 -arch x86_64 -arch ppc"
148
+	    LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib"
149
 	    ;;
150
 
151
 	  *)
152
@@ -129,3 +124,20 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES],
153
     fi
154
 ])
155
 
156
+AC_DEFUN([MACOSX_MUTE_DEPRECATION_WARNINGS],
157
+[
158
+    dnl Lion deprecates a system-provided OpenSSL. Build output
159
+    dnl is cluttered with useless deprecation warnings.
160
+
161
+    AS_IF([test x"$CC" = x"gcc"], [
162
+        case "${host_os}" in
163
+        darwin11*)
164
+            AC_MSG_NOTICE([muting deprecation warnings from compiler])
165
+            OPTOPTS="$OPTOPTS -Wno-deprecated-declarations"
166
+            ;;
167
+
168
+        *)
169
+            ;;
170
+        esac
171
+    ])
172
+])
173
diff --git a/argcargv.c b/argcargv.c
174
index 44111af..d78ca47 100644
175
--- ./argcargv.c
176
+++ ./argcargv.c
177
@@ -48,7 +48,9 @@ acav_parse( ACAV *acav, char *line, char **argv[] )
178
 
179
     if ( acav == NULL ) {
180
 	if ( acavg == NULL ) {
181
-	    acavg = acav_alloc();
182
+	    if (( acavg = acav_alloc()) == NULL ) {
183
+		return( -1 );
184
+	    }
185
 	}
186
 	acav = acavg;
187
     }
188
diff --git a/bin/getsnet b/bin/getsnet
189
deleted file mode 100755
190
index 1136f54..0000000
191
--- ./bin/getsnet
192
+++ /dev/null
193
@@ -1,16 +0,0 @@
194
-#! /bin/sh
195
-
196
-# getsnet: download libsnet source code from SF.net
197
-
198
-proj="libsnet"
199
-rev="1.0.1"
200
-gitroot="git://${proj}.git.sourceforge.net/gitroot/${proj}/${proj}"
201
-
202
-[ -e "${proj}" ] && echo "${proj} already retrieved" && exit 1
203
-[ ! -e "${proj}" ]							\
204
-	&& git clone ${gitroot}						\
205
-	&& (cd "${proj}"						\
206
-	    && git checkout -b "${proj}-${rev}-branch" "${proj}-${rev}"	\
207
-	    && autoconf)
208
-
209
-exit $?
210
diff --git a/command.c b/command.c
211
index 9cf6510..5dc0a54 100644
212
--- ./command.c
213
+++ ./command.c
214
@@ -477,38 +477,90 @@ f_retr( SNET *sn, int ac, char **av )
215
 
216
 /* looks for special file info in transcripts */
217
     char **
218
-special_t( char *transcript, char *epath )
219
+special_t( char *sp_path, char *remote_path )
220
 {
221
-    FILE		*fs;
222
-    int			ac, len;
223
-    char		**av;
224
+    FILE		*fs = NULL;
225
+    int			i, ac, len, ln;
226
+    char		**av = NULL;
227
+    char		*paths[ 4 ] = { NULL };
228
+    char		*p;
229
+    char		sp_t[ MAXPATHLEN ];
230
     static char		line[ MAXPATHLEN ];
231
 
232
-    if (( fs = fopen( transcript, "r" )) == NULL ) {
233
-	return( NULL );
234
-    }
235
-
236
-    while ( fgets( line, MAXPATHLEN, fs ) != NULL ) {
237
-	len = strlen( line );
238
-	if (( line[ len - 1 ] ) != '\n' ) {
239
-	    syslog( LOG_ERR, "special_t: %s: line too long", transcript );
240
-	    break;
241
+    /*
242
+     * in order, we look for special file transcript lines in the
243
+     * following locations:
244
+     *
245
+     *      - A transcript in the same directory and with the same name
246
+     *	      as the special file, but with a ".T" extension.
247
+     *
248
+     *      - A transcript named "<remote_id>.T" in the same directory as
249
+     *        the client's special file directory root.
250
+     *
251
+     *      - /var/radmind/transcript/special.T
252
+     *
253
+     * if no matching transcript line is found, default metadata is
254
+     * returned to the client (type: f; mode: 0444; owner: 0; group: 0).
255
+     */
256
+    paths[ 0 ] = sp_path;
257
+    paths[ 1 ] = special_dir;
258
+    paths[ 2 ] = "transcript/special.T";
259
+    paths[ 3 ] = NULL;
260
+
261
+    for ( i = 0; paths[ i ] != NULL; i++ ) {
262
+	if (( p = strrchr( paths[ i ], '.' )) != NULL
263
+		&& strcmp( p, ".T" ) == 0 ) {
264
+	    if ( strlen( paths[ i ] ) >= MAXPATHLEN ) {
265
+		syslog( LOG_WARNING, "special_t: path \"%s\" too long",
266
+			paths[ i ] );
267
+		continue;
268
+	    }
269
+	    strcpy( sp_t, paths[ i ] );
270
+	} else if ( snprintf( sp_t, MAXPATHLEN, "%s.T",
271
+			      paths[ i ] ) >= MAXPATHLEN ) {
272
+	    syslog( LOG_WARNING, "special_t: path \"%s.T\" too long", sp_path );
273
+	    continue;
274
 	}
275
 
276
-	if (( ac = argcargv( line, &av )) != 8 ) {
277
+	if (( fs = fopen( sp_t, "r" )) == NULL ) {
278
 	    continue;
279
 	}
280
-	if (( *av[ 0 ] != 'f' ) && ( *av[ 0 ] != 'a' )) {
281
-	    continue;
282
+
283
+	ln = 0;
284
+	while ( fgets( line, MAXPATHLEN, fs ) != NULL ) {
285
+	    ln++;
286
+	    len = strlen( line );
287
+	    if (( line[ len - 1 ] ) != '\n' ) {
288
+		syslog( LOG_ERR, "special_t: %s: line %d too long", sp_t, ln );
289
+		break;
290
+	    }
291
+
292
+	    /* only files and applefiles allowed */
293
+	    if ( strncmp( line, "f ", strlen( "f " )) != 0 &&
294
+			strncmp( line, "a ", strlen( "a " )) != 0 ) {
295
+		continue;
296
+	    }
297
+	    if (( ac = argcargv( line, &av )) != 8 ) {
298
+		syslog( LOG_WARNING, "special_t: %s: line %d: "
299
+			"bad transcript line", sp_t, ln );
300
+		continue;
301
+	    }
302
+
303
+	    if ( strcmp( av[ 1 ], remote_path ) == 0 ) { 
304
+		(void)fclose( fs );
305
+		return( av );
306
+	    }
307
 	}
308
 
309
-	if ( strcmp( av[ 1 ], epath ) == 0 ) { 
310
-	    (void)fclose( fs );
311
-	    return( av );
312
+	if ( fclose( fs ) != 0 ) {
313
+	    syslog( LOG_WARNING, "special_t: fclose %s: %m", sp_t );
314
 	}
315
+	fs = NULL;
316
     }
317
-
318
-    (void)fclose( fs );
319
+    if ( fs != NULL ) {
320
+	(void)fclose( fs );
321
+    }
322
+    
323
     return( NULL );
324
 }
325
 
326
@@ -624,11 +676,11 @@ f_stat( SNET *sn, int ac, char *av[] )
327
     switch ( key ) {
328
     case K_COMMAND:
329
 	if ( ac == 2 ) {
330
-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
331
+	    snet_writef( sn, RADMIND_STAT_FMT,
332
 		"f", "command", DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
333
 		st.st_mtime, st.st_size, cksum_b64 );
334
 	} else {
335
-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
336
+	    snet_writef( sn, RADMIND_STAT_FMT,
337
 		"f", av[ 2 ], DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
338
 		st.st_mtime, st.st_size, cksum_b64 );
339
 	}
340
@@ -636,61 +688,33 @@ f_stat( SNET *sn, int ac, char *av[] )
341
         
342
 		    
343
     case K_TRANSCRIPT:
344
-	snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
345
+	snet_writef( sn, RADMIND_STAT_FMT,
346
 		"f", av[ 2 ], 
347
 		DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
348
 		st.st_mtime, st.st_size, cksum_b64 );
349
 	return( 0 );
350
     
351
     case K_SPECIAL:
352
-	/*  status on a special file comes from 1 of three cases:
353
-	 *  1. A transcript in the special file directory
354
-	 *  2. A transcript in the Transcript dir with .T appended
355
-	 *  3. No transcript is found, and constants are returned
356
-	 */
357
-
358
-        /* look for transcript containing the information */
359
-	if ( ( strlen( path ) + 2 ) > MAXPATHLEN ) {
360
-	    syslog( LOG_WARNING, 
361
-		"f_stat: transcript path longer than MAXPATHLEN" );
362
-
363
-	    /* return constants */
364
-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
365
-		    "f", av[ 2 ], 
366
-		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
367
-		    st.st_mtime, st.st_size, cksum_b64 );
368
-	    return( 0 );
369
-	}
370
-
371
-	/* if allowable, check for transcript in the special file directory */
372
-
373
-	strcat( path, ".T" );
374
-
375
-	/* store value of av[ 2 ], because argcargv will be called
376
+	/*
377
+	 * store value of av[ 2 ], because argcargv will be called
378
 	 * from special_t(), and that will blow away the current values
379
-	 * for av[ 2 ]
380
-	 *
381
-	 * Could just use new argvargc API... XXX  Notice how we never free
382
-	 * env_file...
383
+	 * for av[ 2 ].
384
 	 */
385
-
386
 	if (( enc_file = strdup( av[ 2 ] )) == NULL ) {
387
 	    syslog( LOG_ERR, "f_stat: strdup: %s %m", av[ 2 ] );
388
 	    return( -1 );
389
 	}
390
 
391
 	if (( av = special_t( path, enc_file )) == NULL ) {
392
-	    if (( av = special_t( "transcript/special.T", enc_file ))
393
-		    == NULL ) {
394
-		snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
395
-			"f", enc_file, 
396
-			DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
397
-			st.st_mtime, st.st_size, cksum_b64 );
398
-		free( enc_file );
399
-		return( 0 );
400
-	    }
401
+	    /* no special transcript match found, return defaults. */
402
+	    snet_writef( sn, RADMIND_STAT_FMT,
403
+		    "f", enc_file, 
404
+		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
405
+		    st.st_mtime, st.st_size, cksum_b64 );
406
+	    free( enc_file );
407
+	    return( 0 );
408
 	}
409
-	snet_writef( sn, "%s %s %s %s %s %d %" PRIofft "d %s\r\n",
410
+	snet_writef( sn, RADMIND_STAT_FMT,
411
 		av[ 0 ], enc_file,
412
 		av[ 2 ], av[ 3 ], av[ 4 ],
413
 		st.st_mtime, st.st_size, cksum_b64 );
414
@@ -1261,8 +1285,7 @@ command_k( char *path_config, int depth )
415
 	    continue;
416
 	}
417
 	if ( strcmp( av[ 0 ], "@include" ) == 0 ) {
418
-	    depth++;
419
-	    if ( depth > RADMIND_MAX_INCLUDE_DEPTH ) {
420
+	    if ( depth >= RADMIND_MAX_INCLUDE_DEPTH ) {
421
 		syslog( LOG_ERR, "%s: line %d: include %s exceeds max depth",
422
 			path_config, linenum, av[ 1 ] );
423
 		goto command_k_done;
424
@@ -1277,7 +1300,7 @@ command_k( char *path_config, int depth )
425
 		    continue;
426
 		}
427
 	    }
428
-	    if ( command_k( av[ 1 ], depth ) != 0 ) {
429
+	    if ( command_k( av[ 1 ], depth + 1 ) != 0 ) {
430
 		continue;
431
 	    }
432
 
433
@@ -1325,7 +1348,8 @@ command_k( char *path_config, int depth )
434
 
435
     /* If we get here, the host that connected is not in the config
436
        file. So screw him. */
437
-    syslog( LOG_ERR, "host not in config file: %s", remote_host );
438
+    syslog( LOG_ERR, "host %s not in config file %s",
439
+		remote_host, path_config );
440
 
441
 command_k_done:
442
     snet_close( sn );
443
diff --git a/command.h b/command.h
444
index b0ea9f5..e0ee775 100644
445
--- ./command.h
446
+++ ./command.h
447
@@ -13,3 +13,5 @@ struct command {
448
     char	*c_name;
449
     int		(*c_func)( SNET *, int, char *[] );
450
 };
451
+
452
+#define RADMIND_STAT_FMT "%s %s %o %d %d %" PRItimet "d %" PRIofft "d %s\r\n"
453
diff --git a/configure.ac b/configure.ac
454
index 43a243c..e724f32 100644
455
--- ./configure.ac
456
+++ ./configure.ac
457
@@ -44,25 +44,36 @@ AC_SYS_LARGEFILE
458
 
459
 # Check sizes
460
 AC_CHECK_SIZEOF(off_t)
461
+AC_CHECK_SIZEOF(time_t)
462
+
463
+# check early to make any required changes to environment for following tests.
464
+CHECK_UNIVERSAL_BINARIES
465
+
466
+# mute Mac OS X's helpful notices that using dylib OpenSSL
467
+MACOSX_MUTE_DEPRECATION_WARNINGS
468
 
469
 # Checks for libraries.
470
 AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) 
471
 if test x$libc_inet_aton != xyes; then 
472
     AC_CHECK_LIB(resolv, inet_aton) 
473
 fi 
474
-AC_CHECK_LIB(c, lchown)
475
-AC_CHECK_LIB(c, lchmod)
476
+if test x$host_vendor = xapply; then
477
+    AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], [])
478
+    AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], [])
479
+fi
480
 AC_CHECK_LIB(nsl, gethostbyaddr)
481
 AC_CHECK_LIB([socket], [socket])
482
 AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL])
483
 AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file <openssl/ssl.h>
484
 is required for this software.  You may be running RedHat 9.  If so, see the FAQ or the README for further instructions.])])
485
 AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL])
486
-AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
487
+AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
488
 
489
 # PAM
490
-AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes)
491
+AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr)
492
 if test x_"$with_pam" != x_no; then
493
+    CPPFLAGS="${CPPFLAGS} -I$with_pam/include"
494
+    LDFLAGS="${LDFLAGS} -L$with_pam/lib"
495
     AC_CHECK_LIB([pam], [pam_start],
496
 	[
497
 	AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)])
498
@@ -75,7 +86,6 @@ AC_CHECK_HEADER([dns_sd.h], [AC_DEFINE(HAVE_DNSSD)], [], [])
499
 AC_CHECK_LIB(dns_sd, DNSServiceRegister)
500
 
501
 CHECK_ZLIB
502
-CHECK_UNIVERSAL_BINARIES
503
 
504
 # HPUX lacks wait4 and strtoll
505
 AC_CHECK_FUNCS(wait4 strtoll)
506
diff --git a/contrib/specialist b/contrib/specialist
507
new file mode 100755
508
index 0000000..ee796ac
509
--- /dev/null
510
+++ ./contrib/specialist
511
@@ -0,0 +1,79 @@
512
+#! /bin/sh
513
+
514
+# specialist: assist creation of special files.
515
+
516
+PATH=/bin:/usr/bin:/usr/local/bin; export PATH
517
+
518
+SCRIPT=`basename "$0"`
519
+INPUT_FORMAT=${INPUT_FORMAT:=path}
520
+
521
+usage() {
522
+    echo "usage: ${SCRIPT} [ -T ]" 1>&2
523
+    exit 1
524
+}
525
+
526
+die() {
527
+    msg=$*
528
+
529
+    echo "${msg}" 1>&2
530
+    exit 2
531
+}
532
+
533
+# create a special transcript line for the given path.
534
+specialize() {
535
+    local path="$1"
536
+
537
+    [ -n "${path}" -a -f "${path}" ] || die "Invalid path: ${path}"
538
+
539
+    fsdiff -1 -c sha1 "${path}"
540
+    return $?
541
+}
542
+
543
+specialize_transcript() {
544
+    local path=""
545
+    status=0
546
+
547
+    while read type path remainder; do
548
+	if [ x"${type}" != x"f" ]; then
549
+	    continue
550
+	fi
551
+
552
+	specialize "${path}"
553
+    done
554
+}
555
+
556
+specialize_paths() {
557
+    local path=""
558
+    status=0
559
+
560
+    while read path; do
561
+	specialize "${path}"
562
+	if [ $? -ne 0 ]; then
563
+	    status=1
564
+	fi
565
+    done
566
+
567
+    return "${status}"
568
+}
569
+
570
+while getopts T opt; do
571
+    case $opt in
572
+    T)
573
+	INPUT_FORMAT="transcript"
574
+	;;
575
+
576
+    *)
577
+	usage
578
+	;;
579
+	
580
+    esac
581
+done
582
+shift $((OPTIND - 1))
583
+
584
+if [ x"${INPUT_FORMAT}" = x"transcript" ]; then
585
+    specialize_transcript
586
+else
587
+    specialize_paths
588
+fi
589
+
590
+exit $?
591
diff --git a/fsdiff.c b/fsdiff.c
592
index 61fbb03..57d3ff0 100644
593
--- ./fsdiff.c
594
+++ ./fsdiff.c
595
@@ -249,6 +249,144 @@ fs_walk( char *path, struct stat *st, char *type, struct applefileinfo *afinfo,
596
     return;
597
 }
598
 
599
+    static char *
600
+canonicalized_path( char *path )
601
+{
602
+    int			len;
603
+    static char		cpath[ MAXPATHLEN ];
604
+
605
+    if ( path == NULL ) {
606
+	return( NULL );
607
+    }
608
+
609
+    len = strlen( path );
610
+    if ( len >= sizeof( cpath )) {
611
+	fprintf( stderr, "fsdiff: path too long: %s\n", path );
612
+	exit( 2 );
613
+    }
614
+    strcpy( cpath, path );
615
+
616
+    /* Clip trailing '/' */
617
+    if (( len > 1 ) && ( cpath[ len - 1 ] == '/' )) {
618
+	cpath[ len - 1 ] = '\0';
619
+	len--;
620
+    }
621
+
622
+    /*
623
+     * If prefix doesn't contain a directory, canonicalize it by prepending a
624
+     * "./".  This allow paths to be dynamically converted between relative and
625
+     * absolute paths without breaking sort order.
626
+     */
627
+    switch( cpath[ 0 ] ) {
628
+    case '/':
629
+        break;
630
+
631
+    case '.':
632
+	/* Don't rewrite '.' or paths starting with './' */
633
+	if ( len == 1 || cpath[ 1 ] == '/' ) {
634
+	    break;
635
+	}
636
+
637
+    default:
638
+	if ( len + 2 >= sizeof( cpath )) {
639
+	    fprintf( stderr, "fsdiff: path too long: ./%s\n", cpath );
640
+	    exit( 2 );
641
+	}
642
+	memmove( cpath + 2, cpath, len );
643
+	cpath[ 0 ] = '.'; cpath[ 1 ] = '/';
644
+
645
+        break;
646
+    }
647
+
648
+    /*
649
+     * Determine if called with relative or absolute pathing.  Path is relative
650
+     * if it's just '.' or starts with './'.  File names that start with a '.'
651
+     * are absolute.
652
+     */
653
+    if ( cpath[ 0 ] == '.' ) {
654
+	if ( len == 1 ) {
655
+	    tran_format = T_RELATIVE;
656
+	} else if ( cpath[ 1 ] == '/' ) {
657
+	    tran_format = T_RELATIVE;
658
+	} else {
659
+	    tran_format = T_ABSOLUTE;
660
+	}
661
+    } else {
662
+	tran_format = T_ABSOLUTE;
663
+    }
664
+
665
+    return( cpath );
666
+}
667
+
668
+    static void
669
+fsdiff( char *path, char *kfile, int start, int finish, int pdel ) 
670
+{
671
+    struct applefileinfo	afinfo;
672
+    struct stat			st;
673
+    char			type;
674
+    char			lpath[ MAXPATHLEN ];
675
+    int				len;
676
+
677
+    if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) {
678
+	perror( "OOPS!" );
679
+	exit( 2 );
680
+    }
681
+
682
+    if ( skip && strcmp( path, "-" ) == 0 ) {
683
+	/* leave excludes in place */
684
+	skip = skip & ~T_SKIP_EXCLUDES;
685
+
686
+	path_prefix = "/";
687
+	transcript_init( kfile, K_CLIENT );
688
+
689
+	/* run -1 against every line we get from stdin */
690
+	while ( fgets( lpath, sizeof( lpath ), stdin ) != NULL ) {
691
+	    len = strlen( lpath );
692
+	    if ( lpath[ len - 1 ] != '\n' ) {
693
+		fprintf( stderr, "fsdiff: fgets: line too long\n" );
694
+		exit( 2 );
695
+	    }
696
+	    lpath[ len - 1 ] = '\0';
697
+	    path = canonicalized_path( lpath );
698
+
699
+	    if ( radstat( path, &st, &type, &afinfo ) != 0 ) {
700
+		if ( errno != ENOENT ) {
701
+		    perror( lpath );
702
+		    exit( 2 );
703
+		}
704
+
705
+		fprintf( stderr, "Warning: %s: %s\n", path, strerror( errno ));
706
+		continue;
707
+	    }
708
+	    (void)transcript( path, &st, &type, &afinfo, pdel );
709
+	}
710
+	if ( ferror( stdin )) {
711
+	    perror( "fgets" );
712
+	    exit( 2 );
713
+	}
714
+    } else {
715
+	path_prefix = canonicalized_path( path );
716
+
717
+	/* initialize the transcripts */
718
+	transcript_init( kfile, K_CLIENT );
719
+
720
+	if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) {
721
+	    perror( path_prefix );
722
+	    exit( 2 );
723
+	}
724
+
725
+	fs_walk( path_prefix, &st, &type, &afinfo, start, finish, pdel );
726
+    }
727
+
728
+    if ( finish > 0 ) {
729
+	printf( "%%%d\n", ( int )finish );
730
+    }
731
+
732
+    /* free the transcripts */
733
+    transcript_free( );
734
+    hardlink_free( );
735
+}
736
+
737
     int
738
 main( int argc, char **argv ) 
739
 {
740
@@ -258,9 +396,6 @@ main( int argc, char **argv )
741
     int 		c, len, edit_path_change = 0;
742
     int 		errflag = 0, use_outfile = 0;
743
     int			finish = 0;
744
-    struct stat		st;
745
-    char		type, buf[ MAXPATHLEN ];
746
-    struct applefileinfo	afinfo;
747
 
748
     edit_path = CREATABLE;
749
     cksum = 0;
750
@@ -300,7 +435,7 @@ main( int argc, char **argv )
751
 	    break;
752
 
753
 	case '1':
754
-	    skip = 1;
755
+	    skip = T_SKIP_ALL;
756
 	case 'C':
757
 	    edit_path_change++;
758
 	    edit_path = CREATABLE;
759
@@ -347,82 +482,13 @@ main( int argc, char **argv )
760
     }
761
 
762
     if ( errflag || ( argc - optind != 1 )) {
763
-	fprintf( stderr, "usage: %s { -C | -A | -1 } [ -IVW ] ", argv[ 0 ] );
764
+	fprintf( stderr, "usage: %s { -C | -A | -1 } " "[ -IVW ] ", argv[ 0 ] );
765
 	fprintf( stderr, "[ -K command ] " );
766
 	fprintf( stderr, "[ -c checksum ] [ -o file [ -%% ] ] path\n" );
767
 	exit ( 2 );
768
     }
769
 
770
-    path_prefix = argv[ optind ];
771
-    len = strlen( path_prefix );
772
-
773
-    /* Clip trailing '/' */
774
-    if (( len > 1 ) && ( path_prefix[ len - 1 ] == '/' )) {
775
-	path_prefix[ len - 1 ] = '\0';
776
-	len--;
777
-    }
778
-
779
-    /* If path_prefix doesn't contain a directory, canonicalize it by
780
-     * prepending a "./".  This allow paths to be dynamically converted between
781
-     * relative and absolute paths without breaking sort order.
782
-     */
783
-    switch( path_prefix[ 0 ] ) {
784
-    case '/':
785
-        break;
786
-
787
-    case '.':
788
-	/* Don't rewrite '.' or paths starting with './' */
789
-	if (( len == 1 ) || (  path_prefix[ 1 ] == '/' )) {
790
-	    break;
791
-	}
792
-    default:
793
-        if ( snprintf( buf, sizeof( buf ), "./%s",
794
-                path_prefix ) >= MAXPATHLEN ) {
795
-            fprintf( stderr, "path too long\n" );
796
-            exit( 2 );
797
-        }
798
-	path_prefix = buf;
799
-        break;
800
-    }
801
-
802
-    /* Determine if called with relative or absolute pathing.  Path is relative
803
-     * if it's just '.' or starts with './'.  File names that start with a '.'
804
-     * are absolute.
805
-     */
806
-    if ( path_prefix[ 0 ] == '.' ) {
807
-	if ( len == 1 ) {
808
-	    tran_format = T_RELATIVE;
809
-	} else if ( path_prefix[ 1 ] == '/' ) {
810
-	    tran_format = T_RELATIVE;
811
-	} else {
812
-	    tran_format = T_ABSOLUTE;
813
-	}
814
-    } else {
815
-	tran_format = T_ABSOLUTE;
816
-    }
817
-
818
-    if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) {
819
-	perror( path_prefix );
820
-	exit( 2 );
821
-    }
822
-
823
-    if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) {
824
-	perror( "OOPS!" );
825
-	exit( 2 );
826
-    }
827
-
828
-    /* initialize the transcripts */
829
-    transcript_init( kfile, K_CLIENT );
830
-
831
-    fs_walk( path_prefix, &st, &type, &afinfo, 0, finish, 0 );
832
-
833
-    if ( finish > 0 ) {
834
-	printf( "%%%d\n", ( int )finish );
835
-    }
836
-
837
-    /* free the transcripts */
838
-    transcript_free( );
839
-    hardlink_free( );
840
+    fsdiff( argv[ optind ], kfile, 0, finish, 0 );
841
 
842
     /* close the output file */     
843
     fclose( outtran );
844
diff --git a/ktcheck.c b/ktcheck.c
845
index 567a555..9d1f41d 100644
846
--- ./ktcheck.c
847
+++ ./ktcheck.c
848
@@ -459,7 +459,7 @@ check( SNET *sn, char *type, char *file )
849
 	perror( "Incorrect number of arguments\n" );
850
 	return( 2 );
851
     }
852
-    times.modtime = atoi( targv[ 5 ] );
853
+    times.modtime = strtotimet( targv[ 5 ], NULL, 10 );
854
     times.actime = time( NULL );
855
 
856
     if (( stat( path, &st )) != 0 ) {
857
@@ -506,7 +506,7 @@ check( SNET *sn, char *type, char *file )
858
 		needupdate = 1;
859
 	    }
860
 	} else {
861
-	    if ( atoi( targv[ 5 ] ) != (int)st.st_mtime )  {
862
+	    if ( strtotimet( targv[ 5 ], NULL, 10 ) != st.st_mtime )  {
863
 		needupdate = 1;
864
 	    }
865
 	}
866
diff --git a/lapply.c b/lapply.c
867
index c13ad9e..3749617 100644
868
--- ./lapply.c
869
+++ ./lapply.c
870
@@ -651,27 +651,37 @@ dirchecklist:
871
 filechecklist:
872
 		if ( head == NULL ) {
873
 		    if ( unlink( path ) != 0 ) {
874
-			perror( path );
875
-			goto error2;
876
-		    }
877
-		    if ( !quiet && !showprogress ) {
878
-			printf( "%s: deleted\n", path );
879
-		    }
880
-		    if ( showprogress ) {
881
-			progressupdate( PROGRESSUNIT, path );
882
-		    }
883
-		} else {
884
-		    if ( ischildcase( path, head->path, case_sensitive )) {
885
-			if ( unlink( path ) != 0 ) {
886
+			if ( !force || errno != ENOENT ) {
887
 			    perror( path );
888
 			    goto error2;
889
 			}
890
+			fprintf( stderr, "Warning: failed to remove %s: %s\n",
891
+				path, strerror( errno ));
892
+		    } else {
893
 			if ( !quiet && !showprogress ) {
894
 			    printf( "%s: deleted\n", path );
895
 			}
896
 			if ( showprogress ) {
897
 			    progressupdate( PROGRESSUNIT, path );
898
 			}
899
+		    }
900
+		} else {
901
+		    if ( ischildcase( path, head->path, case_sensitive )) {
902
+			if ( unlink( path ) != 0 ) {
903
+			    if ( !force || errno != ENOENT ) {
904
+				perror( path );
905
+				goto error2;
906
+			    }
907
+			    fprintf( stderr, "Warning: failed to remove %s: "
908
+				    "%s\n", path, strerror( errno ));
909
+			} else {
910
+			    if ( !quiet && !showprogress ) {
911
+				printf( "%s: deleted\n", path );
912
+			    }
913
+			    if ( showprogress ) {
914
+				progressupdate( PROGRESSUNIT, path );
915
+			    }
916
+			}
917
 		    } else {
918
 			/* remove head */
919
 			if ( rmdir( head->path ) != 0 ) {
920
diff --git a/largefile.h b/largefile.h
921
index 4a11d3b..3a09ce9 100644
922
--- ./largefile.h
923
+++ ./largefile.h
924
@@ -18,3 +18,15 @@
925
 #define strtoofft(x,y,z)	(strtol((x),(y),(z)))
926
 #define PRIofft			"l"
927
 #endif
928
+
929
+#if SIZEOF_TIME_T == 8
930
+    #ifdef HAVE_STRTOLL
931
+    #define strtotimet(x,y,z)	(strtoll((x),(y),(z)))
932
+    #else /* !HAVE_STRTOLL */
933
+    #define strtotimet(x,y,z)	(strtol((x),(y),(z)))
934
+    #endif /* HAVE_STRTOLL */
935
+    #define PRItimet		"ll"
936
+#else /* SIZEOF_TIME_T != 8 */
937
+    #define strtotimet(x,y,z)	(strtol((x),(y),(z)))
938
+    #define PRItimet		"l"
939
+#endif /* SIZEOF_TIME_T */
940
diff --git a/lcksum.c b/lcksum.c
941
index 40d3c1e..cc09f8c 100644
942
--- ./lcksum.c
943
+++ ./lcksum.c
944
@@ -434,7 +434,7 @@ do_lcksum( char *tpath )
945
 		/* Check to see if checksum is listed in transcript */
946
 		if ( strcmp( targv[ 7 ], "-" ) != 0) {
947
 		    /* use mtime from server */
948
-		    fprintf( ufs, "%s %-37s %4s %5s %5s %9ld "
949
+		    fprintf( ufs, "%s %-37s %4s %5s %5s %9" PRItimet "d "
950
 			    "%7" PRIofft "d %s\n",
951
 			targv[ 0 ], targv[ 1 ], targv[ 2 ], targv[ 3 ],
952
 			targv[ 4 ], st.st_mtime, st.st_size, lcksum );
953
@@ -457,6 +457,12 @@ done:
954
 	}
955
 	free( line );
956
     }
957
+    if ( fclose( f ) != 0 ) {
958
+	fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno ));
959
+	cleanup( updatetran, upath );
960
+	exit( 2 );
961
+    }
962
+
963
     if ( showprogress ) {
964
 	progressupdate( bytes, "" );
965
     }
966
@@ -496,6 +502,10 @@ done:
967
 badline:
968
     exitval = 1;
969
 
970
+    if ( fclose( f ) != 0 ) {
971
+	fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno ));
972
+    }
973
+
974
     if ( checkall ) {
975
 	goto done;
976
     } else {
977
diff --git a/man/lcreate.1 b/man/lcreate.1
978
index 64bdcc2..658c1fc 100644
979
--- ./man/lcreate.1
980
+++ ./man/lcreate.1
981
@@ -45,12 +45,6 @@ will store the file on the server and give a warning.
982
 .sp
983
 If the -n option is given, no files or transcripts are uploaded.  Instead,
984
 .B lcreate
985
-verifies that all files exist in the filesystem and have
986
-the same size as listed in the transcript.  If used with the -c option,
987
-checksums are also verified.
988
-.sp
989
-If the -n option is given, no files or transcripts are uploaded.  Instead,
990
-.B lcreate
991
 uses 
992
 .BR access (2)
993
 to verify that all files in the transcript exist in the
994
diff --git a/man/rash.1 b/man/rash.1
995
index 92c77d3..52fc6f0 100644
996
--- ./man/rash.1
997
+++ ./man/rash.1
998
@@ -11,6 +11,10 @@
999
 |
1000
 .B -q
1001
 ] [
1002
+.BR \-C\  "generate"
1003
+|
1004
+.BI \-C\  checksum
1005
+] [
1006
 .B \-D
1007
 .I workingdir
1008
 ] [
1009
@@ -120,6 +124,24 @@ to use percentage done progress output.
1010
 .B \-c
1011
 use sha1 checksums.
1012
 .TP 19
1013
+.BR \-C\  "generate"
1014
+Print a sha1 checksum of the difference transcript of applied changes. For use with
1015
+.IR auto ,
1016
+.IR force
1017
+or
1018
+.IR update .
1019
+.TP 19
1020
+.BI \-C\  checksum
1021
+In
1022
+.I auto
1023
+mode, exit with an error if the checksum of the difference transcript to be applied does not match
1024
+.IR checksum .
1025
+In
1026
+.I update
1027
+or
1028
+.I force
1029
+mode, warn if the two do not match.
1030
+.TP 19
1031
 .BI \-D\  workingdir
1032
 change to
1033
 .I workingdir
1034
diff --git a/mkdirs.c b/mkdirs.c
1035
index 3839432..65ddeba 100644
1036
--- ./mkdirs.c
1037
+++ ./mkdirs.c
1038
@@ -37,7 +37,9 @@ mkdirs( char *path )
1039
 	if ( mkdir( path, 0777 ) == 0 ) {
1040
 	    break;
1041
 	}
1042
-	if ( errno != ENOENT ) {
1043
+	if ( errno == EEXIST ) {
1044
+	    break;
1045
+	} else if ( errno != ENOENT ) {
1046
 	    return( -1 );
1047
 	}
1048
 	q = p;
1049
diff --git a/ra.sh b/ra.sh
1050
index 8ee8dd4..4152d27 100755
1051
--- ./ra.sh
1052
+++ ./ra.sh
1053
@@ -91,7 +91,7 @@ checkedout() {
1054
 }
1055
 
1056
 usage() {
1057
-    $ECHO "Usage:	$0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
1058
+    $ECHO "Usage:	$0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C <checksum> ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
1059
     exit 1
1060
 }
1061
 
1062
@@ -128,6 +128,38 @@ dopostapply() {
1063
     fi
1064
 }
1065
 
1066
+cksum_generate() {
1067
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
1068
+	FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'`
1069
+    fi
1070
+}
1071
+
1072
+cksum_compare() {
1073
+    if [ -n "$FSDIFF_CHECKSUM" -a \
1074
+	    "$FSDIFF_CHECKSUM" != "generate" -a \
1075
+	    "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then
1076
+	return 1
1077
+    fi
1078
+
1079
+    return 0
1080
+}
1081
+
1082
+cksum_print() {
1083
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
1084
+	$ECHO "Difference transcript checksum: $FTMP_CHECKSUM"
1085
+    fi
1086
+}
1087
+
1088
+cksum_mismatch() {
1089
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
1090
+	$ECHO
1091
+	$ECHO "**** Difference transcript checksum mismatch!"
1092
+	$ECHO "****	Expected: $FSDIFF_CHECKSUM"
1093
+	$ECHO "****	Actual:   $FTMP_CHECKSUM"
1094
+	#ECHO
1095
+    fi
1096
+}
1097
+
1098
 update() {
1099
     opt="$1"
1100
     kopt=
1101
@@ -211,6 +243,11 @@ update() {
1102
     fi
1103
     if [ x"${opt}" = x"interactive" ]; then
1104
 	while [ 1 ]; do
1105
+	    cksum_generate
1106
+	    if ! cksum_compare; then
1107
+		cksum_mismatch
1108
+	    fi
1109
+
1110
 	    if [ x"${can_edit}" = x"yes" ]; then
1111
 		$ECHO -n "(e)dit difference transcript, "
1112
 	    fi
1113
@@ -248,7 +285,8 @@ update() {
1114
 		
1115
     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
1116
     case "$?" in
1117
-    0)	;;
1118
+    0)	cksum_print
1119
+	;;
1120
 
1121
     *)  if [ x"$opt" = x"hook" ]; then
1122
 	    $ECHO -n "Applying changes failed, trying again "
1123
@@ -284,7 +322,7 @@ if [ -f "${DEFAULTS}" ]; then
1124
     . "${DEFAULTS}"
1125
 fi
1126
 
1127
-while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
1128
+while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do
1129
     case $opt in
1130
     %)  PROGRESS="-%"
1131
 	FPROGRESS="-%"
1132
@@ -293,6 +331,13 @@ while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
1133
     q)  PROGRESS="-q"
1134
 	;;
1135
 
1136
+    C)	FSDIFF_CHECKSUM="$OPTARG"
1137
+	if ! type openssl >/dev/null 2>&1; then
1138
+	    $ECHO "-C requires openssl, but no openssl found in PATH $PATH"
1139
+	    cleanup_and_exit
1140
+	fi
1141
+	;;
1142
+
1143
     c)	CHECKSUM="-csha1"
1144
 	;;
1145
 
1146
@@ -524,6 +569,14 @@ auto)
1147
 		cleanup
1148
 		exit 1
1149
 	    fi
1150
+
1151
+	    cksum_generate
1152
+	    if ! cksum_compare; then
1153
+		$ECHO "Auto failure: `hostname`: difference cksum mismatch" 
1154
+		cksum_mismatch
1155
+		cleanup_and_exit
1156
+	    fi
1157
+
1158
 	    dopreapply ${FTMP}
1159
 	    if [ -s ${FTMP} ]; then
1160
 		lapply ${NETOPTS} ${CASE} ${PROGRESS} \
1161
@@ -532,6 +585,7 @@ auto)
1162
 		0)
1163
 		    $ECHO Auto update: `hostname`
1164
 		    cat ${FTMP}
1165
+		    cksum_print
1166
 		    dopostapply ${FTMP}
1167
 		    cleanup
1168
 		    break
1169
@@ -588,14 +642,17 @@ force)
1170
 	exit 0
1171
     fi
1172
     
1173
+    cksum_generate
1174
+    cksum_compare || cksum_mismatch
1175
     dopreapply ${FTMP}
1176
     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
1177
     case "$?" in
1178
-    0)	;;
1179
+    0)	cksum_print
1180
+	;;
1181
 
1182
     *)	cleanup
1183
-	    exit $?
1184
-	    ;;
1185
+	exit $?
1186
+	;;
1187
     esac
1188
     dopostapply ${FTMP}
1189
     
1190
diff --git a/t2pkg.c b/t2pkg.c
1191
index ad43135..a75e8de 100644
1192
--- ./t2pkg.c
1193
+++ ./t2pkg.c
1194
@@ -38,6 +38,7 @@ extern int	showprogress;
1195
 extern off_t	lsize;
1196
 extern char	*version;
1197
 
1198
+int		tran_format = -1;
1199
 int		cksum = 0;
1200
 int		force = 0;
1201
 int		case_sensitive = 1;
1202
@@ -718,31 +719,23 @@ main( int ac, char *av[] )
1203
 	}
1204
 
1205
 	/* create the destination path */
1206
-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
1207
+	if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
1208
 		>= MAXPATHLEN ) {
1209
 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
1210
 			t->t_pinfo.pi_name );
1211
 	    exit( 2 );
1212
 	}
1213
-	if ( mkdirs( tmp ) < 0 ) {
1214
-	    fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno ));
1215
-	}
1216
-	if ( realpath( tmp, dst ) == NULL ) {
1217
-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
1218
-	    exit( 2 );
1219
+	if ( mkdirs( dst ) < 0 ) {
1220
+	    fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno ));
1221
 	}
1222
 
1223
 	/* and the source path */
1224
-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
1225
+	if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
1226
 		>= MAXPATHLEN ) {
1227
 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
1228
 			t->t_pinfo.pi_name );
1229
 	    exit( 2 );
1230
 	}
1231
-	if ( realpath( tmp, src ) == NULL ) {
1232
-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
1233
-	    exit( 2 );
1234
-	}
1235
 
1236
 	if ( local_update( t, dst, src, where ) != 0 ) {
1237
 	    /* XXX is this really a good idea? */
1238
diff --git a/transcript.c b/transcript.c
1239
index cad8d50..94e21ca 100644
1240
--- ./transcript.c
1241
+++ ./transcript.c
1242
@@ -45,7 +45,7 @@ struct list			*exclude_list;
1243
 
1244
 char				*path_prefix = NULL;
1245
 int				edit_path;
1246
-int				skip;
1247
+int				skip = 0;
1248
 int				cksum;
1249
 int				fs_minus;
1250
 int				exclude_warnings = 0;
1251
@@ -271,7 +271,7 @@ transcript_parse( struct transcript *tran )
1252
 	tran->t_pinfo.pi_stat.st_mode = strtol( argv[ 2 ], NULL, 8 );
1253
 	tran->t_pinfo.pi_stat.st_uid = atoi( argv[ 3 ] );
1254
 	tran->t_pinfo.pi_stat.st_gid = atoi( argv[ 4 ] );
1255
-	tran->t_pinfo.pi_stat.st_mtime = atoi( argv[ 5 ] );
1256
+	tran->t_pinfo.pi_stat.st_mtime = strtotimet( argv[ 5 ], NULL, 10 );
1257
 	tran->t_pinfo.pi_stat.st_size = strtoofft( argv[ 6 ], NULL, 10 );
1258
 	if ( tran->t_type != T_NEGATIVE ) {
1259
 	    if (( cksum ) && ( strcmp( "-", argv [ 7 ] ) == 0  )) {
1260
@@ -436,12 +436,13 @@ t_print( struct pathinfo *fs, struct transcript *tran, int flag )
1261
 	 * but the corresponding transcript is negative, hence, retain
1262
 	 * the file system's mtime.  Woof!
1263
 	 */
1264
-	fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9d %7" PRIofft "d %s\n",
1265
+	fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9" PRItimet "d "
1266
+			  "%7" PRIofft "d %s\n",
1267
 		cur->pi_type, epath,
1268
 		(unsigned long)( T_MODE & cur->pi_stat.st_mode ), 
1269
 		(int)cur->pi_stat.st_uid, (int)cur->pi_stat.st_gid,
1270
 		( flag == PR_STATUS_NEG ) ?
1271
-			(int)fs->pi_stat.st_mtime : (int)cur->pi_stat.st_mtime,
1272
+			fs->pi_stat.st_mtime : cur->pi_stat.st_mtime,
1273
 		cur->pi_stat.st_size, cur->pi_cksum_b64 );
1274
 	break;
1275
 
1276
@@ -723,7 +724,7 @@ transcript_select( void )
1277
 	    if ( begin_tran->t_type != T_SPECIAL &&
1278
 		    t_exclude( begin_tran->t_pinfo.pi_name )) {
1279
 		if ( exclude_warnings ) {
1280
-		    fprintf( stderr, "Warning: excluding %s\n",
1281
+		    printf( "#! Warning: excluding %s\n",
1282
 				begin_tran->t_pinfo.pi_name );
1283
 		}
1284
 		transcript_parse( begin_tran );
1285
@@ -769,7 +770,7 @@ transcript( char *path, struct stat *st, char *type,
1286
 	    if ( list_size( special_list ) <= 0
1287
 		    || list_check( special_list, path ) == 0 ) {
1288
 		if ( exclude_warnings ) {
1289
-		    fprintf( stderr, "Warning: excluding %s\n", path );
1290
+		    printf( "#! Warning: excluding %s\n", path );
1291
 		}
1292
 
1293
 		/* move the transcripts ahead */
1294
@@ -949,7 +950,7 @@ transcript_init( char *kfile, int location )
1295
      */
1296
     t_new( T_NULL, NULL, NULL, NULL );
1297
 
1298
-    if ( skip ) {
1299
+    if ( skip == T_SKIP_ALL ) {
1300
 	return;
1301
     }
1302
 
1303
@@ -985,15 +986,17 @@ transcript_init( char *kfile, int location )
1304
 	exit( 2 );
1305
     }
1306
 
1307
-    if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) {
1308
-	/* open the special transcript if there were any special files */
1309
-	if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) {
1310
-	    fprintf( stderr, 
1311
-		    "special path too long: %s%s\n", kdir, special );
1312
-	    exit( 2 );
1313
+    if ( !( skip & T_SKIP_SPECIAL )) {
1314
+	if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) {
1315
+	    /* open the special transcript if there were any special files */
1316
+	    if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) {
1317
+		fprintf( stderr, 
1318
+			"special path too long: %s%s\n", kdir, special );
1319
+		exit( 2 );
1320
+	    }
1321
+	    sprintf( fullpath, "%s%s", kdir, special );
1322
+	    t_new( T_SPECIAL, fullpath, special, "special" );
1323
 	}
1324
-	sprintf( fullpath, "%s%s", kdir, special );
1325
-	t_new( T_SPECIAL, fullpath, special, "special" );
1326
     }
1327
 
1328
     if ( tran_head->t_type == T_NULL  && edit_path == APPLICABLE ) {
1329
@@ -1108,6 +1111,10 @@ read_kfile( char *kfile, int location )
1330
 	    break;
1331
 
1332
 	case 'n':				/* negative */
1333
+	    if ( skip & T_SKIP_NEGATIVE ) {
1334
+		break;
1335
+	    }
1336
+
1337
 	    if ( minus ) { 
1338
 		t_remove( T_NEGATIVE, av[ 1 ] );
1339
 	    } else {
1340
@@ -1116,6 +1123,10 @@ read_kfile( char *kfile, int location )
1341
 	    break;
1342
 
1343
 	case 'p':				/* positive */
1344
+	    if ( skip & T_SKIP_POSITIVE ) {
1345
+		break;
1346
+	    }
1347
+
1348
 	    if ( minus ) {
1349
 		t_remove( T_POSITIVE, av[ 1 ] );
1350
 	    } else {
1351
@@ -1124,6 +1135,10 @@ read_kfile( char *kfile, int location )
1352
 	    break;
1353
 
1354
 	case 'x':				/* exclude */
1355
+	    if ( skip & T_SKIP_EXCLUDES ) {
1356
+		break;
1357
+	    }
1358
+
1359
 	    if (( d_pattern = decode( av[ 1 ] )) == NULL ) {
1360
 		fprintf( stderr, "%s: line %d: decode buffer too small\n",
1361
 		    kfile, linenum );
1362
@@ -1149,6 +1164,10 @@ read_kfile( char *kfile, int location )
1363
 	    break;
1364
 
1365
 	case 's':				/* special */
1366
+	    if ( skip & T_SKIP_SPECIAL ) {
1367
+		break;
1368
+	    }
1369
+
1370
 	    path = av[ 1 ];
1371
 
1372
 	    /* Convert path to match transcript type */
1373
diff --git a/transcript.h b/transcript.h
1374
index 29ae3cf..f4453ca 100644
1375
--- ./transcript.h
1376
+++ ./transcript.h
1377
@@ -39,6 +39,14 @@ extern int		fs_minus;
1378
 extern FILE		*outtran;
1379
 extern char		*path_prefix;
1380
 
1381
+
1382
+#define T_SKIP_POSITIVE		(1 << 1)
1383
+#define T_SKIP_NEGATIVE		(1 << 2)
1384
+#define T_SKIP_SPECIAL		(1 << 3)
1385
+#define T_SKIP_EXCLUDES		(1 << 4)
1386
+#define	T_SKIP_ALL		(T_SKIP_POSITIVE | T_SKIP_NEGATIVE | \
1387
+				 T_SKIP_SPECIAL | T_SKIP_EXCLUDES)
1388
+
1389
 struct pathinfo {
1390
     char			pi_type;
1391
     int				pi_minus;
1392
diff --git a/update.c b/update.c
1393
index fa4227d..47911cc 100644
1394
--- ./update.c
1395
+++ ./update.c
1396
@@ -26,6 +26,7 @@
1397
 #include "update.h"
1398
 #include "code.h"
1399
 #include "radstat.h"
1400
+#include "largefile.h"
1401
 #include "transcript.h"
1402
 #include "progress.h"
1403
 #include "mkdirs.h"
1404
@@ -73,7 +74,7 @@ update( char *path, char *displaypath, int present, int newfile,
1405
 
1406
 	mode = strtol( targv[ 2 ], (char **)NULL, 8 );
1407
 
1408
-	times.modtime = atoi( targv[ 5 ] );
1409
+	times.modtime = strtotimet( targv[ 5 ], NULL, 10 );
1410
 	if ( times.modtime != st->st_mtime ) {
1411
 	    times.actime = st->st_atime;
1412
 	    if ( utime( path, &times ) != 0 ) {
(-)./files/patch-Makefile.in (-50 lines)
Lines 1-50 Link Here
1
--- ./Makefile.in.orig	2010-12-12 22:43:49.000000000 -0500
2
+++ ./Makefile.in	2012-03-20 14:37:54.000000000 -0400
3
@@ -204,37 +204,37 @@
4
 radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile
5
 	${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS}
6
 
7
-fsdiff : ${FSDIFF_OBJ}
8
+fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ}
9
 	${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS}
10
 
11
-ktcheck: ${KTCHECK_OBJ}
12
+ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ}
13
 	${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS}
14
 
15
-lapply: ${LAPPLY_OBJ}
16
+lapply: libsnet/libsnet.la ${LAPPLY_OBJ}
17
 	${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS}
18
 
19
-lcksum: ${LCKSUM_OBJ}
20
+lcksum: libsnet/libsnet.la ${LCKSUM_OBJ}
21
 	${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS}
22
 
23
-lcreate: ${LCREATE_OBJ}
24
+lcreate: libsnet/libsnet.la ${LCREATE_OBJ}
25
 	${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS}
26
 
27
-lmerge: ${LMERGE_OBJ}
28
+lmerge: libsnet/libsnet.la ${LMERGE_OBJ}
29
 	${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS}
30
 
31
-lfdiff: ${LFDIFF_OBJ}
32
+lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ}
33
 	${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS}
34
 
35
-repo : ${REPO_OBJ}
36
+repo: libsnet/libsnet.la ${REPO_OBJ}
37
 	${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS}
38
 
39
 t2pkg: ${T2PKG_OBJ}
40
 	${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS}
41
 
42
-twhich: ${TWHICH_OBJ}
43
+twhich: libsnet/libsnet.la ${TWHICH_OBJ}
44
 	${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS}
45
 
46
-lsort: ${LSORT_OBJ}
47
+lsort: libsnet/libsnet.la ${LSORT_OBJ}
48
 	${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS}
49
 
50
 FRC :
(-)./files/patch-README (-46 lines)
Lines 1-46 Link Here
1
--- ./README.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./README	2012-03-20 14:37:54.000000000 -0400
3
@@ -72,25 +72,25 @@
4
   % "env CPPFLAGS=-I/usr/kerberos/include ./configure"
5
 
6
 -----------------
7
-Building from CVS
8
+Building from git
9
 -----------------
10
 The Radmind Development Team occasionally asks for help testing a new feature
11
 or bug fix. The best way to assist is to download the source code from the
12
-CVS repository and build it manually. The following steps will result in
13
-a build from CVS.
14
+git repository and build it manually. The following steps will result in
15
+a build from git.
16
 
17
-1) Download the source from CVS:
18
+1) Download the source from git:
19
 
20
-cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \
21
-	checkout radmind
22
+    git clone git://radmind.git.sourceforge.net/gitroot/gradmind
23
 
24
 2) Move into the new radmind directory:
25
 
26
-cd radmind
27
+    cd radmind
28
 
29
-3) Download libsnet[1], the network library Radmind uses:
30
+3) Checkout all required submodules [1]:
31
 
32
-sh bin/getsnet
33
+    git submodule init
34
+    git submodule update
35
 
36
 4) Follow steps 2 and 3 from "More detailed instructions" for building, above.
37
 
38
@@ -115,4 +115,7 @@
39
 ----------
40
 References
41
 ----------
42
-[1]: http://sourceforge.net/projects/libsnet
43
+[1]: Current submodules:
44
+
45
+    * libsnet, a networking library with TLS support
46
+	http://sourceforge.net/projects/libsnet
(-)./files/patch-aclocal.m4 (-21 lines)
Lines 1-21 Link Here
1
--- ./aclocal.m4.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./aclocal.m4	2012-03-20 14:37:54.000000000 -0400
3
@@ -105,16 +105,11 @@
4
 	    arches="-arch i386 -arch ppc"
5
 	    ;;
6
 
7
-	  darwin9*)
8
+	  darwin9*|darwin10*|darwin11*)
9
 	    dep_target="-mmacosx-version-min=10.4"
10
 	    macosx_sdk="MacOSX10.5.sdk"
11
 	    arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64"
12
-	    ;;
13
-
14
-	  darwin10*)
15
-	    dep_target="-mmacosx-version-min=10.4"
16
-	    macosx_sdk="MacOSX10.6.sdk"
17
-	    arches="-arch i386 -arch x86_64 -arch ppc"
18
+	    LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib"
19
 	    ;;
20
 
21
 	  *)
(-)./files/patch-configure.ac (-44 lines)
Lines 1-44 Link Here
1
--- ./configure.ac.orig	2010-12-12 22:43:38.000000000 -0500
2
+++ ./configure.ac	2012-03-20 14:37:54.000000000 -0400
3
@@ -45,24 +45,29 @@
4
 # Check sizes
5
 AC_CHECK_SIZEOF(off_t)
6
 
7
+# check early to make any required changes to environment for following tests.
8
+CHECK_UNIVERSAL_BINARIES
9
+
10
 # Checks for libraries.
11
 AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) 
12
 if test x$libc_inet_aton != xyes; then 
13
     AC_CHECK_LIB(resolv, inet_aton) 
14
 fi 
15
-AC_CHECK_LIB(c, lchown)
16
-AC_CHECK_LIB(c, lchmod)
17
+AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], [])
18
+AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], [])
19
 AC_CHECK_LIB(nsl, gethostbyaddr)
20
 AC_CHECK_LIB([socket], [socket])
21
 AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL])
22
 AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file <openssl/ssl.h>
23
 is required for this software.  You may be running RedHat 9.  If so, see the FAQ or the README for further instructions.])])
24
 AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL])
25
-AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
26
+AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
27
 
28
 # PAM
29
-AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes)
30
+AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr)
31
 if test x_"$with_pam" != x_no; then
32
+    CPPFLAGS="${CPPFLAGS} -I$with_pam/include"
33
+    LDFLAGS="${LDFLAGS} -L$with_pam/lib"
34
     AC_CHECK_LIB([pam], [pam_start],
35
 	[
36
 	AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)])
37
@@ -75,7 +80,6 @@
38
 AC_CHECK_LIB(dns_sd, DNSServiceRegister)
39
 
40
 CHECK_ZLIB
41
-CHECK_UNIVERSAL_BINARIES
42
 
43
 # HPUX lacks wait4 and strtoll
44
 AC_CHECK_FUNCS(wait4 strtoll)
(-)./files/patch-lapply.c (-52 lines)
Lines 1-52 Link Here
1
--- ./lapply.c.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./lapply.c	2012-03-20 14:37:54.000000000 -0400
3
@@ -651,27 +651,37 @@
4
 filechecklist:
5
 		if ( head == NULL ) {
6
 		    if ( unlink( path ) != 0 ) {
7
-			perror( path );
8
-			goto error2;
9
-		    }
10
-		    if ( !quiet && !showprogress ) {
11
-			printf( "%s: deleted\n", path );
12
-		    }
13
-		    if ( showprogress ) {
14
-			progressupdate( PROGRESSUNIT, path );
15
-		    }
16
-		} else {
17
-		    if ( ischildcase( path, head->path, case_sensitive )) {
18
-			if ( unlink( path ) != 0 ) {
19
+			if ( !force || errno != ENOENT ) {
20
 			    perror( path );
21
 			    goto error2;
22
 			}
23
+			fprintf( stderr, "Warning: failed to remove %s: %s\n",
24
+				path, strerror( errno ));
25
+		    } else {
26
 			if ( !quiet && !showprogress ) {
27
 			    printf( "%s: deleted\n", path );
28
 			}
29
 			if ( showprogress ) {
30
 			    progressupdate( PROGRESSUNIT, path );
31
 			}
32
+		    }
33
+		} else {
34
+		    if ( ischildcase( path, head->path, case_sensitive )) {
35
+			if ( unlink( path ) != 0 ) {
36
+			    if ( !force || errno != ENOENT ) {
37
+				perror( path );
38
+				goto error2;
39
+			    }
40
+			    fprintf( stderr, "Warning: failed to remove %s: "
41
+				    "%s\n", path, strerror( errno ));
42
+			} else {
43
+			    if ( !quiet && !showprogress ) {
44
+				printf( "%s: deleted\n", path );
45
+			    }
46
+			    if ( showprogress ) {
47
+				progressupdate( PROGRESSUNIT, path );
48
+			    }
49
+			}
50
 		    } else {
51
 			/* remove head */
52
 			if ( rmdir( head->path ) != 0 ) {
(-)./files/patch-man__lcreate.1 (-15 lines)
Lines 1-15 Link Here
1
--- ./man/lcreate.1.orig	2010-12-12 22:50:53.000000000 -0500
2
+++ ./man/lcreate.1	2012-03-20 14:38:03.000000000 -0400
3
@@ -45,12 +45,6 @@
4
 .sp
5
 If the -n option is given, no files or transcripts are uploaded.  Instead,
6
 .B lcreate
7
-verifies that all files exist in the filesystem and have
8
-the same size as listed in the transcript.  If used with the -c option,
9
-checksums are also verified.
10
-.sp
11
-If the -n option is given, no files or transcripts are uploaded.  Instead,
12
-.B lcreate
13
 uses 
14
 .BR access (2)
15
 to verify that all files in the transcript exist in the
(-)./files/patch-man__rash.1 (-38 lines)
Lines 1-38 Link Here
1
--- ./man/rash.1.orig	2010-12-12 22:50:53.000000000 -0500
2
+++ ./man/rash.1	2012-03-20 14:38:08.000000000 -0400
3
@@ -11,6 +11,10 @@
4
 |
5
 .B -q
6
 ] [
7
+.BR \-C\  "generate"
8
+|
9
+.BI \-C\  checksum
10
+] [
11
 .B \-D
12
 .I workingdir
13
 ] [
14
@@ -120,6 +124,24 @@
15
 .B \-c
16
 use sha1 checksums.
17
 .TP 19
18
+.BR \-C\  "generate"
19
+Print a sha1 checksum of the difference transcript of applied changes. For use with
20
+.IR auto ,
21
+.IR force
22
+or
23
+.IR update .
24
+.TP 19
25
+.BI \-C\  checksum
26
+In
27
+.I auto
28
+mode, exit with an error if the checksum of the difference transcript to be applied does not match
29
+.IR checksum .
30
+In
31
+.I update
32
+or
33
+.I force
34
+mode, warn if the two do not match.
35
+.TP 19
36
 .BI \-D\  workingdir
37
 change to
38
 .I workingdir
(-)./files/patch-mkdirs.c (-13 lines)
Lines 1-13 Link Here
1
--- ./mkdirs.c.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./mkdirs.c	2012-03-20 14:38:08.000000000 -0400
3
@@ -37,7 +37,9 @@
4
 	if ( mkdir( path, 0777 ) == 0 ) {
5
 	    break;
6
 	}
7
-	if ( errno != ENOENT ) {
8
+	if ( errno == EEXIST ) {
9
+	    break;
10
+	} else if ( errno != ENOENT ) {
11
 	    return( -1 );
12
 	}
13
 	q = p;
(-)./files/patch-ra.sh (-139 lines)
Lines 1-139 Link Here
1
--- ./ra.sh.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./ra.sh	2012-03-20 14:38:08.000000000 -0400
3
@@ -91,7 +91,7 @@
4
 }
5
 
6
 usage() {
7
-    $ECHO "Usage:	$0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
8
+    $ECHO "Usage:	$0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C <checksum> ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
9
     exit 1
10
 }
11
 
12
@@ -128,6 +128,38 @@
13
     fi
14
 }
15
 
16
+cksum_generate() {
17
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
18
+	FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'`
19
+    fi
20
+}
21
+
22
+cksum_compare() {
23
+    if [ -n "$FSDIFF_CHECKSUM" -a \
24
+	    "$FSDIFF_CHECKSUM" != "generate" -a \
25
+	    "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then
26
+	return 1
27
+    fi
28
+
29
+    return 0
30
+}
31
+
32
+cksum_print() {
33
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
34
+	$ECHO "Difference transcript checksum: $FTMP_CHECKSUM"
35
+    fi
36
+}
37
+
38
+cksum_mismatch() {
39
+    if [ -n "$FSDIFF_CHECKSUM" ]; then
40
+	$ECHO
41
+	$ECHO "**** Difference transcript checksum mismatch!"
42
+	$ECHO "****	Expected: $FSDIFF_CHECKSUM"
43
+	$ECHO "****	Actual:   $FTMP_CHECKSUM"
44
+	#ECHO
45
+    fi
46
+}
47
+
48
 update() {
49
     opt="$1"
50
     kopt=
51
@@ -211,6 +243,11 @@
52
     fi
53
     if [ x"${opt}" = x"interactive" ]; then
54
 	while [ 1 ]; do
55
+	    cksum_generate
56
+	    if ! cksum_compare; then
57
+		cksum_mismatch
58
+	    fi
59
+
60
 	    if [ x"${can_edit}" = x"yes" ]; then
61
 		$ECHO -n "(e)dit difference transcript, "
62
 	    fi
63
@@ -248,7 +285,8 @@
64
 		
65
     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
66
     case "$?" in
67
-    0)	;;
68
+    0)	cksum_print
69
+	;;
70
 
71
     *)  if [ x"$opt" = x"hook" ]; then
72
 	    $ECHO -n "Applying changes failed, trying again "
73
@@ -284,7 +322,7 @@
74
     . "${DEFAULTS}"
75
 fi
76
 
77
-while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
78
+while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do
79
     case $opt in
80
     %)  PROGRESS="-%"
81
 	FPROGRESS="-%"
82
@@ -293,6 +331,13 @@
83
     q)  PROGRESS="-q"
84
 	;;
85
 
86
+    C)	FSDIFF_CHECKSUM="$OPTARG"
87
+	if ! type openssl >/dev/null 2>&1; then
88
+	    $ECHO "-C requires openssl, but no openssl found in PATH $PATH"
89
+	    cleanup_and_exit
90
+	fi
91
+	;;
92
+
93
     c)	CHECKSUM="-csha1"
94
 	;;
95
 
96
@@ -524,6 +569,14 @@
97
 		cleanup
98
 		exit 1
99
 	    fi
100
+
101
+	    cksum_generate
102
+	    if ! cksum_compare; then
103
+		$ECHO "Auto failure: `hostname`: difference cksum mismatch" 
104
+		cksum_mismatch
105
+		cleanup_and_exit
106
+	    fi
107
+
108
 	    dopreapply ${FTMP}
109
 	    if [ -s ${FTMP} ]; then
110
 		lapply ${NETOPTS} ${CASE} ${PROGRESS} \
111
@@ -532,6 +585,7 @@
112
 		0)
113
 		    $ECHO Auto update: `hostname`
114
 		    cat ${FTMP}
115
+		    cksum_print
116
 		    dopostapply ${FTMP}
117
 		    cleanup
118
 		    break
119
@@ -588,14 +642,17 @@
120
 	exit 0
121
     fi
122
     
123
+    cksum_generate
124
+    cksum_compare || cksum_mismatch
125
     dopreapply ${FTMP}
126
     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
127
     case "$?" in
128
-    0)	;;
129
+    0)	cksum_print
130
+	;;
131
 
132
     *)	cleanup
133
-	    exit $?
134
-	    ;;
135
+	exit $?
136
+	;;
137
     esac
138
     dopostapply ${FTMP}
139
     
(-)./files/patch-t2pkg.c (-46 lines)
Lines 1-46 Link Here
1
--- ./t2pkg.c.orig	2010-12-12 22:42:49.000000000 -0500
2
+++ ./t2pkg.c	2012-03-20 14:38:08.000000000 -0400
3
@@ -38,6 +38,7 @@
4
 extern off_t	lsize;
5
 extern char	*version;
6
 
7
+int		tran_format = -1;
8
 int		cksum = 0;
9
 int		force = 0;
10
 int		case_sensitive = 1;
11
@@ -718,31 +719,23 @@
12
 	}
13
 
14
 	/* create the destination path */
15
-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
16
+	if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
17
 		>= MAXPATHLEN ) {
18
 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
19
 			t->t_pinfo.pi_name );
20
 	    exit( 2 );
21
 	}
22
-	if ( mkdirs( tmp ) < 0 ) {
23
-	    fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno ));
24
-	}
25
-	if ( realpath( tmp, dst ) == NULL ) {
26
-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
27
-	    exit( 2 );
28
+	if ( mkdirs( dst ) < 0 ) {
29
+	    fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno ));
30
 	}
31
 
32
 	/* and the source path */
33
-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
34
+	if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
35
 		>= MAXPATHLEN ) {
36
 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
37
 			t->t_pinfo.pi_name );
38
 	    exit( 2 );
39
 	}
40
-	if ( realpath( tmp, src ) == NULL ) {
41
-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
42
-	    exit( 2 );
43
-	}
44
 
45
 	if ( local_update( t, dst, src, where ) != 0 ) {
46
 	    /* XXX is this really a good idea? */
(-)./pkg-descr (-1 / +3 lines)
Lines 3-6 Link Here
3
of hosts at the filesystem level. It can also act as an intelligent
3
of hosts at the filesystem level. It can also act as an intelligent
4
tripwire.
4
tripwire.
5
5
6
WWW:	http://rsug.itd.umich.edu/software/radmind/
6
This port contains security and functionality patches through May 22, 2014.
7
8
WWW:	http://sourceforge.net/projects/radmind/
(-)./pkg-plist (-8 / +20 lines)
Lines 10-27 Link Here
10
bin/repo
10
bin/repo
11
bin/twhich
11
bin/twhich
12
sbin/radmind
12
sbin/radmind
13
man/man1/fsdiff.1.gz
14
man/man1/ktcheck.1.gz
15
man/man1/lapply.1.gz
16
man/man1/lcksum.1.gz
17
man/man1/lcreate.1.gz
18
man/man1/lfdiff.1.gz
19
man/man1/lmerge.1.gz
20
man/man1/lsort.1.gz
21
man/man1/rash.1.gz
22
man/man1/repo.1.gz
23
man/man1/twhich.1.gz
24
man/man5/applefile.5.gz
25
man/man8/radmind.8.gz
13
%%PORTDOCS%%%%DOCSDIR%%/COPYRIGHT
26
%%PORTDOCS%%%%DOCSDIR%%/COPYRIGHT
14
%%PORTDOCS%%%%DOCSDIR%%/README
27
%%PORTDOCS%%%%DOCSDIR%%/README
15
%%PORTDOCS%%%%DOCSDIR%%/SPEC
28
%%PORTDOCS%%%%DOCSDIR%%/SPEC
16
%%PORTDOCS%%@dirrm %%DOCSDIR%%
29
%%PORTDOCS%%
17
@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%
30
@mode 700
18
@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/cert
19
@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/client
20
@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/preapply
21
@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/postapply
22
@exec chown -R %%RADMINUSER%%:%%RADMINUSER%% %%RADMIND_BASE_DIR%%
23
@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi
24
%%RADMIND_BASE_DIR%%/config.sample
31
%%RADMIND_BASE_DIR%%/config.sample
32
@mode
33
@exec chown -R %%RADMINUSER%% %%RADMIND_BASE_DIR%%
34
@exec chgrp -R %%RADMINUSER%% %%RADMIND_BASE_DIR%%
35
36
@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi
25
@dirrmtry %%RADMIND_BASE_DIR%%/transcript
37
@dirrmtry %%RADMIND_BASE_DIR%%/transcript
26
@dirrmtry %%RADMIND_BASE_DIR%%/tmp/transcript
38
@dirrmtry %%RADMIND_BASE_DIR%%/tmp/transcript
27
@dirrmtry %%RADMIND_BASE_DIR%%/tmp/file
39
@dirrmtry %%RADMIND_BASE_DIR%%/tmp/file

Return to bug 190120