/* * GEM MINE - The ROCK Linux Package Manager * Copyright (C) 2002-2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "mine.h" enum { MINE_MODE_NONE, MINE_MODE_INSTALL, MINE_MODE_REMOVE, MINE_MODE_PKGLIST, MINE_MODE_SHOWFILE, MINE_MODE_SHOWKEY, MINE_MODE_CHECK, MINE_MODE_MKPDB }; int mine_mode = MINE_MODE_NONE; int mine_mode_test; int mine_mode_verbose; int mine_mode_force; int mine_mode_sub; int mine_mode_header_line; int mine_mode_header_block; char * mine_file_key_name; char * mine_root_dir; char ** patterns=NULL; /*This function adds strings to array of strings it accepts a NULL strings to imply a new array it also buffers the array with a NULL pointer so look for that when parsing this array */ char ** add_string_array(char ** strings, char * new_string) { int i=-1; if(!strings) { strings = malloc(sizeof(char*)*2); i++; } else { while(strings[++i]); strings = realloc(strings, sizeof(char*)*(i+2)); } strings[i] = strdup(new_string); strings[i+1] = NULL; return strings; } /*Frees the above string arrays*/ void free_string_array(char ** strings) { int i=0; while(strings[i]) free(strings[i++]); free(strings); } void help() { fprintf(stderr, "\n" "GEM MINE v" MINE_VERSION " - ROCK Linux Package Management Tool\n" "Copyright 2002 - 2005 Clifford Wolf (GPL'ed)\n" "\n" "Install (-i), remove (-r) and check (-y) GEM packages:\n" "\n" " mine -i [ -R root ] [ -t ] [ -v ] [ -f ] [-x glob ] package1.gem [ .. ]\n" " mine -r [ -R root ] [ -t ] [ -v ] [ -f ] [ -s ] package1 [ package2 [ .. ] ]\n" " mine -y [ -R root ] package1 [ package2 [ .. ] ]\n" "\n" "Query installed packages or GEM package files:\n" "\n" " mine {query-mode} [ -R root ] [ -h | -H ] [ package1 [ package2.gem [ .. ] ] ]\n" "\n" " Where {query-mode} might be one of:\n" "\n" " -q name and version -p long description -l file list\n" " -m md5sums -c cksums -d dependencies\n" "\n" " -k key (for *.gem files only, use 'LIST' as key to list all keys)\n" " -P create 'packages.db' records (for *.gem files only)\n" "\n" " Query all installed packages if no package name or file is passed.\n" "\n" "Options:\n" "\n" " -t run in test mode\n" " -v be more verbose\n" " -f force (skip md5sum checking)\n" " -s also remove sub-packages (e.g. *:doc or *:dev)\n" " -x next parameter is a pattern for files to skip\n" " -R next parameter is the root directory\n" "\n" "Create GEM (-C) and .tar.bz2 (-T) package files from installed packages:\n" "\n" " mine -C var-adm-dir package-tar-bz2 package-name gem-file\n" " mine -T var-adm-dir root-dir package-name package-tar-bz2\n" "\n" "E.g. this will create a GEM file from the mine package installed in /:\n" "\n" " mine -T /var/adm / mine mine.tar.bz2\n" " mine -C /var/adm mine.tar.bz2 mine mine.gem\n" "\n" "Hint: After installing, updating or removing packages you should run the\n" " scripts 'cron.run' and 'postinstall'. This updates some important\n" " system files.\n" "\n" ); exit(1); } void help_keys() { fprintf(stderr, "\n" "The following keys are defined in a GEM file:\n" "\n" " pkg_name The name of the package\n" " pkg_version The name of the package\n" " pkg_tarbz2 The package data (as tar.bz2 file)\n" " pkg_config The config-id generated by scripts/Config\n" "\n" " packages The /var/adm/packages/ file\n" " flists The /var/adm/flists/ file\n" " md5sums The /var/adm/md5sums/ file\n" " cksums The /var/adm/cksums/ file\n" " dependencies The /var/adm/dependencies/ file\n" " descs The /var/adm/descs/ file\n" "\n" " creator ID of the application which created the GEM file\n" "\n" " [A-Z]* The records from /var/adm/descs/\n" "\n" ); exit(1); } void set_mode(int mode) { if (mine_mode == MINE_MODE_NONE) mine_mode = mode; else help(); } int do_gem_install(char * url) { char gemfile[4096]; char command[8192]; int c; if ( !strncmp(url, "https://", 7) || !strncmp(url, "file://", 7) || !strncmp(url, "ftp://", 6) ) { snprintf(gemfile, 4096, "%s/%s", GEMCACHE, url); for (c = strlen(GEMCACHE)+1; gemfile[c]; c++) if ( gemfile[c] == '/' ) gemfile[c] = '_'; if ( access(gemfile, F_OK) ) { snprintf(command, 8192, "mkdir -p '%s';" "curl --progress-bar %s -o '%s.part' '%s' && " "mv '%s.part' '%s'", GEMCACHE, access(MINECURLOPT, F_OK) ? "" : MINECURLOPT, gemfile, url, gemfile, gemfile); printf("Downloading %s ..\n", url); system(command); } else if ( mine_mode_verbose ) printf("Using cached %s ..\n", gemfile); } else { snprintf(gemfile, 4096, "%s", url); } return gem_install(mine_root_dir, mine_mode_test, mine_mode_verbose, mine_mode_force, gemfile, patterns); } int main(int argc, char ** argv) { int opt, ret=0, rc; /* No Zombies */ signal(SIGCHLD, SIG_IGN); if ( argc == 6 && !strcmp(argv[1], "-C") ) { gem_create(argv[2], argv[3], argv[4], argv[5]); return 0; } if ( argc == 6 && !strcmp(argv[1], "-T") ) { char command[4096]; snprintf(command, 4096, "( cd '%s'\ncut -f2- -d' ' '%s/flists/%s' | \\\n" "\ttar -cf- --no-recursion --files-from=- | bzip2\n" ") > '%s'\n", argv[3][0] ? argv[3] : "/", argv[2], argv[4], argv[5]); system(command); return 0; } while ( (opt = getopt(argc, argv, "iryqPplmcdk:tvfshHR:x:")) != -1 ) { switch (opt) { case 'i': set_mode(MINE_MODE_INSTALL); break; case 'r': set_mode(MINE_MODE_REMOVE); break; case 'y': set_mode(MINE_MODE_CHECK); break; case 'q': set_mode(MINE_MODE_PKGLIST); break; case 'P': set_mode(MINE_MODE_MKPDB); break; case 'p': set_mode(MINE_MODE_SHOWFILE); mine_file_key_name = "packages"; break; case 'l': set_mode(MINE_MODE_SHOWFILE); mine_file_key_name = "flists"; break; case 'm': set_mode(MINE_MODE_SHOWFILE); mine_file_key_name = "md5sums"; break; case 'c': set_mode(MINE_MODE_SHOWFILE); mine_file_key_name = "cksums"; break; case 'd': set_mode(MINE_MODE_SHOWFILE); mine_file_key_name = "dependencies"; break; case 'k': if (!strcmp(optarg, "LIST")) help_keys(); set_mode(MINE_MODE_SHOWKEY); mine_file_key_name = optarg; break; case 't': if ( !mine_mode_test && (mine_mode == MINE_MODE_INSTALL || mine_mode == MINE_MODE_REMOVE) ) { mine_mode_test=1; } else help(); break; case 'v': if ( !mine_mode_verbose && (mine_mode == MINE_MODE_INSTALL || mine_mode == MINE_MODE_REMOVE) ) { mine_mode_verbose=1; } else help(); break; case 'f': if ( !mine_mode_force && (mine_mode == MINE_MODE_INSTALL || mine_mode == MINE_MODE_REMOVE) ) { mine_mode_force=1; } else help(); break; case 's': if ( !mine_mode_sub && (mine_mode == MINE_MODE_REMOVE || mine_mode == MINE_MODE_PKGLIST || mine_mode == MINE_MODE_SHOWFILE || mine_mode == MINE_MODE_CHECK)) { mine_mode_sub=1; } else help(); break; case 'h': if ( !mine_mode_header_line && !mine_mode_header_block && (mine_mode == MINE_MODE_SHOWFILE || mine_mode == MINE_MODE_SHOWKEY) ) { mine_mode_header_line=1; } else help(); break; case 'H': if ( !mine_mode_header_line && !mine_mode_header_block && (mine_mode == MINE_MODE_SHOWFILE || mine_mode == MINE_MODE_SHOWKEY) ) { mine_mode_header_block=1; } else help(); break; case 'R': if ( mine_root_dir == NULL ) { mine_root_dir = optarg; } else help(); break; case 'x': if ( mine_mode == MINE_MODE_INSTALL ) { patterns=add_string_array(patterns, optarg); } else help(); break; default: help(); } } if ( mine_mode == MINE_MODE_NONE ) help(); if ( mine_root_dir == NULL ) mine_root_dir = ""; else if ( !(mine_mode == MINE_MODE_INSTALL || mine_mode == MINE_MODE_REMOVE || mine_mode == MINE_MODE_CHECK || mine_mode == MINE_MODE_PKGLIST || mine_mode == MINE_MODE_SHOWFILE) ) help(); if (optind < argc) { while (optind < argc) { rc = 0; switch (mine_mode) { case MINE_MODE_INSTALL: rc = do_gem_install(argv[optind]); if(patterns) free_string_array(patterns); break; case MINE_MODE_REMOVE: rc = gem_remove(mine_root_dir, mine_mode_test, mine_mode_verbose, mine_mode_force, mine_mode_sub, argv[optind]); break; case MINE_MODE_CHECK: rc = gem_check(mine_root_dir, mine_mode_sub, argv[optind]); break; case MINE_MODE_PKGLIST: rc = gem_pkglist(mine_root_dir, mine_mode_sub, argv[optind]); break; case MINE_MODE_SHOWFILE: rc = gem_showfile( mine_root_dir, mine_file_key_name, mine_mode_header_block, mine_mode_sub, argv[optind]); break; case MINE_MODE_SHOWKEY: rc = gem_showkey( mine_file_key_name, mine_mode_header_line, mine_mode_header_block, argv[optind]); break; case MINE_MODE_MKPDB: rc = gem_mkpdb(argv[optind]); break; default: help(); } if ( rc > ret ) ret = rc; optind++;; } } else { struct dirent **namelist; int n; if ( mine_mode == MINE_MODE_INSTALL || mine_mode == MINE_MODE_REMOVE || mine_mode == MINE_MODE_SHOWKEY ) help(); char buffer[1024]; snprintf(buffer, 1024, "%s/var/adm/packages", mine_root_dir); n = scandir(buffer, &namelist, 0, alphasort); if (n < 0) { char buffer2[1024]; snprintf(buffer2, 1024, "Can't read %s", buffer); perror(buffer2); exit(1); } while(n--) { rc = 0; switch (mine_mode) { case MINE_MODE_PKGLIST: rc = gem_pkglist(mine_root_dir, 0, namelist[n]->d_name); break; case MINE_MODE_SHOWFILE: rc = gem_showfile(mine_root_dir, mine_file_key_name, mine_mode_header_block, 0, namelist[n]->d_name); break; case MINE_MODE_CHECK: rc = gem_check(mine_root_dir, 0, namelist[n]->d_name); break; } free(namelist[n]); if ( rc > ret ) ret = rc; } free(namelist); } return ret; }