Re: [pacman-dev] [PATCH] Replace CURLOPT_PROGRESSFUNCTION with CURLOPT_XFERINFOFUNCTION

2016-08-31 Thread Will Miles

On 2016-08-30 11:01 PM, Allan McRae wrote:


OK.   I don't think pacman is used anywhere where curl older than August
2013 is an issue...

Allan

I guess I'm the exception that proves the rule -- I'm using pacman on 
QNX 6.6, which ships with libcurl 7.24.0 from Jan 2012.Alas, RTOS 
folks are notoriously conservative thanks to long certification processes.


That said, I would still endorse this patch; it's no big deal for me to 
arrange to build an updated curl for our platform, now that I have 
pacman to manage its deployment. :)


-Will


[pacman-dev] [PATCH v2] Fix handling of unavailable backup hashes

2016-04-11 Thread Will Miles
This patch fixes several places where an unavailable (NULL) backup hash may be
passed to a printf() call, which segfaults on some libcs.  This includes
local database writes where unavailable hashes are represented by the file
name only.  This condition may occur when an updated package changes the
contents of its backup=() list.

Signed-off-by: Will Miles <wmi...@sgl.com>
---
 lib/libalpm/add.c  | 6 +++---
 lib/libalpm/be_local.c | 6 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f5c9a95..629e2a5 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -339,9 +339,9 @@ static int extract_single_file(alpm_handle_t *handle, 
struct archive *archive,
hash_pkg = backup ? backup->hash : 
alpm_compute_md5sum(filename);
 
_alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", 
origfile);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", hash_local);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", hash_pkg);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
+   _alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", (hash_local 
? hash_local : "NULL") );
+   _alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", (hash_pkg ? 
hash_pkg : "NULL") );
+   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", (hash_orig 
? hash_orig : "NULL") );
 
