Radix cross Linux package tools

Package Tools – is a set of utilities to create, install, and update RcL packages

3 Commits   0 Branches   2 Tags
11c606a6 (kx 2023-04-11 01:18:34 +0300    1) 
11c606a6 (kx 2023-04-11 01:18:34 +0300    2) /**********************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300    3) 
11c606a6 (kx 2023-04-11 01:18:34 +0300    4)   Copyright 2019 Andrey V.Kosteltsev
11c606a6 (kx 2023-04-11 01:18:34 +0300    5) 
11c606a6 (kx 2023-04-11 01:18:34 +0300    6)   Licensed under the Radix.pro License, Version 1.0 (the "License");
11c606a6 (kx 2023-04-11 01:18:34 +0300    7)   you may not use this file  except  in compliance with the License.
11c606a6 (kx 2023-04-11 01:18:34 +0300    8)   You may obtain a copy of the License at
11c606a6 (kx 2023-04-11 01:18:34 +0300    9) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   10)      https://radix.pro/licenses/LICENSE-1.0-en_US.txt
11c606a6 (kx 2023-04-11 01:18:34 +0300   11) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   12)   Unless required by applicable law or agreed to in writing, software
11c606a6 (kx 2023-04-11 01:18:34 +0300   13)   distributed under the License is distributed on an "AS IS" BASIS,
11c606a6 (kx 2023-04-11 01:18:34 +0300   14)   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11c606a6 (kx 2023-04-11 01:18:34 +0300   15)   implied.
11c606a6 (kx 2023-04-11 01:18:34 +0300   16) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   17)  **********************************************************************/
11c606a6 (kx 2023-04-11 01:18:34 +0300   18) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   19) #include <config.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   20) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   21) #include <stdlib.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   22) #include <stdio.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   23) #include <sys/types.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   24) #include <stdint.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   25) #include <dirent.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   26) #include <sys/stat.h> /* chmod(2)    */
11c606a6 (kx 2023-04-11 01:18:34 +0300   27) #include <sys/file.h> /* flock(2)    */
11c606a6 (kx 2023-04-11 01:18:34 +0300   28) #include <fcntl.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   29) #include <linux/limits.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   30) #include <alloca.h>   /* alloca(3)   */
11c606a6 (kx 2023-04-11 01:18:34 +0300   31) #include <string.h>   /* strdup(3)   */
11c606a6 (kx 2023-04-11 01:18:34 +0300   32) #include <strings.h>  /* index(3)    */
11c606a6 (kx 2023-04-11 01:18:34 +0300   33) #include <libgen.h>   /* basename(3) */
11c606a6 (kx 2023-04-11 01:18:34 +0300   34) #include <ctype.h>    /* tolower(3)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300   35) #include <errno.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   36) #include <time.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   37) #include <sys/time.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   38) #include <pwd.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   39) #include <grp.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   40) #include <stdarg.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   41) #include <unistd.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   42) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   43) #include <sys/wait.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   44) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   45) #include <sys/resource.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   46) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   47) #include <signal.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   48) #if !defined SIGCHLD && defined SIGCLD
11c606a6 (kx 2023-04-11 01:18:34 +0300   49) # define SIGCHLD SIGCLD
11c606a6 (kx 2023-04-11 01:18:34 +0300   50) #endif
11c606a6 (kx 2023-04-11 01:18:34 +0300   51) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   52) #define _GNU_SOURCE
11c606a6 (kx 2023-04-11 01:18:34 +0300   53) #include <getopt.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   54) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   55) #include <msglog.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   56) #include <wrapper.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   57) #include <system.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   58) #include <cmpvers.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   59) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   60) #define PROGRAM_NAME "check-package"
11c606a6 (kx 2023-04-11 01:18:34 +0300   61) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   62) #include <defs.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300   63) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   64) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   65) char *program = PROGRAM_NAME;
11c606a6 (kx 2023-04-11 01:18:34 +0300   66) char *root = NULL, *pkgs_path = NULL, *pkg_fname = NULL, *pkg_found = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   67)      *tmpdir = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300   68) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   69) int   quiet = 0, print_broken_files = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300   70) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   71) int   exit_status = EXIT_SUCCESS; /* errors counter */
11c606a6 (kx 2023-04-11 01:18:34 +0300   72) char *selfdir     = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300   73) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   74) static char           *pkgname = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   75)                        *pkgver = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   76)                          *arch = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   77)                    *distroname = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   78)                     *distrover = NULL,
11c606a6 (kx 2023-04-11 01:18:34 +0300   79)                         *group = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300   80) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   81) static char *installed_version = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300   82) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   83) enum _input_type {
11c606a6 (kx 2023-04-11 01:18:34 +0300   84)   IFMT_PKG = 0,
11c606a6 (kx 2023-04-11 01:18:34 +0300   85)   IFMT_LOG,
11c606a6 (kx 2023-04-11 01:18:34 +0300   86) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   87)   IFMT_UNKNOWN
11c606a6 (kx 2023-04-11 01:18:34 +0300   88) } input_format = IFMT_PKG;
11c606a6 (kx 2023-04-11 01:18:34 +0300   89) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   90) 
11c606a6 (kx 2023-04-11 01:18:34 +0300   91) #define FREE_PKGINFO_VARIABLES() \
11c606a6 (kx 2023-04-11 01:18:34 +0300   92)   if( pkgname )           { free( pkgname );           } pkgname = NULL;            \
11c606a6 (kx 2023-04-11 01:18:34 +0300   93)   if( pkgver )            { free( pkgver );            } pkgver = NULL;             \
11c606a6 (kx 2023-04-11 01:18:34 +0300   94)   if( arch )              { free( arch );              } arch = NULL;               \
11c606a6 (kx 2023-04-11 01:18:34 +0300   95)   if( distroname )        { free( distroname );        } distroname = NULL;         \
11c606a6 (kx 2023-04-11 01:18:34 +0300   96)   if( distrover )         { free( distrover );         } distrover = NULL;          \
11c606a6 (kx 2023-04-11 01:18:34 +0300   97)   if( group )             { free( group );             } group = NULL;              \
11c606a6 (kx 2023-04-11 01:18:34 +0300   98)   if( installed_version ) { free( installed_version ); } installed_version = NULL
11c606a6 (kx 2023-04-11 01:18:34 +0300   99) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  100) void free_resources()
11c606a6 (kx 2023-04-11 01:18:34 +0300  101) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  102)   if( root )         { free( root );         root         = NULL; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  103)   if( pkgs_path )    { free( pkgs_path );    pkgs_path    = NULL; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  104)   if( pkg_fname )    { free( pkg_fname );    pkg_fname    = NULL; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  105) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  106)   if( selfdir )      { free( selfdir );      selfdir      = NULL; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  107) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  108)   FREE_PKGINFO_VARIABLES();
11c606a6 (kx 2023-04-11 01:18:34 +0300  109) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  110) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  111) void usage()
11c606a6 (kx 2023-04-11 01:18:34 +0300  112) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  113)   free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300  114) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  115)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  116)   fprintf( stdout, "Usage: %s [options] <package|pkglog|pkgname>\n", program );
11c606a6 (kx 2023-04-11 01:18:34 +0300  117)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  118)   fprintf( stdout, "This utility checks if specified package is installed.  If package\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  119)   fprintf( stdout, "or some another version  of this package is already installed then\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  120)   fprintf( stdout, "this utility checks if installed package is correct.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  121)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  122)   fprintf( stdout, "Options:\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  123)   fprintf( stdout, "  -h,--help                     Display this information.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  124)   fprintf( stdout, "  -v,--version                  Display the version of %s utility.\n", program );
11c606a6 (kx 2023-04-11 01:18:34 +0300  125)   fprintf( stdout, "  -p,--print-broken-files       Print the list of broken directories,\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  126)   fprintf( stdout, "                                files, or symbolic links to stdout.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  127)   fprintf( stdout, "  -q,--quiet                    Do not display explanations for\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  128)   fprintf( stdout, "                                return codes.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  129)   fprintf( stdout, "  -r,--root=<DIR>               Target rootfs path.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  130)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  131)   fprintf( stdout, "Parameter:\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  132)   fprintf( stdout, "  <package|pkglog|pkgname>      The PKGNAME, PACKAGE tarball or PKGLOG.\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  133)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  134)   fprintf( stdout, "Return codes:\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  135)   fprintf( stdout, "  ------+---------------------------+--------------------\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  136)   fprintf( stdout, "   code |          status           | what can be done\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  137)   fprintf( stdout, "  ------+---------------------------+--------------------\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  138)   fprintf( stdout, "     30 | not installed             | install\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  139)   fprintf( stdout, "     31 | installed correctly       | nothing to do\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  140)   fprintf( stdout, "     32 | installed but not correct | repair, re-install\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  141)   fprintf( stdout, "     33 | installed correctly       | upgrade\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  142)   fprintf( stdout, "     34 | installed but not correct | repair, upgrade\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  143)   fprintf( stdout, "     35 | installed correctly       | downgrade\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  144)   fprintf( stdout, "     36 | installed but not correct | repair, downgrade\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  145)   fprintf( stdout, "  ------+---------------------------+--------------------\n"  );
11c606a6 (kx 2023-04-11 01:18:34 +0300  146)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  147)   fprintf( stdout, "Other non-zero codes assumes that this utility faced to errors not\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  148)   fprintf( stdout, "related to quality of installed package.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  149)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  150)   fprintf( stdout, "If package specified by short name (probably with version) instead\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  151)   fprintf( stdout, "of regular files such as package tarball or pkglog file  then this\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  152)   fprintf( stdout, "utility doesn't check other installed versions of this package.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  153)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  154) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  155)   exit( EXIT_FAILURE );
11c606a6 (kx 2023-04-11 01:18:34 +0300  156) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  157) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  158) void to_lowercase( char *s )
11c606a6 (kx 2023-04-11 01:18:34 +0300  159) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  160)   char *p = s;
11c606a6 (kx 2023-04-11 01:18:34 +0300  161)   while( p && *p ) { int c = *p; *p = tolower( c ); ++p; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  162) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  163) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  164) void to_uppercase( char *s )
11c606a6 (kx 2023-04-11 01:18:34 +0300  165) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  166)   char *p = s;
11c606a6 (kx 2023-04-11 01:18:34 +0300  167)   while( p && *p ) { int c = *p; *p = toupper( c ); ++p; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  168) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  169) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  170) void version()
11c606a6 (kx 2023-04-11 01:18:34 +0300  171) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  172)   char *upper = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  173) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  174)   upper = (char *)alloca( strlen( program ) + 1 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  175) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  176)   strcpy( (char *)upper, (const char *)program );
11c606a6 (kx 2023-04-11 01:18:34 +0300  177)   to_uppercase( upper );
11c606a6 (kx 2023-04-11 01:18:34 +0300  178) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  179)   fprintf( stdout, "%s (%s) %s\n", program, upper, PROGRAM_VERSION );
11c606a6 (kx 2023-04-11 01:18:34 +0300  180) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  181)   fprintf( stdout, "Copyright (C) 2019 Andrey V.Kosteltsev.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  182)   fprintf( stdout, "This is free software.   There is NO warranty; not even\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  183)   fprintf( stdout, "for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  184)   fprintf( stdout, "\n" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  185) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  186)   free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300  187)   exit( EXIT_SUCCESS );
11c606a6 (kx 2023-04-11 01:18:34 +0300  188) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  189) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  190) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  191) static void remove_trailing_slash( char *dir )
11c606a6 (kx 2023-04-11 01:18:34 +0300  192) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  193)   char *s;
11c606a6 (kx 2023-04-11 01:18:34 +0300  194) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  195)   if( !dir || dir[0] == '\0' ) return;
11c606a6 (kx 2023-04-11 01:18:34 +0300  196) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  197)   s = dir + strlen( dir ) - 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  198)   while( *s == '/' )
11c606a6 (kx 2023-04-11 01:18:34 +0300  199)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  200)     *s = '\0'; --s;
11c606a6 (kx 2023-04-11 01:18:34 +0300  201)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  202) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  203) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  204) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  205) static int _mkdir_p( const char *dir, const mode_t mode )
11c606a6 (kx 2023-04-11 01:18:34 +0300  206) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  207)   char  *buf;
11c606a6 (kx 2023-04-11 01:18:34 +0300  208)   char  *p = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  209)   struct stat sb;
11c606a6 (kx 2023-04-11 01:18:34 +0300  210) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  211)   if( !dir ) return -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  212) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  213)   buf = (char *)alloca( strlen( dir ) + 1 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  214)   strcpy( buf, dir );
11c606a6 (kx 2023-04-11 01:18:34 +0300  215) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  216)   remove_trailing_slash( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300  217) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  218)   /* check if path exists and is a directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  219)   if( stat( buf, &sb ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  220)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  221)     if( S_ISDIR(sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  222)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  223)       return 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  224)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  225)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  226) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  227)   /* mkdir -p */
11c606a6 (kx 2023-04-11 01:18:34 +0300  228)   for( p = buf + 1; *p; ++p )
11c606a6 (kx 2023-04-11 01:18:34 +0300  229)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  230)     if( *p == '/' )
11c606a6 (kx 2023-04-11 01:18:34 +0300  231)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  232)       *p = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  233)       /* test path */
11c606a6 (kx 2023-04-11 01:18:34 +0300  234)       if( stat( buf, &sb ) != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  235)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  236)         /* path does not exist - create directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  237)         if( mkdir( buf, mode ) < 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  238)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300  239)           return -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  240)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300  241)       } else if( !S_ISDIR(sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  242)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  243)         /* not a directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  244)         return -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  245)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  246)       *p = '/';
11c606a6 (kx 2023-04-11 01:18:34 +0300  247)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  248)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  249) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  250)   /* test path */
11c606a6 (kx 2023-04-11 01:18:34 +0300  251)   if( stat( buf, &sb ) != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  252)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  253)     /* path does not exist - create directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  254)     if( mkdir( buf, mode ) < 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  255)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  256)       return -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  257)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  258)   } else if( !S_ISDIR(sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  259)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  260)     /* not a directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  261)     return -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  262)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  263) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  264)   return 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  265) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  266) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  267) static void _rm_tmpdir( const char *dirpath )
11c606a6 (kx 2023-04-11 01:18:34 +0300  268) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  269)   DIR    *dir;
11c606a6 (kx 2023-04-11 01:18:34 +0300  270)   char   *path;
11c606a6 (kx 2023-04-11 01:18:34 +0300  271)   size_t  len;
11c606a6 (kx 2023-04-11 01:18:34 +0300  272) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  273)   struct stat    path_sb, entry_sb;
11c606a6 (kx 2023-04-11 01:18:34 +0300  274)   struct dirent *entry;
11c606a6 (kx 2023-04-11 01:18:34 +0300  275) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  276)   if( stat( dirpath, &path_sb ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  277)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  278)     return; /* stat returns error code; errno is set */
11c606a6 (kx 2023-04-11 01:18:34 +0300  279)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  280) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  281)   if( S_ISDIR(path_sb.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  282)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  283)     return; /* dirpath is not a directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  284)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  285) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  286)   if( (dir = opendir(dirpath) ) == NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  287)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  288)     return; /* Cannot open direcroty; errno is set */
11c606a6 (kx 2023-04-11 01:18:34 +0300  289)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  290) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  291)   len = strlen( dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  292) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  293)   while( (entry = readdir( dir )) != NULL)
11c606a6 (kx 2023-04-11 01:18:34 +0300  294)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  295) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  296)     /* skip entries '.' and '..' */
11c606a6 (kx 2023-04-11 01:18:34 +0300  297)     if( ! strcmp( entry->d_name, "." ) || ! strcmp( entry->d_name, ".." ) ) continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300  298) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  299)     /* determinate a full name of an entry */
11c606a6 (kx 2023-04-11 01:18:34 +0300  300)     path = alloca( len + strlen( entry->d_name ) + 2 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  301)     strcpy( path, dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  302)     strcat( path, "/" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  303)     strcat( path, entry->d_name );
11c606a6 (kx 2023-04-11 01:18:34 +0300  304) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  305)     if( stat( path, &entry_sb ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  306)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  307)       if( S_ISDIR(entry_sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  308)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  309)         /* recursively remove a nested directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  310)         _rm_tmpdir( path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  311)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  312)       else
11c606a6 (kx 2023-04-11 01:18:34 +0300  313)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  314)         /* remove a file object */
11c606a6 (kx 2023-04-11 01:18:34 +0300  315)         (void)unlink( path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  316)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  317)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  318)     /* else { stat() returns error code; errno is set; and we have to continue the loop } */
11c606a6 (kx 2023-04-11 01:18:34 +0300  319) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  320)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  321) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  322)   /* remove the devastated directory and close the object of this directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300  323)   (void)rmdir( dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  324) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  325)   closedir( dir );
11c606a6 (kx 2023-04-11 01:18:34 +0300  326) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  327) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  328) static char *_mk_tmpdir( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300  329) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  330)   char   *buf = NULL, *p, *tmp = "/tmp";
11c606a6 (kx 2023-04-11 01:18:34 +0300  331)   size_t  len = 0, size = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  332) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  333)   (void)umask( S_IWGRP | S_IWOTH ); /* octal 022 */
11c606a6 (kx 2023-04-11 01:18:34 +0300  334) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  335)   /* Get preferred directory for tmp files */
11c606a6 (kx 2023-04-11 01:18:34 +0300  336)   if( (p = getenv( "TMP" )) != NULL ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  337)     tmp = p;
11c606a6 (kx 2023-04-11 01:18:34 +0300  338)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  339)   else if( (p = getenv( "TEMP" )) != NULL ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  340)     tmp = p;
11c606a6 (kx 2023-04-11 01:18:34 +0300  341)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  342) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  343)   size = strlen( tmp ) + strlen( DISTRO_NAME ) + strlen( program ) + 12;
11c606a6 (kx 2023-04-11 01:18:34 +0300  344) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  345)   buf = (char *)malloc( size );
11c606a6 (kx 2023-04-11 01:18:34 +0300  346)   if( !buf ) return NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  347) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  348)   len = snprintf( buf, size, (const char *)"%s/%s/%s-%.7u", tmp, DISTRO_NAME, program, getpid() );
11c606a6 (kx 2023-04-11 01:18:34 +0300  349)   if( len == 0 || len == size - 1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  350)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  351)     free( buf ); return NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  352)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  353) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  354)   _rm_tmpdir( (const char *)&buf[0] );
11c606a6 (kx 2023-04-11 01:18:34 +0300  355) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  356)   if( _mkdir_p( buf, S_IRWXU | S_IRWXG | S_IRWXO ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  357)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  358)     return buf;
11c606a6 (kx 2023-04-11 01:18:34 +0300  359)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  360) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  361)   free( buf ); return NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  362) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  363) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  364) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  365) void fatal_error_actions( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300  366) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  367)   logmsg( errlog, MSG_NOTICE, "Free resources on FATAL error..." );
11c606a6 (kx 2023-04-11 01:18:34 +0300  368)   if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300  369)   free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300  370) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  371) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  372) void sigint( int signum )
11c606a6 (kx 2023-04-11 01:18:34 +0300  373) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  374)   (void)signum;
11c606a6 (kx 2023-04-11 01:18:34 +0300  375) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  376)   if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300  377)   free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300  378) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  379) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  380) static void set_signal_handlers()
11c606a6 (kx 2023-04-11 01:18:34 +0300  381) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  382)   struct sigaction  sa;
11c606a6 (kx 2023-04-11 01:18:34 +0300  383)   sigset_t          set;
11c606a6 (kx 2023-04-11 01:18:34 +0300  384) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  385)   memset( &sa, 0, sizeof( sa ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  386)   sa.sa_handler = sigint;          /* TERM, INT */
11c606a6 (kx 2023-04-11 01:18:34 +0300  387)   sa.sa_flags = SA_RESTART;
11c606a6 (kx 2023-04-11 01:18:34 +0300  388)   sigemptyset( &set );
11c606a6 (kx 2023-04-11 01:18:34 +0300  389)   sigaddset( &set, SIGTERM );
11c606a6 (kx 2023-04-11 01:18:34 +0300  390)   sigaddset( &set, SIGINT );
11c606a6 (kx 2023-04-11 01:18:34 +0300  391)   sa.sa_mask = set;
11c606a6 (kx 2023-04-11 01:18:34 +0300  392)   sigaction( SIGTERM, &sa, NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300  393)   sigaction( SIGINT, &sa,  NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300  394) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  395)   memset( &sa, 0, sizeof( sa ) );  /* ignore SIGPIPE */
11c606a6 (kx 2023-04-11 01:18:34 +0300  396)   sa.sa_handler = SIG_IGN;
11c606a6 (kx 2023-04-11 01:18:34 +0300  397)   sa.sa_flags = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  398)   sigaction( SIGPIPE, &sa, NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300  399) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  400)   /* System V fork+wait does not work if SIGCHLD is ignored */
11c606a6 (kx 2023-04-11 01:18:34 +0300  401)   signal( SIGCHLD, SIG_DFL );
11c606a6 (kx 2023-04-11 01:18:34 +0300  402) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  403) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  404) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  405) static enum _input_type check_input_file( char *uncompress, const char *fname )
11c606a6 (kx 2023-04-11 01:18:34 +0300  406) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  407)   struct stat st;
11c606a6 (kx 2023-04-11 01:18:34 +0300  408)   size_t pkglog_size = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  409)   unsigned char buf[8];
11c606a6 (kx 2023-04-11 01:18:34 +0300  410)   int rc, fd;
11c606a6 (kx 2023-04-11 01:18:34 +0300  411) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  412)   /* SIGNATURES: https://www.garykessler.net/library/file_sigs.html */
11c606a6 (kx 2023-04-11 01:18:34 +0300  413) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  414)   if( uncompress )
11c606a6 (kx 2023-04-11 01:18:34 +0300  415)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  416)     *uncompress = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  417)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  418) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  419)   if( stat( fname, &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  420)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  421)     FATAL_ERROR( "Cannot access %s file: %s", basename( (char *)fname ), strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  422)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  423) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  424)   pkglog_size = st.st_size;
11c606a6 (kx 2023-04-11 01:18:34 +0300  425) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  426)   if( (fd = open( fname, O_RDONLY )) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  427)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  428)     FATAL_ERROR( "Cannot open %s file: %s", basename( (char *)fname ), strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  429)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  430) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  431)   rc = (int)read( fd, (void *)&buf[0], 7 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  432)   if( rc != 7 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  433)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  434)     close( fd ); return IFMT_UNKNOWN;
11c606a6 (kx 2023-04-11 01:18:34 +0300  435)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  436)   buf[7] = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  437) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  438)   /* TEXT */
11c606a6 (kx 2023-04-11 01:18:34 +0300  439)   if( !strncmp( (const char *)&buf[0], "PACKAGE", 7 ) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  440)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  441)     close( fd ); return IFMT_LOG;
11c606a6 (kx 2023-04-11 01:18:34 +0300  442)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  443) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  444)   /* GZ */
11c606a6 (kx 2023-04-11 01:18:34 +0300  445)   if( buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x08 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  446)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  447)     if( uncompress ) { *uncompress = 'x'; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  448)     close( fd ); return IFMT_PKG;
11c606a6 (kx 2023-04-11 01:18:34 +0300  449)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  450) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  451)   /* BZ2 */
11c606a6 (kx 2023-04-11 01:18:34 +0300  452)   if( buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  453)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  454)     if( uncompress ) { *uncompress = 'j'; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  455)     close( fd ); return IFMT_PKG;
11c606a6 (kx 2023-04-11 01:18:34 +0300  456)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  457) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  458)   /* XZ */
11c606a6 (kx 2023-04-11 01:18:34 +0300  459)   if( buf[0] == 0xFD && buf[1] == 0x37 && buf[2] == 0x7A &&
11c606a6 (kx 2023-04-11 01:18:34 +0300  460)       buf[3] == 0x58 && buf[4] == 0x5A && buf[5] == 0x00   )
11c606a6 (kx 2023-04-11 01:18:34 +0300  461)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  462)     if( uncompress ) { *uncompress = 'J'; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  463)     close( fd ); return IFMT_PKG;
11c606a6 (kx 2023-04-11 01:18:34 +0300  464)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  465) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  466)   if( pkglog_size > 262 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  467)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  468)     if( lseek( fd, 257, SEEK_SET ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  469)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  470)       FATAL_ERROR( "Cannot check signature of %s file: %s", basename( (char *)fname ), strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  471)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  472)     rc = (int)read( fd, &buf[0], 5 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  473)     if( rc != 5 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  474)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  475)       FATAL_ERROR( "Cannot read signature of %s file", basename( (char *)fname ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  476)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  477)     /* TAR */
11c606a6 (kx 2023-04-11 01:18:34 +0300  478)     if( buf[0] == 0x75 && buf[1] == 0x73 && buf[2] == 0x74 && buf[3] == 0x61 && buf[4] == 0x72 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  479)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  480)       close( fd ); return IFMT_PKG;
11c606a6 (kx 2023-04-11 01:18:34 +0300  481)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  482)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  483) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  484)   close( fd ); return IFMT_UNKNOWN;
11c606a6 (kx 2023-04-11 01:18:34 +0300  485) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  486) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  487) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  488) void get_args( int argc, char *argv[] )
11c606a6 (kx 2023-04-11 01:18:34 +0300  489) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  490)   const char* short_options = "hvpqr:";
11c606a6 (kx 2023-04-11 01:18:34 +0300  491) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  492)   const struct option long_options[] =
11c606a6 (kx 2023-04-11 01:18:34 +0300  493)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  494)     { "help",               no_argument,       NULL, 'h' },
11c606a6 (kx 2023-04-11 01:18:34 +0300  495)     { "version",            no_argument,       NULL, 'v' },
11c606a6 (kx 2023-04-11 01:18:34 +0300  496)     { "print-broken-files", no_argument,       NULL, 'p' },
11c606a6 (kx 2023-04-11 01:18:34 +0300  497)     { "quiet",              no_argument,       NULL, 'q' },
11c606a6 (kx 2023-04-11 01:18:34 +0300  498)     { "root",               required_argument, NULL, 'r' },
11c606a6 (kx 2023-04-11 01:18:34 +0300  499)     { NULL,                 0,                 NULL,  0  }
11c606a6 (kx 2023-04-11 01:18:34 +0300  500)   };
11c606a6 (kx 2023-04-11 01:18:34 +0300  501) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  502)   int ret;
11c606a6 (kx 2023-04-11 01:18:34 +0300  503)   int option_index = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  504) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  505)   while( (ret = getopt_long( argc, argv, short_options, long_options, &option_index )) != -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  506)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  507)     switch( ret )
11c606a6 (kx 2023-04-11 01:18:34 +0300  508)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  509)       case 'h':
11c606a6 (kx 2023-04-11 01:18:34 +0300  510)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  511)         usage();
11c606a6 (kx 2023-04-11 01:18:34 +0300  512)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  513)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  514)       case 'v':
11c606a6 (kx 2023-04-11 01:18:34 +0300  515)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  516)         version();
11c606a6 (kx 2023-04-11 01:18:34 +0300  517)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  518)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  519)       case 'p':
11c606a6 (kx 2023-04-11 01:18:34 +0300  520)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  521)         print_broken_files = 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  522)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  523)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  524)       case 'q':
11c606a6 (kx 2023-04-11 01:18:34 +0300  525)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  526)         quiet = 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  527)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  528)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  529) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  530)       case 'r':
11c606a6 (kx 2023-04-11 01:18:34 +0300  531)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  532)         if( optarg != NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  533)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300  534)           root = xstrdup( (const char *)optarg );
11c606a6 (kx 2023-04-11 01:18:34 +0300  535)           remove_trailing_slash( root );
11c606a6 (kx 2023-04-11 01:18:34 +0300  536)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300  537)         else
11c606a6 (kx 2023-04-11 01:18:34 +0300  538)           /* option is present but without value */
11c606a6 (kx 2023-04-11 01:18:34 +0300  539)           usage();
11c606a6 (kx 2023-04-11 01:18:34 +0300  540)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  541)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  542) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  543)       case '?': default:
11c606a6 (kx 2023-04-11 01:18:34 +0300  544)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  545)         usage();
11c606a6 (kx 2023-04-11 01:18:34 +0300  546)         break;
11c606a6 (kx 2023-04-11 01:18:34 +0300  547)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  548)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  549)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  550) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  551) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  552)   if( optind < argc )
11c606a6 (kx 2023-04-11 01:18:34 +0300  553)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  554)     pkg_fname = xstrdup( (const char *)argv[optind] );
11c606a6 (kx 2023-04-11 01:18:34 +0300  555)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  556)   else
11c606a6 (kx 2023-04-11 01:18:34 +0300  557)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  558)     usage();
11c606a6 (kx 2023-04-11 01:18:34 +0300  559)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  560) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  561) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  562)   if( !pkgs_path )
11c606a6 (kx 2023-04-11 01:18:34 +0300  563)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  564)     struct stat st;
11c606a6 (kx 2023-04-11 01:18:34 +0300  565)     char  *buf = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  566) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  567)     bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  568) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  569)     buf = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  570)     if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300  571)     bzero( (void *)buf, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  572) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  573)     if( !root )
11c606a6 (kx 2023-04-11 01:18:34 +0300  574)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  575)       buf[0] = '/'; buf[1] = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  576)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  577)     else
11c606a6 (kx 2023-04-11 01:18:34 +0300  578)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  579)       int len = strlen( root );
11c606a6 (kx 2023-04-11 01:18:34 +0300  580) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  581)       (void)strcpy( buf, (const char *)root );
11c606a6 (kx 2023-04-11 01:18:34 +0300  582)       if( buf[ len - 1 ] != '/' )
11c606a6 (kx 2023-04-11 01:18:34 +0300  583)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  584)         buf[len] = '/'; buf[len+1] = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  585)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  586)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  587) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  588)     (void)strcat( buf, PACKAGES_PATH );
11c606a6 (kx 2023-04-11 01:18:34 +0300  589)     if( stat( (const char *)&buf[0], &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  590)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  591)       FATAL_ERROR( "Cannot access '%s' file or directory: %s", buf, strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  592)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  593) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  594)     if( S_ISDIR(st.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  595)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  596)       pkgs_path = xstrdup( (const char *)&buf[0] );
11c606a6 (kx 2023-04-11 01:18:34 +0300  597)       free( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300  598)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  599)     else
11c606a6 (kx 2023-04-11 01:18:34 +0300  600)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  601)       FATAL_ERROR( "Defined --root '%s' is not a directory", buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300  602)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  603) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  604)   } /* End if( !pkgs_path ) */
11c606a6 (kx 2023-04-11 01:18:34 +0300  605) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  606) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  607) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  608) /***********************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  609)   Remove leading spaces and take non-space characters only:
11c606a6 (kx 2023-04-11 01:18:34 +0300  610)   (Especialy for pkginfo lines)
11c606a6 (kx 2023-04-11 01:18:34 +0300  611)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300  612) static char *skip_spaces( char *s )
11c606a6 (kx 2023-04-11 01:18:34 +0300  613) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  614)   char *q, *p = (char *)0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  615) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  616)   if( !s || *s == '\0' ) return p;
11c606a6 (kx 2023-04-11 01:18:34 +0300  617) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  618)   p = s;
11c606a6 (kx 2023-04-11 01:18:34 +0300  619) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  620)   while( (*p == ' ' || *p == '\t') && *p != '\0' ) { ++p; } q = p;
11c606a6 (kx 2023-04-11 01:18:34 +0300  621)   while(  *q != ' ' && *q != '\t'  && *q != '\0' ) { ++q; } *q = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  622) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  623)   if( *p == '\0' ) return (char *)0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  624) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  625)   return( xstrdup( (const char *)p ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  626) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  627) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  628) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  629) /*******************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  630)   remove spaces at end of line:
11c606a6 (kx 2023-04-11 01:18:34 +0300  631)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300  632) static void skip_eol_spaces( char *s )
11c606a6 (kx 2023-04-11 01:18:34 +0300  633) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  634)   char *p = (char *)0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  635) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  636)   if( !s || *s == '\0' ) return;
11c606a6 (kx 2023-04-11 01:18:34 +0300  637) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  638)   p = s + strlen( s ) - 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  639)   while( isspace( *p ) ) { *p-- = '\0'; }
11c606a6 (kx 2023-04-11 01:18:34 +0300  640) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  641) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  642) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  643) /***************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  644)   Probe functions:
11c606a6 (kx 2023-04-11 01:18:34 +0300  645)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300  646) static void _probe_pkglog( const char *dirpath, const char *grp )
11c606a6 (kx 2023-04-11 01:18:34 +0300  647) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  648)   DIR    *dir;
11c606a6 (kx 2023-04-11 01:18:34 +0300  649)   char   *path;
11c606a6 (kx 2023-04-11 01:18:34 +0300  650)   size_t  len;
11c606a6 (kx 2023-04-11 01:18:34 +0300  651) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  652)   struct stat    path_sb, entry_sb;
11c606a6 (kx 2023-04-11 01:18:34 +0300  653)   struct dirent *entry;
11c606a6 (kx 2023-04-11 01:18:34 +0300  654) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  655)   if( pkg_found ) return;
11c606a6 (kx 2023-04-11 01:18:34 +0300  656) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  657)   if( stat( dirpath, &path_sb ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  658)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  659)     FATAL_ERROR( "%s: Cannot stat Setup Database or destination directory", dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  660)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  661) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  662)   if( S_ISDIR(path_sb.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  663)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  664)     FATAL_ERROR( "%s: Setup Database or destination is not a directory", dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  665)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  666) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  667)   if( (dir = opendir(dirpath) ) == NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  668)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  669)     FATAL_ERROR( "Canot access %s directory: %s", dirpath, strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  670)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  671) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  672)   len = strlen( dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  673) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  674)   while( (entry = readdir( dir )) != NULL)
11c606a6 (kx 2023-04-11 01:18:34 +0300  675)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  676)     /* skip entries '.' and '..' */
11c606a6 (kx 2023-04-11 01:18:34 +0300  677)     if( ! strcmp( entry->d_name, "." ) || ! strcmp( entry->d_name, ".." ) ) continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300  678) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  679)     /* determinate a full name of an entry */
11c606a6 (kx 2023-04-11 01:18:34 +0300  680)     path = alloca( len + strlen( entry->d_name ) + 2 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  681) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  682)     strcpy( path, dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  683)     strcat( path, "/" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  684)     strcat( path, entry->d_name );
11c606a6 (kx 2023-04-11 01:18:34 +0300  685) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  686)     if( stat( path, &entry_sb ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  687)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  688)       if( S_ISREG(entry_sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  689)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  690)         char *match  = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  691)         char *pkglog = basename( path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  692) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  693)         if( (match = strstr( pkglog, (const char *)basename( pkg_fname ) )) && match == pkglog )
11c606a6 (kx 2023-04-11 01:18:34 +0300  694)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300  695)           char *buf = NULL, *p = NULL, *q = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  696) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  697)           p = q = buf = xstrdup( (const char *)pkglog );
11c606a6 (kx 2023-04-11 01:18:34 +0300  698)           ++p;
11c606a6 (kx 2023-04-11 01:18:34 +0300  699)           while( *p != '\0' && !isblank(*p) && !(*q == '-' && isdigit(*p)) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  700)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300  701)             /* package version starts with a number and separated by '-' */
11c606a6 (kx 2023-04-11 01:18:34 +0300  702)             ++p; ++q;
11c606a6 (kx 2023-04-11 01:18:34 +0300  703)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300  704)           *(--p) = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300  705) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  706)           /*******************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  707)             We have to make sure that the name we are looking for
11c606a6 (kx 2023-04-11 01:18:34 +0300  708)             is not shorter than the name of the found package.
11c606a6 (kx 2023-04-11 01:18:34 +0300  709)            */
11c606a6 (kx 2023-04-11 01:18:34 +0300  710)           if( strlen(pkg_fname) >= strlen(buf) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  711)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300  712) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  713)             pkg_found = xstrdup( (const char *)path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  714)             free( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300  715)             closedir( dir );
11c606a6 (kx 2023-04-11 01:18:34 +0300  716)             return;
11c606a6 (kx 2023-04-11 01:18:34 +0300  717)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300  718)           free( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300  719)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300  720)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  721)       if( S_ISDIR(entry_sb.st_mode) && grp == NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  722)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  723)         _probe_pkglog( (const char *)path, (const char *)entry->d_name );
11c606a6 (kx 2023-04-11 01:18:34 +0300  724)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  725)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  726)     /* else { stat() returns error code; errno is set; and we have to continue the loop } */
11c606a6 (kx 2023-04-11 01:18:34 +0300  727)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  728) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  729)   closedir( dir );
11c606a6 (kx 2023-04-11 01:18:34 +0300  730) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  731) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  732) /***********************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  733)   probe_package():
11c606a6 (kx 2023-04-11 01:18:34 +0300  734)   ---------------
11c606a6 (kx 2023-04-11 01:18:34 +0300  735)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300  736) char *probe_package( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300  737) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  738)   char *ret = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  739) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  740)   _probe_pkglog( (const char *)pkgs_path, NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300  741)   if( pkg_found )
11c606a6 (kx 2023-04-11 01:18:34 +0300  742)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  743)     free( pkg_fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300  744)     ret = pkg_fname = pkg_found;
11c606a6 (kx 2023-04-11 01:18:34 +0300  745)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  746) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  747)   return ret;
11c606a6 (kx 2023-04-11 01:18:34 +0300  748) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  749) /*
11c606a6 (kx 2023-04-11 01:18:34 +0300  750)   Enf of Probe functions.
11c606a6 (kx 2023-04-11 01:18:34 +0300  751)  ***********************************************************/
11c606a6 (kx 2023-04-11 01:18:34 +0300  752) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  753) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  754) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  755) static void read_input_pkginfo( const char *pkginfo_fname )
11c606a6 (kx 2023-04-11 01:18:34 +0300  756) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  757)   char *ln      = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  758)   char *line    = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  759) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  760)   FILE *pkginfo = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  761) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  762)   if( pkginfo_fname != NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  763)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  764)     pkginfo = fopen( (const char *)pkginfo_fname, "r" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  765)     if( !pkginfo )
11c606a6 (kx 2023-04-11 01:18:34 +0300  766)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  767)       FATAL_ERROR( "Cannot open %s file", pkginfo_fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300  768)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  769)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  770) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  771)   line = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  772)   if( !line )
11c606a6 (kx 2023-04-11 01:18:34 +0300  773)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  774)     FATAL_ERROR( "Cannot allocate memory" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  775)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  776) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  777)   while( (ln = fgets( line, PATH_MAX, pkginfo )) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  778)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  779)     char *match = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  780) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  781)     ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
11c606a6 (kx 2023-04-11 01:18:34 +0300  782)     skip_eol_spaces( ln );     /* remove spaces at end-of-line */
11c606a6 (kx 2023-04-11 01:18:34 +0300  783) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  784)     if( (match = strstr( ln, "pkgname" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  785)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  786)       if( p != NULL ) pkgname = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  787)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  788)     if( (match = strstr( ln, "pkgver" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  789)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  790)       if( p != NULL ) pkgver = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  791)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  792)     if( (match = strstr( ln, "arch" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  793)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  794)       if( p != NULL ) arch = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  795)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  796)     if( (match = strstr( ln, "distroname" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  797)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  798)       if( p != NULL ) distroname = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  799)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  800)     if( (match = strstr( ln, "distrover" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  801)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  802)       if( p != NULL ) distrover = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  803)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  804) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  805)     if( (match = strstr( ln, "group" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  806)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  807)       if( p != NULL ) group = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  808)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  809)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  810) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  811)   free( line );
11c606a6 (kx 2023-04-11 01:18:34 +0300  812) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  813)   if( !pkgname || !pkgver || !arch || !distroname || !distrover )
11c606a6 (kx 2023-04-11 01:18:34 +0300  814)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  815)     FATAL_ERROR( "Invalid input .PKGINFO file" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  816)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  817) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  818)   fclose( pkginfo );
11c606a6 (kx 2023-04-11 01:18:34 +0300  819) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  820) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  821) static void read_found_pkginfo( const char *pkginfo_fname )
11c606a6 (kx 2023-04-11 01:18:34 +0300  822) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  823)   char *ln      = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  824)   char *line    = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  825) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  826)   FILE *pkginfo = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  827) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  828)   char *pn = NULL, *pv = NULL, *ar = NULL, *dn = NULL, *dv = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  829) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  830)   if( pkginfo_fname != NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  831)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  832)     pkginfo = fopen( (const char *)pkginfo_fname, "r" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  833)     if( !pkginfo )
11c606a6 (kx 2023-04-11 01:18:34 +0300  834)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  835)       FATAL_ERROR( "Cannot open %s file", pkginfo_fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300  836)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  837)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  838) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  839)   line = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  840)   if( !line )
11c606a6 (kx 2023-04-11 01:18:34 +0300  841)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  842)     FATAL_ERROR( "Cannot allocate memory" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  843)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  844) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  845)   while( (ln = fgets( line, PATH_MAX, pkginfo )) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  846)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  847)     char *match = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  848) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  849)     ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
11c606a6 (kx 2023-04-11 01:18:34 +0300  850)     skip_eol_spaces( ln );     /* remove spaces at end-of-line */
11c606a6 (kx 2023-04-11 01:18:34 +0300  851) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  852)     if( (match = strstr( ln, "pkgname" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  853)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  854)       if( p != NULL ) pn = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  855)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  856)     if( (match = strstr( ln, "pkgver" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  857)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  858)       if( p != NULL ) pv = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  859)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  860)     if( (match = strstr( ln, "arch" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  861)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  862)       if( p != NULL ) ar = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  863)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  864)     if( (match = strstr( ln, "distroname" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  865)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  866)       if( p != NULL ) dn = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  867)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  868)     if( (match = strstr( ln, "distrover" )) && match == ln ) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  869)       char *p = index( match, '=' ) + 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  870)       if( p != NULL ) dv = skip_spaces( p );
11c606a6 (kx 2023-04-11 01:18:34 +0300  871)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300  872)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  873) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  874)   free( line );
11c606a6 (kx 2023-04-11 01:18:34 +0300  875) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  876)   if( !pn || !pv || !ar || !dn || !dv )
11c606a6 (kx 2023-04-11 01:18:34 +0300  877)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  878)     FATAL_ERROR( "Invalid input .PKGINFO file" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  879)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  880)   else
11c606a6 (kx 2023-04-11 01:18:34 +0300  881)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  882)     if( pn ) free( pn );
11c606a6 (kx 2023-04-11 01:18:34 +0300  883)     if( pv ) installed_version = pv;
11c606a6 (kx 2023-04-11 01:18:34 +0300  884)     if( ar ) free( ar );
11c606a6 (kx 2023-04-11 01:18:34 +0300  885)     if( dn ) free( dn );
11c606a6 (kx 2023-04-11 01:18:34 +0300  886)     if( dv ) free( dv );
11c606a6 (kx 2023-04-11 01:18:34 +0300  887)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  888) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  889)   fclose( pkginfo );
11c606a6 (kx 2023-04-11 01:18:34 +0300  890) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  891) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  892) static void _get_found_pkginfo( const char *pkglog )
11c606a6 (kx 2023-04-11 01:18:34 +0300  893) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  894)   pid_t p = (pid_t) -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300  895)   int   rc;
11c606a6 (kx 2023-04-11 01:18:34 +0300  896) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  897)   int   len = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300  898)   char *tmp= NULL, *cmd = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300  899) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  900)   tmp = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  901)   if( !tmp ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300  902)   bzero( (void *)tmp, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  903) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  904)   (void)sprintf( &tmp[0], "%s", tmpdir );
11c606a6 (kx 2023-04-11 01:18:34 +0300  905)   if( _mkdir_p( tmp, S_IRWXU | S_IRWXG | S_IRWXO ) != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  906)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  907)     FATAL_ERROR( "Cannot get PKGINFO from '%s' file", basename( (char *)pkglog ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  908)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  909) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  910)   cmd = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  911)   if( !cmd ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300  912)   bzero( (void *)cmd, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  913) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  914)   len = snprintf( &cmd[0], PATH_MAX,
11c606a6 (kx 2023-04-11 01:18:34 +0300  915)                   "%s/pkginfo -d %s -o pkginfo,restore-links,filelist %s > /dev/null 2>&1",
11c606a6 (kx 2023-04-11 01:18:34 +0300  916)                   selfdir, tmp, pkglog );
11c606a6 (kx 2023-04-11 01:18:34 +0300  917)   if( len == 0 || len == PATH_MAX - 1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  918)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  919)     FATAL_ERROR( "Cannot get PKGINFO from %s file", basename( (char *)pkglog ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  920)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  921)   p = sys_exec_command( cmd );
11c606a6 (kx 2023-04-11 01:18:34 +0300  922)   rc = sys_wait_command( p, (char *)NULL, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300  923)   if( rc != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  924)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  925)     FATAL_ERROR( "Cannot get PKGINFO from '%s' file", basename( (char *)pkglog ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  926)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  927) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  928)   (void)strcat( tmp, "/.PKGINFO" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  929)   read_found_pkginfo( (const char *)&tmp[0] );
11c606a6 (kx 2023-04-11 01:18:34 +0300  930)   *(strstr( tmp, "/.PKGINFO" )) = '\0'; /* :restore tmpdir in tmp[] buffer */
11c606a6 (kx 2023-04-11 01:18:34 +0300  931) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  932)   free( tmp );
11c606a6 (kx 2023-04-11 01:18:34 +0300  933)   free( cmd );
11c606a6 (kx 2023-04-11 01:18:34 +0300  934) }
11c606a6 (kx 2023-04-11 01:18:34 +0300  935) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  936) static void _search_pkglog( const char *dirpath, const char *grp )
11c606a6 (kx 2023-04-11 01:18:34 +0300  937) {
11c606a6 (kx 2023-04-11 01:18:34 +0300  938)   DIR    *dir;
11c606a6 (kx 2023-04-11 01:18:34 +0300  939)   char   *path;
11c606a6 (kx 2023-04-11 01:18:34 +0300  940)   size_t  len;
11c606a6 (kx 2023-04-11 01:18:34 +0300  941) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  942)   struct stat    path_sb, entry_sb;
11c606a6 (kx 2023-04-11 01:18:34 +0300  943)   struct dirent *entry;
11c606a6 (kx 2023-04-11 01:18:34 +0300  944) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  945)   char   *pname = (char *)dirpath + strlen( root ); /* do not remove leading '/' */
11c606a6 (kx 2023-04-11 01:18:34 +0300  946) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  947)   if( stat( dirpath, &path_sb ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  948)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  949)     FATAL_ERROR( "%s: Cannot stat Setup Database or group directory", pname );
11c606a6 (kx 2023-04-11 01:18:34 +0300  950)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  951) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  952)   if( S_ISDIR(path_sb.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  953)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  954)     FATAL_ERROR( "%s: Setup Database or group is not a directory", pname );
11c606a6 (kx 2023-04-11 01:18:34 +0300  955)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  956) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  957)   if( (dir = opendir(dirpath) ) == NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  958)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  959)     FATAL_ERROR( "Canot access %s directory: %s", pname, strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300  960)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300  961) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  962)   len = strlen( dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  963) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  964)   while( (entry = readdir( dir )) != NULL)
11c606a6 (kx 2023-04-11 01:18:34 +0300  965)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300  966)     /* skip entries '.' and '..' */
11c606a6 (kx 2023-04-11 01:18:34 +0300  967)     if( ! strcmp( entry->d_name, "." ) || ! strcmp( entry->d_name, ".." ) ) continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300  968) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  969)     /* determinate a full name of an entry */
11c606a6 (kx 2023-04-11 01:18:34 +0300  970)     path = alloca( len + strlen( entry->d_name ) + 2 );
11c606a6 (kx 2023-04-11 01:18:34 +0300  971) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  972)     strcpy( path, dirpath );
11c606a6 (kx 2023-04-11 01:18:34 +0300  973)     strcat( path, "/" );
11c606a6 (kx 2023-04-11 01:18:34 +0300  974)     strcat( path, entry->d_name );
11c606a6 (kx 2023-04-11 01:18:34 +0300  975) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  976)     if( stat( path, &entry_sb ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300  977)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300  978)       if( S_ISREG(entry_sb.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  979)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  980)         char *match = NULL, *name  = basename( path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  981) 
11c606a6 (kx 2023-04-11 01:18:34 +0300  982)         if( (match = strstr( name, pkgname )) && match == name )
11c606a6 (kx 2023-04-11 01:18:34 +0300  983)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300  984)           /****************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300  985)             Здесь мы еще должны проверить, что найденный пакет не имеет
11c606a6 (kx 2023-04-11 01:18:34 +0300  986)             более длинное имя, которое начинается с имени искомого пакета.
11c606a6 (kx 2023-04-11 01:18:34 +0300  987)             Полагаясь на факт, что версия может начинаться только с цифры,
11c606a6 (kx 2023-04-11 01:18:34 +0300  988)             мы пропускаем символ '-', разделяющий имя и версию пакета,
11c606a6 (kx 2023-04-11 01:18:34 +0300  989)             а затем проверяем начальный символ версии:
11c606a6 (kx 2023-04-11 01:18:34 +0300  990)            */
11c606a6 (kx 2023-04-11 01:18:34 +0300  991)           if( *(name + strlen( pkgname )) == '-' && isdigit( *(name + strlen( pkgname ) + 1) ) )
11c606a6 (kx 2023-04-11 01:18:34 +0300  992)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300  993)             _get_found_pkginfo( (const char *)path );
11c606a6 (kx 2023-04-11 01:18:34 +0300  994)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300  995)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300  996)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300  997)       if( S_ISDIR(entry_sb.st_mode) && grp == NULL )
11c606a6 (kx 2023-04-11 01:18:34 +0300  998)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300  999)         /**************************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1000)           NOTE:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1001)             In the Setup Database can be only one package with the same pkgname
11c606a6 (kx 2023-04-11 01:18:34 +0300 1002)             but in different groups. For example, the package named 'cairo'
11c606a6 (kx 2023-04-11 01:18:34 +0300 1003)             has two instance: libs/cairo-1.14.6 and xlibs/cairo-1.14.6. During
11c606a6 (kx 2023-04-11 01:18:34 +0300 1004)             system installation the package libs/cairo-1.14.6 installed first
11c606a6 (kx 2023-04-11 01:18:34 +0300 1005)             and then updated by xlibs/cairo-1.14.6 and PKGLOG of libs/cairo-1.14.6
11c606a6 (kx 2023-04-11 01:18:34 +0300 1006)             moved from /var/log/radix/packages to /var/log/radix/removed-packages.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1007) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1008)             So here we have to look for the PKGLOG in all group directories:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1009)          */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1010)         _search_pkglog( (const char *)path, (const char *)entry->d_name );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1011)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1012)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1013)     /* else { stat() returns error code; errno is set; and we have to continue the loop } */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1014)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1015) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1016)   closedir( dir );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1017) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1018) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1019) static void find_installed_package( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1020) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1021)   char *tmp = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1022) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1023)   tmp = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1024)   if( !tmp ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1025)   bzero( (void *)tmp, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1026) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1027)   (void)sprintf( &tmp[0], "%s", pkgs_path );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1028) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1029)   _search_pkglog( (const char *)&tmp[0], NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1030) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1031)   free( tmp );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1032) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1033) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1034) /***************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1035)   check_input_package():
11c606a6 (kx 2023-04-11 01:18:34 +0300 1036)   ---------------------
11c606a6 (kx 2023-04-11 01:18:34 +0300 1037) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1038)     Возвращает:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1039)      -1 если пакет установлен, но его версия меньше
11c606a6 (kx 2023-04-11 01:18:34 +0300 1040)         запрашиваемого,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1041)       0 если пакет не установлен или версия установленного и
11c606a6 (kx 2023-04-11 01:18:34 +0300 1042)         запрашиваемого равны,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1043)       1 если пакет установлен, но его версия больше
11c606a6 (kx 2023-04-11 01:18:34 +0300 1044)         запрашиваемого.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1045) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1046)     В случае возврата -1 или 1, устанавливается переменная
11c606a6 (kx 2023-04-11 01:18:34 +0300 1047)     installed_version, равная версии уже установленного пакета.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1048) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1049)     В случае возврата нуля есть два варанта:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1050)       а) пакет установлен и его надо проверить на целостность
11c606a6 (kx 2023-04-11 01:18:34 +0300 1051)          (переменная installed_version != NULL );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1052)       б) пакет не установлен.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1053) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1054)     Если installed_version != NULL, проверка целостности
11c606a6 (kx 2023-04-11 01:18:34 +0300 1055)     пакета будет осуществлена, вне зависимости от его версии.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1056)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1057) static int check_input_package( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1058) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1059)   struct stat st;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1060)   char *fname = pkg_fname;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1061) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1062)   enum _input_type  type = IFMT_UNKNOWN;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1063)   char              uncompress = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300 1064) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1065)   int ret = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1066) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1067)   bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1068) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1069)   if( stat( (const char *)fname, &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1070)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1071)     /*************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1072)       Specified pkg_fname is not a file or directory.
11c606a6 (kx 2023-04-11 01:18:34 +0300 1073)       Try to find installed package  with name equal
11c606a6 (kx 2023-04-11 01:18:34 +0300 1074)       to pkg_fname:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1075)      */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1076)     fname = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1077)     fname = probe_package();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1078)     if( !fname )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1079)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1080)       if( !quiet ) fprintf( stdout, "Specified package '%s' is not installed.\n\n", pkg_fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1081) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1082)       exit_status = 30; /* Package is not installed: install */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1083) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1084)       if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1085)       free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1086) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1087)       exit( exit_status );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1088)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1089)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1090) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1091)   /* check pkg_fname again: */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1092)   if( stat( (const char *)fname, &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1093)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1094)     FATAL_ERROR( "Cannot access input '%s' file: %s", fname, strerror( errno ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1095)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1096) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1097)   type = check_input_file( &uncompress, fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1098)   if( type == IFMT_UNKNOWN )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1099)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1100)     FATAL_ERROR( "Unknown format of input '%s' file", fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1101)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1102) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1103)   if( S_ISREG(st.st_mode) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1104)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1105)     pid_t p = (pid_t) -1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1106)     int   rc;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1107) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1108)     int   len = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1109)     char *tmp= NULL, *cmd = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1110) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1111)     tmp = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1112)     if( !tmp ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1113)     bzero( (void *)tmp, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1114) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1115)     (void)sprintf( &tmp[0], "%s", tmpdir );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1116)     if( _mkdir_p( tmp, S_IRWXU | S_IRWXG | S_IRWXO ) != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1117)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1118)       FATAL_ERROR( "Cannot get PKGINFO from '%s' file", basename( (char *)fname ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1119)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1120) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1121)     cmd = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1122)     if( !cmd ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1123)     bzero( (void *)cmd, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1124) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1125)     len = snprintf( &cmd[0], PATH_MAX,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1126)                     "%s/pkginfo -d %s -o pkginfo,restore-links,filelist %s > /dev/null 2>&1",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1127)                     selfdir, tmp, fname );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1128)     if( len == 0 || len == PATH_MAX - 1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1129)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1130)       FATAL_ERROR( "Cannot get PKGINFO from %s file", basename( (char *)fname ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1131)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1132)     p = sys_exec_command( cmd );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1133)     rc = sys_wait_command( p, (char *)NULL, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1134)     if( rc != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1135)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1136)       FATAL_ERROR( "Cannot get PKGINFO from '%s' file", basename( (char *)fname ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1137)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1138) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1139)     (void)strcat( tmp, "/.PKGINFO" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1140)     read_input_pkginfo( (const char *)&tmp[0] );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1141)     *(strstr( tmp, "/.PKGINFO" )) = '\0'; /* :restore tmpdir in tmp[] buffer */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1142) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1143)     find_installed_package();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1144) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1145)     free( cmd );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1146)     free( tmp );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1147) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1148)     if( installed_version )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1149)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1150)       ret = cmp_version( (const char *)installed_version, (const char *)pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1151)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1152)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1153)   else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1154)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1155)     FATAL_ERROR( "Input %s file is not a regular file", basename( (char *)fname ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1156)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1157) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1158)   return ret;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1159) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1160) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1161) static int check_package_integrity( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1162) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1163)   struct stat st;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1164)   FILE  *fp = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1165) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1166)   char *ln   = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1167)   char *line = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1168) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1169)   char *buf = NULL, *tmp = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1170) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1171)   int restore_links = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1172)   int ret = 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1173) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1174)   buf = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1175)   if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1176)   bzero( (void *)buf, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1177) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1178)   tmp = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1179)   if( !tmp ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1180)   bzero( (void *)tmp, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1181) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1182)   /* Check if .RESTORELINKS is present */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1183)   (void)sprintf( &tmp[0], "%s/.RESTORELINKS", tmpdir );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1184)   bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1185)   if( (stat( (const char *)&tmp[0], &st ) == 0) && (st.st_size > 8) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1186)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1187)     restore_links = 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1188)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1189) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1190)   (void)sprintf( &tmp[0], "%s/.FILELIST", tmpdir );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1191)   fp = fopen( (const char *)&tmp[0], "r" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1192)   if( !fp )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1193)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1194)     FATAL_ERROR( "Cannot open .FILELIST file" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1195)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1196) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1197)   line = (char *)malloc( (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1198)   if( !line ) { FATAL_ERROR( "Cannot allocate memory" ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1199)   bzero( (void *)line, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1200) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1201)   while( (ln = fgets( line, PATH_MAX, fp )) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1202)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1203)     int dir = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1204) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1205)     ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1206)     skip_eol_spaces( ln );     /* remove spaces at end-of-line */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1207) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1208)     if( *(ln + strlen(ln) - 1) == '/' ) { dir = 1; *(ln + strlen(ln) - 1) = '\0'; }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1209)     else                                { dir = 0; }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1210) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1211)     if( !dir )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1212)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1213)       char *p = rindex( ln, '.' );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1214)       if( p && !strncmp( (const char *)p, ".new", 4 ) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1215)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1216)         /**************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1217)           Do not check .new files:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1218)          */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1219)         *p = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300 1220)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1221)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1222) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1223)     (void)sprintf( &buf[0], "%s/%s", root, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1224)     bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1225) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1226)     if( lstat( (const char *)&buf[0], &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1227)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1228)       /* cannot access file list entry */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1229)       if( dir )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1230)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1231)         if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1232)           fprintf( stdout, "%s-%s: /%s: no such directory\n", pkgname, installed_version, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1233)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1234)       else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1235)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1236)         if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1237)           fprintf( stdout, "%s-%s: /%s: no such file\n", pkgname, installed_version, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1238)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1239) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1240)       ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1241)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1242) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1243)     if( dir )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1244)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1245)       if( S_ISDIR(st.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1246)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1247)         /* not a directory */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1248)         if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1249)           fprintf( stdout, "%s-%s: /%s: not a directory\n", pkgname, installed_version, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1250)         ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1251)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1252)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1253)     else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1254)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1255)       if( S_ISREG(st.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1256)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1257)         /* not a regular file */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1258)         if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1259)           fprintf( stdout, "%s-%s: /%s: not a regular file\n", pkgname, installed_version, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1260)         ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1261)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1262)       if( !restore_links )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1263)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1264)         if( S_ISLNK(st.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1265)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1266)           /* not a symbolic link */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1267)           if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1268)             fprintf( stdout, "%s-%s: /%s: not a symbolic link\n", pkgname, installed_version, ln );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1269)           ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1270)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1271)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1272)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1273)   } /* End of while( file list entry ) */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1274)   fclose( fp );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1275) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1276) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1277)   (void)sprintf( &tmp[0], "%s/.RESTORELINKS", tmpdir );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1278)   bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1279) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1280)   if( stat( (const char *)&tmp[0], &st ) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1281)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1282)     fp = fopen( (const char *)&tmp[0], "r" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1283)     if( !fp )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1284)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1285)       FATAL_ERROR( "Cannot open .RESTORELINKS file" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1286)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1287) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1288)     while( (ln = fgets( line, PATH_MAX, fp )) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1289)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1290)       char *match = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1291) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1292)       ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1293)       skip_eol_spaces( ln );     /* remove spaces at end-of-line */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1294) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1295)       if( (match = strstr( ln, "; rm -rf " )) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1296)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1297)         char *q = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1298)         char *p = strstr( ln, "cd" ) + 2;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1299)         char *f = strstr( ln, "; rm -rf" ) + 8;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1300) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1301)         if( !p || !f ) continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1302) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1303)         while( (*p == ' ' || *p == '\t') && *p != '\0' ) ++p;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1304)         while( (*f == ' ' || *f == '\t') && *f != '\0' ) ++f;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1305) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1306)         q = p; while( *q != ' ' && *q != '\t' && *q != ';' && *q != '\0' ) ++q; *q = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300 1307)         q = f; while( *q != ' ' && *q != '\t' && *q != ';' && *q != '\0' ) ++q; *q = '\0';
11c606a6 (kx 2023-04-11 01:18:34 +0300 1308) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1309)         if( p && f )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1310)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1311)           (void)sprintf( &buf[0], "%s/%s/%s", root, p, f );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1312)           bzero( (void *)&st, sizeof( struct stat ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1313) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1314)           if( lstat( (const char *)&buf[0], &st ) == -1 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1315)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1316)             /* cannot access restore links entry */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1317)             if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1318)               fprintf( stdout, "%s-%s: /%s/%s: no such file or directory\n", pkgname, installed_version, p, f );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1319)             ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1320)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1321) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1322)           if( S_ISLNK(st.st_mode) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1323)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1324)             /* not a symbolic link */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1325)             if( print_broken_files )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1326)               fprintf( stdout, "%s-%s: /%s/%s: not a symbolic link\n", pkgname, installed_version, p, f );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1327)             ret = 0; continue;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1328)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1329)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1330)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1331)     } /* End of while( restore links entry ) */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1332)     fclose( fp );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1333)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1334) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1335)   free( line );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1336)   free( tmp );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1337)   free( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1338) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1339)   return ret;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1340) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1341) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1342) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1343) /*********************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1344)   Get directory where this program is placed:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1345)  */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1346) char *get_selfdir( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1347) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1348)   char    *buf = NULL;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1349)   ssize_t  len;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1350) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1351)   buf = (char *)malloc( PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1352)   if( !buf )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1353)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1354)     FATAL_ERROR( "Cannot allocate memory" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1355)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1356) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1357)   bzero( (void *)buf, PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1358)   len = readlink( "/proc/self/exe", buf, (size_t)PATH_MAX );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1359)   if( len > 0 && len < PATH_MAX )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1360)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1361)     char *p = xstrdup( (const char *)dirname( buf ) );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1362)     free( buf );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1363)     return p;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1364)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1365)   FATAL_ERROR( "Cannot determine self directory. Please mount /proc filesystem" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1366) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1367) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1368) void set_stack_size( void )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1369) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1370)   const rlim_t   stack_size = 16 * 1024 * 1024; /* min stack size = 16 MB */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1371)   struct rlimit  rl;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1372)   int ret;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1373) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1374)   ret = getrlimit( RLIMIT_STACK, &rl );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1375)   if( ret == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1376)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1377)     if( rl.rlim_cur < stack_size )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1378)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1379)       rl.rlim_cur = stack_size;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1380)       ret = setrlimit( RLIMIT_STACK, &rl );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1381)       if( ret != 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1382)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1383)         fprintf(stderr, "setrlimit returned result = %d\n", ret);
11c606a6 (kx 2023-04-11 01:18:34 +0300 1384)         FATAL_ERROR( "Cannot set stack size" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1385)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1386)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1387)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1388) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1389) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1390) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1391) int main( int argc, char *argv[] )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1392) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1393)   gid_t  gid;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1394) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1395)   set_signal_handlers();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1396) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1397)   gid = getgid();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1398)   setgroups( 1, &gid );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1399) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1400)   fatal_error_hook = fatal_error_actions;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1401) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1402)   selfdir = get_selfdir();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1403) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1404)   errlog = stderr;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1405) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1406)   program = basename( argv[0] );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1407)   get_args( argc, argv );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1408) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1409)   /* set_stack_size(); */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1410) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1411)   tmpdir = _mk_tmpdir();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1412)   if( !tmpdir )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1413)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1414)     FATAL_ERROR( "Cannot create temporary directory" );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1415)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1416) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1417) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1418)   {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1419)     int status = 0, correctly = 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 1420) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1421)     /**********************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 1422)       Fill pkginfo data and put or replace pkglog into tmpdir:
11c606a6 (kx 2023-04-11 01:18:34 +0300 1423)      */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1424)     status = check_input_package();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1425) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1426)     if( installed_version )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1427)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1428)       /* In this case we have to check package integrity */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1429)       correctly = check_package_integrity(); /* returns 1 if correct */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1430)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1431) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1432)     if( exit_status == EXIT_SUCCESS )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1433)     {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1434)       if( status < 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1435)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1436)         if( !correctly )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1437)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1438)           if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1439)             fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1440)                      "Previous version '%s' of specified package '%s-%s' is installed but not correct.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1441)                      installed_version, pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1442)           exit_status = 34;   /* Package is installed but not correct: repair, upgrade    */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1443)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1444)         else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1445)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1446)           if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1447)             fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1448)                      "Previous version '%s' of specified package '%s-%s' is installed.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1449)                      installed_version, pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1450)           exit_status = 33;   /* Package is installed correctly: upgrade                  */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1451)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1452)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1453)       else if( status > 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1454)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1455)         if( !correctly )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1456)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1457)           if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1458)             fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1459)                      "A newer version '%s' of specified package '%s-%s' is installed but not correct.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1460)                      installed_version, pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1461)           exit_status = 36;   /* Package is installed but not correct: repair, downgrade  */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1462)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1463)         else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1464)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1465)           if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1466)             fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1467)                      "A newer version '%s' of specified package '%s-%s' is installed.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1468)                      installed_version, pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1469)           exit_status = 35;   /* Package is installed correctly: downgrade                */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1470)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1471)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1472)       else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1473)       {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1474)         if( installed_version )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1475)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1476)           if( !correctly )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1477)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1478)             if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1479)               fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1480)                        "Specified package '%s-%s' is already installed but not correct.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1481)                        pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1482)             exit_status = 32; /* Package is installed but not correct: repair, re-install */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1483)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1484)           else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1485)           {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1486)             if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1487)               fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1488)                        "Specified package '%s-%s' is already installed.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1489)                        pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1490)             exit_status = 31; /* Package is installed correctly: nothing to do            */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1491)           }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1492)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1493)         else
11c606a6 (kx 2023-04-11 01:18:34 +0300 1494)         {
11c606a6 (kx 2023-04-11 01:18:34 +0300 1495)           if( !quiet )
11c606a6 (kx 2023-04-11 01:18:34 +0300 1496)             fprintf( stdout,
11c606a6 (kx 2023-04-11 01:18:34 +0300 1497)                      "Specified package '%s-%s' is not installed.\n\n",
11c606a6 (kx 2023-04-11 01:18:34 +0300 1498)                      pkgname, pkgver );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1499)           exit_status = 30;   /* Package is not installed: install */
11c606a6 (kx 2023-04-11 01:18:34 +0300 1500)         }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1501)       }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1502)     }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1503) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1504)   }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1505) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1506) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1507)   if( tmpdir ) { _rm_tmpdir( (const char *)tmpdir ); free( tmpdir ); }
11c606a6 (kx 2023-04-11 01:18:34 +0300 1508)   free_resources();
11c606a6 (kx 2023-04-11 01:18:34 +0300 1509) 
11c606a6 (kx 2023-04-11 01:18:34 +0300 1510)   exit( exit_status );
11c606a6 (kx 2023-04-11 01:18:34 +0300 1511) }