[3d3a3590] | 1 | /* |
---|
| 2 | * $Id$ |
---|
| 3 | */ |
---|
| 4 | |
---|
| 5 | #include <stdio.h> |
---|
| 6 | #include <string.h> |
---|
| 7 | #include <process.h> |
---|
| 8 | |
---|
| 9 | #include <io.h> |
---|
| 10 | |
---|
| 11 | void * xmalloc( int size ) |
---|
| 12 | { |
---|
| 13 | void * p = (void *)malloc( size ); |
---|
| 14 | if ( !p ) { |
---|
| 15 | fprintf( stderr, "out of memory\n" ); |
---|
| 16 | exit( 1 ); |
---|
| 17 | } |
---|
| 18 | return p; |
---|
| 19 | } |
---|
| 20 | void * xrealloc( void * old, int size ) |
---|
| 21 | { |
---|
| 22 | void * p = (void *)realloc( old, size ); |
---|
| 23 | if ( !p ) { |
---|
| 24 | fprintf( stderr, "out of memory\n" ); |
---|
| 25 | exit( 1 ); |
---|
| 26 | } |
---|
| 27 | return p; |
---|
| 28 | } |
---|
| 29 | |
---|
| 30 | char ** argv_fix( int * argc, char ** argv ) |
---|
| 31 | { |
---|
| 32 | char ** new = NULL; |
---|
| 33 | int max = 20; |
---|
| 34 | int cnt = 0; |
---|
| 35 | int j; |
---|
| 36 | |
---|
| 37 | for ( j = 1; argv[j]; ++j ) |
---|
| 38 | if ( argv[j][0] == '@' && access(argv[j]+1,0)==0 ) |
---|
| 39 | break; |
---|
| 40 | if ( argv[j] == NULL ) |
---|
| 41 | return argv; |
---|
| 42 | |
---|
| 43 | new = (char **)xmalloc( max * sizeof *new ); |
---|
| 44 | new[cnt++] = *argv++; |
---|
| 45 | for ( ; *argv; ++argv ) { |
---|
| 46 | if ( cnt >= max ) |
---|
| 47 | new = (char **)realloc( new, (max*=2) * sizeof *new ); |
---|
| 48 | |
---|
| 49 | if ( argv[0][0] != '@' || access(argv[0]+1,0) ) { |
---|
| 50 | new[cnt++] = *argv; |
---|
| 51 | } else { |
---|
| 52 | char line[ 1000 ]; |
---|
| 53 | FILE * f = fopen( argv[0]+1, "r" ); |
---|
| 54 | if ( !f ) { |
---|
| 55 | perror( argv[0]+1 ); |
---|
| 56 | exit( 2 ); |
---|
| 57 | } |
---|
| 58 | while ( fgets( line, sizeof line, f ) ) { |
---|
| 59 | int len = strlen( line ); |
---|
| 60 | /* delete trailing newlines */ |
---|
| 61 | while ( line[len-1] == '\n' || line[len-1] == '\r' ) |
---|
| 62 | line[--len] = '\0'; |
---|
| 63 | if ( cnt >= max ) |
---|
| 64 | new = (char **)xrealloc( new, (max*=2) * sizeof *new ); |
---|
| 65 | new[cnt] = (char *)xmalloc( len+1 ); |
---|
| 66 | strcpy( new[cnt], line ); |
---|
| 67 | ++cnt; |
---|
| 68 | } |
---|
| 69 | fclose( f ); |
---|
| 70 | } |
---|
| 71 | } |
---|
| 72 | if ( cnt >= max ) |
---|
| 73 | new = (char **)xrealloc( new, (max+1) * sizeof *new ); |
---|
| 74 | new[cnt] = NULL; |
---|
| 75 | *argc = cnt; |
---|
| 76 | return new; |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | const char * USAGE = |
---|
| 81 | "usage: $progname [ -cNvmV ] file [ file ... ] dest-directory-or-file\n" |
---|
| 82 | " -v -- verbose\n" |
---|
| 83 | " -V suffix -- suffix to append to targets (before any . suffix)\n" |
---|
| 84 | " eg: -V _g would change 'foo' to 'foo_g' and\n" |
---|
| 85 | " 'libfoo.a' to 'libfoo_g.a'\n" |
---|
| 86 | " -m mode -- mode for new file(s)\n" |
---|
| 87 | " -c -- copy instead of move (always on)\n" |
---|
| 88 | " -N -- copy only if source is newer than target\n" |
---|
| 89 | ; |
---|
| 90 | |
---|
| 91 | void fatal( char * msg ) |
---|
| 92 | { |
---|
| 93 | if ( msg ) |
---|
| 94 | fprintf( stderr, "%s\n", msg ); |
---|
| 95 | fprintf( stderr, "%s", USAGE ); |
---|
| 96 | exit( 1 ); |
---|
| 97 | } |
---|
| 98 | |
---|
| 99 | char * basename( char * f ) |
---|
| 100 | { |
---|
| 101 | char * b = strrchr( f, '/' ); |
---|
| 102 | if ( b ) ++b; |
---|
| 103 | else b = f; |
---|
| 104 | return b; |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | #include <sys/stat.h> |
---|
| 108 | int is_dir( char * path ) |
---|
| 109 | { |
---|
| 110 | struct stat buf; |
---|
| 111 | if ( stat( path, &buf ) ) |
---|
| 112 | return 0; |
---|
| 113 | return buf.st_mode & S_IFDIR; |
---|
| 114 | } |
---|
| 115 | int is_file( char * path ) |
---|
| 116 | { |
---|
| 117 | struct stat buf; |
---|
| 118 | if ( stat( path, &buf ) ) |
---|
| 119 | return 0; |
---|
| 120 | return buf.st_mode & S_IFREG; |
---|
| 121 | } |
---|
| 122 | int newer( char * p1, char * p2 ) |
---|
| 123 | { |
---|
| 124 | struct stat buf1; |
---|
| 125 | struct stat buf2; |
---|
| 126 | if ( stat( p1, &buf1 ) ) |
---|
| 127 | return 0; |
---|
| 128 | if ( stat( p2, &buf2 ) ) |
---|
| 129 | return 0; |
---|
| 130 | return buf1.st_mtime > buf2.st_mtime; |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | int filecopy( char * d, char * s, int preserve_time ) |
---|
| 134 | { |
---|
| 135 | #if 0 |
---|
| 136 | int status; |
---|
| 137 | char * argv[ 5 ]; |
---|
| 138 | argv[0] = "cp"; |
---|
| 139 | argv[1] = "-p"; |
---|
| 140 | argv[2] = s; |
---|
| 141 | argv[3] = d; |
---|
| 142 | argv[4] = NULL; |
---|
| 143 | status = spawnvp( P_WAIT, argv[0], argv ); |
---|
| 144 | if ( status ) |
---|
| 145 | perror( "cp" ); |
---|
| 146 | return status; |
---|
| 147 | #else |
---|
| 148 | FILE * fs; |
---|
| 149 | FILE * fd; |
---|
| 150 | char buffer[ 8192 ]; |
---|
| 151 | int n; |
---|
| 152 | struct ftime When; |
---|
| 153 | struct stat Stat; |
---|
| 154 | |
---|
| 155 | fs = fopen( s, "rb" ); |
---|
| 156 | if ( fs == NULL ) { |
---|
| 157 | perror( s ); |
---|
| 158 | return 1; |
---|
| 159 | } |
---|
| 160 | fd = fopen( d, "wb" ); |
---|
| 161 | if ( fd == NULL ) { |
---|
| 162 | perror( d ); |
---|
| 163 | fclose( fs ); |
---|
| 164 | return 2; |
---|
| 165 | } |
---|
| 166 | |
---|
| 167 | if ( preserve_time ) |
---|
| 168 | if ( getftime( fileno(fs), &When ) ) { |
---|
| 169 | perror( s ); |
---|
| 170 | preserve_time = 0; |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | do { |
---|
| 174 | n = fread( buffer, 1, sizeof buffer, fs ); |
---|
| 175 | if ( n > 0 ) |
---|
| 176 | if ( fwrite( buffer, 1, n, fd ) < 0 ) { |
---|
| 177 | perror( d ); |
---|
| 178 | return 3; |
---|
| 179 | } |
---|
| 180 | } while ( n > 0 ); |
---|
| 181 | |
---|
| 182 | fclose( fs ); |
---|
| 183 | |
---|
| 184 | /* Fix time stamp */ |
---|
| 185 | if ( preserve_time ) |
---|
| 186 | if ( setftime( fileno(fd), &When ) ) { |
---|
| 187 | perror( s ); |
---|
| 188 | preserve_time = 0; |
---|
| 189 | } |
---|
| 190 | fclose( fd ); |
---|
| 191 | |
---|
| 192 | /* Fix access rights */ |
---|
| 193 | if ( stat( s, &Stat ) ) |
---|
| 194 | perror( s ); |
---|
| 195 | else if ( chmod( d, Stat.st_mode ) ) |
---|
| 196 | perror( d ); |
---|
| 197 | |
---|
| 198 | return 0; |
---|
| 199 | #endif |
---|
| 200 | } |
---|
| 201 | |
---|
| 202 | |
---|
| 203 | |
---|
| 204 | |
---|
| 205 | |
---|
| 206 | int main( int argc, char * argv[] ) |
---|
| 207 | { |
---|
| 208 | char * progname; |
---|
| 209 | int verbose = 0; |
---|
| 210 | int only_if_newer= 0; |
---|
| 211 | char * suffix = NULL; |
---|
| 212 | char * mode = NULL; |
---|
| 213 | char * dest; |
---|
| 214 | char ** pp; |
---|
| 215 | |
---|
| 216 | argv = argv_fix( &argc, argv ); |
---|
| 217 | |
---|
| 218 | progname = basename( *argv++ ); |
---|
| 219 | |
---|
| 220 | /* process the options */ |
---|
| 221 | while ( argv[0] && argv[0][0] == '-' ) { |
---|
| 222 | switch ( argv[0][1] ) { |
---|
| 223 | case 'N': |
---|
| 224 | ++argv; |
---|
| 225 | only_if_newer = 1; |
---|
| 226 | break; |
---|
| 227 | case 'c': |
---|
| 228 | ++argv; |
---|
| 229 | /* We always copy, regardless */ |
---|
| 230 | break; |
---|
| 231 | case 'v': |
---|
| 232 | ++argv; |
---|
| 233 | verbose = 1; |
---|
| 234 | break; |
---|
| 235 | case 'V': |
---|
| 236 | ++argv; |
---|
| 237 | suffix = *argv; |
---|
| 238 | ++argv; |
---|
| 239 | break; |
---|
| 240 | case 'm': |
---|
| 241 | ++argv; |
---|
| 242 | mode = *argv; |
---|
| 243 | ++argv; |
---|
| 244 | break; |
---|
| 245 | default: |
---|
| 246 | fatal( NULL ); |
---|
| 247 | } |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | /* Separate source file(s) from dest directory or file */ |
---|
| 251 | #if 0 |
---|
| 252 | if ( !argv[0] || !argv[1] ) |
---|
| 253 | fatal( "missing files or invalid destination" ); |
---|
| 254 | #else |
---|
| 255 | /* We used to require at least one file; not any more */ |
---|
| 256 | if ( !argv[0] ) |
---|
| 257 | fatal( "missing files or invalid destination" ); |
---|
| 258 | if ( !argv[1] ) |
---|
| 259 | return 0; |
---|
| 260 | #endif |
---|
| 261 | for ( pp = argv; *pp; ++pp ) |
---|
| 262 | continue; |
---|
| 263 | --pp; |
---|
| 264 | dest = *pp; |
---|
| 265 | *pp = NULL; |
---|
| 266 | |
---|
| 267 | /* Process the arguments */ |
---|
| 268 | for (; *argv; ++argv ) { |
---|
| 269 | char * f = *argv; |
---|
| 270 | char * leaf = basename( f ); |
---|
| 271 | char target[ 128 ]; |
---|
| 272 | |
---|
| 273 | strcpy( target, dest ); |
---|
| 274 | |
---|
| 275 | if ( is_dir( target ) ) { |
---|
| 276 | strcat( target, "/" ); |
---|
| 277 | /* if we were given a suffix, then add it as appropriate */ |
---|
| 278 | if ( suffix ) { |
---|
| 279 | char * dot = strchr( leaf, '.' ); |
---|
| 280 | if ( dot ) { |
---|
| 281 | strncat( target, leaf, dot-leaf ); |
---|
| 282 | strcat( target, suffix ); |
---|
| 283 | strcat( target, dot ); |
---|
| 284 | if ( verbose ) |
---|
| 285 | printf( "%s: %s will be installed as %s", |
---|
| 286 | progname, f, strrchr(target,'/')+1 ); |
---|
| 287 | } else { |
---|
| 288 | strcat( target, leaf ); |
---|
| 289 | strcat( target, suffix ); |
---|
| 290 | } |
---|
| 291 | } else { |
---|
| 292 | strcat( target, leaf ); |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | if ( access( f, 0 ) ) { |
---|
| 297 | char buf[200]; |
---|
| 298 | sprintf( buf, "cannot read %s", f ); |
---|
| 299 | fatal( buf ); |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | if ( only_if_newer && is_file( target ) && !newer( f, target ) ) { |
---|
| 303 | if ( verbose ) |
---|
| 304 | printf( "'%s' not newer than '%s'\n", f, target ); |
---|
| 305 | continue; |
---|
| 306 | } |
---|
| 307 | |
---|
| 308 | if ( verbose ) |
---|
| 309 | printf( "rm -f %s\n", target ); |
---|
| 310 | if ( chmod( target, 0777 ) ) |
---|
| 311 | if ( verbose ) |
---|
| 312 | perror( target ); |
---|
| 313 | if ( unlink( target ) ) |
---|
| 314 | if ( verbose ) |
---|
| 315 | perror( target ); |
---|
| 316 | if ( verbose ) |
---|
| 317 | printf( "cp -p %s %s\n", f, target ); |
---|
| 318 | if ( filecopy( target, f, 1 ) ) |
---|
| 319 | return 1; |
---|
| 320 | if ( mode ) { |
---|
| 321 | char buf[ 255 ]; |
---|
| 322 | sprintf( buf, "chmod %s %s\n", mode, target ); |
---|
| 323 | if ( verbose ) |
---|
| 324 | printf( "%s\n", buf ); |
---|
| 325 | system( buf ); |
---|
| 326 | } |
---|
| 327 | } |
---|
| 328 | |
---|
| 329 | return 0; |
---|
| 330 | } |
---|
| 331 | |
---|