From 4823ea99910665c2aabae07e20624599fc584868 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Mon, 17 Aug 2015 16:23:37 +0000 Subject: [PATCH] kpm: command line options git-svn-id: svn://kolibrios.org@5737 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/other/kpm/Makefile | 5 +- contrib/other/kpm/getopt.h | 144 +++++++++++++++++++ contrib/other/kpm/http.h | 3 + contrib/other/kpm/kpm.c | 260 ++++++++--------------------------- contrib/other/kpm/package.h | 2 + contrib/other/kpm/utils.c | 266 ++++++++++++++++++++++++++++++++++++ 6 files changed, 474 insertions(+), 206 deletions(-) create mode 100644 contrib/other/kpm/getopt.h create mode 100644 contrib/other/kpm/utils.c diff --git a/contrib/other/kpm/Makefile b/contrib/other/kpm/Makefile index 90e86c0854..a85b19616d 100644 --- a/contrib/other/kpm/Makefile +++ b/contrib/other/kpm/Makefile @@ -20,14 +20,15 @@ INCLUDES+=-I$(SDK_DIR)/sources/freetype/include #DEFINES= -DDEBUG=1 DEFINES= -DNDEBUG -LIBS:= -lsupc++ -lgcc_eh -lc.dll -lapp -lgcc +LIBS:= -liberty -lsupc++ -lgcc_eh -lc.dll -lapp -lgcc LIBPATH:= -L$(LIB_DIR) -L/home/autobuild/tools/win32/mingw32/lib -LDFLAGS = -static -nostdlib --stack 0x30000 -Map kpm.map -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0 +LDFLAGS = -static -nostdlib --stack 0x10000 -Map kpm.map -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0 SOURCES = http.asm \ kpm.c \ + utils.c \ collection.cpp \ tinyxml/tinyxml.cpp \ tinyxml/tinystr.cpp \ diff --git a/contrib/other/kpm/getopt.h b/contrib/other/kpm/getopt.h new file mode 100644 index 0000000000..5421cabed8 --- /dev/null +++ b/contrib/other/kpm/getopt.h @@ -0,0 +1,144 @@ +/* Declarations for getopt. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000, + 2002 Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + 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, 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is + undefined, we haven't run the autoconf check so provide the + declaration without arguments. If it is 0, we checked and failed + to find the declaration so provide a fully prototyped one. If it + is 1, we found it so don't provide any declaration at all. */ +#if !HAVE_DECL_GETOPT +#if defined (__GNU_LIBRARY__) || defined (HAVE_DECL_GETOPT) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in unistd.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else +#ifndef __cplusplus +extern int getopt (); +#endif /* __cplusplus */ +#endif +#endif /* !HAVE_DECL_GETOPT */ + +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* getopt.h */ diff --git a/contrib/other/kpm/http.h b/contrib/other/kpm/http.h index 3a844fd80f..b7b3980a95 100644 --- a/contrib/other/kpm/http.h +++ b/contrib/other/kpm/http.h @@ -52,5 +52,8 @@ unsigned __stdcall con_set_flags(unsigned new_flags); void __stdcall con_cls(void); void __stdcall con_write_asciiz(const char* string); +char *make_url(const char *name); +char *make_tmp_path(const char *path); +char *make_cache_path(const char *path); #endif /* __HTTP_H__ */ diff --git a/contrib/other/kpm/kpm.c b/contrib/other/kpm/kpm.c index 9b228c2b83..b91f9dd789 100644 --- a/contrib/other/kpm/kpm.c +++ b/contrib/other/kpm/kpm.c @@ -1,130 +1,41 @@ #include #include #include -#include -#include -#include #include #include +#include "getopt.h" #include "package.h" #include "http.h" #define BUFFSIZE (64*1024) -char conbuf[256]; +extern char conbuf[256]; -char *make_url(const char *name) +#define OPTION_STD_BASE 150 + +enum option_values { - static char url_buf[128] = "http://ftp.kolibrios.org/users/Serge/new/OS/"; - strcpy(&url_buf[44], name); - return url_buf; + OPTION_HELP = OPTION_STD_BASE, + OPTION_LIST_PACKAGES, + OPTION_LIST_INSTALLED }; -char *make_tmp_path(const char *path) +static const struct option longopts[] = { - static char path_buf[64] = "/tmp0/1/"; - strcpy(&path_buf[8], path); - return path_buf; + {"list-packages", no_argument, NULL, OPTION_LIST_PACKAGES}, + {"list-installed",no_argument, NULL, OPTION_LIST_INSTALLED}, + {NULL,0,NULL,0} }; -char *make_cache_path(const char *path) -{ - static char path_buf[64] = "/kolibrios/kpm/cache/"; - strcpy(&path_buf[21], path); - return path_buf; -}; - -int http_load_file(const char *path, const char *url) -{ - http_t *http; - int received = 0; - int offset = 0; - int tail; - char *buf; - int fd; - int i; - - buf = user_alloc(BUFFSIZE); - for(i = 0; i < 16; i++) - buf[i*4096] = 0; - - fd = open(path, O_CREAT|O_WRONLY); - if(fd == -1) - { - user_free(buf); - return 0; - }; - - http = http_get(url, NULL,FLAG_STREAM|FLAG_REUSE_BUFFER, NULL); - if(http == NULL) - goto err_get; - - do - { - if(http_receive_with_retry(http, 500) == 0) - { - int count; - -// if(http->flags & 0xffff0000) -// break; - - count = http->content_received - received; - if(count+offset <= BUFFSIZE) - { - memcpy(buf+offset, http->content_ptr, count); - offset+= count; - } else - { - tail = count+offset-BUFFSIZE; - count = BUFFSIZE - offset; - if(count) - { - memcpy(buf+offset, http->content_ptr, count); - offset = 0; - }; - - write(fd, buf, BUFFSIZE); - - if(tail) - { - memcpy(buf, http->content_ptr+count, tail); - offset = tail; - } - - sprintf(conbuf, "%d bytes loaded\r", http->content_received); - con_write_asciiz(conbuf); - - } - received = http->content_received; - } - else break; - - }while( (http->flags & FLAG_GOT_ALL_DATA) == 0); - - if(offset) - { - write(fd, buf, offset); - } - -// ftruncate(fd, received); - close(fd); - - if(http->content_ptr) - user_free(http->content_ptr); - http_free(http); - - user_free(buf); - - return received; - -err_get: - printf("HTTP GET failed\n"); - return received; -} - int main(int argc, char *argv[]) { + LIST_HEAD(server_list); + LIST_HEAD(download_list); + LIST_HEAD(cache_list); + LIST_HEAD(local_list); + LIST_HEAD(task_list); + int count; char *cache_path; char *tmp_path; @@ -132,6 +43,8 @@ int main(int argc, char *argv[]) if(http_init()) goto err_init; + set_cwd("/tmp0/1"); + con_init(80, 25, 80, 250, "Kolibri package manager"); tmp_path = make_tmp_path("packages.xml"); @@ -139,14 +52,45 @@ int main(int argc, char *argv[]) count = http_load_file(tmp_path, make_url("packages.xml")); if(count) + build_server_list(&server_list, tmp_path); + + while(1) + { + int val; + int index; + + val = getopt_long_only(argc, argv,"",longopts, &index); + + if(val == -1) + break; + + switch(val) + { + case OPTION_LIST_PACKAGES: + sprintf(conbuf,"available packages:\n\n"); + con_write_asciiz(conbuf); + print_pkg_list(&server_list); + con_exit(0); + return 0; + + case OPTION_LIST_INSTALLED: + sprintf(conbuf,"installed packages:\n\n"); + con_write_asciiz(conbuf); + print_pkg_list(&local_list); + con_exit(0); + return 0; + + default: + break; + } + }; + +#if 0 { - collection_t *collection; package_t *pkg; LIST_HEAD(install_list); LIST_HEAD(download_list); - collection = load_collection_file(tmp_path); - if(collection && build_install_list(&install_list, collection)) { if(build_download_list(&download_list, &install_list)) @@ -161,11 +105,10 @@ int main(int argc, char *argv[]) con_write_asciiz(conbuf); }; - set_cwd("/tmp0/1"); - do_install(&install_list); }; } +#endif con_exit(0); @@ -176,97 +119,6 @@ err_init: return -1; } -int build_install_list(list_t *list, collection_t *collection) -{ - pkg_group_t *gr; - int count = 0; - - list_for_each_entry(gr, &collection->groups, list) - { - package_t *pkg, *tmp; - - list_for_each_entry(tmp, &gr->packages, list) - { - pkg = (package_t*)malloc(sizeof(package_t)); - - INIT_LIST_HEAD(&pkg->file_list); - pkg->id = tmp->id; - pkg->name = strdup(tmp->name); - pkg->version = strdup(tmp->version); - pkg->filename = strdup(tmp->filename); - pkg->description = strdup(tmp->description); - list_add_tail(&pkg->list, list); - count++; - } - }; - return count; -} - -int build_download_list(list_t *download, list_t *src) -{ - int count = 0; - char *cache_path; - package_t *pkg, *tmp; - fileinfo_t info; - list_for_each_entry(tmp, src, list) - { - cache_path = make_cache_path(tmp->filename); - - if( get_fileinfo(cache_path, &info) != 0) - { - pkg = (package_t*)malloc(sizeof(package_t)); - - INIT_LIST_HEAD(&pkg->file_list); - pkg->id = tmp->id; - pkg->name = strdup(tmp->name); - pkg->version = strdup(tmp->version); - pkg->filename = strdup(tmp->filename); - pkg->description = strdup(tmp->description); - list_add_tail(&pkg->list, download); - count++; - }; - } - return count; -}; - -void do_download(list_t *download_list) -{ - package_t *pkg, *tmp; - char *cache_path; - int count; - - list_for_each_entry_safe(pkg, tmp, download_list, list) - { - sprintf(conbuf,"package %s-%s\n", pkg->name, pkg->version); - con_write_asciiz(conbuf); - cache_path = make_cache_path(pkg->filename); - count = http_load_file(cache_path, make_url(pkg->filename)); - sprintf(conbuf,"%s %d bytes loaded\n",cache_path, count); - con_write_asciiz(conbuf); - if( !test_archive(cache_path)) - list_del_pkg(pkg); - else - unlink(cache_path); - }; -} - -void remove_missing_packages(list_t *install, list_t *missed) -{ - package_t *mpkg, *mtmp, *ipkg, *itmp; - - list_for_each_entry_safe(mpkg, mtmp, missed, list) - { - list_for_each_entry_safe(ipkg, itmp, install, list) - { - if(ipkg->id == mpkg->id) - { - sprintf(conbuf,"skip missing package %s-%s\n", ipkg->name, ipkg->version); - con_write_asciiz(conbuf); - list_del_pkg(ipkg); - }; - } - list_del_pkg(mpkg); - }; -}; + diff --git a/contrib/other/kpm/package.h b/contrib/other/kpm/package.h index 6f2235dbd5..c05a3dfede 100644 --- a/contrib/other/kpm/package.h +++ b/contrib/other/kpm/package.h @@ -43,10 +43,12 @@ static inline void list_del_pkg(package_t *pkg) collection_t* load_collection_file(const char *name); collection_t* load_collection_buffer(const char *buffer); +int build_server_list(list_t *slist, const char *path); int build_install_list(list_t *list, collection_t *collection); int build_download_list(list_t *download, list_t *src); void remove_missing_packages(list_t *install, list_t *missed); char *make_cache_path(const char *path); +void print_pkg_list(list_t *list); void do_download(list_t *download); void do_install(list_t *install); diff --git a/contrib/other/kpm/utils.c b/contrib/other/kpm/utils.c new file mode 100644 index 0000000000..cfa7ad21bb --- /dev/null +++ b/contrib/other/kpm/utils.c @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "package.h" +#include "http.h" + +#define BUFFSIZE (64*1024) + +char conbuf[256]; + + +char *make_url(const char *name) +{ + static char url_buf[128] = "http://ftp.kolibrios.org/users/Serge/new/OS/"; + strcpy(&url_buf[44], name); + return url_buf; +}; + +char *make_tmp_path(const char *path) +{ + static char path_buf[64] = "/tmp0/1/"; + strcpy(&path_buf[8], path); + return path_buf; +}; + +char *make_cache_path(const char *path) +{ + static char path_buf[64] = "/kolibrios/kpm/cache/"; + strcpy(&path_buf[21], path); + return path_buf; +}; + +int http_load_file(const char *path, const char *url) +{ + http_t *http; + int received = 0; + int offset = 0; + int tail; + char *buf; + int fd; + int i; + + buf = user_alloc(BUFFSIZE); + for(i = 0; i < 16; i++) + buf[i*4096] = 0; + + fd = open(path, O_CREAT|O_WRONLY); + if(fd == -1) + { + user_free(buf); + return 0; + }; + + http = http_get(url, NULL,FLAG_STREAM|FLAG_REUSE_BUFFER, NULL); + if(http == NULL) + goto err_get; + + do + { + if(http_receive_with_retry(http, 500) == 0) + { + int count; + +// if(http->flags & 0xffff0000) +// break; + + count = http->content_received - received; + if(count+offset <= BUFFSIZE) + { + memcpy(buf+offset, http->content_ptr, count); + offset+= count; + } + else + { + tail = count+offset-BUFFSIZE; + count = BUFFSIZE - offset; + if(count) + { + memcpy(buf+offset, http->content_ptr, count); + offset = 0; + }; + + write(fd, buf, BUFFSIZE); + + if(tail) + { + memcpy(buf, http->content_ptr+count, tail); + offset = tail; + } + + sprintf(conbuf, "%d bytes loaded\r", http->content_received); + con_write_asciiz(conbuf); + + } + received = http->content_received; + } + else break; + + }while( (http->flags & FLAG_GOT_ALL_DATA) == 0); + + if(offset) + { + write(fd, buf, offset); + } + +// ftruncate(fd, received); + close(fd); + + if(http->content_ptr) + user_free(http->content_ptr); + http_free(http); + + user_free(buf); + + return received; + +err_get: + printf("HTTP GET failed\n"); + return received; +} + + +int build_download_list(list_t *download, list_t *src) +{ + int count = 0; + char *cache_path; + package_t *pkg, *tmp; + fileinfo_t info; + list_for_each_entry(tmp, src, list) + { + cache_path = make_cache_path(tmp->filename); + + if( get_fileinfo(cache_path, &info) != 0) + { + pkg = (package_t*)malloc(sizeof(package_t)); + + INIT_LIST_HEAD(&pkg->file_list); + pkg->id = tmp->id; + pkg->name = strdup(tmp->name); + pkg->version = strdup(tmp->version); + pkg->filename = strdup(tmp->filename); + pkg->description = strdup(tmp->description); + list_add_tail(&pkg->list, download); + count++; + }; + } + return count; +}; + +void do_download(list_t *download_list) +{ + package_t *pkg, *tmp; + char *cache_path; + int count; + + list_for_each_entry_safe(pkg, tmp, download_list, list) + { + sprintf(conbuf,"package %s-%s\n", pkg->name, pkg->version); + con_write_asciiz(conbuf); + cache_path = make_cache_path(pkg->filename); + count = http_load_file(cache_path, make_url(pkg->filename)); + sprintf(conbuf,"%s %d bytes loaded\n",cache_path, count); + con_write_asciiz(conbuf); + if( !test_archive(cache_path)) + list_del_pkg(pkg); + else + unlink(cache_path); + }; +} + +void remove_missing_packages(list_t *install, list_t *missed) +{ + package_t *mpkg, *mtmp, *ipkg, *itmp; + + list_for_each_entry_safe(mpkg, mtmp, missed, list) + { + list_for_each_entry_safe(ipkg, itmp, install, list) + { + if(ipkg->id == mpkg->id) + { + sprintf(conbuf,"skip missing package %s-%s\n", ipkg->name, ipkg->version); + con_write_asciiz(conbuf); + list_del_pkg(ipkg); + }; + } + list_del_pkg(mpkg); + }; +}; + +int build_install_list(list_t *list, collection_t *collection) +{ + pkg_group_t *gr; + int count = 0; + + list_for_each_entry(gr, &collection->groups, list) + { + package_t *pkg, *tmp; + + list_for_each_entry(tmp, &gr->packages, list) + { + pkg = (package_t*)malloc(sizeof(package_t)); + + INIT_LIST_HEAD(&pkg->file_list); + pkg->id = tmp->id; + pkg->name = strdup(tmp->name); + pkg->version = strdup(tmp->version); + pkg->filename = strdup(tmp->filename); + pkg->description = strdup(tmp->description); + list_add_tail(&pkg->list, list); + count++; + } + }; + return count; +} + +int build_server_list(list_t *slist, const char *path) +{ + collection_t *collection; + package_t *pkg; + LIST_HEAD(install_list); + LIST_HEAD(download_list); + int count = 0; + + collection = load_collection_file(path); + + if(collection) + { + pkg_group_t *gr; + + list_for_each_entry(gr, &collection->groups, list) + { + package_t *pkg, *tmp; + + list_for_each_entry(tmp, &gr->packages, list) + { + pkg = (package_t*)malloc(sizeof(package_t)); + + INIT_LIST_HEAD(&pkg->file_list); + pkg->id = tmp->id; + pkg->name = strdup(tmp->name); + pkg->version = strdup(tmp->version); + pkg->filename = strdup(tmp->filename); + pkg->description = strdup(tmp->description); + list_add_tail(&pkg->list, slist); + count++; + } + }; + }; + return count; +} + +void print_pkg_list(list_t *list) +{ + package_t *pkg; + + list_for_each_entry(pkg, list, list) + { + sprintf(conbuf,"%s-%s\n", pkg->name, pkg->version); + con_write_asciiz(conbuf); + } +}