| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <config.h> |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <stdint.h> |
| #include <dirent.h> |
| #include <sys/stat.h> /* chmod(2) */ |
| #include <sys/file.h> /* flock(2) */ |
| #include <fcntl.h> |
| #include <linux/limits.h> |
| #include <alloca.h> /* alloca(3) */ |
| #include <string.h> /* strdup(3) */ |
| #include <strings.h> /* index(3) */ |
| #include <libgen.h> /* basename(3) */ |
| #include <ctype.h> /* tolower(3) */ |
| #include <errno.h> |
| #include <time.h> |
| #include <sys/time.h> |
| #include <pwd.h> |
| #include <grp.h> |
| #include <stdarg.h> |
| #include <unistd.h> |
| |
| #include <sys/resource.h> |
| |
| #include <signal.h> |
| #if !defined SIGCHLD && defined SIGCLD |
| # define SIGCHLD SIGCLD |
| #endif |
| |
| #define _GNU_SOURCE |
| #include <getopt.h> |
| |
| #include <msglog.h> |
| #include <wrapper.h> |
| #include <system.h> |
| |
| #define PROGRAM_NAME "chrefs" |
| |
| #include <defs.h> |
| |
| |
| char *program = PROGRAM_NAME; |
| char *destination = NULL, *operation = NULL, *pkglog_fname = NULL, |
| *tmpdir = NULL, *requires_fname = NULL; |
| |
| int exit_status = EXIT_SUCCESS; |
| char *selfdir = NULL; |
| |
| char *pkgname = NULL, |
| *pkgver = NULL, |
| *arch = NULL, |
| *distroname = NULL, |
| *distrover = NULL, |
| *group = NULL; |
| |
| |
| |
| |
| |
| struct package { |
| char *name; |
| char *version; |
| char *arch; |
| char *distro_name; |
| char *distro_version; |
| }; |
| |
| static struct package *create_package( char *name, char *version, |
| char *arch, char *distro_name, |
| char *distro_version ); |
| static void free_package( struct package *pkg ); |
| static struct package **create_requires( size_t size ); |
| static void free_requires( struct package **requires ); |
| |
| |
| |
| |
| struct package **requires = NULL; |
| |
| |
| |
| |
| |
| static int __lock_file( FILE *fp ); |
| static void __unlock_file( int fd ); |
| |
| |
| |
| |
| |
| #define FREE_PKGINFO_VARIABLES() \ |
| if( pkgname ) { free( pkgname ); } pkgname = NULL; \ |
| if( pkgver ) { free( pkgver ); } pkgver = NULL; \ |
| if( arch ) { free( arch ); } arch = NULL; \ |
| if( distroname ) { free( distroname ); } distroname = NULL; \ |
| if( distrover ) { free( distrover ); } distrover = NULL; \ |
| if( group ) { free( group ); } group = NULL; \ |
| if( requires ) { free_requires( requires ); } requires = NULL |
| |
| void free_resources() |
| { |
| if( selfdir ) { free( selfdir ); selfdir = NULL; } |
| if( destination ) { free( destination ); destination = NULL; } |
| if( operation ) { free( operation ); operation = NULL; } |
| if( pkglog_fname ) { free( pkglog_fname ); pkglog_fname = NULL; } |
| if( requires_fname ) { free( requires_fname ); requires_fname = NULL; } |
| |
| FREE_PKGINFO_VARIABLES(); |
| } |
| |
| void usage() |
| { |
| free_resources(); |
| |
| fprintf( stdout, "\n" ); |
| fprintf( stdout, "Usage: %s [options] <pkglog>\n", program ); |
| fprintf( stdout, "\n" ); |
| fprintf( stdout, "Increment or Decrement reference counters in required PKGLOG files\n" ); |
| fprintf( stdout, "in the Setup Database packages directory, which is determined by\n" ); |
| fprintf( stdout, "option --destination OR by the directory where the input <pkglog>\n" ); |
| fprintf( stdout, "file is located. If destination is defined then <pkglog> file name\n" ); |
| fprintf( stdout, "should be defined relative to destination.\n" ); |
| fprintf( stdout, "\n" ); |
| fprintf( stdout, "Options:\n" ); |
| fprintf( stdout, " -h,--help Display this information.\n" ); |
| fprintf( stdout, " -v,--version Display the version of %s utility.\n", program ); |
| fprintf( stdout, " -d,--destination=<DIR> Setup Database packages directory.\n" ); |
| fprintf( stdout, " -o,--operation=<inc|dec> Operation: Increment or Decrement.\n" ); |
| fprintf( stdout, "\n" ); |
| fprintf( stdout, "Parameter:\n" ); |
| fprintf( stdout, " <pkglog> Input PKGLOG file (TEXT format).\n" ); |
| fprintf( stdout, "\n" ); |
| |
| exit( EXIT_FAILURE ); |
| } |
| |
| void to_lowercase( char *s ) |
| { |
| char *p = s; |
| while( p && *p ) { int c = *p; *p = tolower( c ); ++p; } |
| } |
| |
| void to_uppercase( char *s ) |
| { |
| char *p = s; |
| while( p && *p ) { int c = *p; *p = toupper( c ); ++p; } |
| } |
| |
| void version() |
| { |
| char *upper = NULL; |
| |
| upper = (char *)alloca( strlen( program ) + 1 ); |
| |
| strcpy( (char *)upper, (const char *)program ); |
| to_uppercase( upper ); |
| |
| fprintf( stdout, "%s (%s) %s\n", program, upper, PROGRAM_VERSION ); |
| |
| fprintf( stdout, "Copyright (C) 2019 Andrey V.Kosteltsev.\n" ); |
| fprintf( stdout, "This is free software. There is NO warranty; not even\n" ); |
| fprintf( stdout, "for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ); |
| fprintf( stdout, "\n" ); |
| |
| free_resources(); |
| exit( EXIT_SUCCESS ); |
| } |
| |
| |
| static void remove_trailing_slash( char *dir ) |
| { |
| char *s; |
| |
| if( !dir || dir[0] == '\0' ) return; |
| |
| s = dir + strlen( dir ) - 1; |
| while( *s == '/' ) |
| { |
| *s = '\0'; --s; |
| } |
| } |
| |
| |
| static int _mkdir_p( const char *dir, const mode_t mode ) |
| { |
| char *buf; |
| char *p = NULL; |
| struct stat sb; |
| |
| if( !dir ) return -1; |
| |
| buf = (char *)alloca( strlen( dir ) + 1 ); |
| strcpy( buf, dir ); |
| |
| remove_trailing_slash( buf ); |
| |
| |
| if( stat( buf, &sb ) == 0 ) |
| { |
| if( S_ISDIR(sb.st_mode) ) |
| { |
| return 0; |
| } |
| } |
| |
| |
| for( p = buf + 1; *p; ++p ) |
| { |
| if( *p == '/' ) |
| { |
| *p = 0; |
| |
| if( stat( buf, &sb ) != 0 ) |
| { |
| |
| if( mkdir( buf, mode ) < 0 ) |
| { |
| return -1; |
| } |
| } else if( !S_ISDIR(sb.st_mode) ) |
| { |
| |
| return -1; |
| } |
| *p = '/'; |
| } |
| } |
| |
| |
| if( stat( buf, &sb ) != 0 ) |
| { |
| |
| if( mkdir( buf, mode ) < 0 ) |
| { |
| return -1; |
| } |
| } else if( !S_ISDIR(sb.st_mode) ) |
| { |
| |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| static void _rm_tmpdir( const char *dirpath ) |
| { |
| DIR *dir; |
| char *path; |
| size_t len; |
| |
| struct stat path_sb, entry_sb; |
| struct dirent *entry; |
| |
| if( stat( dirpath, &path_sb ) == -1 ) |
| { |
| return; |
| } |
| |
| if( S_ISDIR(path_sb.st_mode) == 0 ) |
| { |
| return; |
| } |
| |
| if( (dir = opendir(dirpath) ) == NULL ) |
| { |
| return; |
| } |
| |
| len = strlen( dirpath ); |
| |
| while( (entry = readdir( dir )) != NULL) |
| { |
| |
| |
| if( ! strcmp( entry->d_name, "." ) || ! strcmp( entry->d_name, ".." ) ) continue; |
| |
| |
| path = alloca( len + strlen( entry->d_name ) + 2 ); |
| strcpy( path, dirpath ); |
| strcat( path, "/" ); |
| strcat( path, entry->d_name ); |
| |
| if( stat( path, &entry_sb ) == 0 ) |
| { |
| if( S_ISDIR(entry_sb.st_mode) ) |
| { |
| |
| _rm_tmpdir( path ); |
| } |
| else |
| { |
| |
| (void)unlink( path ); |
| } |
| } |
| |
| |
| } |
| |
| |
| (void)rmdir( dirpath ); |
| |
| closedir( dir ); |
| } |
| |
| |
| static char *_mk_tmpdir( void ) |
| { |
| char *buf = NULL, *p, *tmp = "/tmp"; |
| size_t len = 0, size = 0; |
| |
| (void)umask( S_IWGRP | S_IWOTH ); |
| |
| |
| if( (p = getenv( "TMP" )) != NULL ) { |
| tmp = p; |
| } |
| else if( (p = getenv( "TEMP" )) != NULL ) { |
| tmp = p; |
| } |
| |
| size = strlen( tmp ) + strlen( DISTRO_NAME ) + strlen( program ) + 12; |
| |
| buf = (char *)malloc( size ); |
| if( !buf ) return NULL; |
| |
| len = snprintf( buf, size, (const char *)"%s/%s/%s-%.7u", tmp, DISTRO_NAME, program, getpid() ); |
| if( len == 0 || len == size - 1 ) |
| { |
| free( buf ); return NULL; |
| } |
| |
| _rm_tmpdir( (const char *)&buf[0] ); |
| |
| if( _mkdir_p( buf, S_IRWXU | S_IRWXG | S_IRWXO ) == 0 ) |
| { |
| return buf; |
| } |
| |
| free( buf ); return NULL; |
| } |
| |
| |
| |
| |
| |
| static struct package *create_package( char *name, char *version, |
| char *arch, char *distro_name, |
| char *distro_version ) |
| { |
| struct package *pkg = (struct package *)0; |
| |
| if( !name || *name == '\0' ) return pkg; |
| if( !version || *version == '\0' ) return pkg; |
| if( !arch || *arch == '\0' ) return pkg; |
| if( !distro_name || *distro_name == '\0' ) return pkg; |
| if( !distro_version || *distro_version == '\0' ) return pkg; |
| |
| pkg = (struct package *)malloc( sizeof(struct package) ); |
| if( pkg ) |
| { |
| pkg->name = xstrdup( (const char *)name ); |
| pkg->version = xstrdup( (const char *)version ); |
| pkg->arch = xstrdup( (const char *)arch ); |
| pkg->distro_name = xstrdup( (const char *)distro_name ); |
| pkg->distro_version = xstrdup( (const char *)distro_version ); |
| } |
| |
| return pkg; |
| } |
| |
| static void free_package( struct package *pkg ) |
| { |
| if( pkg ) |
| { |
| if( pkg->name ) free( pkg->name ); |
| if( pkg->version ) free( pkg->version ); |
| if( pkg->arch ) free( pkg->arch ); |
| if( pkg->distro_name ) free( pkg->distro_name ); |
| if( pkg->distro_version ) free( pkg->distro_version ); |
| |
| free( pkg ); |
| } |
| } |
| |
| static struct package **create_requires( size_t size ) |
| { |
| struct package **requires = (struct package **)0; |
| |
| if( size > 0 ) |
| { |
| requires = (struct package **)malloc( size * sizeof(struct package *) ); |
| bzero( (void *)requires, size * sizeof(struct package *) ); |
| } |
| |
| return( requires ); |
| } |
| |
| static void free_requires( struct package **requires ) |
| { |
| if( requires ) |
| { |
| struct package **ptr = requires; |
| |
| while( *ptr ) |
| { |
| if( *ptr ) free_package( *ptr ); |
| ptr++; |
| } |
| free( requires ); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| static int __lock_file( FILE *fp ) |
| { |
| int fd = fileno( fp ); |
| |
| if( flock( fd, LOCK_EX ) == -1 ) |
| { |
| return -1; |
| |
| |
| |
| |
| |
| |
| |
| } |
| return fd; |
| } |
| |
| static void __unlock_file( int fd ) |
| { |
| if( fd != -1 ) flock( fd, LOCK_UN ); |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| |
| void fatal_error_actions( void ) |
| { |
| logmsg( errlog, MSG_NOTICE, "Free resources on FATAL error..." ); |
| if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); } |
| free_resources(); |
| } |
| |
| void sigint( int signum ) |
| { |
| (void)signum; |
| |
| if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); } |
| free_resources(); |
| } |
| |
| static void set_signal_handlers() |
| { |
| struct sigaction sa; |
| sigset_t set; |
| |
| memset( &sa, 0, sizeof( sa ) ); |
| sa.sa_handler = sigint; |
| sa.sa_flags = SA_RESTART; |
| sigemptyset( &set ); |
| sigaddset( &set, SIGTERM ); |
| sigaddset( &set, SIGINT ); |
| sa.sa_mask = set; |
| sigaction( SIGTERM, &sa, NULL ); |
| sigaction( SIGINT, &sa, NULL ); |
| |
| memset( &sa, 0, sizeof( sa ) ); |
| sa.sa_handler = SIG_IGN; |
| sa.sa_flags = 0; |
| sigaction( SIGPIPE, &sa, NULL ); |
| |
| |
| signal( SIGCHLD, SIG_DFL ); |
| } |
| |
| enum _pkglog_type |
| { |
| PKGLOG_TEXT = 0, |
| PKGLOG_GZ, |
| PKGLOG_BZ2, |
| PKGLOG_XZ, |
| PKGLOG_TAR, |
| |
| PKGLOG_UNKNOWN |
| }; |
| |
| static enum _pkglog_type pkglog_type = PKGLOG_UNKNOWN; |
| static char uncompress[2] = { 0, 0 }; |
| |
| |
| static enum _pkglog_type check_pkglog_file( const char *fname ) |
| { |
| struct stat st; |
| size_t pkglog_size = 0; |
| unsigned char buf[8]; |
| int rc, fd; |
| |
| |
| |
| uncompress[0] = '\0'; |
| |
| if( stat( fname, &st ) == -1 ) |
| { |
| FATAL_ERROR( "Cannot access %s file: %s", basename( (char *)fname ), strerror( errno ) ); |
| } |
| |
| pkglog_size = st.st_size; |
| |
| if( (fd = open( fname, O_RDONLY )) == -1 ) |
| { |
| FATAL_ERROR( "Cannot open %s file: %s", basename( (char *)fname ), strerror( errno ) ); |
| } |
| |
| rc = (int)read( fd, (void *)&buf[0], 7 ); |
| if( rc != 7 ) |
| { |
| FATAL_ERROR( "Unknown type of input file %s", basename( (char *)fname ) ); |
| } |
| buf[7] = '\0'; |
| |
| |
| if( !strncmp( (const char *)&buf[0], "PACKAGE", 7 ) ) |
| { |
| close( fd ); return PKGLOG_TEXT; |
| } |
| |
| |
| if( buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x08 ) |
| { |
| uncompress[0] = 'x'; |
| close( fd ); return PKGLOG_GZ; |
| } |
| |
| |
| if( buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68 ) |
| { |
| uncompress[0] = 'j'; |
| close( fd ); return PKGLOG_BZ2; |
| } |
| |
| |
| if( buf[0] == 0xFD && buf[1] == 0x37 && buf[2] == 0x7A && |
| buf[3] == 0x58 && buf[4] == 0x5A && buf[5] == 0x00 ) |
| { |
| uncompress[0] = 'J'; |
| close( fd ); return PKGLOG_XZ; |
| } |
| |
| if( pkglog_size > 262 ) |
| { |
| if( lseek( fd, 257, SEEK_SET ) == -1 ) |
| { |
| FATAL_ERROR( "Cannot check signature of %s file: %s", basename( (char *)fname ), strerror( errno ) ); |
| } |
| rc = (int)read( fd, &buf[0], 5 ); |
| if( rc != 5 ) |
| { |
| FATAL_ERROR( "Cannot read signature of %s file", basename( (char *)fname ) ); |
| } |
| |
| if( buf[0] == 0x75 && buf[1] == 0x73 && buf[2] == 0x74 && buf[3] == 0x61 && buf[4] == 0x72 ) |
| { |
| close( fd ); return PKGLOG_TAR; |
| } |
| } |
| |
| close( fd ); return PKGLOG_UNKNOWN; |
| } |
| |
| |
| void get_args( int argc, char *argv[] ) |
| { |
| const char* short_options = "hvd:o:"; |
| |
| const struct option long_options[] = |
| { |
| { "help", no_argument, NULL, 'h' }, |
| { "version", no_argument, NULL, 'v' }, |
| { "destination", required_argument, NULL, 'd' }, |
| { "operation", required_argument, NULL, 'o' }, |
| { NULL, 0, NULL, 0 } |
| }; |
| |
| int ret; |
| int option_index = 0; |
| |
| while( (ret = getopt_long( argc, argv, short_options, long_options, &option_index )) != -1 ) |
| { |
| switch( ret ) |
| { |
| case 'h': |
| { |
| usage(); |
| break; |
| } |
| case 'v': |
| { |
| version(); |
| break; |
| } |
| |
| case 'd': |
| { |
| if( optarg != NULL ) |
| { |
| destination = xstrdup( (const char *)optarg ); |
| remove_trailing_slash( destination ); |
| } |
| else |
| |
| usage(); |
| break; |
| } |
| case 'o': |
| { |
| operation = xstrdup( (const char *)optarg ); |
| to_lowercase( operation ); |
| if( strcmp( operation, "inc" ) != 0 && strcmp( operation, "dec" ) != 0 ) |
| { |
| ERROR( "Invalid '%s' operation requested", operation ); |
| usage(); |
| } |
| break; |
| } |
| |
| case '?': default: |
| { |
| usage(); |
| break; |
| } |
| } |
| } |
| |
| |
| if( operation == NULL ) |
| { |
| usage(); |
| } |
| |
| |
| if( optind < argc ) |
| { |
| char *buf = NULL; |
| |
| buf = (char *)malloc( (size_t)PATH_MAX ); |
| if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); } |
| |
| if( destination == NULL ) |
| { |
| pkglog_fname = xstrdup( (const char *)argv[optind++] ); |
| if( pkglog_fname == NULL ) |
| { |
| FATAL_ERROR( "Unable to set input PKGLOG file name" ); |
| } |
| |
| bzero( (void *)buf, PATH_MAX ); |
| (void)sprintf( buf, "%s", pkglog_fname ); |
| destination = xstrdup( (const char *)dirname( buf ) ); |
| if( destination == NULL ) |
| { |
| FATAL_ERROR( "Unable to set destination directory" ); |
| } |
| |
| } |
| else |
| { |
| bzero( (void *)buf, PATH_MAX ); |
| (void)sprintf( buf, "%s/%s", destination, argv[optind++] ); |
| pkglog_fname = xstrdup( (const char *)buf ); |
| if( pkglog_fname == NULL ) |
| { |
| FATAL_ERROR( "Unable to set inpit PKGLOG file name" ); |
| } |
| } |
| |
| free( buf ); |
| |
| pkglog_type = check_pkglog_file( (const char *)pkglog_fname ); |
| if( pkglog_type != PKGLOG_TEXT ) |
| { |
| ERROR( "%s: Unknown input file format", basename( pkglog_fname ) ); |
| usage(); |
| } |
| |
| } |
| else |
| { |
| usage(); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| static char *skip_spaces( char *s ) |
| { |
| char *q, *p = (char *)0; |
| |
| if( !s || *s == '\0' ) return p; |
| |
| p = s; |
| |
| while( (*p == ' ' || *p == '\t') && *p != '\0' ) { ++p; } q = p; |
| while( *q != ' ' && *q != '\t' && *q != '\0' ) { ++q; } *q = '\0'; |
| |
| if( *p == '\0' ) return (char *)0; |
| |
| return( xstrdup( (const char *)p ) ); |
| } |
| |
| |
| |
| |
| |
| static void skip_eol_spaces( char *s ) |
| { |
| char *p = (char *)0; |
| |
| if( !s || *s == '\0' ) return; |
| |
| p = s + strlen( s ) - 1; |
| while( isspace( *p ) ) { *p-- = '\0'; } |
| } |
| |
| |
| |
| int get_pkginfo() |
| { |
| int ret = -1; |
| FILE *log = NULL; |
| |
| if( pkglog_fname != NULL ) |
| { |
| log = fopen( (const char *)pkglog_fname, "r" ); |
| if( !log ) |
| { |
| FATAL_ERROR( "Cannot open %s file", pkglog_fname ); |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| char *pkgname_pattern = "PACKAGE NAME:", |
| *pkgver_pattern = "PACKAGE VERSION:", |
| *group_pattern = "GROUP:", |
| *arch_pattern = "ARCH:", |
| *distroname_pattern = "DISTRO:", |
| *distrover_pattern = "DISTRO VERSION:"; |
| |
| int last = 10; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| if( last ) |
| { |
| int n = 1; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| if( (match = strstr( ln, pkgname_pattern )) && match == ln ) |
| { |
| pkgname = skip_spaces( ln + strlen( pkgname_pattern ) ); |
| } |
| if( (match = strstr( ln, pkgver_pattern )) && match == ln ) |
| { |
| pkgver = skip_spaces( ln + strlen( pkgver_pattern ) ); |
| } |
| if( (match = strstr( ln, arch_pattern )) && match == ln ) |
| { |
| arch = skip_spaces( ln + strlen( arch_pattern ) ); |
| } |
| if( (match = strstr( ln, distroname_pattern )) && match == ln ) |
| { |
| distroname = skip_spaces( ln + strlen( distroname_pattern ) ); |
| } |
| if( (match = strstr( ln, distrover_pattern )) && match == ln ) |
| { |
| distrover = skip_spaces( ln + strlen( distrover_pattern ) ); |
| } |
| if( (match = strstr( ln, group_pattern )) && match == ln ) |
| { |
| group = skip_spaces( ln + strlen( group_pattern ) ); |
| } |
| |
| if( n < last ) ++n; |
| else break; |
| |
| } |
| |
| } |
| |
| free( line ); |
| |
| if( pkgname == NULL ) ++ret; |
| if( pkgver == NULL ) ++ret; |
| if( arch == NULL ) ++ret; |
| if( distroname == NULL ) ++ret; |
| if( distrover == NULL ) ++ret; |
| |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| |
| int get_references_section( int *start, int *stop, unsigned int *cnt, FILE *log ) |
| { |
| int ret = -1, found = 0; |
| |
| if( !start || !stop || !cnt ) return ret; |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "REFERENCE COUNTER:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| |
| |
| { |
| unsigned int count; |
| int rc; |
| |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| rc = sscanf( ln, "REFERENCE COUNTER: %u", &count ); |
| if( rc == 1 && cnt != NULL ) |
| { |
| *cnt = count; |
| } |
| } |
| } |
| if( (match = strstr( ln, "REQUIRES:" )) && match == ln ) |
| { |
| *stop = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 2 ) ? 0 : 1; |
| |
| fseek( log, 0, SEEK_SET ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| |
| int get_requires_section( int *start, int *stop, const char *log_fname ) |
| { |
| int ret = -1, found = 0; |
| |
| FILE *log = NULL; |
| |
| if( !start || !stop ) return ret; |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( !log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "REQUIRES:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| } |
| if( (match = strstr( ln, "PACKAGE DESCRIPTION:" )) && match == ln ) |
| { |
| *stop = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 2 ) ? 0 : 1; |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| int get_description_section( int *start, int *stop, const char *log_fname ) |
| { |
| int ret = -1, found = 0; |
| |
| FILE *log = NULL; |
| |
| if( !start || !stop ) return ret; |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( !log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "PACKAGE DESCRIPTION:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| } |
| if( (match = strstr( ln, "RESTORE LINKS:" )) && match == ln ) |
| { |
| *stop = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 2 ) ? 0 : 1; |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| int get_restore_links_section( int *start, int *stop, const char *log_fname ) |
| { |
| int ret = -1, found = 0; |
| |
| FILE *log = NULL; |
| |
| if( !start || !stop ) return ret; |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( !log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "RESTORE LINKS:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| } |
| if( (match = strstr( ln, "INSTALL SCRIPT:" )) && match == ln ) |
| { |
| *stop = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 2 ) ? 0 : 1; |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| int get_install_script_section( int *start, int *stop, const char *log_fname ) |
| { |
| int ret = -1, found = 0; |
| |
| FILE *log = NULL; |
| |
| if( !start || !stop ) return ret; |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( !log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "INSTALL SCRIPT:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| } |
| if( (match = strstr( ln, "FILE LIST:" )) && match == ln ) |
| { |
| *stop = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 2 ) ? 0 : 1; |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| int get_file_list_section( int *start, int *stop, const char *log_fname ) |
| { |
| int ret = -1, found = 0; |
| |
| FILE *log = NULL; |
| |
| if( !start || !stop ) return ret; |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( !log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( log != NULL ) |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| *stop = 0; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| char *match = NULL; |
| |
| if( (match = strstr( ln, "FILE LIST:" )) && match == ln ) |
| { |
| *start = ret + 1; |
| ++found; |
| } |
| |
| ++ret; |
| } |
| |
| free( line ); |
| |
| ret = ( found == 1 ) ? 0 : 1; |
| |
| fclose( log ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int get_requires( const char *requires, const char *log_fname ) |
| { |
| int ret = -1; |
| FILE *req = NULL, *log = NULL; |
| |
| int start = 0, stop = 0; |
| |
| if( get_requires_section( &start, &stop, log_fname ) != 0 ) |
| { |
| return ret; |
| } |
| |
| if( log_fname != NULL ) |
| { |
| log = fopen( (const char *)log_fname, "r" ); |
| if( ! log ) |
| { |
| return ret; |
| } |
| } |
| |
| if( requires != NULL ) |
| { |
| req = fopen( (const char *)requires, "w" ); |
| if( ! req ) |
| { |
| return ret; |
| } |
| } |
| |
| |
| { |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| if( start && start < stop ) |
| { |
| int n = 1, lines = 0; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| if( (n > start) && (n < stop) ) |
| { |
| fprintf( req, "%s\n", ln ); |
| ++lines; |
| } |
| ++n; |
| } |
| |
| ret = lines; |
| } |
| |
| free( line ); |
| |
| fclose( log ); |
| fflush( req ); fclose( req ); |
| } |
| |
| return( ret ); |
| } |
| |
| |
| struct package **read_requires( const char *fname, int n ) |
| { |
| struct package **requires = (struct package **)0; |
| struct package **ptr = (struct package **)0; |
| |
| FILE *file; |
| |
| if( ! fname ) return NULL; |
| |
| requires = create_requires( n + 1 ); |
| if( requires ) |
| { |
| int i; |
| char *ln = NULL; |
| char *line = NULL; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| struct package *package; |
| |
| file = fopen( fname, "r" ); |
| if( !file ) |
| { |
| free( line ); |
| free_requires( requires ); |
| return NULL; |
| } |
| |
| ptr = requires; |
| for( i = 0; i < n; ++i ) |
| { |
| if( (ln = fgets( line, PATH_MAX, file )) ) |
| { |
| char *d, *name, *version; |
| |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| |
| d = index( ln, '=' ); *d = '\0'; |
| version = ++d; name = ln; |
| |
| package = create_package( name, version, arch, DISTRO_NAME, DISTRO_VERSION ); |
| if( package ) |
| { |
| *ptr = package; |
| ptr++; |
| } |
| } |
| } |
| *ptr = (struct package *)0; |
| |
| free( line ); |
| } |
| |
| return requires; |
| } |
| |
| int find_requires( char *pname, const char *grp ) |
| { |
| char *name = NULL; |
| char *buf = NULL; |
| |
| struct package **ptr = requires; |
| |
| buf = (char *)malloc( (size_t)PATH_MAX ); |
| |
| if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); } |
| |
| while( *ptr ) |
| { |
| if( grp && *grp != '\0' ) |
| { |
| char *p = NULL; |
| size_t len = strlen( (*ptr)->name ); |
| |
| if( (p = strstr( (*ptr)->name, grp )) && (p == (*ptr)->name) ) |
| { |
| |
| name = alloca( len + 1 ); |
| strcpy( name, (const char *)(*ptr)->name ); |
| |
| name = index( name, '/' ) + 1; |
| } |
| else |
| { |
| |
| name = alloca( len + strlen( grp ) + 2 ); |
| (void)sprintf( name, "%s/%s", grp, (const char *)(*ptr)->name ); |
| } |
| } |
| else |
| { |
| name = (*ptr)->name; |
| } |
| |
| (void)sprintf( buf, "%s-%s-%s-%s-%s", |
| name, (*ptr)->version, (*ptr)->arch, |
| (*ptr)->distro_name, (*ptr)->distro_version ); |
| |
| if( ! strcmp( buf, pname ) ) |
| { |
| free( buf ); return 1; |
| } |
| ptr++; |
| } |
| |
| free( buf ); |
| |
| return 0; |
| } |
| |
| |
| int save_tmp_head( FILE *log, int stop, const char *fname ) |
| { |
| FILE *fp; |
| int ret = -1; |
| |
| char *ln = NULL; |
| char *line = NULL; |
| int n = 1, lines = 0; |
| |
| if( !stop || !log || !fname || *fname == '\0' ) return ret; |
| |
| fp = fopen( fname, "w" ); |
| if( !fp ) |
| { |
| return ret; |
| } |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| if( n < stop ) |
| { |
| fprintf( fp, "%s\n", ln ); |
| ++n; ++lines; |
| } |
| else |
| break; |
| } |
| |
| ret = lines; |
| |
| free( line ); |
| |
| fseek( log, 0, SEEK_SET ); |
| fclose( fp ); |
| |
| return ret; |
| } |
| |
| int save_tmp_tail( FILE *log, int start, const char *fname ) |
| { |
| FILE *fp; |
| int ret = -1; |
| |
| char *ln = NULL; |
| char *line = NULL; |
| int n = 1, lines = 0; |
| |
| if( !start || !log || !fname || *fname == '\0' ) return ret; |
| |
| fp = fopen( fname, "w" ); |
| if( !fp ) |
| { |
| return ret; |
| } |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) && (n < start) ) ++n; |
| |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| fprintf( fp, "%s\n", ln ); |
| ++lines; |
| } |
| |
| ret = lines; |
| |
| free( line ); |
| |
| fseek( log, 0, SEEK_SET ); |
| fclose( fp ); |
| |
| return ret; |
| } |
| |
| int write_tmp_part( FILE *log, const char *fname ) |
| { |
| FILE *fp; |
| int ret = -1; |
| |
| char *ln = NULL; |
| char *line = NULL; |
| int lines = 0; |
| |
| if( !log || !fname || *fname == '\0' ) return ret; |
| |
| fp = fopen( fname, "r" ); |
| if( !fp ) |
| { |
| return ret; |
| } |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| ++ret; |
| |
| while( (ln = fgets( line, PATH_MAX, fp )) ) |
| { |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| fprintf( log, "%s\n", ln ); |
| ++lines; |
| } |
| |
| ret = lines; |
| |
| free( line ); |
| |
| fclose( fp ); |
| |
| return ret; |
| } |
| |
| |
| |
| static char **create_references( size_t size ) |
| { |
| char **references = (char **)0; |
| |
| if( size > 0 ) |
| { |
| references = (char **)malloc( size * sizeof(char *) ); |
| bzero( (void *)references, size * sizeof(char *) ); |
| } |
| |
| return( references ); |
| } |
| |
| static void free_references( char **references ) |
| { |
| if( references ) |
| { |
| char **ptr = references; |
| |
| while( *ptr ) |
| { |
| if( *ptr ) free( *ptr ); |
| ptr++; |
| } |
| free( references ); |
| } |
| } |
| |
| |
| static char **get_references( FILE *log, int start, unsigned int *cnt, char *grp, char *name, char *version ) |
| { |
| char **refs = (char **)0; |
| char **ptr; |
| |
| char *ln = NULL; |
| char *line = NULL; |
| int n = 1; |
| |
| size_t len = 0; |
| |
| unsigned int counter, pkgs; |
| |
| char *pkg = NULL; |
| |
| if( !log || !cnt || *cnt == 0 || !name || !version ) return refs; |
| |
| line = (char *)malloc( (size_t)PATH_MAX ); |
| if( !line ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| pkg = (char *)malloc( (size_t)PATH_MAX ); |
| if( !pkg ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| counter = *cnt; |
| |
| if( grp && *grp != '\0' ) { (void)sprintf( pkg, "%s/%s=", grp, name ); } |
| else { (void)sprintf( pkg, "%s=", name ); } |
| |
| len = strlen( pkg ); |
| |
| refs = ptr = create_references( counter + 1 ); |
| |
| while( (ln = fgets( line, PATH_MAX, log )) && (n < start) ) ++n; |
| |
| n = 0; pkgs = 0; |
| while( (ln = fgets( line, PATH_MAX, log )) ) |
| { |
| ln[strlen(ln) - 1] = '\0'; |
| skip_eol_spaces( ln ); |
| |
| if( strstr( ln, "REQUIRES:" ) ) break; |
| |
| if( n < counter ) |
| { |
| if( strncmp( ln, pkg, len ) ) |
| { |
| if( refs ) |
| { |
| *ptr = xstrdup( (const char *)ln ); ++ptr; |
| *ptr = (char *)0; |
| ++pkgs; |
| } |
| } |
| ++n; |
| } |
| else |
| break; |
| } |
| |
| free( line ); free( pkg ); |
| |
| fseek( log, 0, SEEK_SET ); |
| |
| if( pkgs == 0 ) |
| { |
| free_references( refs ); |
| refs = (char **)0; |
| } |
| |
| *cnt = pkgs; |
| |
| return refs; |
| } |
| |
| |
| static void _change_references( char *grp, char *name, char *version, const char *log_fname ) |
| { |
| int fd; |
| FILE *log; |
| |
| char *head_fname = NULL, *tail_fname = NULL; |
| int head_lines, tail_lines; |
| |
| int rc, start, stop; |
| unsigned int counter; |
| |
| int inc = ( strcmp( operation, "inc" ) == 0 ) ? 1 : 0; |
| |
| char **references = NULL; |
| |
| if( !name || !version || log_fname == NULL ) return; |
| if( check_pkglog_file( log_fname ) != PKGLOG_TEXT ) return; |
| |
| log = fopen( (const char *)log_fname, "r+" ); |
| if( !log ) |
| { |
| ERROR( "Cannot access %s file: %s", log_fname, strerror( errno ) ); |
| return; |
| } |
| |
| fd = __lock_file( log ); |
| |
| rc = get_references_section( &start, &stop, &counter, log ); |
| if( rc != 0 ) |
| { |
| ERROR( "%s: PKGLOG doesn't contains REFERENCE COUNTER section", log_fname ); |
| __unlock_file( fd ); fclose( log ); |
| return; |
| } |
| |
| head_fname = (char *)alloca( strlen( tmpdir ) + 7 ); |
| (void)sprintf( head_fname, "%s/.HEAD", tmpdir ); |
| |
| tail_fname = (char *)alloca( strlen( tmpdir ) + 7 ); |
| (void)sprintf( tail_fname, "%s/.TAIL", tmpdir ); |
| |
| head_lines = save_tmp_head( log, start, (const char *)head_fname ); |
| tail_lines = save_tmp_tail( log, stop - 1, (const char *)tail_fname ); |
| |
| if( head_lines < 10 && tail_lines < 12 ) |
| { |
| ERROR( "%s: Invalid PKGLOG file", log_fname ); |
| __unlock_file( fd ); fclose( log ); |
| return; |
| } |
| |
| references = get_references( log, start, &counter, grp, name, version ); |
| |
| if( ftruncate( fd, 0 ) != 0 ) |
| { |
| ERROR( "Cannot change REFERENCE COUNTER in the %s file: %s", log_fname, strerror( errno ) ); |
| free_references( references ); |
| __unlock_file( fd ); fclose( log ); |
| return; |
| } |
| |
| head_lines = write_tmp_part( log, (const char *)head_fname ); |
| |
| if( inc ) ++counter; |
| fprintf( log, "REFERENCE COUNTER: %u\n", counter ); |
| if( inc ) |
| { |
| if( grp && *grp != '\0' ) |
| { |
| fprintf( log, "%s/%s=%s\n", grp, name, version ); |
| } |
| else |
| { |
| fprintf( log, "%s=%s\n", name, version ); |
| } |
| } |
| |
| if( references ) |
| { |
| char **ptr = references; |
| |
| while( *ptr ) |
| { |
| if( *ptr ) fprintf( log, "%s\n", *ptr ); |
| ptr++; |
| } |
| |
| free_references( references ); |
| } |
| |
| tail_lines = write_tmp_part( log, (const char *)tail_fname ); |
| |
| __unlock_file( fd ); |
| fclose( log ); |
| } |
| |
| |
| static void _search_required_packages( const char *dirpath, const char *grp ) |
| { |
| DIR *dir; |
| char *path; |
| size_t len; |
| |
| struct stat path_sb, entry_sb; |
| struct dirent *entry; |
| |
| if( stat( dirpath, &path_sb ) == -1 ) |
| { |
| FATAL_ERROR( "%s: Cannot stat Setup Database or destination directory", dirpath ); |
| } |
| |
| if( S_ISDIR(path_sb.st_mode) == 0 ) |
| { |
| FATAL_ERROR( "%s: Setup Database or destination is not a directory", dirpath ); |
| } |
| |
| if( (dir = opendir(dirpath) ) == NULL ) |
| { |
| FATAL_ERROR( "Canot access %s directory: %s", dirpath, strerror( errno ) ); |
| } |
| |
| len = strlen( dirpath ); |
| |
| while( (entry = readdir( dir )) != NULL) |
| { |
| |
| if( ! strcmp( entry->d_name, "." ) || ! strcmp( entry->d_name, ".." ) ) continue; |
| |
| |
| path = alloca( len + strlen( entry->d_name ) + 2 ); |
| |
| strcpy( path, dirpath ); |
| strcat( path, "/" ); |
| strcat( path, entry->d_name ); |
| |
| if( stat( path, &entry_sb ) == 0 ) |
| { |
| if( S_ISREG(entry_sb.st_mode) ) |
| { |
| if( find_requires( entry->d_name, grp ) ) |
| { |
| _change_references( group, pkgname, pkgver, (const char *)path ); |
| } |
| } |
| if( S_ISDIR(entry_sb.st_mode) && grp == NULL ) |
| { |
| _search_required_packages( (const char *)path, (const char *)entry->d_name ); |
| } |
| } |
| |
| |
| } |
| |
| closedir( dir ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| char *get_selfdir( void ) |
| { |
| char *buf = NULL; |
| ssize_t len; |
| |
| buf = (char *)malloc( PATH_MAX ); |
| if( !buf ) |
| { |
| FATAL_ERROR( "Cannot allocate memory" ); |
| } |
| |
| bzero( (void *)buf, PATH_MAX ); |
| len = readlink( "/proc/self/exe", buf, (size_t)PATH_MAX ); |
| if( len > 0 && len < PATH_MAX ) |
| { |
| char *p = xstrdup( (const char *)dirname( buf ) ); |
| free( buf ); |
| return p; |
| } |
| FATAL_ERROR( "Cannot determine self directory. Please mount /proc filesystem" ); |
| } |
| |
| void set_stack_size( void ) |
| { |
| const rlim_t stack_size = 16 * 1024 * 1024; |
| struct rlimit rl; |
| int ret; |
| |
| ret = getrlimit( RLIMIT_STACK, &rl ); |
| if( ret == 0 ) |
| { |
| if( rl.rlim_cur < stack_size ) |
| { |
| rl.rlim_cur = stack_size; |
| ret = setrlimit( RLIMIT_STACK, &rl ); |
| if( ret != 0 ) |
| { |
| fprintf(stderr, "setrlimit returned result = %d\n", ret); |
| FATAL_ERROR( "Cannot set stack size" ); |
| } |
| } |
| } |
| } |
| |
| |
| int main( int argc, char *argv[] ) |
| { |
| gid_t gid; |
| |
| int ret; |
| |
| set_signal_handlers(); |
| |
| gid = getgid(); |
| setgroups( 1, &gid ); |
| |
| fatal_error_hook = fatal_error_actions; |
| |
| selfdir = get_selfdir(); |
| |
| errlog = stderr; |
| |
| program = basename( argv[0] ); |
| get_args( argc, argv ); |
| |
| |
| |
| exit_status = get_pkginfo(); |
| if( exit_status != 0 ) |
| { |
| FATAL_ERROR( "%s: Invalid input PKGLOG file", basename( pkglog_fname ) ); |
| } |
| |
| tmpdir = _mk_tmpdir(); |
| if( !tmpdir ) |
| { |
| FATAL_ERROR( "Cannot create temporary directory" ); |
| } |
| else |
| { |
| char *buf = NULL; |
| |
| buf = (char *)malloc( (size_t)strlen( tmpdir ) + 11 ); |
| if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); } |
| |
| (void)sprintf( (char *)&buf[0], "%s/.REQUIRES", tmpdir ); |
| requires_fname = xstrdup( (const char *)&buf[0] ); |
| free( buf ); |
| } |
| |
| |
| |
| |
| if( (ret = get_requires( (const char *)requires_fname, (const char *)pkglog_fname )) > 0 ) |
| { |
| |
| requires = read_requires( (const char *)requires_fname, ret ); |
| _search_required_packages( (const char *)destination, NULL ); |
| } |
| |
| if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); } |
| free_resources(); |
| |
| exit( exit_status ); |
| } |
| |