if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) 
{
/* local and new files are the same, updating anyway to 
get
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index f817822..21166cb 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1037,7 +1037,11 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t 
*info, alpm_dbinfrq_t inforeq
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
-   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   if (backup->hash) {
+   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   } else {
+   fprintf(fp, "%s\n", backup->name);
+   }
}
fputc('\n', fp);
}
-- 
2.6.3


Re: [pacman-dev] [PATCH] Fix segfault during install when a package update adds a new file to 'backup'

2016-04-05 Thread Will Miles

On 2016-04-05 12:13 AM, Andrew Gregory wrote:

On 04/01/16 at 10:52am, Will Miles wrote:

When a new package release adds a new entry to the backup list, no hash exists
for that file in the previously installed package version.  Fix two places
where that nonexistent hash may be dereferenced.

Signed-off-by: Will Miles <wmi...@sgl.com>
---
  lib/libalpm/add.c  | 2 +-
  lib/libalpm/be_local.c | 4 +++-
  2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f5c9a95..ff0b81d 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -341,7 +341,7 @@ static int extract_single_file(alpm_handle_t *handle, 
struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", 
origfile);
_alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", hash_local);
_alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", hash_pkg);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
+   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", (hash_orig ? 
hash_orig : "NULL") );

All of these hashed can potentially be NULL if we encounter an error
when reading the file.  This check should be applied to all of them.


OK.   For n=3, would you prefer an inline function or a macro?




if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) 
{
/* local and new files are the same, updating anyway to 
get
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index f817822..5e39199 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1037,7 +1037,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, 
alpm_dbinfrq_t inforeq
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
-   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   if (backup->hash) {
+   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   }

We should still add these entries to the database even if we don't
have hashes for them.  Just skip printing the hash itself (or replace
it with an empty string) if it's NULL.


OK.  I'll review the read hash operation to make sure it handles reading 
an empty string as a non-error as well.





}
fputc('\n', fp);
}
--
2.6.3


Re: [pacman-dev] [PATCH] Fix segfault during install when a package update adds a new file to 'backup'

2016-04-04 Thread Will Miles

On 2016-04-02 2:55 AM, Allan McRae wrote:

On 02/04/16 00:52, Will Miles wrote:

When a new package release adds a new entry to the backup list, no hash exists
for that file in the previously installed package version.  Fix two places
where that nonexistent hash may be dereferenced.

Signed-off-by: Will Miles <wmi...@sgl.com>
---

Just as a query, where are you seeing these non-existent backup hashes?
  Corrupt local databases?



I ran in to it when I had a case where I was upgrading a package that 
had a new file added to the backup list.   Something like these PKGBUILD 
fragments:


pkgname=example
pkgver=3.2.0
backup=( 'etc/example.conf' )

getting upgraded to:

pkgname=example
pkgver=4.0.0
backup=( 'etc/example.conf' 'etc/example_auth.conf' )

When the upgrade install is running, there's no hash for 
'etc/example_auth.conf' in the database yet.   I think that's the 
expected behaviour, though, and it seems to be handled correctly 
everywhere except these two places where passing the NULL into printf() 
broke QNX's libc.   We ran into it while developing PKGBUILDs for some 
of our internal software.


-Will




  lib/libalpm/add.c  | 2 +-
  lib/libalpm/be_local.c | 4 +++-
  2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f5c9a95..ff0b81d 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -341,7 +341,7 @@ static int extract_single_file(alpm_handle_t *handle, 
struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", 
origfile);
_alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", hash_local);
_alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", hash_pkg);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
+   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", (hash_orig ? 
hash_orig : "NULL") );
  

Fine - I guess this is needed for non-glibc systems.


if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) 
{
/* local and new files are the same, updating anyway to 
get
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index f817822..5e39199 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1037,7 +1037,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, 
alpm_dbinfrq_t inforeq
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
-   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   if (backup->hash) {
+   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   }

How can this ever happen?


}
fputc('\n', fp);
}



[pacman-dev] [PATCH] Fix segfault during install when a package update adds a new file to 'backup'

2016-04-01 Thread Will Miles
When a new package release adds a new entry to the backup list, no hash exists
for that file in the previously installed package version.  Fix two places
where that nonexistent hash may be dereferenced.

Signed-off-by: Will Miles <wmi...@sgl.com>
---
 lib/libalpm/add.c  | 2 +-
 lib/libalpm/be_local.c | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f5c9a95..ff0b81d 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -341,7 +341,7 @@ static int extract_single_file(alpm_handle_t *handle, 
struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", 
origfile);
_alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", hash_local);
_alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", hash_pkg);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
+   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", (hash_orig 
? hash_orig : "NULL") );
 
if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) 
{
/* local and new files are the same, updating anyway to 
get
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index f817822..5e39199 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1037,7 +1037,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, 
alpm_dbinfrq_t inforeq
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
-   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   if (backup->hash) {
+   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   }
}
fputc('\n', fp);
}
-- 
2.6.3


[pacman-dev] [PATCH] Fix segfaults during install when a package adds a new file to 'backup'

2016-02-29 Thread Will Miles
When adding a new package release adds a new entry to the 'backup' list, no
hash exists for that file in the previously installed package version.
This patch fixes two places where that nonexistent hash may be dereferenced.

Signed-off-by: Will Miles <wmi...@sgl.com>
---
 lib/libalpm/add.c  | 2 +-
 lib/libalpm/be_local.c | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f5c9a95..ff0b81d 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -341,7 +341,7 @@ static int extract_single_file(alpm_handle_t *handle, 
struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", 
origfile);
_alpm_log(handle, ALPM_LOG_DEBUG, "current:  %s\n", hash_local);
_alpm_log(handle, ALPM_LOG_DEBUG, "new:  %s\n", hash_pkg);
-   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
+   _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", (hash_orig 
? hash_orig : "NULL") );
 
if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) 
{
/* local and new files are the same, updating anyway to 
get
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index f817822..5e39199 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1037,7 +1037,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, 
alpm_dbinfrq_t inforeq
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
-   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   if (backup->hash) {
+   fprintf(fp, "%s\t%s\n", backup->name, 
backup->hash);
+   }
}
fputc('\n', fp);
}
-- 
2.6.3


Re: [pacman-dev] [PATCH 3/6] common: Add support for wcwidth and wcswidth for systems without.

2015-03-03 Thread Will Miles

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:

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 wmi...@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






[pacman-dev] [PATCH 2/6] common: Avoid errors on systems that define strnlen but not strndup

2015-02-27 Thread Will Miles
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 wmi...@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


[pacman-dev] [PATCH 6/6] Add QNX operating system specific implementations to libalpm and pacman.

2015-02-27 Thread Will Miles
Signed-off-by: Will Miles wmi...@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

[pacman-dev] [PATCH 3/6] common: Add support for wcwidth and wcswidth for systems without.

2015-02-27 Thread Will Miles
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 wmi...@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+) 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

[pacman-dev] QNX patches, v2

2015-02-27 Thread Will Miles
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.


[pacman-dev] [PATCH 4/6] common: Add support for systems without asprintf/vasprintf.

2015-02-27 Thread Will Miles
Signed-off-by: Will Miles wmi...@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


[pacman-dev] [PATCH 1/6] util: Use util-common for strndup in pacsort and pactree

2015-02-27 Thread Will Miles
This small refactor reduces the number of replications of the local
imeplementation of strndup.

Signed-off-by: Will Miles wmi...@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 12 src/util/util-common.c
 create mode 12 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 12
index 000..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 12
index 000..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


Re: [pacman-dev] [PATCH 3/6] common: Add support for wcwidth and wcswidth for systems without.

2015-02-27 Thread Will Miles
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:

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 wmi...@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




[pacman-dev] [PATCH 4/5] common: Add support for systems without asprintf/vasprintf.

2015-02-26 Thread Will Miles
Signed-off-by: Will Miles wmi...@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 e977550..d7ef08b 100644
--- a/src/common/util-common.c
+++ b/src/common/util-common.c
@@ -305,4 +305,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


[pacman-dev] Patches for QNX support

2015-02-26 Thread Will Miles
This patch set adds support for the QNX RTOS.  The first four patches
are essentially workarounds for QNX's libc; the last patch implements the
QNX-specific sections in libalpm.


[pacman-dev] [PATCH 5/5] Add QNX operating system specific implementations to libalpm and pacman.

2015-02-26 Thread Will Miles
Signed-off-by: Will Miles wmi...@sgl.com
---
 lib/libalpm/diskspace.c | 38 +++
 lib/libalpm/trans.c | 37 +++
 lib/libalpm/util.c  | 68 +
 src/pacman/pacman.c |  4 +++
 4 files changed, 147 insertions(+)

diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 3b496c2..5142d05 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -119,6 +119,44 @@ 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: use the /proc calls directly */
+   char buffer[_POSIX_PATH_MAX];
+   FILE *cmd = popen(mount | cut -d ' ' -f 3, r);
+
+   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)) {
+   struct statvfs fsp;
+
+   /* 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/trans.c b/lib/libalpm/trans.c
index 6a26e75..1c8196c 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -41,6 +41,43 @@
 #include alpm.h
 #include deps.h
 
+#ifdef __QNX__
+/* 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 *XX = templateName + length - 6;
+
+   if ((length  6) || strncmp(XX, XX, 6))
+   return 0;
+
+   for (int i = 0; i  256; ++i) {
+   int v = rand();
+
+   /* Fill in the random bits.  */
+   XX[0] = letters[v % 62];
+   v /= 62;
+   XX[1] = letters[v % 62];
+   v /= 62;
+   XX[2] = letters[v % 62];
+   v /= 62;
+   XX[3] = letters[v % 62];
+   v /= 62;
+   XX[4] = letters[v % 62];
+   v /= 62;
+   XX[5] = letters[v % 62];
+
+   if (!mkdir(templateName, 0700))
+   return templateName;
+   }
+
+   return 0;
+}
+#endif
+
 /** \addtogroup alpm_trans Transaction Functions
  * @brief Functions to manipulate libalpm transactions
  * @{
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 4d85132..5e246df 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -89,6 +89,68 @@ 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

[pacman-dev] [PATCH 2/5] common: Avoid errors on systems that define strnlen but not strndup

2015-02-26 Thread Will Miles
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 wmi...@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


[pacman-dev] [PATCH 1/5] util: Use util-common for strndup in pacsort and pactree

2015-02-26 Thread Will Miles
This small refactor reduces the number of replications of the local
imeplementation of strndup.

Signed-off-by: Will Miles wmi...@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 12 src/util/util-common.c
 create mode 12 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 12
index 000..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 12
index 000..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


[pacman-dev] [PATCH 3/5] common: Add support for wcwidth and wcswidth for systems without.

2015-02-26 Thread Will Miles
The specific implementation has been borrowed from glibc-2.21.

Signed-off-by: Will Miles wmi...@sgl.com
---
 src/common/util-common.c | 142 +++
 src/common/util-common.h |   6 ++
 2 files changed, 148 insertions(+)

diff --git a/src/common/util-common.c b/src/common/util-common.c
index e834168..e977550 100644
--- a/src/common/util-common.c
+++ b/src/common/util-common.c
@@ -163,4 +163,146 @@ char *strndup(const char *s, size_t n)
 }
 #endif
 
+
+#ifndef HAVE_WCWIDTH
+/* Implementation derived from glibc. */
+
+struct interval {
+   unsigned short first;
+   unsigned short 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 functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ *- The null character (U+) 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.
+ *
+ *- 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
+ *  FullWidth (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 */
+   static const struct interval combining[] = {
+   { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
+   { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
+   { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+   { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
+   { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+   { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+   { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
+   { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
+   { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
+   { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
+   { 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
+   { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
+   { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
+   { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 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 },
+   { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+   { 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 }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },
+   { 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },
+   { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },
+   { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
+   { 0xFB1E, 0xFB1E