Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
29
 
59
 
30
 
60
 
31
#include "config.h"
61
#include "config.h"
32
#include "system.h"
62
#include "system.h"
33
#include "c_types.h"
63
#include "c_types.h"
34
#include "error.h"
64
#include "error.h"
35
#include "file.h"
65
#include "file.h"
36
#include "ustring.h"
66
#include "ustring.h"
37
#include "xalloc.h"
67
#include "xalloc.h"
38
 
68
 
39
 
69
 
40
/*
70
/*
41
    FILE SEEKING FLAG
71
    FILE SEEKING FLAG
42
 
72
 
43
    The flag good_fseek is true if a simple fseek on the byte count has
73
    The flag good_fseek is true if a simple fseek on the byte count has
44
    the desired effect, and false otherwise (for example on DOS machines).
74
    the desired effect, and false otherwise (for example on DOS machines).
45
    Similarly binary_mode is true if there are separate text and binary
75
    Similarly binary_mode is true if there are separate text and binary
46
    file modes.  The flag good_stat is true if the st_dev and st_ino
76
    file modes.  The flag good_stat is true if the st_dev and st_ino
47
    fields of struct stat are sufficient to uniquely identify a file
77
    fields of struct stat are sufficient to uniquely identify a file
48
    (this may not be true for machines with small ino_t types and
78
    (this may not be true for machines with small ino_t types and
49
    file systems mounted from machines with large ino_t types).
79
    file systems mounted from machines with large ino_t types).
50
*/
80
*/
51
 
81
 
52
int good_fseek = 1 ;
82
int good_fseek = 1;
53
int good_stat = 0 ;
83
int good_stat = 0;
54
int text_mode = 0 ;
84
int text_mode = 0;
55
int binary_mode = 0 ;
85
int binary_mode = 0;
56
int file_sep = '/' ;
86
int file_sep = '/';
57
int drive_sep = 0 ;
87
int drive_sep = 0;
58
 
88
 
59
 
89
 
60
/*
90
/*
61
    SEEK A POSITION IN A FILE
91
    SEEK A POSITION IN A FILE
62
 
92
 
63
    This routine seeks a position n bytes from the start of the file f.
93
    This routine seeks a position n bytes from the start of the file f.
64
    It returns 0 if good_fseek is false, otherwise it returns 1 for
94
    It returns 0 if good_fseek is false, otherwise it returns 1 for
65
    successful seeks and -1 otherwise.
95
    successful seeks and -1 otherwise.
66
*/
96
*/
67
 
97
 
68
int file_seek
98
int
69
    PROTO_N ( ( f, n ) )
-
 
70
    PROTO_T ( FILE *f X long n )
99
file_seek(FILE *f, long n)
71
{
100
{
72
    if ( n == 0 ) {
101
	if (n == 0) {
73
	/* Can always rewind a file */
102
		/* Can always rewind a file */
74
	rewind ( f ) ;
103
		rewind(f);
75
	return ( 1 ) ;
104
		return (1);
76
    }
105
	}
77
    if ( good_fseek ) {
106
	if (good_fseek) {
78
	/* Use fseek if it works */
107
		/* Use fseek if it works */
79
	int s = fseek ( f, n, SEEK_SET ) ;
108
		int s = fseek(f, n, SEEK_SET);
80
	if ( s == -1 ) return ( -1 ) ;
109
		if (s == -1) {
81
	return ( 1 ) ;
110
			return (-1);
82
    }
111
		}
-
 
112
		return (1);
-
 
113
	}
83
    return ( 0 ) ;
114
	return (0);
84
}
115
}
85
 
116
 
86
 
117
 
87
/*
118
/*
88
    CONVERT A TIME TO AN UNSIGNED LONG
119
    CONVERT A TIME TO AN UNSIGNED LONG
89
 
120
 
90
    This macro converts the time_t value A to an unsigned long.  Since
121
    This macro converts the time_t value A to an unsigned long.  Since
91
    time_t may be any arithmetic type, this may not be totally portable.
122
    time_t may be any arithmetic type, this may not be totally portable.
92
*/
123
*/
93
 
124
 
94
#define time_value( A )		( ( unsigned long ) ( A ) )
125
#define time_value(A)		((unsigned long)(A))
95
 
126
 
96
 
127
 
