[pacman-dev] QNX patches, v2
This patch set is a cleaned up version of the the first attempt to add QNX support. Changes from the first version include: * Using Markus Kuhn's implementation of wcwidth and wcswidth * Breaking the mkdtemp replacement into its own patch, with a proper configure test instead of #ifdef __QNX__ * Cleaning up code style everywhere. Sorry! Thanks again for taking the time to review my first attempt.
This small refactor reduces the number of replications of the local imeplementation of strndup. Signed-off-by: Will Miles <wmiles@sgl.com> --- src/util/Makefile.am | 4 ++-- src/util/pacsort.c | 23 +---------------------- src/util/pactree.c | 24 ++---------------------- src/util/util-common.c | 1 + src/util/util-common.h | 1 + 5 files changed, 7 insertions(+), 46 deletions(-) create mode 120000 src/util/util-common.c create mode 120000 src/util/util-common.h diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 25c025b..936d7ff 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -20,10 +20,10 @@ AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS) cleanupdelta_SOURCES = cleanupdelta.c cleanupdelta_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la -pacsort_SOURCES = pacsort.c +pacsort_SOURCES = pacsort.c util-common.c pacsort_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la -pactree_SOURCES = pactree.c +pactree_SOURCES = pactree.c util-common.c pactree_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la testpkg_SOURCES = testpkg.c diff --git a/src/util/pacsort.c b/src/util/pacsort.c index 02b9084..7081f5a 100644 --- a/src/util/pacsort.c +++ b/src/util/pacsort.c @@ -25,6 +25,7 @@ #include <string.h> #include <alpm.h> +#include "util-common.h" #define DELIM ' ' @@ -69,28 +70,6 @@ static struct options_t { char delim; } opts; -#ifndef HAVE_STRNDUP -/* A quick and dirty implementation derived from glibc */ -static size_t strnlen(const char *s, size_t max) -{ - register const char *p; - for(p = s; *p && max--; ++p); - return (p - s); -} - -char *strndup(const char *s, size_t n) -{ - size_t len = strnlen(s, n); - char *new = (char *) malloc(len + 1); - - if(new == NULL) - return NULL; - - new[len] = '\0'; - return (char *)memcpy(new, s, len); -} -#endif - static struct buffer_t *buffer_new(size_t initial_size) { struct buffer_t *buf; diff --git a/src/util/pactree.c b/src/util/pactree.c index 67f456f..11ad7ca 100644 --- a/src/util/pactree.c +++ b/src/util/pactree.c @@ -29,6 +29,8 @@ #include <langinfo.h> #endif +#include "util-common.h" + #define LINE_MAX 512 typedef struct tdepth { @@ -121,28 +123,6 @@ int searchsyncs = 0; const char *dbpath = DBPATH; const char *configfile = CONFFILE; -#ifndef HAVE_STRNDUP -/* A quick and dirty implementation derived from glibc */ -static size_t strnlen(const char *s, size_t max) -{ - register const char *p; - for(p = s; *p && max--; ++p); - return (p - s); -} - -char *strndup(const char *s, size_t n) -{ - size_t len = strnlen(s, n); - char *new = (char *) malloc(len + 1); - - if(new == NULL) - return NULL; - - new[len] = '\0'; - return (char *)memcpy(new, s, len); -} -#endif - static size_t strtrim(char *str) { char *end, *pch = str; diff --git a/src/util/util-common.c b/src/util/util-common.c new file mode 120000 index 0000000..a2f6c50 --- /dev/null +++ b/src/util/util-common.c @@ -0,0 +1 @@ +../common/util-common.c \ No newline at end of file diff --git a/src/util/util-common.h b/src/util/util-common.h new file mode 120000 index 0000000..3f0b982 --- /dev/null +++ b/src/util/util-common.h @@ -0,0 +1 @@ +../common/util-common.h \ No newline at end of file -- 2.3.0
Add a configure test for a system library supplied strnlen, and disable the embedded version in common if one is found. Signed-off-by: Will Miles <wmiles@sgl.com> --- configure.ac | 4 ++-- src/common/util-common.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 735fdc3..359d61b 100644 --- a/configure.ac +++ b/configure.ac @@ -304,8 +304,8 @@ AC_FUNC_MKTIME AC_FUNC_STRCOLL AC_CHECK_FUNCS([dup2 getcwd getmntinfo gettimeofday memmove memset \ mkdir realpath regcomp rmdir setenv setlocale strcasecmp \ - strchr strcspn strdup strerror strndup strrchr strsep strstr \ - strtol swprintf tcflush wcwidth uname]) + strchr strcspn strdup strerror strndup strnlen strrchr \ + strsep strstr strtol swprintf tcflush wcwidth uname]) AC_CHECK_MEMBERS([struct stat.st_blksize],,,[[#include <sys/stat.h>]]) # For the diskspace code diff --git a/src/common/util-common.c b/src/common/util-common.c index f5b00f1..e834168 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -127,7 +127,7 @@ char *safe_fgets(char *s, int size, FILE *stream) return ret; } -#ifndef HAVE_STRNDUP +#ifndef HAVE_STRNLEN /* A quick and dirty implementation derived from glibc */ /** Determines the length of a fixed-size string. * @param s string to be measured @@ -140,7 +140,9 @@ static size_t strnlen(const char *s, size_t max) for(p = s; *p && max--; ++p); return (p - s); } +#endif +#ifndef HAVE_STRNDUP /** Copies a string. * Returned string needs to be freed * @param s string to be copied -- 2.3.0
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c Signed-off-by: Will Miles <wmiles@sgl.com> --- src/common/util-common.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++ src/common/util-common.h | 6 ++ 2 files changed, 231 insertions(+) diff --git a/src/common/util-common.c b/src/common/util-common.c index e834168..6c9b263 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -163,4 +163,229 @@ char *strndup(const char *s, size_t n) } #endif + +#ifndef HAVE_WCWIDTH +/* + * This is an implementation of wcwidth() and wcswidth() (defined in + * IEEE Std 1002.1-2001) for Unicode. + * + * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html + * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html + * + * In fixed-width output devices, Latin characters all occupy a single + * "cell" position of equal width, whereas ideographic CJK characters + * occupy two such cells. Interoperability between terminal-line + * applications and (teletype-style) character terminals using the + * UTF-8 encoding requires agreement on which character should advance + * the cursor by how many cell positions. No established formal + * standards exist at present on which Unicode character shall occupy + * how many cell positions on character terminals. These routines are + * a first attempt of defining such behavior based on simple rules + * applied to data provided by the Unicode Consortium. + * + * For some graphical characters, the Unicode standard explicitly + * defines a character-cell width via the definition of the East Asian + * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. + * In all these cases, there is no ambiguity about which width a + * terminal shall use. For characters in the East Asian Ambiguous (A) + * class, the width choice depends purely on a preference of backward + * compatibility with either historic CJK or Western practice. + * Choosing single-width for these characters is easy to justify as + * the appropriate long-term solution, as the CJK practice of + * displaying these characters as double-width comes from historic + * implementation simplicity (8-bit encoded characters were displayed + * single-width and 16-bit ones double-width, even for Greek, + * Cyrillic, etc.) and not any typographic considerations. + * + * Much less clear is the choice of width for the Not East Asian + * (Neutral) class. Existing practice does not dictate a width for any + * of these characters. It would nevertheless make sense + * typographically to allocate two character cells to characters such + * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be + * represented adequately with a single-width glyph. The following + * routines at present merely assign a single-cell width to all + * neutral characters, in the interest of simplicity. This is not + * entirely satisfactory and should be reconsidered before + * establishing a formal standard in this area. At the moment, the + * decision which Not East Asian (Neutral) characters should be + * represented by double-width glyphs cannot yet be answered by + * applying a simple rule from the Unicode database content. Setting + * up a proper standard for the behavior of UTF-8 character terminals + * will require a careful analysis not only of each Unicode character, + * but also of each presentation form, something the author of these + * routines has avoided to do so far. + * + * http://www.unicode.org/unicode/reports/tr11/ + * + * Markus Kuhn -- 2007-05-26 (Unicode 5.0) + * + * Permission to use, copy, modify, and distribute this software + * for any purpose and without fee is hereby granted. The author + * disclaims all warranties with regard to this software. + * + * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c + */ + +#include <wchar.h> + +struct interval +{ + int first; + int last; +}; + +/* auxiliary function for binary search in interval table */ +static int bisearch(wchar_t ucs, const struct interval *table, int max) +{ + int min = 0; + int mid; + + if(ucs < table[0].first || ucs > table[max].last) + return 0; + while(max >= min) { + mid = (min + max) / 2; + if(ucs > table[mid].last) + min = mid + 1; + else if(ucs < table[mid].first) + max = mid - 1; + else + return 1; + } + + return 0; +} + + +/* The following two functions define the column width of an ISO 10646 + * character as follows: + * + * - The null character (U+0000) has a column width of 0. + * + * - Other C0/C1 control characters and DEL will lead to a return + * value of -1. + * + * - Non-spacing and enclosing combining characters (general + * category code Mn or Me in the Unicode database) have a + * column width of 0. + * + * - SOFT HYPHEN (U+00AD) has a column width of 1. + * + * - Other format characters (general category code Cf in the Unicode + * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. + * + * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) + * have a column width of 0. + * + * - Spacing characters in the East Asian Wide (W) or East Asian + * Full-width (F) category as defined in Unicode Technical + * Report #11 have a column width of 2. + * + * - All remaining characters (including all printable + * ISO 8859-1 and WGL4 characters, Unicode control characters, + * etc.) have a column width of 1. + * + * This implementation assumes that wchar_t characters are encoded + * in ISO 10646. + */ + +int wcwidth(wchar_t ucs) +{ + /* sorted list of non-overlapping intervals of non-spacing characters + * generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" + */ + static const struct interval combining[] = { + { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, + { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, + { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, + { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, + { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, + { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, + { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, + { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, + { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, + { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, + { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, + { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, + { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, + { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, + { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, + { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, + { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, + { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, + { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, + { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, + { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, + { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, + { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, + { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, + { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, + { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, + { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, + { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, + { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, + { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, + { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, + { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, + { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, + { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, + { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, + { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, + { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, + { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, + { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, + { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, + { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, + { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, + { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, + { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, + { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, + { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, + { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, + { 0xE0100, 0xE01EF } + }; + + /* test for 8-bit control characters */ + if(ucs == 0) + return 0; + if(ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return -1; + + /* binary search in table of non-spacing characters */ + if(bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1) == 0) + return 0; + + /* if we arrive here, ucs is not a combining or C0/C1 control character */ + + return 1 + + (ucs >= 0x1100 && + (ucs <= 0x115f || /* Hangul Jamo init. consonants */ + ucs == 0x2329 || ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && + ucs != 0x303f) || /* CJK ... Yi */ + (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ + (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ + (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ + (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ + (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ + (ucs >= 0xffe0 && ucs <= 0xffe6) || + (ucs >= 0x20000 && ucs <= 0x2fffd) || + (ucs >= 0x30000 && ucs <= 0x3fffd))); +} + + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int w, width = 0; + + for(;*pwcs && n-- > 0; pwcs++) + if((w = wcwidth(*pwcs)) < 0) + return -1; + else + width += w; + + return width; +} +#endif /* HAVE_WCWIDTH */ + + /* vim: set noet: */ diff --git a/src/common/util-common.h b/src/common/util-common.h index a2093be..117486f 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -34,6 +34,12 @@ char *safe_fgets(char *s, int size, FILE *stream); char *strndup(const char *s, size_t n); #endif +#ifndef HAVE_WCWIDTH +int wcwidth(wchar_t ucs); +int wcswidth(const wchar_t *pwcs, size_t n); +#endif + + #endif /* _PM_UTIL_COMMON_H */ /* vim: set noet: */ -- 2.3.0
On 28/02/15 05:43, Will Miles wrote:
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
Signed-off-by: Will Miles <wmiles@sgl.com>
I don't intend to accept reimplementations of POSIX functions into pacman. I'm not even sure what system we supported that did not have strndup... Cygwin maybe? Check if gnulib provides all the needed functions. If so, that might be the root to take. Allan
On 28/02/15 06:24, Allan McRae wrote:
On 28/02/15 05:43, Will Miles wrote:
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
Signed-off-by: Will Miles <wmiles@sgl.com>
I don't intend to accept reimplementations of POSIX functions into pacman. I'm not even sure what system we supported that did not have strndup... Cygwin maybe?
Answering my own question - OSX.
Check if gnulib provides all the needed functions. If so, that might be the root to take.
Allan
Gnulib does indeed have the necessary bits for patches 3, 4, and 5. Consider them withdrawn, then, and I'll update my QNX build environment accordingly. -Will On 2/27/2015 3:27 PM, Allan McRae wrote:
On 28/02/15 06:24, Allan McRae wrote:
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
Signed-off-by: Will Miles <wmiles@sgl.com> I don't intend to accept reimplementations of POSIX functions into
On 28/02/15 05:43, Will Miles wrote: pacman. I'm not even sure what system we supported that did not have strndup... Cygwin maybe? Answering my own question - OSX.
Check if gnulib provides all the needed functions. If so, that might be the root to take.
Allan
From what I understand, if gnulib does work then we should add it as a git submodule and adjust our configure to use functions from there when necessary.
We can look into that further if you gnulib does lots of what you need. Thanks, Allan On 28/02/15 07:20, Will Miles wrote:
Gnulib does indeed have the necessary bits for patches 3, 4, and 5. Consider them withdrawn, then, and I'll update my QNX build environment accordingly.
-Will
On 2/27/2015 3:27 PM, Allan McRae wrote:
On 28/02/15 06:24, Allan McRae wrote:
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
Signed-off-by: Will Miles <wmiles@sgl.com> I don't intend to accept reimplementations of POSIX functions into
On 28/02/15 05:43, Will Miles wrote: pacman. I'm not even sure what system we supported that did not have strndup... Cygwin maybe? Answering my own question - OSX.
Check if gnulib provides all the needed functions. If so, that might be the root to take.
Allan
Hi Allan, Gnulib has solutions for patches 3, 4, and 5 (wcwidth/wcswidth, asprintf/vasprintf, and mkdtemp) - basically everything QNX is missing. A solution to embed gnulib would be very practical. I tried a simple build by following the gnulib instructions, but had some trouble getting it to build PIC for including mkdtemp in libalpm; unfortunately I got called away to another project before I could investigate further. If you have any specific tips for how best to perform the integration, I'd be very interested. Thanks, -Will On 2015-03-02 11:50 PM, Allan McRae wrote:
From what I understand, if gnulib does work then we should add it as a git submodule and adjust our configure to use functions from there when necessary.
We can look into that further if you gnulib does lots of what you need.
Thanks, Allan
On 28/02/15 07:20, Will Miles wrote:
Gnulib does indeed have the necessary bits for patches 3, 4, and 5. Consider them withdrawn, then, and I'll update my QNX build environment accordingly.
-Will
On 2/27/2015 3:27 PM, Allan McRae wrote:
On 28/02/15 06:24, Allan McRae wrote:
The specific implementation has been copied from Markus Kuhn at http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
Signed-off-by: Will Miles <wmiles@sgl.com> I don't intend to accept reimplementations of POSIX functions into
On 28/02/15 05:43, Will Miles wrote: pacman. I'm not even sure what system we supported that did not have strndup... Cygwin maybe? Answering my own question - OSX.
Check if gnulib provides all the needed functions. If so, that might be the root to take.
Allan
On 04/03/15 00:44, Will Miles wrote:
Hi Allan,
Gnulib has solutions for patches 3, 4, and 5 (wcwidth/wcswidth, asprintf/vasprintf, and mkdtemp) - basically everything QNX is missing. A solution to embed gnulib would be very practical. I tried a simple build by following the gnulib instructions, but had some trouble getting it to build PIC for including mkdtemp in libalpm; unfortunately I got called away to another project before I could investigate further. If you have any specific tips for how best to perform the integration, I'd be very interested.
I have only looked at using it once very long ago, so I can not help much here. I'm sure I could find someone in the wider Arch community to help us out if needed. Cheers, Allan
Signed-off-by: Will Miles <wmiles@sgl.com> --- configure.ac | 2 +- src/common/util-common.c | 27 +++++++++++++++++++++++++++ src/common/util-common.h | 7 +++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 359d61b..da1953e 100644 --- a/configure.ac +++ b/configure.ac @@ -302,7 +302,7 @@ AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK AC_FUNC_MALLOC AC_FUNC_MKTIME AC_FUNC_STRCOLL -AC_CHECK_FUNCS([dup2 getcwd getmntinfo gettimeofday memmove memset \ +AC_CHECK_FUNCS([asprintf dup2 getcwd getmntinfo gettimeofday memmove memset \ mkdir realpath regcomp rmdir setenv setlocale strcasecmp \ strchr strcspn strdup strerror strndup strnlen strrchr \ strsep strstr strtol swprintf tcflush wcwidth uname]) diff --git a/src/common/util-common.c b/src/common/util-common.c index 6c9b263..a7284a8 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -388,4 +388,31 @@ int wcswidth(const wchar_t *pwcs, size_t n) #endif /* HAVE_WCWIDTH */ +#ifndef HAVE_ASPRINTF +int asprintf(char **strp, const char *fmt, ...) +{ + int ret = 0; + va_list args; + + /* print the message using va_arg list */ + va_start(args, fmt); + ret = vasprintf(strp, fmt, args); + va_end(args); + return ret; +} + +int vasprintf(char **strp, const char *fmt, va_list ap) +{ + /* measure the string */ + int len = vsnprintf(NULL,0,fmt,ap); + /* try allocating some memory */ + if((len < 0) || ((*strp = malloc(++len)) == NULL)) return -1; + /* print the string */ + len = vsnprintf(*strp,len,fmt,ap); + /* handle failure */ + if(len < 0) free(*strp); + return len; +} +#endif /* HAVE_ASPRINTF */ + /* vim: set noet: */ diff --git a/src/common/util-common.h b/src/common/util-common.h index 117486f..ca1bc5d 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -22,6 +22,9 @@ #include <stdio.h> #include <sys/stat.h> /* struct stat */ +#ifndef HAVE_ASPRINTF +#include <stdarg.h> +#endif const char *mbasename(const char *path); char *mdirname(const char *path); @@ -39,6 +42,10 @@ int wcwidth(wchar_t ucs); int wcswidth(const wchar_t *pwcs, size_t n); #endif +#ifndef HAVE_ASPRINTF +int asprintf(char **strp, const char *fmt, ...) __attribute__((format(printf,2,3))); +int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__((format(printf,3,0))); +#endif #endif /* _PM_UTIL_COMMON_H */ -- 2.3.0
Signed-off-by: Will Miles <wmiles@sgl.com> --- configure.ac | 6 +++--- lib/libalpm/trans.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index da1953e..0a1ef44 100644 --- a/configure.ac +++ b/configure.ac @@ -303,9 +303,9 @@ AC_FUNC_MALLOC AC_FUNC_MKTIME AC_FUNC_STRCOLL AC_CHECK_FUNCS([asprintf dup2 getcwd getmntinfo gettimeofday memmove memset \ - mkdir realpath regcomp rmdir setenv setlocale strcasecmp \ - strchr strcspn strdup strerror strndup strnlen strrchr \ - strsep strstr strtol swprintf tcflush wcwidth uname]) + mkdir mkdtemp realpath regcomp rmdir setenv setlocale \ + strcasecmp strchr strcspn strdup strerror strndup strnlen \ + strrchr strsep strstr strtol swprintf tcflush wcwidth uname]) AC_CHECK_MEMBERS([struct stat.st_blksize],,,[[#include <sys/stat.h>]]) # For the diskspace code diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 6a26e75..b3f6044 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -41,6 +41,41 @@ #include "alpm.h" #include "deps.h" +#ifndef HAVE_MKDTEMP +/* supply a workaround implementation of mkdtemp as the system does not */ +static char *mkdtemp(char *templateName) +{ + static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + const int length = strlen(templateName); + char *XXXXXX = templateName + length - 6; + + if((length < 6) || (strncmp(XXXXXX, "XXXXXX", 6) != 0)) + return 0; + + for(int i = 0; i < 256; ++i) { + int v = rand(); + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + if(mkdir(templateName, 0700) == 0) + return templateName; + } + + return 0; +} +#endif + /** \addtogroup alpm_trans Transaction Functions * @brief Functions to manipulate libalpm transactions * @{ -- 2.3.0
Signed-off-by: Will Miles <wmiles@sgl.com> --- lib/libalpm/diskspace.c | 37 ++++++++++++++++++++++++++ lib/libalpm/util.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/pacman.c | 4 +++ 3 files changed, 110 insertions(+) diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 3b496c2..4bd1821 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -119,6 +119,43 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle) } endmntent(fp); +#elif defined(__QNX__) + /* QNX + * This is done the long way via a system command + * TODO: walk /proc/mount + */ + char buffer[_POSIX_PATH_MAX]; + FILE *cmd = popen("mount | cut -d ' ' -f 3", "r"); + struct statvfs fsp; + + if(cmd == NULL) { + _alpm_log(handle, ALPM_LOG_WARNING, "Failed to get mount list: %s", strerror(errno)); + return NULL; + } + + memset(buffer, '\0', _POSIX_PATH_MAX); + + while(fgets(buffer, _POSIX_PATH_MAX-1, cmd)) { + /* eat trailing newline */ + buffer[strlen(buffer) - 1] = '\0'; + + if(statvfs(buffer, &fsp) != 0) { + _alpm_log(handle, ALPM_LOG_WARNING, + _("could not get filesystem information for %s: %s\n"), + buffer, strerror(errno)); + continue; + } + + CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + mp->mount_dir = strdup(buffer); + mp->mount_dir_len = strlen(mp->mount_dir); + memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs)); + mp->read_only = fsp.f_flag & ST_RDONLY; + + mount_points = alpm_list_add(mount_points, mp); + } + + pclose(cmd); #elif defined(HAVE_GETMNTENT) && defined(HAVE_MNTTAB_H) /* Solaris, Illumos */ struct mnttab mnt; diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 4d85132..6b75cfa 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -89,6 +89,69 @@ char *strsep(char **str, const char *delims) } #endif +#ifdef __QNX__ +/** QNX execv workaround + * On QNX, we must ensure that the loader is present and the pipe server is + * started in our chroot environment. This function ensures that these + * services are correctly set up and torn down. + */ +int qnx_execv(const char *cmd, char *const argv[]) +{ + int result; + int linked_loader = 0; + int started_pipe_server = 0; + struct stat stat_tmp; + + /* Check to see if the loader exists; if not, link it */ + if(stat("/usr/lib/ldqnx.so.2", &stat_tmp) != 0) { + result = link("/lib/libc.so.3","/usr/lib/ldqnx.so.2"); + if(result != 0) { + fprintf(stderr, _("call to link loader failed (%s)\n"), strerror(errno)); + exit(1); + } + linked_loader = 1; + } + + /* Check to see if the pipe server is running; if not, start it + * Be aware that this clones the pipe fds to the pipe server, ie it is not 'fully' daemonized + * This means that the pacman host process will hang until the pipe server is terminated. + */ + if(stat("/dev/pipe", &stat_tmp) != 0) { + started_pipe_server = spawnl(P_NOWAIT,"/sbin/pipe","pipe",NULL); + if(started_pipe_server == -1) { + fprintf(stderr, _("call to start pipe server failed (%s)\n"), strerror(errno)); + if(linked_loader) { + unlink("/usr/lib/ldqnx.so.2"); + } + exit(-1); + } + } + + /* Run the program, collect the result */ + result = spawnv(P_WAIT,cmd,argv); + if(result == -1) { + result = -errno; + } else { + result = WEXITSTATUS(result); + } + + /* Clean up */ + if(started_pipe_server) { + kill(started_pipe_server, SIGTERM); + } + if(linked_loader) { + unlink("/usr/lib/ldqnx.so.2"); + } + + if(result < 0) { + fprintf(stderr, _("call to spawnv failed (%s)\n"), strerror(-result)); + exit(1); + } else { + exit(result); + } +} +#endif + int _alpm_makepath(const char *path) { return _alpm_makepath_mode(path, 0755); @@ -557,10 +620,16 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]) exit(1); } umask(0022); + +#ifdef __QNX__ + /* never returns */ + qnx_execv(cmd, argv); +#else execv(cmd, argv); /* execv only returns if there was an error */ fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno)); exit(1); +#endif } else { /* this code runs for the parent only (wait on the child) */ int status; diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index fce0131..a419416 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1058,7 +1058,11 @@ int main(int argc, char *argv[]) /* Set up the structure to specify the new action. */ new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); +#ifdef __QNX__ + new_action.sa_flags = 0; +#else new_action.sa_flags = SA_RESTART; +#endif /* assign our handler to any signals we care about */ for(i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) { -- 2.3.0
participants (2)
-
Allan McRae
-
Will Miles