97
/*
128
/*
98
    CURRENT TIME
129
    CURRENT TIME
99
 
130
 
100
    These variables are used to hold the current time as a struct tm.
131
    These variables are used to hold the current time as a struct tm.
101
    The date is also used to form a string which is unique for each
132
    The date is also used to form a string which is unique for each
102
    translation unit.
133
    translation unit.
103
*/
134
*/
104
 
135
 
105
char uniq_string [50] ;
136
char uniq_string[50];
106
unsigned long crt_time = 0 ;
137
unsigned long crt_time = 0;
107
static int have_crt_time = 0 ;
138
static int have_crt_time = 0;
108
static struct tm crt_time_str ;
139
static struct tm crt_time_str;
109
 
140
 
110
 
141
 
111
/*
142
/*
112
    FIND THE CURRENT TIME
143
    FIND THE CURRENT TIME
113
 
144
 
114
    This routine assigns the current time to the variables above, returning
145
    This routine assigns the current time to the variables above, returning
115
    a pointer to crt_time_str.  Note that the actual time is taken only the
146
    a pointer to crt_time_str.  Note that the actual time is taken only the
116
    first time the function is called.
147
    first time the function is called.
117
*/
148
*/
118
 
149
 
119
static struct tm *get_crt_time
150
static struct tm *
120
    PROTO_Z ()
151
get_crt_time(void)
121
{
152
{
122
    if ( !have_crt_time ) {
153
	if (!have_crt_time) {
123
	CONST char *s1, *s2 ;
154
		CONST char *s1, *s2;
124
	time_t t = time ( NIL ( time_t ) ) ;
155
		time_t t = time(NIL(time_t));
125
	if ( t == ( time_t ) -1 ) {
156
		if (t == (time_t) -1) {
126
	    /* Use a (seemingly) random date if time fails */
157
			/* Use a (seemingly) random date if time fails */
127
	    struct tm *st = &crt_time_str ;
158
			struct tm *st = &crt_time_str;
128
	    st->tm_mday = 24 ;
159
			st->tm_mday = 24;
129
	    st->tm_mon = 6 /* July */ ;
160
			st->tm_mon = 6 /* July */ ;
130
	    st->tm_year = 62 ;
161
			st->tm_year = 62;
131
	    st->tm_hour = 23 ;
162
			st->tm_hour = 23;
132
	    st->tm_min = 30 ;
163
			st->tm_min = 30;
133
	    st->tm_sec = 0 ;
164
			st->tm_sec = 0;
134
	    error ( ERROR_INTERNAL, "Can't find current date" ) ;
165
			error(ERROR_INTERNAL, "Can't find current date");
135
	} else {
166
		} else {
136
	    struct tm *st = localtime ( &t ) ;
167
			struct tm *st = localtime(&t);
137
	    crt_time_str = *st ;
168
			crt_time_str = *st;
138
	    crt_time = time_value ( t ) ;
169
			crt_time = time_value(t);
139
	}
170
		}
140
	have_crt_time = 1 ;
171
		have_crt_time = 1;
141
	s1 = find_time ( "%.2d%.2d%.2d" ) ;
172
		s1 = find_time("%.2d%.2d%.2d");
142
	s2 = find_date ( "%s%.2d_%d" ) ;
173
		s2 = find_date("%s%.2d_%d");
143
	sprintf_v ( uniq_string, "%s_%s", s1, s2 ) ;
174
		sprintf_v(uniq_string, "%s_%s", s1, s2);
144
    }
175
	}
145
    return ( &crt_time_str ) ;
176
	return (&crt_time_str);
146
}
177
}
147
 
178
 
148
 
179
 
149
/*
180
/*
150
    PRINT THE CURRENT DATE
181
    PRINT THE CURRENT DATE
151
 
182
 
152
    This routine returns a string giving the current date in the form
183
    This routine returns a string giving the current date in the form
153
    given by fmt.  This is used in the __DATE__ built-in macro.
184
    given by fmt.  This is used in the __DATE__ built-in macro.
154
*/
185
*/
155
 
186
 
156
CONST char *find_date
187
CONST char *
157
    PROTO_N ( ( fmt ) )
-
 
158
    PROTO_T ( CONST char *fmt )
188
find_date(CONST char *fmt)
159
{
189
{
160
    static char buff [20] ;
190
	static char buff[20];
161
    static CONST char *month_name [12] = {
191
	static CONST char *month_name[12] = {
162
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
192
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
163
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
193
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
164
    } ;
194
	};
165
    struct tm *st = get_crt_time () ;
195
	struct tm *st = get_crt_time();
166
    int day = st->tm_mday ;
196
	int day = st->tm_mday;
167
    CONST char *month = month_name [ st->tm_mon ] ;
197
	CONST char *month = month_name[st->tm_mon];
168
    int year = 1900 + st->tm_year ;
198
	int year = 1900 + st->tm_year;
169
    sprintf_v ( buff, fmt, month, day, year ) ;
199
	sprintf_v(buff, fmt, month, day, year);
170
    return ( buff ) ;
200
	return (buff);
171
}
201
}
172
 
202
 
173
 
203
 
174
/*
204
/*
175
    PRINT THE CURRENT TIME
205
    PRINT THE CURRENT TIME
176
 
206
 
177
    This routine returns a string giving the current time in the form
207
    This routine returns a string giving the current time in the form
178
    given by fmt.  This is used in the __TIME__ built-in macro.
208
    given by fmt.  This is used in the __TIME__ built-in macro.
179
*/
209
*/
180
 
210
 
181
CONST char *find_time
211
CONST char *
182
    PROTO_N ( ( fmt ) )
-
 
183
    PROTO_T ( CONST char *fmt )
212
find_time(CONST char *fmt)
184
{
213
{
185
    static char buff [20] ;
214
	static char buff[20];
186
    struct tm *st = get_crt_time () ;
215
	struct tm *st = get_crt_time();
187
    int hour = st->tm_hour ;
216
	int hour = st->tm_hour;
188
    int min = st->tm_min ;
217
	int min = st->tm_min;
189
    int sec = st->tm_sec ;
218
	int sec = st->tm_sec;
190
    sprintf_v ( buff, fmt, hour, min, sec ) ;
219
	sprintf_v(buff, fmt, hour, min, sec);
191
    return ( buff ) ;
220
	return (buff);
192
}
221
}
193
 
222
 
194
 
223
 
195
/*
224
/*
196
    FIND FILE STATISTICS
225
    FIND FILE STATISTICS
197
 
226
 
198
    This routine finds the file statistics for the file with pathname nm
227
    This routine finds the file statistics for the file with pathname nm
199
    and assigns them into fs.  It returns fs if this is successful and the
228
    and assigns them into fs.  It returns fs if this is successful and the
200
    null pointer otherwise.
229
    null pointer otherwise.
201
*/
230
*/
202
 
231
 
203
STAT_TYPE *stat_func
232
STAT_TYPE *
204
    PROTO_N ( ( nm, fs ) )
-
 
205
    PROTO_T ( char *nm X STAT_TYPE *fs )
233
stat_func(char *nm, STAT_TYPE *fs)
206
{
234
{
207
#if FS_POSIX
235
#if FS_POSIX
208
    int s = stat ( nm, fs ) ;
236
	int s = stat(nm, fs);
209
    if ( s != -1 ) return ( fs ) ;
237
	if (s != -1) {
-
 
238
		return (fs);
-
 
239
	}
210
#endif
240
#endif
211
    UNUSED ( nm ) ;
241
	UNUSED(nm);
212
    return ( NULL ) ;
242
	return (NULL);
213
}
243
}
214
 
244
 
215
 
245
 
216
/*
246
/*
217
    FIND A FILE DATE
247
    FIND A FILE DATE
218
 
248
 
219
    This routine converts the date from the file statistics fs to an
249
    This routine converts the date from the file statistics fs to an
220
    unsigned long.
250
    unsigned long.
221
*/
251
*/
222
 
252
 
223
unsigned long stat_date
253
unsigned long
224
    PROTO_N ( ( fs ) )
-
 
225
    PROTO_T ( STAT_TYPE *fs )
254
stat_date(STAT_TYPE *fs)
226
{
255
{
227
    unsigned long date = 0 ;
256
	unsigned long date = 0;
-
 
257
	if (fs) {
228
    if ( fs ) date = time_value ( fs->st_mtime ) ;
258
		date = time_value(fs->st_mtime);
-
 
259
	}
229
    return ( date ) ;
260
	return (date);
230
}
261
}
231
 
262
 
232
 
263
 
233
/*
264
/*
234
    ARE TWO FILES EQUAL?
265
    ARE TWO FILES EQUAL?
Line 237... Line 268...
237
    gs represent the same file.  Two files are the same if their device
268
    gs represent the same file.  Two files are the same if their device
238
    and inode numbers are equal (except on machines where good_stat is
269
    and inode numbers are equal (except on machines where good_stat is
239
    false).
270
    false).
240
*/
271
*/
241
 
272
 
242
int stat_equal
273
int
243
    PROTO_N ( ( fs, gs ) )
-
 
244
    PROTO_T ( STAT_TYPE *fs X STAT_TYPE *gs )
274
stat_equal(STAT_TYPE *fs, STAT_TYPE *gs)
245
{
275
{
246
    if ( fs && gs ) {
276
	if (fs && gs) {
247
	if ( fs->st_dev == gs->st_dev && fs->st_ino == gs->st_ino ) {
277
		if (fs->st_dev == gs->st_dev && fs->st_ino == gs->st_ino) {
248
	    return ( good_stat ) ;
278
			return (good_stat);
-
 
279
		}
249
	}
280
	}
250
    }
-
 
251
    return ( 0 ) ;
281
	return (0);
252
}
282
}
253
 
283
 
254
 
284
 
255
/*
285
/*
256
    FIND THE CURRENT WORKING DIRECTORY
286
    FIND THE CURRENT WORKING DIRECTORY
257
 
287
 
258
    This routine finds the current working directory, returning '.' if
288
    This routine finds the current working directory, returning '.' if
259
    this cannot be found.
289
    this cannot be found.
260
*/
290
*/
261
 
291
 
262
CONST char *find_cwd
292
CONST char *
263
    PROTO_Z ()
293
find_cwd(void)
264
{
294
{
265
    static CONST char *crt_directory = NULL ;
295
	static CONST char *crt_directory = NULL;
266
    if ( crt_directory == NULL ) {
296
	if (crt_directory == NULL) {
267
#if FS_POSIX
297
#if FS_POSIX
268
	char buff [1024] ;
298
		char buff[1024];
269
	char *nm = getcwd ( buff, 1024 ) ;
299
		char *nm = getcwd(buff, 1024);
270
	if ( nm ) {
300
		if (nm) {
271
	    /* Copy result */
301
			/* Copy result */
272
	    string dir = xustrcpy ( ustrlit ( nm ) ) ;
302
			string dir = xustrcpy(ustrlit(nm));
273
	    dir = make_pathname ( dir ) ;
303
			dir = make_pathname(dir);
274
	    crt_directory = strlit ( dir ) ;
304
			crt_directory = strlit(dir);
275
	} else {
305
		} else {
276
	    crt_directory = "." ;
306
			crt_directory = ".";
277
	}
307
		}
278
#else
308
#else
279
	crt_directory = "." ;
309
		crt_directory = ".";
280
#endif
310
#endif
281
    }
311
	}
282
    return ( crt_directory ) ;
312
	return (crt_directory);
283
}
313
}
284
 
314
 
285
 
315
 
286
/*
316
/*
287
    FIND THE CURRENT MACHINE
317
    FIND THE CURRENT MACHINE
288
 
318
 
289
    This routine finds the name of the machine on which the program is
319
    This routine finds the name of the machine on which the program is
290
    running, returning the empty string if this cannot be found.
320
    running, returning the empty string if this cannot be found.
291
*/
321
*/
292
 
322
 
293
CONST char *find_machine
323
CONST char *
294
    PROTO_Z ()
324
find_machine(void)
295
{
325
{
296
    static CONST char *machine_name = NULL ;
326
	static CONST char *machine_name = NULL;
297
    if ( machine_name == NULL ) {
327
	if (machine_name == NULL) {
298
#if FS_UTSNAME
328
#if FS_UTSNAME
299
	struct utsname un ;
329
		struct utsname un;
300
	if ( uname ( &un ) != -1 ) {
330
		if (uname(&un) != -1) {
301
	    string s = ustrlit ( un.nodename ) ;
331
			string s = ustrlit(un.nodename);
302
	    s = xustrcpy ( s ) ;
332
			s = xustrcpy(s);
303
	    machine_name = strlit ( s ) ;
333
			machine_name = strlit(s);
304
	    return ( machine_name ) ;
334
			return (machine_name);
305
	}
335
		}
306
#endif
336
#endif
307
	machine_name = "" ;
337
		machine_name = "";
308
    }
338
	}
309
    return ( machine_name ) ;
339
	return (machine_name);
310
}
340
}