Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge remote-tracking branch 'origin/master' into periodic
Alex Kozlov committed 13 years ago
commit 677d1b3cf807360087a9d8fbbe2497c8c4b6b0f5
parent 4ea7a48
68 files changed +2263 -1546
modified AUTHORS
@@ -17,3 +17,4 @@ Brad Davis <brd@FreeBSD.org>
Matthew Seaman <matthew@FreeBSD.org>
Bryan Drewery <bryan@shatow.net>
Eitan Adler <eadler@FreeBSD.org>
+
Romain Tartière <romain@FreeBSD.org>
modified external/uthash/uthash.h
@@ -1,5 +1,5 @@
/*
-
Copyright (c) 2003-2012, Troy D. Hanson     http://uthash.sourceforge.net
+
Copyright (c) 2003-2013, Troy D. Hanson     http://uthash.sourceforge.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,7 @@ typedef unsigned char uint8_t;
#include <inttypes.h>   /* uint32_t */
#endif

-
#define UTHASH_VERSION 1.9.6
+
#define UTHASH_VERSION 1.9.7

#ifndef uthash_fatal
#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
@@ -215,7 +215,7 @@ do {
        _hd_hh_del = &((delptr)->hh);                                            \
        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
            (head)->hh.tbl->tail =                                               \
-
                (UT_hash_handle*)((ptrdiff_t*)((delptr)->hh.prev) +              \
+
                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
                (head)->hh.tbl->hho);                                            \
        }                                                                        \
        if ((delptr)->hh.prev) {                                                 \
@@ -502,7 +502,7 @@ do {
 *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
 *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
 */
-
#if (defined(__i386__) || defined(__x86_64__)) 
+
#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))
#define MUR_GETBLOCK(p,i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
@@ -541,10 +541,12 @@ do { \
  uint32_t _mur_h1 = 0xf88D5353;                                       \
  uint32_t _mur_c1 = 0xcc9e2d51;                                       \
  uint32_t _mur_c2 = 0x1b873593;                                       \
+
  uint32_t _mur_k1 = 0;                                                \
+
  const uint8_t *_mur_tail;                                            \
  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
  int _mur_i;                                                          \
  for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
-
    uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);               \
+
    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \
    _mur_k1 *= _mur_c1;                                                \
    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
    _mur_k1 *= _mur_c2;                                                \
@@ -553,8 +555,8 @@ do { \
    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
    _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
  }                                                                    \
-
  const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
-
  uint32_t _mur_k1=0;                                                  \
+
  _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4);            \
+
  _mur_k1=0;                                                           \
  switch((keylen) & 3) {                                               \
    case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
    case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
added external/uthash/utlist.h
@@ -0,0 +1,733 @@
+
/*
+
Copyright (c) 2007-2013, Troy D. Hanson   http://uthash.sourceforge.net
+
All rights reserved.
+

+
Redistribution and use in source and binary forms, with or without
+
modification, are permitted provided that the following conditions are met:
+

+
    * Redistributions of source code must retain the above copyright
+
      notice, this list of conditions and the following disclaimer.
+

+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
*/
+

+
#ifndef UTLIST_H
+
#define UTLIST_H
+

+
#define UTLIST_VERSION 1.9.7
+

+
#include <assert.h>
+

+
/* 
+
 * This file contains macros to manipulate singly and doubly-linked lists.
+
 *
+
 * 1. LL_ macros:  singly-linked lists.
+
 * 2. DL_ macros:  doubly-linked lists.
+
 * 3. CDL_ macros: circular doubly-linked lists.
+
 *
+
 * To use singly-linked lists, your structure must have a "next" pointer.
+
 * To use doubly-linked lists, your structure must "prev" and "next" pointers.
+
 * Either way, the pointer to the head of the list must be initialized to NULL.
+
 * 
+
 * ----------------.EXAMPLE -------------------------
+
 * struct item {
+
 *      int id;
+
 *      struct item *prev, *next;
+
 * }
+
 *
+
 * struct item *list = NULL:
+
 *
+
 * int main() {
+
 *      struct item *item;
+
 *      ... allocate and populate item ...
+
 *      DL_APPEND(list, item);
+
 * }
+
 * --------------------------------------------------
+
 *
+
 * For doubly-linked lists, the append and delete macros are O(1)
+
 * For singly-linked lists, append and delete are O(n) but prepend is O(1)
+
 * The sort macro is O(n log(n)) for all types of single/double/circular lists.
+
 */
+

+
/* These macros use decltype or the earlier __typeof GNU extension.
+
   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+
   when compiling c++ code), this code uses whatever method is needed
+
   or, for VS2008 where neither is available, uses casting workarounds. */
+
#ifdef _MSC_VER            /* MS compiler */
+
#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
+
#define LDECLTYPE(x) decltype(x)
+
#else                     /* VS2008 or older (or VS2010 in C mode) */
+
#define NO_DECLTYPE
+
#define LDECLTYPE(x) char*
+
#endif
+
#else                      /* GNU, Sun and other compilers */
+
#define LDECLTYPE(x) __typeof(x)
+
#endif
+

+
/* for VS2008 we use some workarounds to get around the lack of decltype,
+
 * namely, we always reassign our tmp variable to the list head if we need
+
 * to dereference its prev/next pointers, and save/restore the real head.*/
+
#ifdef NO_DECLTYPE
+
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
+
#define _NEXT(elt,list,next) ((char*)((list)->next))
+
#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
+
/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
+
#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
+
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
+
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
+
#else 
+
#define _SV(elt,list)
+
#define _NEXT(elt,list,next) ((elt)->next)
+
#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
+
/* #define _PREV(elt,list,prev) ((elt)->prev) */
+
#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
+
#define _RS(list)
+
#define _CASTASGN(a,b) (a)=(b)
+
#endif
+

+
/******************************************************************************
+
 * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort    *
+
 * Unwieldy variable names used here to avoid shadowing passed-in variables.  *
+
 *****************************************************************************/
+
#define LL_SORT(list, cmp)                                                                     \
+
    LL_SORT2(list, cmp, next)
+

+
#define LL_SORT2(list, cmp, next)                                                              \
+
do {                                                                                           \
+
  LDECLTYPE(list) _ls_p;                                                                       \
+
  LDECLTYPE(list) _ls_q;                                                                       \
+
  LDECLTYPE(list) _ls_e;                                                                       \
+
  LDECLTYPE(list) _ls_tail;                                                                    \
+
  LDECLTYPE(list) _ls_oldhead;                                                                 \
+
  LDECLTYPE(list) _tmp;                                                                        \
+
  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
+
  if (list) {                                                                                  \
+
    _ls_insize = 1;                                                                            \
+
    _ls_looping = 1;                                                                           \
+
    while (_ls_looping) {                                                                      \
+
      _CASTASGN(_ls_p,list);                                                                   \
+
      _CASTASGN(_ls_oldhead,list);                                                             \
+
      list = NULL;                                                                             \
+
      _ls_tail = NULL;                                                                         \
+
      _ls_nmerges = 0;                                                                         \
+
      while (_ls_p) {                                                                          \
+
        _ls_nmerges++;                                                                         \
+
        _ls_q = _ls_p;                                                                         \
+
        _ls_psize = 0;                                                                         \
+
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
+
          _ls_psize++;                                                                         \
+
          _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
+
          if (!_ls_q) break;                                                                   \
+
        }                                                                                      \
+
        _ls_qsize = _ls_insize;                                                                \
+
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
+
          if (_ls_psize == 0) {                                                                \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
          } else {                                                                             \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
          }                                                                                    \
+
          if (_ls_tail) {                                                                      \
+
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
          } else {                                                                             \
+
            _CASTASGN(list,_ls_e);                                                             \
+
          }                                                                                    \
+
          _ls_tail = _ls_e;                                                                    \
+
        }                                                                                      \
+
        _ls_p = _ls_q;                                                                         \
+
      }                                                                                        \
+
      _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                       \
+
      if (_ls_nmerges <= 1) {                                                                  \
+
        _ls_looping=0;                                                                         \
+
      }                                                                                        \
+
      _ls_insize *= 2;                                                                         \
+
    }                                                                                          \
+
  } else _tmp=NULL; /* quiet gcc unused variable warning */                                    \
+
} while (0)
+

+

+
#define DL_SORT(list, cmp)                                                                     \
+
    DL_SORT2(list, cmp, prev, next)
+

+
#define DL_SORT2(list, cmp, prev, next)                                                        \
+
do {                                                                                           \
+
  LDECLTYPE(list) _ls_p;                                                                       \
+
  LDECLTYPE(list) _ls_q;                                                                       \
+
  LDECLTYPE(list) _ls_e;                                                                       \
+
  LDECLTYPE(list) _ls_tail;                                                                    \
+
  LDECLTYPE(list) _ls_oldhead;                                                                 \
+
  LDECLTYPE(list) _tmp;                                                                        \
+
  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
+
  if (list) {                                                                                  \
+
    _ls_insize = 1;                                                                            \
+
    _ls_looping = 1;                                                                           \
+
    while (_ls_looping) {                                                                      \
+
      _CASTASGN(_ls_p,list);                                                                   \
+
      _CASTASGN(_ls_oldhead,list);                                                             \
+
      list = NULL;                                                                             \
+
      _ls_tail = NULL;                                                                         \
+
      _ls_nmerges = 0;                                                                         \
+
      while (_ls_p) {                                                                          \
+
        _ls_nmerges++;                                                                         \
+
        _ls_q = _ls_p;                                                                         \
+
        _ls_psize = 0;                                                                         \
+
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
+
          _ls_psize++;                                                                         \
+
          _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
+
          if (!_ls_q) break;                                                                   \
+
        }                                                                                      \
+
        _ls_qsize = _ls_insize;                                                                \
+
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
+
          if (_ls_psize == 0) {                                                                \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
          } else {                                                                             \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
          }                                                                                    \
+
          if (_ls_tail) {                                                                      \
+
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
          } else {                                                                             \
+
            _CASTASGN(list,_ls_e);                                                             \
+
          }                                                                                    \
+
          _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
+
          _ls_tail = _ls_e;                                                                    \
+
        }                                                                                      \
+
        _ls_p = _ls_q;                                                                         \
+
      }                                                                                        \
+
      _CASTASGN(list->prev, _ls_tail);                                                         \
+
      _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                       \
+
      if (_ls_nmerges <= 1) {                                                                  \
+
        _ls_looping=0;                                                                         \
+
      }                                                                                        \
+
      _ls_insize *= 2;                                                                         \
+
    }                                                                                          \
+
  } else _tmp=NULL; /* quiet gcc unused variable warning */                                    \
+
} while (0)
+

+
#define CDL_SORT(list, cmp)                                                                    \
+
    CDL_SORT2(list, cmp, prev, next)
+

+
#define CDL_SORT2(list, cmp, prev, next)                                                       \
+
do {                                                                                           \
+
  LDECLTYPE(list) _ls_p;                                                                       \
+
  LDECLTYPE(list) _ls_q;                                                                       \
+
  LDECLTYPE(list) _ls_e;                                                                       \
+
  LDECLTYPE(list) _ls_tail;                                                                    \
+
  LDECLTYPE(list) _ls_oldhead;                                                                 \
+
  LDECLTYPE(list) _tmp;                                                                        \
+
  LDECLTYPE(list) _tmp2;                                                                       \
+
  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
+
  if (list) {                                                                                  \
+
    _ls_insize = 1;                                                                            \
+
    _ls_looping = 1;                                                                           \
+
    while (_ls_looping) {                                                                      \
+
      _CASTASGN(_ls_p,list);                                                                   \
+
      _CASTASGN(_ls_oldhead,list);                                                             \
+
      list = NULL;                                                                             \
+
      _ls_tail = NULL;                                                                         \
+
      _ls_nmerges = 0;                                                                         \
+
      while (_ls_p) {                                                                          \
+
        _ls_nmerges++;                                                                         \
+
        _ls_q = _ls_p;                                                                         \
+
        _ls_psize = 0;                                                                         \
+
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
+
          _ls_psize++;                                                                         \
+
          _SV(_ls_q,list);                                                                     \
+
          if (_NEXT(_ls_q,list,next) == _ls_oldhead) {                                         \
+
            _ls_q = NULL;                                                                      \
+
          } else {                                                                             \
+
            _ls_q = _NEXT(_ls_q,list,next);                                                    \
+
          }                                                                                    \
+
          _RS(list);                                                                           \
+
          if (!_ls_q) break;                                                                   \
+
        }                                                                                      \
+
        _ls_qsize = _ls_insize;                                                                \
+
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
+
          if (_ls_psize == 0) {                                                                \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
+
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
+
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
+
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
+
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
+
          } else {                                                                             \
+
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
+
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
+
          }                                                                                    \
+
          if (_ls_tail) {                                                                      \
+
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
          } else {                                                                             \
+
            _CASTASGN(list,_ls_e);                                                             \
+
          }                                                                                    \
+
          _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
+
          _ls_tail = _ls_e;                                                                    \
+
        }                                                                                      \
+
        _ls_p = _ls_q;                                                                         \
+
      }                                                                                        \
+
      _CASTASGN(list->prev,_ls_tail);                                                          \
+
      _CASTASGN(_tmp2,list);                                                                   \
+
      _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2,next); _RS(list);                      \
+
      if (_ls_nmerges <= 1) {                                                                  \
+
        _ls_looping=0;                                                                         \
+
      }                                                                                        \
+
      _ls_insize *= 2;                                                                         \
+
    }                                                                                          \
+
  } else _tmp=NULL; /* quiet gcc unused variable warning */                                    \
+
} while (0)
+

+
/******************************************************************************
+
 * singly linked list macros (non-circular)                                   *
+
 *****************************************************************************/
+
#define LL_PREPEND(head,add)                                                                   \
+
    LL_PREPEND2(head,add,next)
+

+
#define LL_PREPEND2(head,add,next)                                                             \
+
do {                                                                                           \
+
  (add)->next = head;                                                                          \
+
  head = add;                                                                                  \
+
} while (0)
+

+
#define LL_CONCAT(head1,head2)                                                                 \
+
    LL_CONCAT2(head1,head2,next)
+

+
#define LL_CONCAT2(head1,head2,next)                                                           \
+
do {                                                                                           \
+
  LDECLTYPE(head1) _tmp;                                                                       \
+
  if (head1) {                                                                                 \
+
    _tmp = head1;                                                                              \
+
    while (_tmp->next) { _tmp = _tmp->next; }                                                  \
+
    _tmp->next=(head2);                                                                        \
+
  } else {                                                                                     \
+
    (head1)=(head2);                                                                           \
+
  }                                                                                            \
+
} while (0)
+

+
#define LL_APPEND(head,add)                                                                    \
+
    LL_APPEND2(head,add,next)
+

+
#define LL_APPEND2(head,add,next)                                                              \
+
do {                                                                                           \
+
  LDECLTYPE(head) _tmp;                                                                        \
+
  (add)->next=NULL;                                                                            \
+
  if (head) {                                                                                  \
+
    _tmp = head;                                                                               \
+
    while (_tmp->next) { _tmp = _tmp->next; }                                                  \
+
    _tmp->next=(add);                                                                          \
+
  } else {                                                                                     \
+
    (head)=(add);                                                                              \
+
  }                                                                                            \
+
} while (0)
+

+
#define LL_DELETE(head,del)                                                                    \
+
    LL_DELETE2(head,del,next)
+

+
#define LL_DELETE2(head,del,next)                                                              \
+
do {                                                                                           \
+
  LDECLTYPE(head) _tmp;                                                                        \
+
  if ((head) == (del)) {                                                                       \
+
    (head)=(head)->next;                                                                       \
+
  } else {                                                                                     \
+
    _tmp = head;                                                                               \
+
    while (_tmp->next && (_tmp->next != (del))) {                                              \
+
      _tmp = _tmp->next;                                                                       \
+
    }                                                                                          \
+
    if (_tmp->next) {                                                                          \
+
      _tmp->next = ((del)->next);                                                              \
+
    }                                                                                          \
+
  }                                                                                            \
+
} while (0)
+

+
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
+
#define LL_APPEND_VS2008(head,add)                                                             \
+
    LL_APPEND2_VS2008(head,add,next)
+

+
#define LL_APPEND2_VS2008(head,add,next)                                                       \
+
do {                                                                                           \
+
  if (head) {                                                                                  \
+
    (add)->next = head;     /* use add->next as a temp variable */                             \
+
    while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
+
    (add)->next->next=(add);                                                                   \
+
  } else {                                                                                     \
+
    (head)=(add);                                                                              \
+
  }                                                                                            \
+
  (add)->next=NULL;                                                                            \
+
} while (0)
+

+
#define LL_DELETE_VS2008(head,del)                                                             \
+
    LL_DELETE2_VS2008(head,del,next)
+

+
#define LL_DELETE2_VS2008(head,del,next)                                                       \
+
do {                                                                                           \
+
  if ((head) == (del)) {                                                                       \
+
    (head)=(head)->next;                                                                       \
+
  } else {                                                                                     \
+
    char *_tmp = (char*)(head);                                                                \
+
    while ((head)->next && ((head)->next != (del))) {                                          \
+
      head = (head)->next;                                                                     \
+
    }                                                                                          \
+
    if ((head)->next) {                                                                        \
+
      (head)->next = ((del)->next);                                                            \
+
    }                                                                                          \
+
    {                                                                                          \
+
      char **_head_alias = (char**)&(head);                                                    \
+
      *_head_alias = _tmp;                                                                     \
+
    }                                                                                          \
+
  }                                                                                            \
+
} while (0)
+
#ifdef NO_DECLTYPE
+
#undef LL_APPEND
+
#define LL_APPEND LL_APPEND_VS2008
+
#undef LL_DELETE
+
#define LL_DELETE LL_DELETE_VS2008
+
#undef LL_DELETE2
+
#define LL_DELETE2_VS2008
+
#undef LL_APPEND2
+
#define LL_APPEND2 LL_APPEND2_VS2008
+
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
+
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
+
#endif
+
/* end VS2008 replacements */
+

+
#define LL_FOREACH(head,el)                                                                    \
+
    LL_FOREACH2(head,el,next)
+

+
#define LL_FOREACH2(head,el,next)                                                              \
+
    for(el=head;el;el=(el)->next)
+

+
#define LL_FOREACH_SAFE(head,el,tmp)                                                           \
+
    LL_FOREACH_SAFE2(head,el,tmp,next)
+

+
#define LL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
+
  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+

+
#define LL_SEARCH_SCALAR(head,out,field,val)                                                   \
+
    LL_SEARCH_SCALAR2(head,out,field,val,next)
+

+
#define LL_SEARCH_SCALAR2(head,out,field,val,next)                                             \
+
do {                                                                                           \
+
    LL_FOREACH2(head,out,next) {                                                               \
+
      if ((out)->field == (val)) break;                                                        \
+
    }                                                                                          \
+
} while(0) 
+

+
#define LL_SEARCH(head,out,elt,cmp)                                                            \
+
    LL_SEARCH2(head,out,elt,cmp,next)
+

+
#define LL_SEARCH2(head,out,elt,cmp,next)                                                      \
+
do {                                                                                           \
+
    LL_FOREACH2(head,out,next) {                                                               \
+
      if ((cmp(out,elt))==0) break;                                                            \
+
    }                                                                                          \
+
} while(0) 
+

+
#define LL_REPLACE_ELEM(head, el, add)                                                         \
+
do {                                                                                           \
+
 LDECLTYPE(head) _tmp;                                                                         \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 (add)->next = (el)->next;                                                                     \
+
 if ((head) == (el)) {                                                                         \
+
  (head) = (add);                                                                              \
+
 } else {                                                                                      \
+
  _tmp = head;                                                                                 \
+
  while (_tmp->next && (_tmp->next != (el))) {                                                 \
+
   _tmp = _tmp->next;                                                                          \
+
  }                                                                                            \
+
  if (_tmp->next) {                                                                            \
+
    _tmp->next = (add);                                                                        \
+
  }                                                                                            \
+
 }                                                                                             \
+
} while (0)
+

+
#define LL_PREPEND_ELEM(head, el, add)                                                         \
+
do {                                                                                           \
+
 LDECLTYPE(head) _tmp;                                                                         \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 (add)->next = (el);                                                                           \
+
 if ((head) == (el)) {                                                                         \
+
  (head) = (add);                                                                              \
+
 } else {                                                                                      \
+
  _tmp = head;                                                                                 \
+
  while (_tmp->next && (_tmp->next != (el))) {                                                 \
+
   _tmp = _tmp->next;                                                                          \
+
  }                                                                                            \
+
  if (_tmp->next) {                                                                            \
+
    _tmp->next = (add);                                                                        \
+
  }                                                                                            \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

+

+
/******************************************************************************
+
 * doubly linked list macros (non-circular)                                   *
+
 *****************************************************************************/
+
#define DL_PREPEND(head,add)                                                                   \
+
    DL_PREPEND2(head,add,prev,next)
+

+
#define DL_PREPEND2(head,add,prev,next)                                                        \
+
do {                                                                                           \
+
 (add)->next = head;                                                                           \
+
 if (head) {                                                                                   \
+
   (add)->prev = (head)->prev;                                                                 \
+
   (head)->prev = (add);                                                                       \
+
 } else {                                                                                      \
+
   (add)->prev = (add);                                                                        \
+
 }                                                                                             \
+
 (head) = (add);                                                                               \
+
} while (0)
+

+
#define DL_APPEND(head,add)                                                                    \
+
    DL_APPEND2(head,add,prev,next)
+

+
#define DL_APPEND2(head,add,prev,next)                                                         \
+
do {                                                                                           \
+
  if (head) {                                                                                  \
+
      (add)->prev = (head)->prev;                                                              \
+
      (head)->prev->next = (add);                                                              \
+
      (head)->prev = (add);                                                                    \
+
      (add)->next = NULL;                                                                      \
+
  } else {                                                                                     \
+
      (head)=(add);                                                                            \
+
      (head)->prev = (head);                                                                   \
+
      (head)->next = NULL;                                                                     \
+
  }                                                                                            \
+
} while (0) 
+

+
#define DL_CONCAT(head1,head2)                                                                 \
+
    DL_CONCAT2(head1,head2,prev,next)
+

+
#define DL_CONCAT2(head1,head2,prev,next)                                                      \
+
do {                                                                                           \
+
  LDECLTYPE(head1) _tmp;                                                                       \
+
  if (head2) {                                                                                 \
+
    if (head1) {                                                                               \
+
        _tmp = (head2)->prev;                                                                  \
+
        (head2)->prev = (head1)->prev;                                                         \
+
        (head1)->prev->next = (head2);                                                         \
+
        (head1)->prev = _tmp;                                                                  \
+
    } else {                                                                                   \
+
        (head1)=(head2);                                                                       \
+
    }                                                                                          \
+
  }                                                                                            \
+
} while (0) 
+

+
#define DL_DELETE(head,del)                                                                    \
+
    DL_DELETE2(head,del,prev,next)
+

+
#define DL_DELETE2(head,del,prev,next)                                                         \
+
do {                                                                                           \
+
  assert((del)->prev != NULL);                                                                 \
+
  if ((del)->prev == (del)) {                                                                  \
+
      (head)=NULL;                                                                             \
+
  } else if ((del)==(head)) {                                                                  \
+
      (del)->next->prev = (del)->prev;                                                         \
+
      (head) = (del)->next;                                                                    \
+
  } else {                                                                                     \
+
      (del)->prev->next = (del)->next;                                                         \
+
      if ((del)->next) {                                                                       \
+
          (del)->next->prev = (del)->prev;                                                     \
+
      } else {                                                                                 \
+
          (head)->prev = (del)->prev;                                                          \
+
      }                                                                                        \
+
  }                                                                                            \
+
} while (0) 
+

+

+
#define DL_FOREACH(head,el)                                                                    \
+
    DL_FOREACH2(head,el,next)
+

+
#define DL_FOREACH2(head,el,next)                                                              \
+
    for(el=head;el;el=(el)->next)
+

+
/* this version is safe for deleting the elements during iteration */
+
#define DL_FOREACH_SAFE(head,el,tmp)                                                           \
+
    DL_FOREACH_SAFE2(head,el,tmp,next)
+

+
#define DL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
+
  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+

+
/* these are identical to their singly-linked list counterparts */
+
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
+
#define DL_SEARCH LL_SEARCH
+
#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
+
#define DL_SEARCH2 LL_SEARCH2
+

+
#define DL_REPLACE_ELEM(head, el, add)                                                         \
+
do {                                                                                           \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 if ((head) == (el)) {                                                                         \
+
  (head) = (add);                                                                              \
+
  (add)->next = (el)->next;                                                                    \
+
  if ((el)->next == NULL) {                                                                    \
+
   (add)->prev = (add);                                                                        \
+
  } else {                                                                                     \
+
   (add)->prev = (el)->prev;                                                                   \
+
   (add)->next->prev = (add);                                                                  \
+
  }                                                                                            \
+
 } else {                                                                                      \
+
  (add)->next = (el)->next;                                                                    \
+
  (add)->prev = (el)->prev;                                                                    \
+
  (add)->prev->next = (add);                                                                   \
+
  if ((el)->next == NULL) {                                                                    \
+
   (head)->prev = (add);                                                                       \
+
  } else {                                                                                     \
+
   (add)->next->prev = (add);                                                                  \
+
  }                                                                                            \
+
 }                                                                                             \
+
} while (0)
+

+
#define DL_PREPEND_ELEM(head, el, add)                                                         \
+
do {                                                                                           \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 (add)->next = (el);                                                                           \
+
 (add)->prev = (el)->prev;                                                                     \
+
 (el)->prev = (add);                                                                           \
+
 if ((head) == (el)) {                                                                         \
+
  (head) = (add);                                                                              \
+
 } else {                                                                                      \
+
  (add)->prev->next = (add);                                                                   \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

+

+
/******************************************************************************
+
 * circular doubly linked list macros                                         *
+
 *****************************************************************************/
+
#define CDL_PREPEND(head,add)                                                                  \
+
    CDL_PREPEND2(head,add,prev,next)
+

+
#define CDL_PREPEND2(head,add,prev,next)                                                       \
+
do {                                                                                           \
+
 if (head) {                                                                                   \
+
   (add)->prev = (head)->prev;                                                                 \
+
   (add)->next = (head);                                                                       \
+
   (head)->prev = (add);                                                                       \
+
   (add)->prev->next = (add);                                                                  \
+
 } else {                                                                                      \
+
   (add)->prev = (add);                                                                        \
+
   (add)->next = (add);                                                                        \
+
 }                                                                                             \
+
(head)=(add);                                                                                  \
+
} while (0)
+

+
#define CDL_DELETE(head,del)                                                                   \
+
    CDL_DELETE2(head,del,prev,next)
+

+
#define CDL_DELETE2(head,del,prev,next)                                                        \
+
do {                                                                                           \
+
  if ( ((head)==(del)) && ((head)->next == (head))) {                                          \
+
      (head) = 0L;                                                                             \
+
  } else {                                                                                     \
+
     (del)->next->prev = (del)->prev;                                                          \
+
     (del)->prev->next = (del)->next;                                                          \
+
     if ((del) == (head)) (head)=(del)->next;                                                  \
+
  }                                                                                            \
+
} while (0) 
+

+
#define CDL_FOREACH(head,el)                                                                   \
+
    CDL_FOREACH2(head,el,next)
+

+
#define CDL_FOREACH2(head,el,next)                                                             \
+
    for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) 
+

+
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
+
    CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
+

+
#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)                                         \
+
  for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL);                                        \
+
      (el) && ((tmp2)=(el)->next, 1);                                                          \
+
      ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
+

+
#define CDL_SEARCH_SCALAR(head,out,field,val)                                                  \
+
    CDL_SEARCH_SCALAR2(head,out,field,val,next)
+

+
#define CDL_SEARCH_SCALAR2(head,out,field,val,next)                                            \
+
do {                                                                                           \
+
    CDL_FOREACH2(head,out,next) {                                                              \
+
      if ((out)->field == (val)) break;                                                        \
+
    }                                                                                          \
+
} while(0) 
+

+
#define CDL_SEARCH(head,out,elt,cmp)                                                           \
+
    CDL_SEARCH2(head,out,elt,cmp,next)
+

+
#define CDL_SEARCH2(head,out,elt,cmp,next)                                                     \
+
do {                                                                                           \
+
    CDL_FOREACH2(head,out,next) {                                                              \
+
      if ((cmp(out,elt))==0) break;                                                            \
+
    }                                                                                          \
+
} while(0) 
+

+
#define CDL_REPLACE_ELEM(head, el, add)                                                        \
+
do {                                                                                           \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 if ((el)->next == (el)) {                                                                     \
+
  (add)->next = (add);                                                                         \
+
  (add)->prev = (add);                                                                         \
+
  (head) = (add);                                                                              \
+
 } else {                                                                                      \
+
  (add)->next = (el)->next;                                                                    \
+
  (add)->prev = (el)->prev;                                                                    \
+
  (add)->next->prev = (add);                                                                   \
+
  (add)->prev->next = (add);                                                                   \
+
  if ((head) == (el)) {                                                                        \
+
   (head) = (add);                                                                             \
+
  }                                                                                            \
+
 }                                                                                             \
+
} while (0)
+

+
#define CDL_PREPEND_ELEM(head, el, add)                                                        \
+
do {                                                                                           \
+
 assert(head != NULL);                                                                         \
+
 assert(el != NULL);                                                                           \
+
 assert(add != NULL);                                                                          \
+
 (add)->next = (el);                                                                           \
+
 (add)->prev = (el)->prev;                                                                     \
+
 (el)->prev = (add);                                                                           \
+
 (add)->prev->next = (add);                                                                    \
+
 if ((head) == (el)) {                                                                         \
+
  (head) = (add);                                                                              \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

+
#endif /* UTLIST_H */
+

modified libpkg/Makefile
@@ -6,9 +6,8 @@ WARNS= 6
PREFIX?=	/usr/local
LIBDIR=		${PREFIX}/lib
INCLUDEDIR=	${PREFIX}/include
-
SHLIB_MAJOR=	0
+
SHLIB_MAJOR=	1

-
#gr_utils.c has to be deleted as soon as it goes in base
PC=		pkg.pc
PKGH=		pkg.h
SRCS=		${PC} \
@@ -37,7 +36,6 @@ SRCS= ${PC} \
		rsa.c \
		scripts.c \
		update.c \
-
		usergroup.c \
		utils.c \
		plugins.c \
		pkg_old.c \
@@ -61,15 +59,6 @@ all: ${PC}
realinstall: ${PC}
	${INSTALL} -m 644 ${PC} ${PREFIX}/libdata/pkgconfig

-
HAVE_GRUTILS!=	grep -q gr_copy /usr/include/libutil.h && echo yes || echo no
-

-
.if ${HAVE_GRUTILS} != yes
-
SRCS+=	gr_util.c
-
.else
-
CFLAGS+=	-DHAVE_GRUTILS
-
.endif
-

-

#
# Set DEFAULT_MIRROR_TYPE default to SRV
# Possible values are:
modified libpkg/backup.c
@@ -43,7 +43,7 @@
   Default page size is 1024 bytes on Unix */
#define NPAGES	512

-
static int 
+
static int
ps_cb(void *ps, int ncols, char **coltext, __unused char **colnames)
{
	/* We should have exactly one row and one column of output */
modified libpkg/elfhints.c
@@ -30,7 +30,6 @@
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
-
#include <sys/queue.h>

#include <assert.h>
#include <ctype.h>
modified libpkg/fetch.c
@@ -1,4 +1,5 @@
/*-
+
 * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -44,11 +45,11 @@

struct http_mirror {
	struct url *url;
-
	STAILQ_ENTRY(http_mirror) next;
+
	struct http_mirror *next;
};

static struct dns_srvinfo *srv_mirrors = NULL;
-
static STAILQ_HEAD(,http_mirror) http_mirrors = STAILQ_HEAD_INITIALIZER(http_mirrors);
+
static struct http_mirror *http_mirrors = NULL;

static void
gethttpmirrors(const char *url) {
@@ -75,10 +76,10 @@ gethttpmirrors(const char *url) {
			if (*line == '\0')
				continue;

-
			if ((u = fetchParseURL(url)) != NULL) {
+
			if ((u = fetchParseURL(line)) != NULL) {
				m = malloc(sizeof(struct http_mirror));
				m->url = u;
-
				STAILQ_INSERT_TAIL(&http_mirrors, m, next);
+
				LL_APPEND(http_mirrors, m);
			}
		}
	}
@@ -140,6 +141,9 @@ pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
	retry = max_retry;

	u = fetchParseURL(url);
+
	if (t != 0)
+
		u->ims_time = t;
+

	doc = u->doc;
	while (remote == NULL) {
		if (retry == max_retry) {
@@ -161,16 +165,16 @@ pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
				snprintf(zone, sizeof(zone),
				    "%s://%s", u->scheme, u->host);
				pthread_mutex_lock(&mirror_mtx);
-
				if (STAILQ_EMPTY(&http_mirrors))
+
				if (http_mirrors == NULL)
					gethttpmirrors(zone);
				pthread_mutex_unlock(&mirror_mtx);
-
				http_current = STAILQ_FIRST(&http_mirrors);
+
				http_current = http_mirrors;
			}
		}

		if (srv && srv_mirrors != NULL)
			strlcpy(u->host, srv_current->host, sizeof(u->host));
-
		else if (http && !STAILQ_EMPTY(&http_mirrors)) {
+
		else if (http && http_mirrors != NULL) {
			strlcpy(u->scheme, http_current->url->scheme, sizeof(u->scheme));
			strlcpy(u->host, http_current->url->host, sizeof(u->host));
			snprintf(docpath, MAXPATHLEN, "%s%s", http_current->url->doc, doc);
@@ -178,8 +182,12 @@ pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
			u->port = http_current->url->port;
		}

-
		remote = fetchXGet(u, &st, "");
+
		remote = fetchXGet(u, &st, "i");
		if (remote == NULL) {
+
			if (fetchLastErrCode == FETCH_OK) {
+
				retcode = EPKG_UPTODATE;
+
				goto cleanup;
+
			}
			--retry;
			if (retry <= 0) {
				pkg_emit_error("%s: %s", url,
@@ -191,10 +199,10 @@ pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
				srv_current = srv_current->next;
				if (srv_current == NULL)
					srv_current = srv_mirrors;
-
			} else if (http && !STAILQ_EMPTY(&http_mirrors)) {
-
				http_current = STAILQ_NEXT(http_current, next);
+
			} else if (http && http_mirrors != NULL) {
+
				http_current = http_mirrors->next;
				if (http_current == NULL)
-
					http_current = STAILQ_FIRST(&http_mirrors);
+
					http_current = http_mirrors;
			} else {
				sleep(1);
			}
deleted libpkg/gr_util.c
@@ -1,305 +0,0 @@
-

-
#include <sys/param.h>
-
#include <sys/errno.h>
-
#include <sys/stat.h>
-

-
#include <ctype.h>
-
#include <err.h>
-
#include <fcntl.h>
-
#include <grp.h>
-
#include <inttypes.h>
-
#include <libutil.h>
-
#include <paths.h>
-
#include <stdbool.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <unistd.h>
-

-
#include "private/gr_util.h"
-

-
static int lockfd = -1;
-
static char group_dir[PATH_MAX];
-
static char group_file[PATH_MAX];
-
static char tempname[PATH_MAX];
-
static int initialized;
-

-
int
-
gr_init(const char *dir, const char *group)
-
{
-
	if (dir == NULL) {
-
		strcpy(group_dir, _PATH_ETC);
-
	} else {
-
		if (strlen(dir) >= sizeof(group_dir)) {
-
			errno = ENAMETOOLONG;
-
			return (-1);
-
		}
-
		strcpy(group_dir, dir);
-
	}
-

-
	if (group == NULL) {
-
		if (dir == NULL) {
-
			strcpy(group_file, _PATH_GROUP);
-
		} else if (snprintf(group_file, sizeof(group_file), "%s/group",
-
			group_dir) > (int)sizeof(group_file)) {
-
			errno = ENAMETOOLONG;
-
			return (-1);
-
		}
-
	} else {
-
		if (strlen(group) >= sizeof(group_file)) {
-
			errno = ENAMETOOLONG;
-
			return (-1);
-
		}
-
		strcpy(group_file, group);
-
	}
-
	initialized = 1;
-
	return (0);
-
}
-

-
/*
-
 * Lock the group file
-
 */
-
int
-
gr_lock(void)
-
{
-
	if (*group_file == '\0')
-
		return (-1);
-

-
	for (;;) {
-
		struct stat st;
-

-
		lockfd = open(group_file, O_RDONLY, 0);
-
		if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
-
			err(1, "%s", group_file);
-
		if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
-
			if (errno == EWOULDBLOCK) {
-
				errx(1, "the group file is busy");
-
			} else {
-
				err(1, "could not lock the group file: ");
-
			}
-
		}
-
		if (fstat(lockfd, &st) == -1)
-
			err(1, "fstat() failed: ");
-
		if (st.st_nlink != 0)
-
			break;
-
		close(lockfd);
-
		lockfd = -1;
-
	}
-
	return (lockfd);
-
}
-

-
/*
-
 * Create and open a presmuably safe temp file for editing group data
-
 */
-
int
-
gr_tmp(int mfd)
-
{
-
	char buf[8192];
-
	ssize_t nr;
-
	const char *p;
-
	int tfd;
-

-
	if (*group_file == '\0')
-
		return (-1);
-
	if ((p = strrchr(group_file, '/')))
-
		++p;
-
	else
-
		p = group_file;
-
	if (snprintf(tempname, sizeof(tempname), "%.*sgroup.XXXXXX",
-
		(int)(p - group_file), group_file) >= (int)sizeof(tempname)) {
-
		errno = ENAMETOOLONG;
-
		return (-1);
-
	}
-
	if ((tfd = mkstemp(tempname)) == -1)
-
		return (-1);
-
	if (mfd != -1) {
-
		while ((nr = read(mfd, buf, sizeof(buf))) > 0)
-
			if (write(tfd, buf, (size_t)nr) != nr)
-
				break;
-
		if (nr != 0) {
-
			unlink(tempname);
-
			*tempname = '\0';
-
			close(tfd);
-
			return (-1);
-
		}
-
	}
-
	return (tfd);
-
}
-

-
/*
-
 * Copy the group file from one descriptor to another, replacing, deleting
-
 * or adding a single record on the way.
-
 */
-
int
-
gr_copy(int ffd, int tfd, const struct group *gr, struct group *old_gr)
-
{
-
	char buf[8192], *end, *line, *p, *q, *r, t;
-
	struct group *fgr;
-
	const struct group *sgr;
-
	size_t len;
-
	int eof, readlen;
-

-
	sgr = gr;
-
	if (gr == NULL) {
-
		line = NULL;
-
		if (old_gr == NULL)
-
			return (-1);
-
		sgr = old_gr;
-
	} else if ((line = gr_make(gr)) == NULL)
-
		return (-1);
-

-
	eof = 0;
-
	len = 0;
-
	p = q = end = buf;
-
	for (;;) {
-
		/* find the end of the current line */
-
		for (p = q; q < end && *q != '\0'; ++q)
-
			if (*q == '\n')
-
				break;
-

-
		/* if we don't have a complete line, fill up the buffer */
-
		if (q >= end) {
-
			if (eof)
-
				break;
-
			if ((size_t)(q - p) >= sizeof(buf)) {
-
				warnx("group line too long");
-
				errno = EINVAL; /* hack */
-
				goto err;
-
			}
-
			if (p < end) {
-
				q = memmove(buf, p, end -p);
-
				end -= p - buf;
-
			} else {
-
				p = q = end = buf;
-
			}
-
			readlen = read(ffd, end, sizeof(buf) - (end -buf));
-
			if (readlen == -1)
-
				goto err;
-
			else
-
				len = (size_t)readlen;
-
			if (len == 0 && p == buf)
-
				break;
-
			end += len;
-
			len = end - buf;
-
			if (len < (ssize_t)sizeof(buf)) {
-
				eof = 1;
-
				if (len > 0 && buf[len -1] != '\n')
-
					++len, *end++ = '\n';
-
			}
-
			continue;
-
		}
-

-
		/* is it a blank line or a comment? */
-
		for (r = p; r < q && isspace(*r); ++r)
-
			/* nothing */;
-
		if (r == q || *r == '#') {
-
			/* yep */
-
			if (write(tfd, p, q -p + 1) != q - p + 1)
-
				goto err;
-
			++q;
-
			continue;
-
		}
-

-
		/* is it the one we're looking for? */
-

-
		t = *q;
-
		*q = '\0';
-

-
		fgr = gr_scan(r);
-

-
		/* fgr is either a struct group for the current line,
-
		 * or NULL if the line is malformed.
-
		 */
-

-
		*q = t;
-
		if (fgr == NULL || fgr->gr_gid != sgr->gr_gid) {
-
			/* nope */
-
			if (fgr != NULL)
-
				free(fgr);
-
			if (write(tfd, p, q - p + 1) != q - p + 1)
-
				goto err;
-
			++q;
-
			continue;
-
		}
-
		if (old_gr && !gr_equal(fgr, old_gr)) {
-
			warnx("entry inconsistent");
-
			free(fgr);
-
			errno = EINVAL; /* hack */
-
			goto err;
-
		}
-
		free(fgr);
-

-
		/* it is, replace or remove it */
-
		if (line != NULL) {
-
			len = strlen(line);
-
			if (write(tfd, line, len) != (int) len)
-
				goto err;
-
		} else {
-
			/* when removed, avoid the \n */
-
			q++;
-
		}
-
		/* we're done, just copy the rest over */
-
		for (;;) {
-
			if (write(tfd, q, end - q) != end - q)
-
				goto err;
-
			q = buf;
-
			readlen = read(ffd, buf, sizeof(buf));
-
			if (readlen == 0)
-
				break;
-
			else
-
				len = (size_t)readlen;
-
			if (readlen == -1)
-
				goto err;
-
			end = buf + len;
-
		}
-
		goto done;
-
	}
-

-
	/* if we got here, we didn't find the old entry */
-
	if (line == NULL) {
-
		errno = ENOENT;
-
		goto err;
-
	}
-
	len = strlen(line);
-
	if ((size_t)write(tfd, line, len) != len ||
-
	   write(tfd, "\n", 1) != 1)
-
		goto err;
-
 done:
-
	if (line != NULL)
-
		free(line);
-
	return (0);
-
 err:
-
	if (line != NULL)
-
		free(line);
-
	return (-1);
-
}
-

-
/*
-
 * Regenerate the group file
-
 */
-
int
-
gr_mkdb(void)
-
{
-
	return (rename(tempname, group_file));
-
}
-

-
/*
-
 * Clean up. Preserver errno for the caller's convenience.
-
 */
-
void
-
gr_fini(void)
-
{
-
	int serrno;
-

-
	if (!initialized)
-
		return;
-
	initialized = 0;
-
	serrno = errno;
-
	if (*tempname != '\0') {
-
		unlink(tempname);
-
		*tempname = '\0';
-
	}
-
	if (lockfd != -1)
-
		close(lockfd);
-
	errno = serrno;
-
}
modified libpkg/pkg.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
 * All rights reserved.
@@ -95,6 +95,7 @@ pkg_reset(struct pkg *pkg, pkg_t type)
	pkg->new_flatsize = 0;
	pkg->new_pkgsize = 0;
	pkg->time = 0;
+
	pkg->flags = 0;
	pkg->automatic = false;
	pkg->locked = false;
	pkg->licenselogic = LICENSE_SINGLE;
@@ -357,7 +358,7 @@ pkg_set_mtree(struct pkg *pkg, const char *mtree) {


int
-
pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *path)
+
pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *path, bool trimcr)
{
	char *buf = NULL;
	off_t size = 0;
@@ -369,6 +370,9 @@ pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *path)
	if ((ret = file_to_buffer(path, &buf, &size)) !=  EPKG_OK)
		return (ret);

+
	while (trimcr && buf[strlen(buf) - 1] == '\n')
+
		buf[strlen(buf) - 1] = '\0';
+

	ret = pkg_set(pkg, attr, buf);

	free(buf);
@@ -1108,7 +1112,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
{
	struct pkg_file *f = NULL;
	const char *path;
-
	struct hardlinks hl = { NULL, 0, 0 };
+
	struct hardlinks *hl = NULL;
	int64_t flatsize = 0;
	int64_t oldflatsize;
	struct stat st;
@@ -1129,7 +1133,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)

			/* special case for hardlinks */
			if (st.st_nlink > 1)
-
				regular = is_hardlink(&hl, &st);
+
				regular = is_hardlink(hl, &st);

			if (regular)
				flatsize += st.st_size;
@@ -1162,7 +1166,7 @@ pkg_is_installed(struct pkgdb *db, const char *origin)
}

bool
-
pkg_has_dir(struct pkg *p, const char *path)
+
pkg_has_file(struct pkg *p, const char *path)
{
	struct pkg_file *f;

@@ -1172,7 +1176,7 @@ pkg_has_dir(struct pkg *p, const char *path)
}

bool
-
pkg_has_file(struct pkg *p, const char *path)
+
pkg_has_dir(struct pkg *p, const char *path)
{
	struct pkg_dir *d;

modified libpkg/pkg.h.in
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
 * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
@@ -125,22 +125,26 @@ typedef enum {
	 */
	MATCH_ALL,
	/**
-
	 * The argument is the exact pattern.
+
	 * The argument is the exact pattern.  Match will be case
+
	 * sensitive or case insensitive according to
+
	 * pkgdb_case_sensitive()
	 */
	MATCH_EXACT,
	/**
-
	 * The argument is a globbing expression.
+
	 * The argument is an exact pattern except that matches will
+
	 * be made case insensitively.  Match is always case sensitive
	 */
	MATCH_GLOB,
	/**
	 * The argument is a regular expression ('modern' style
-
	 * according to re_format(7).
+
	 * according to re_format(7).  Match will be case sensitive or
+
	 * case insensitive according to pkgdb_case_sensitive()
	 */
	MATCH_REGEX,
	/**
	 * The argument is a WHERE clause to use as condition
	 */
-
	MATCH_CONDITION
+
	MATCH_CONDITION,
} match_t;

/**
@@ -242,6 +246,12 @@ typedef enum {
} pkg_file_attr;

typedef enum {
+
	PKG_DIR_PATH = 0,
+
	PKG_DIR_UNAME,
+
	PKG_DIR_GNAME
+
} pkg_dir_attr;
+

+
typedef enum {
	PKG_DEPS = 0,
	PKG_RDEPS,
	PKG_LICENSES,
@@ -285,6 +295,9 @@ typedef enum _pkg_flags {
	PKG_FLAG_RECURSIVE = (1U << 2),
	PKG_FLAG_AUTOMATIC = (1U << 3),
	PKG_FLAG_WITH_DEPS = (1U << 4),
+
	PKG_FLAG_NOSCRIPT = (1U << 5),
+
	PKG_FLAG_PKG_VERSION_TEST = (1U << 6),
+
	PKG_FLAG_UPGRADES_FOR_INSTALLED = (1U << 7),
} pkg_flags;

typedef enum _pkg_config_key {
@@ -316,6 +329,7 @@ typedef enum _pkg_config_key {
	PKG_CONFIG_HTTP_PROXY,
	PKG_CONFIG_FTP_PROXY,
	PKG_CONFIG_NAMESERVER,
+
	PKG_CONFIG_EVENT_PIPE,
} pkg_config_key;

typedef enum {
@@ -601,7 +615,7 @@ int pkgdb_file_set_cksum(struct pkgdb *db, struct pkg_file *file,
/**
 * Read the content of a file into a buffer, then call pkg_set().
 */
-
int pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *file);
+
int pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *file, bool trimcr);

/**
 * Allocate a new struct pkg and add it to the deps of pkg.
@@ -735,27 +749,26 @@ int pkg_emit_manifest(struct pkg *pkg, char **buf);

/* pkg_dep */
const char *pkg_dep_get(struct pkg_dep const * const , const pkg_dep_attr);
-

-
const char *pkg_dep_name(struct pkg_dep const * const);
-
const char *pkg_dep_origin(struct pkg_dep const * const);
-
const char *pkg_dep_version(struct pkg_dep const * const);
+
#define pkg_dep_name(d) pkg_dep_get(d, PKG_DEP_NAME)
+
#define pkg_dep_origin(d) pkg_dep_get(d, PKG_DEP_ORIGIN)
+
#define pkg_dep_version(d) pkg_dep_get(d, PKG_DEP_VERSION)
bool pkg_dep_is_locked(struct pkg_dep const * const);

/* pkg_file */
const char *pkg_file_get(struct pkg_file const * const, const pkg_file_attr);
-

-
const char *pkg_file_path(struct pkg_file const * const);
-
const char *pkg_file_cksum(struct pkg_file const * const);
-
const char *pkg_file_uname(struct pkg_file const * const);
-
const char *pkg_file_gname(struct pkg_file const * const);
+
#define pkg_file_path(f) pkg_file_get(f, PKG_FILE_PATH)
+
#define pkg_file_cksum(f) pkg_file_get(f, PKG_FILE_SUM)
+
#define pkg_file_uname(f) pkg_file_get(f, PKG_FILE_UNAME)
+
#define pkg_file_gname(f) pkg_file_get(f, PKG_FILE_GNAME)
mode_t pkg_file_mode(struct pkg_file const * const);

bool pkg_has_dir(struct pkg *, const char *);
bool pkg_has_file(struct pkg *, const char *);
/* pkg_dir */
-
const char *pkg_dir_path(struct pkg_dir const * const);
-
const char *pkg_dir_uname(struct pkg_dir const * const);
-
const char *pkg_dir_gname(struct pkg_dir const * const);
+
const char *pkg_dir_get(struct pkg_dir const * const, const pkg_dir_attr);
+
#define pkg_dir_path(d) pkg_dir_get(d, PKG_DIR_PATH)
+
#define pkg_dir_uname(d) pkg_dir_get(d, PKG_DIR_UNAME)
+
#define pkg_dir_gname(d) pkg_dir_get(d, PKG_DIR_GNAME)
mode_t pkg_dir_mode(struct pkg_dir const * const);
bool pkg_dir_try(struct pkg_dir const * const);

@@ -788,6 +801,8 @@ const char *pkg_shlib_name(struct pkg_shlib const * const);
 * @param origin Package origin
 * @return EPKG_OK if the package is installed,
 * and != EPKG_OK if the package is not installed or an error occurred
+
 * Match will be case sensitive or insensitive depending on
+
 * pkgdb_case_sensitive()
 */
int pkg_is_installed(struct pkgdb *db, const char *origin);

@@ -855,6 +870,17 @@ int pkgdb_register_ports(struct pkgdb *db, struct pkg *pkg);
int pkgdb_unregister_pkg(struct pkgdb *pkg, const char *origin);

/**
+
 * Set the case sensitivity flag on or off.  Defaults to 
+
 * true (case_sensitive)
+
 */
+
void pkgdb_set_case_sensitivity(bool);
+

+
/**
+
 * Query the state of the case sensitity setting.
+
 */
+
bool pkgdb_case_sensitive(void);
+

+
/**
 * Query the local package database.
 * @param type Describe how pattern should be used.
 * @warning Returns NULL on failure.
@@ -922,6 +948,7 @@ int pkg_add(struct pkgdb *db, const char *path, unsigned flags);
#define PKG_ADD_USE_UPGRADE_SCRIPTS	(1U << 1)
#define PKG_ADD_AUTOMATIC		(1U << 2)
#define PKG_ADD_FORCE			(1U << 3)
+
#define PKG_ADD_NOSCRIPT		(1U << 4)

/**
 * Allocate a new pkg_jobs.
@@ -979,9 +1006,7 @@ int pkg_create_installed(const char *, pkg_formats, const char *,
 * Create package from stage install with a metadata directory
 */
int pkg_create_staged(const char *, pkg_formats, const char *, const char *,
-
		      char *);
-
int pkg_create_oldstaged(const char *, pkg_formats, const char *, const char *,
-
		      char *);
+
		      char *, bool);

/**
 * Download the latest repo db file and checks its signature if any
@@ -1108,6 +1133,7 @@ struct pkg_event {
		struct {
			const char *func;
			const char *arg;
+
			int no;
		} e_errno;
		struct {
			char *msg;
@@ -1166,6 +1192,7 @@ struct pkg_event {
			struct pkg_plugin *plugin;
			const char *func;
			const char *arg;
+
			int no;
		} e_plugin_errno;
		struct {
			struct pkg_plugin *plugin;
@@ -1200,4 +1227,5 @@ int pkg_old_load_from_path(struct pkg *pkg, const char *path);
int pkg_old_emit_content(struct pkg *pkg, char **dest);
int pkg_from_old(struct pkg *pkg);
int pkg_to_old(struct pkg *pkg);
+
int pkg_register_old(struct pkg *pkg);
#endif
modified libpkg/pkg_add.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -42,23 +42,6 @@
#include "private/pkg.h"

static int
-
dep_installed(struct pkg_dep *dep, struct pkgdb *db) {
-
	struct pkg	*p = NULL;
-
	struct pkgdb_it	*it;
-
	int		 ret = EPKG_FATAL;
-

-
	it = pkgdb_query(db, pkg_dep_origin(dep), MATCH_EXACT);
-

-
	if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK)
-
		ret = EPKG_OK;
-

-
	pkgdb_it_free(it);
-
	pkg_free(p);
-

-
	return (ret);
-
}
-

-
static int
do_extract(struct archive *a, struct archive_entry *ae)
{
	int	retcode = EPKG_OK;
@@ -117,6 +100,58 @@ do_extract(struct archive *a, struct archive_entry *ae)
	return (retcode);
}

+
static int
+
do_extract_mtree(char *mtree, const char *prefix)
+
{
+
	struct archive *a = NULL;
+
	struct archive_entry *ae;
+
	char path[MAXPATHLEN];
+
	const char *fpath;
+
	int retcode = EPKG_OK;
+
	int ret;
+

+
	if (mtree == NULL || *mtree == '\0')
+
		return EPKG_OK;
+

+
	a = archive_read_new();
+
	archive_read_support_compression_none(a);
+
	archive_read_support_format_mtree(a);
+

+
	if (archive_read_open_memory(a, mtree, strlen(mtree)) != ARCHIVE_OK) {
+
		pkg_emit_error("Fail to extract the mtree: %s",
+
		    archive_error_string(a));
+
		retcode = EPKG_FATAL;
+
		goto cleanup;
+
	}
+

+
	while ((ret = archive_read_next_header(a, &ae)) != ARCHIVE_EOF) {
+
		if (ret != ARCHIVE_OK) {
+
			pkg_emit_error("Skipping unsupported mtree line: %s",
+
			    archive_error_string(a));
+
			continue;
+
		}
+
		fpath = archive_entry_pathname(ae);
+

+
		if (*fpath != '/') {
+
			snprintf(path, sizeof(path), "%s/%s", prefix, fpath);
+
			archive_entry_set_pathname(ae, path);
+
		}
+

+
		if (archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS) != ARCHIVE_OK) {
+
			pkg_emit_error("Fail to extract some of the mtree entries: %s",
+
			    archive_error_string(a));
+
			retcode = EPKG_FATAL;
+
			break;
+
		}
+
	}
+

+
cleanup:
+
	if (a != NULL)
+
		archive_read_finish(a);
+

+
	return (retcode);
+
}
+

int
pkg_add(struct pkgdb *db, const char *path, unsigned flags)
{
@@ -128,12 +163,13 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags)
	struct pkg	*pkg = NULL;
	struct pkg_dep	*dep = NULL;
	struct pkg      *pkg_inst = NULL;
-
	struct pkgdb_it *it = NULL;
	bool		 extract = true;
	bool		 handle_rc = false;
	char		 dpath[MAXPATHLEN + 1];
	const char	*basedir;
	const char	*ext;
+
	char		*mtree;
+
	char		*prefix;
	int		 retcode = EPKG_OK;
	int		 ret;

@@ -183,12 +219,7 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags)
	 * Check if the package is already installed
	 */

-
	ret = EPKG_FATAL; /* assume package is not installed */
-
	if ((it = pkgdb_query(db, origin, MATCH_EXACT)) != NULL) {
-
		ret = pkgdb_it_next(it, &pkg_inst, PKG_LOAD_BASIC);
-
		pkgdb_it_free(it);
-
	}
-

+
	ret = pkg_is_installed(db, origin);
	if (ret == EPKG_OK) {
		pkg_emit_already_installed(pkg_inst);
		pkg_free(pkg_inst);
@@ -211,7 +242,7 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags)
	}

	while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
		if (dep_installed(dep, db) != EPKG_OK) {
+
		if (pkg_is_installed(db, pkg_dep_origin(dep)) != EPKG_OK) {
			const char *dep_name = pkg_dep_name(dep);
			const char *dep_ver = pkg_dep_version(dep);

@@ -243,10 +274,14 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags)
	if (retcode != EPKG_OK)
		goto cleanup;

+
	pkg_get(pkg, PKG_PREFIX, &prefix, PKG_MTREE, &mtree);
+
	if ((retcode = do_extract_mtree(mtree, prefix)) != EPKG_OK)
+
		goto cleanup_reg;
+

	/*
	 * Execute pre-install scripts
	 */
-
	if ((flags & PKG_ADD_USE_UPGRADE_SCRIPTS) == 0)
+
	if ((flags & (PKG_ADD_NOSCRIPT | PKG_ADD_USE_UPGRADE_SCRIPTS)) == 0)
		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL);

	/* add the user and group if necessary */
@@ -265,10 +300,12 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags)
	/*
	 * Execute post install scripts
	 */
-
	if (flags & PKG_ADD_USE_UPGRADE_SCRIPTS)
-
		pkg_script_run(pkg, PKG_SCRIPT_POST_UPGRADE);
-
	else
-
		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL);
+
	if ((flags & PKG_ADD_NOSCRIPT) == 0) {
+
		if (flags & PKG_ADD_USE_UPGRADE_SCRIPTS)
+
			pkg_script_run(pkg, PKG_SCRIPT_POST_UPGRADE);
+
		else
+
			pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL);
+
	}

	/*
	 * start the different related services if the users do want that
modified libpkg/pkg_attributes.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -77,30 +77,6 @@ pkg_dep_get(struct pkg_dep const * const d, const pkg_dep_attr attr)
	}
}

-
const char *
-
pkg_dep_name(struct pkg_dep const * const d)
-
{
-
	assert( d != NULL);
-

-
	return (sbuf_get(d->name));
-
}
-

-
const char *
-
pkg_dep_origin(struct pkg_dep const * const d)
-
{
-
	assert( d != NULL);
-

-
	return (sbuf_get(d->origin));
-
}
-

-
const char *
-
pkg_dep_version(struct pkg_dep const * const d)
-
{
-
	assert( d != NULL);
-

-
	return (sbuf_get(d->version));
-
}
-

bool
pkg_dep_is_locked(struct pkg_dep const * const d)
{
@@ -155,38 +131,6 @@ pkg_file_get(struct pkg_file const * const f, const pkg_file_attr attr)
	}
}

-
const char *
-
pkg_file_path(struct pkg_file const * const f)
-
{
-
	assert(f != NULL);
-

-
	return (f->path);
-
}
-

-
const char *
-
pkg_file_cksum(struct pkg_file const * const f)
-
{
-
	assert(f != NULL);
-

-
	return (f->sum);
-
}
-

-
const char *
-
pkg_file_uname(struct pkg_file const * const f)
-
{
-
	assert(f != NULL);
-

-
	return (f->uname);
-
}
-

-
const char *
-
pkg_file_gname(struct pkg_file const * const f)
-
{
-
	assert(f != NULL);
-

-
	return (f->gname);
-
}
-

mode_t
pkg_file_mode(struct pkg_file const * const f)
{
@@ -219,27 +163,22 @@ pkg_dir_free(struct pkg_dir *d)
}

const char *
-
pkg_dir_path(struct pkg_dir const * const d)
+
pkg_dir_get(struct pkg_dir const * const d, const pkg_dir_attr attr)
{
	assert(d != NULL);
-

-
	return (d->path);
-
}
-

-
const char *
-
pkg_dir_uname(struct pkg_dir const * const d)
-
{
-
	assert(d != NULL);
-

-
	return (d->uname);
-
}
-

-
const char *
-
pkg_dir_gname(struct pkg_dir const * const d)
-
{
-
	assert(d != NULL);
-

-
	return (d->gname);
+
	switch (attr) {
+
	case PKG_DIR_PATH:
+
		return (d->path);
+
		break;
+
	case PKG_DIR_UNAME:
+
		return (d->uname);
+
		break;
+
	case PKG_DIR_GNAME:
+
		return (d->gname);
+
		break;
+
	default:
+
		return(NULL);
+
	}
}

mode_t
modified libpkg/pkg_config.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -25,11 +25,12 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

-
#include <sys/queue.h>
-

#include <assert.h>
+
#include <sys/socket.h>
+
#include <sys/un.h>
#include <ctype.h>
#include <dlfcn.h>
+
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
@@ -45,6 +46,7 @@
#define ABI_VAR_STRING "${ABI}"

pthread_mutex_t mirror_mtx;
+
int eventpipe = -1;

struct config_entry {
	uint8_t type;
@@ -79,7 +81,11 @@ static struct config_entry c[] = {
	[PKG_CONFIG_PORTSDIR] = {
		PKG_CONFIG_STRING,
		"PORTSDIR",
+
#ifdef PORTSDIR
+
		PORTSDIR,
+
#else
		"/usr/ports",
+
#endif
	},
	[PKG_CONFIG_REPOKEY] = {
		PKG_CONFIG_STRING,
@@ -104,7 +110,7 @@ static struct config_entry c[] = {
	[PKG_CONFIG_REPOS] = {
		PKG_CONFIG_KVLIST,
		"REPOS",
-
		"NULL",
+
		NULL,
	},
	[PKG_CONFIG_PLIST_KEYWORDS_DIR] = {
		PKG_CONFIG_STRING,
@@ -174,7 +180,7 @@ static struct config_entry c[] = {
	[PKG_CONFIG_PLUGINS] = {
		PKG_CONFIG_LIST,
		"PLUGINS",
-
		"NULL",
+
		NULL,
	},
	[PKG_CONFIG_DEBUG_SCRIPTS] = {
		PKG_CONFIG_BOOL,
@@ -211,11 +217,63 @@ static struct config_entry c[] = {
		"NAMESERVER",
		NULL,
	},
+
	[PKG_CONFIG_EVENT_PIPE] = {
+
		PKG_CONFIG_STRING,
+
		"EVENT_PIPE",
+
		NULL,
+
	}
};

static bool parsed = false;
static size_t c_size = sizeof(c) / sizeof(struct config_entry);

+
static void pkg_config_kv_free(struct pkg_config_kv *);
+

+
static void
+
connect_evpipe(const char *evpipe) {
+
	struct stat st;
+
	struct sockaddr_un sock;
+
	int flag = O_WRONLY;
+

+
	if (stat(evpipe, &st) != 0) {
+
		pkg_emit_error("No such event pipe: %s", evpipe);
+
		return;
+
	}
+

+
	if (!S_ISFIFO(st.st_mode) && !S_ISSOCK(st.st_mode)) {
+
		pkg_emit_error("%s is not a fifo or socket", evpipe);
+
		return;
+
	}
+

+
	if (S_ISFIFO(st.st_mode)) {
+
		flag |= O_NONBLOCK;
+
		if ((eventpipe = open(evpipe, flag)) == -1)
+
			pkg_emit_errno("open event pipe", evpipe);
+
		return;
+
	}
+

+
	if (S_ISSOCK(st.st_mode)) {
+
		if ((eventpipe = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+
			pkg_emit_errno("Open event pipe", evpipe);
+
			return;
+
		}
+
		memset(&sock, 0, sizeof(struct sockaddr_un));
+
		sock.sun_family = AF_UNIX;
+
		if (strlcpy(sock.sun_path, evpipe, sizeof(sock.sun_path)) >=
+
		    sizeof(sock.sun_path)) {
+
			pkg_emit_error("Socket path too long: %s", evpipe);
+
			close(eventpipe);
+
			return;
+
		}
+

+
		if (connect(eventpipe, (struct sockaddr *)&sock, SUN_LEN(&sock)) == -1) {
+
			pkg_emit_errno("Connect event pipe", evpipe);
+
			return;
+
		}
+
	}
+

+
}
+

static void
parse_config_sequence(yaml_document_t *doc, yaml_node_t *seq, struct pkg_config *conf)
{
@@ -296,7 +354,7 @@ pkg_config_parse(yaml_document_t *doc, yaml_node_t *node, struct pkg_config *con
			sbuf_putc(b, toupper(key->data.scalar.value[i]));

		sbuf_finish(b);
-
		HASH_FIND(hhkey, conf_by_key, sbuf_data(b), sbuf_len(b), conf);
+
		HASH_FIND(hhkey, conf_by_key, sbuf_data(b), (size_t)sbuf_len(b), conf);
		if (conf != NULL) {
			switch (conf->type) {
			case PKG_CONFIG_STRING:
@@ -351,11 +409,13 @@ pkg_config_parse(yaml_document_t *doc, yaml_node_t *node, struct pkg_config *con
				parse_config_mapping(doc, val, conf);
				break;
			case PKG_CONFIG_LIST:
-
				if (val->type != YAML_SEQUENCE_NODE) {
-
					pkg_emit_error("Expecting a string list for key %s,"
-
					    " ignoring...", key->data.scalar.value);
+
				if (!conf->fromenv) {
+
					if (val->type != YAML_SEQUENCE_NODE) {
+
						pkg_emit_error("Expecting a string list for key %s,"
+
						    " ignoring...", key->data.scalar.value);
+
					}
+
					parse_config_sequence(doc, val, conf);
				}
-
				parse_config_sequence(doc, val, conf);
				break;
			}
		}
@@ -562,10 +622,14 @@ pkg_init(const char *path)
	yaml_node_t *node;
	size_t i;
	const char *val = NULL;
+
	const char *buf, *walk, *value, *key;
	const char *errstr = NULL;
	const char *proxy = NULL;
	const char *nsname = NULL;
+
	const char *evpipe = NULL;
	struct pkg_config *conf;
+
	struct pkg_config_value *v;
+
	struct pkg_config_kv *kv;

	pkg_get_myarch(myabi, BUFSIZ);
	if (parsed != false) {
@@ -623,9 +687,72 @@ pkg_init(const char *path)
			break;
		case PKG_CONFIG_KVLIST:
			conf->kvlist = NULL;
+
			if (val == NULL)
+
				val = c[i].def;
+
			else
+
				conf->fromenv = false;
+
			if (val != NULL) {
+
				printf("%s\n", val);
+
				walk = buf = val;
+
				while ((buf = strchr(buf, ',')) != NULL) {
+
					key = walk;
+
					value = walk;
+
					while (*value != ',') {
+
						if (*value == '=')
+
							break;
+
						value++;
+
					}
+
					if (value == buf || (value - key) == 0) {
+
						pkg_emit_error("Malformed Key/Value for %s", c[i].key);
+
						pkg_config_kv_free(conf->kvlist);
+
						conf->kvlist = NULL;
+
						break;
+
					}
+
					kv = malloc(sizeof(struct pkg_config_kv));
+
					kv->key = strndup(key, value - key);
+
					kv->value = strndup(value + 1, buf - value -1);
+
					HASH_ADD_STR(conf->kvlist, value, kv);
+
					buf++;
+
					walk = buf;
+
				}
+
				key = walk;
+
				value = walk;
+
				while (*value != '\0') {
+
					if (*value == '=')
+
						break;
+
					value++;
+
				}
+
				if (*value == '\0' || (value - key) == 0) {
+
					pkg_emit_error("Malformed Key/Value for %s: %s", c[i].key, val);
+
					pkg_config_kv_free(conf->kvlist);
+
					conf->kvlist = NULL;
+
					break;
+
				}
+
				kv = malloc(sizeof(struct pkg_config_kv));
+
				kv->key = strndup(key, value - key);
+
				kv->value = strdup(value + 1);
+
				HASH_ADD_STR(conf->kvlist, value, kv);
+
			}
			break;
		case PKG_CONFIG_LIST:
			conf->list = NULL;
+
			if (val == NULL)
+
				val = c[i].def;
+
			else
+
				conf->fromenv = true;
+
			if (val != NULL) {
+
				walk = buf = val;
+
				while ((buf = strchr(buf, ',')) != NULL) {
+
					v = malloc(sizeof(struct pkg_config_value));
+
					v->value = strndup(walk, buf - walk);
+
					HASH_ADD_STR(conf->list, value, v);
+
					buf++;
+
					walk = buf;
+
				}
+
				v = malloc(sizeof(struct pkg_config_value));
+
				v->value = strdup(walk);
+
				HASH_ADD_STR(conf->list, value, v);
+
			}
			break;
		}

@@ -670,6 +797,11 @@ pkg_init(const char *path)

	parsed = true;

+
	/* Start the event pipe */
+
	pkg_config_string(PKG_CONFIG_EVENT_PIPE, &evpipe);
+
	if (evpipe != NULL)
+
		connect_evpipe(evpipe);
+

	/* set the environement variable for libfetch for proxies if any */
	pkg_config_string(PKG_CONFIG_HTTP_PROXY, &proxy);
	if (proxy != NULL)
@@ -689,6 +821,9 @@ pkg_init(const char *path)
static void
pkg_config_kv_free(struct pkg_config_kv *k)
{
+
	if (k == NULL)
+
		return;
+

	free(k->key);
	free(k->value);
	free(k);
modified libpkg/pkg_create.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -89,6 +89,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	 */
	if (pkg->type == PKG_OLD_FILE) {
		const char *desc, *display, *comment;
+
		char oldcomment[BUFSIZ];

		pkg_old_emit_content(pkg, &m);
		packing_append_buffer(pkg_archive, m, "+CONTENTS", strlen(m));
@@ -97,7 +98,8 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
		pkg_get(pkg, PKG_DESC, &desc, PKG_MESSAGE, &display, PKG_COMMENT, &comment);
		packing_append_buffer(pkg_archive, desc, "+DESC", strlen(desc));
		packing_append_buffer(pkg_archive, display, "+DISPLAY", strlen(display));
-
		packing_append_buffer(pkg_archive, comment, "+COMMENT", strlen(comment));
+
		snprintf(oldcomment, sizeof(oldcomment), "%s\n", comment);
+
		packing_append_buffer(pkg_archive, oldcomment, "+COMMENT", strlen(oldcomment));
	} else {
		pkg_register_shlibs(pkg);

@@ -198,14 +200,8 @@ static const char * const scripts[] = {
};

int
-
pkg_create_oldstaged(const char *outdir __unused, pkg_formats format __unused, const char *rootdir __unused,
-
    const char *md_dir __unused, char *plist __unused)
-
{
-
	return (EPKG_OK);
-
}
-
int
pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
-
    const char *md_dir, char *plist)
+
    const char *md_dir, char *plist, bool old)
{
	struct pkg	*pkg = NULL;
	struct pkg_file	*file = NULL;
@@ -226,7 +222,7 @@ pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
	if (snprintf(path, sizeof(path), "%s/+MANIFEST", md_dir) == -1)
		goto cleanup;

-
	pkg_new(&pkg, PKG_FILE);
+
	pkg_new(&pkg, old ? PKG_OLD_FILE : PKG_FILE);
	if (pkg == NULL)
		goto cleanup;

@@ -242,7 +238,7 @@ pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
		if (snprintf(path, sizeof(path), "%s/+DESC", md_dir) == -1)
			goto cleanup;
		if (access(path, F_OK) == 0)
-
			pkg_set_from_file(pkg, PKG_DESC, path);
+
			pkg_set_from_file(pkg, PKG_DESC, path, false);
	}

	/* if no message try to get it from a file */
@@ -252,7 +248,7 @@ pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
		if (ret == -1)
			goto cleanup;
		if (access(path, F_OK) == 0)
-
			pkg_set_from_file(pkg, PKG_MESSAGE, path);
+
			pkg_set_from_file(pkg, PKG_MESSAGE, path, false);
	}

	/* if no arch autodetermine it */
@@ -269,7 +265,7 @@ pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
		if (ret == -1)
			goto cleanup;
		if (access(path, F_OK) == 0)
-
			pkg_set_from_file(pkg, PKG_MTREE, path);
+
			pkg_set_from_file(pkg, PKG_MTREE, path, false);
	}

	for (i = 0; scripts[i] != NULL; i++) {
modified libpkg/pkg_delete.c
@@ -97,20 +97,22 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags)
	if (handle_rc)
		pkg_start_stop_rc_scripts(pkg, PKG_RC_STOP);

-
	if (flags & PKG_DELETE_UPGRADE) {
-
		ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_UPGRADE);
-
		if (ret != EPKG_OK)
-
			return (ret);
-
	} else {
-
		ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL);
-
		if (ret != EPKG_OK)
-
			return (ret);
+
	if ((flags & PKG_DELETE_NOSCRIPT) == 0) {
+
		if (flags & PKG_DELETE_UPGRADE) {
+
			ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_UPGRADE);
+
			if (ret != EPKG_OK)
+
				return (ret);
+
		} else {
+
			ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL);
+
			if (ret != EPKG_OK)
+
				return (ret);
+
		}
	}

	if ((ret = pkg_delete_files(pkg, flags & PKG_DELETE_FORCE)) != EPKG_OK)
		return (ret);

-
	if ((flags & PKG_DELETE_UPGRADE) == 0) {
+
	if ((flags & (PKG_DELETE_NOSCRIPT | PKG_DELETE_UPGRADE)) == 0) {
		ret = pkg_script_run(pkg, PKG_SCRIPT_POST_DEINSTALL);
		if (ret != EPKG_OK)
			return (ret);
modified libpkg/pkg_elf.c
@@ -43,6 +43,7 @@
#ifndef BUNDLED_LIBELF
#include <link.h>
#endif
+
#include <paths.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
@@ -554,8 +555,8 @@ pkg_get_myarch(char *dest, size_t sz)
		return (EPKG_FATAL);
	}

-
	if ((fd = open("/bin/sh", O_RDONLY)) < 0) {
-
		pkg_emit_errno("open", "/bin/sh");
+
	if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
+
		pkg_emit_errno("open", _PATH_BSHELL);
		snprintf(dest, sz, "%s", "unknown");
		return (EPKG_FATAL);
	}
modified libpkg/pkg_event.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -25,14 +25,299 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

+
#include <errno.h>
+
#include <string.h>
#include <syslog.h>

+
#define _WITH_DPRINTF
#include "pkg.h"
+
#include "private/pkg.h"
#include "private/event.h"

static pkg_event_cb _cb = NULL;
static void *_data = NULL;

+
static char *
+
sbuf_json_escape(struct sbuf *buf, const char *str)
+
{
+
	sbuf_clear(buf);
+
	while (*str != '\0') {
+
		if (*str == '"' || *str == '\\')
+
			sbuf_putc(buf, '\\');
+
		sbuf_putc(buf, *str);
+
		str++;
+
	}
+
	sbuf_finish(buf);
+

+
	return (sbuf_data(buf));
+
}
+

+
static void
+
pipeevent(struct pkg_event *ev)
+
{
+
	struct pkg *pkg = NULL;
+
	struct pkg_dep *dep = NULL;
+
	struct sbuf *msg, *buf;
+
	const char *message;
+
	const char *name, *version, *newversion;
+

+
	if (eventpipe < 0)
+
		return;
+

+
	msg = sbuf_new_auto();
+
	buf = sbuf_new_auto();
+

+
	switch(ev->type) {
+
	case PKG_EVENT_ERRNO:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR\", "
+
		    "\"data\": {"
+
		    "\"msg\": \"%s(%s): %s\","
+
		    "\"errno\": %d}}",
+
		    sbuf_json_escape(buf, ev->e_errno.func),
+
		    sbuf_json_escape(buf, ev->e_errno.arg),
+
		    sbuf_json_escape(buf, strerror(ev->e_errno.no)),
+
		    ev->e_errno.no);
+
		break;
+
	case PKG_EVENT_ERROR:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR\", "
+
		    "\"data\": {\"msg\": \"%s\"}}",
+
		    sbuf_json_escape(buf, ev->e_pkg_error.msg));
+
		break;
+
	case PKG_EVENT_DEVELOPER_MODE:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR\", "
+
		    "\"data\": {\"msg\": \"DEVELOPER_MODE: %s\"}}",
+
		    sbuf_json_escape(buf, ev->e_pkg_error.msg));
+
		break;
+
	case PKG_EVENT_FETCHING:
+
		sbuf_printf(msg, "{ \"type\": \"INFO_FETCH\", "
+
		    "\"data\": { "
+
		    "\"url\": \"%s\", "
+
		    "\"fetched\": %" PRId64 ", "
+
		    "\"total\": %" PRId64
+
		    "}}",
+
		    sbuf_json_escape(buf, ev->e_fetching.url),
+
		    ev->e_fetching.done,
+
		    ev->e_fetching.total
+
		    );
+
		break;
+
	case PKG_EVENT_INSTALL_BEGIN:
+
		pkg_get(ev->e_install_begin.pkg, PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_INSTALL_BEGIN\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version
+
		    );
+
		break;
+
	case PKG_EVENT_INSTALL_FINISHED:
+
		pkg_get(ev->e_install_finished.pkg,
+
		    PKG_MESSAGE, &message,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_INSTALL_FINISHED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\", "
+
		    "\"message\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version,
+
		    sbuf_json_escape(buf, message));
+
		break;
+
	case PKG_EVENT_INTEGRITYCHECK_BEGIN:
+
		sbuf_printf(msg, "{ \"type\": \"INFO_INTEGRITYCHECK_BEGIN\", "
+
		    "\"data\": {}}");
+
		break;
+
	case PKG_EVENT_INTEGRITYCHECK_FINISHED:
+
		sbuf_printf(msg, "{ \"type\": \"INFO_INTEGRITYCHECK_FINISHED\", "
+
		    "\"data\": {}}");
+
		break;
+
	case PKG_EVENT_DEINSTALL_BEGIN:
+
		pkg_get(ev->e_deinstall_begin.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_DEINSTALL_BEGIN\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version);
+
		break;
+
	case PKG_EVENT_DEINSTALL_FINISHED:
+
		pkg_get(ev->e_deinstall_finished.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_DEINSTALL_FINISHED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version);
+
		break;
+
	case PKG_EVENT_UPGRADE_BEGIN:
+
		pkg_get(ev->e_upgrade_begin.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version,
+
		    PKG_NEWVERSION, &newversion);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_UPGRADE_BEGIN\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\" ,"
+
		    "\"pkgnewversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version,
+
		    newversion);
+
		break;
+
	case PKG_EVENT_UPGRADE_FINISHED:
+
		pkg_get(ev->e_upgrade_finished.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version,
+
		    PKG_NEWVERSION, &newversion);
+

+
		sbuf_printf(msg, "{ \"type\": \"INFO_UPGRADE_FINISHED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\" ,"
+
		    "\"pkgnewversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version,
+
		    newversion);
+
		break;
+
	case PKG_EVENT_LOCKED:
+
		pkg_get(ev->e_locked.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_LOCKED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version);
+
		break;
+
	case PKG_EVENT_REQUIRED:
+
		pkg_get(ev->e_required.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_REQUIRED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\", "
+
		    "\"force\": %s, "
+
		    "\"required_by\": [",
+
		    name,
+
		    version,
+
		    ev->e_required.force == 1 ? "true": "false");
+
		while (pkg_rdeps(pkg, &dep) == EPKG_OK)
+
			sbuf_printf(msg, "{ \"pkgname\": \"%s\", "
+
			    "\"pkgversion\": \"%s\" }, ",
+
			    pkg_dep_name(dep),
+
			    pkg_dep_version(dep));
+
		sbuf_setpos(msg, sbuf_len(msg) - 2);
+
		sbuf_cat(msg, "]}}");
+
		break;
+
	case PKG_EVENT_ALREADY_INSTALLED:
+
		pkg_get(ev->e_already_installed.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_ALREADY_INSTALLED\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version);
+
		break;
+
	case PKG_EVENT_MISSING_DEP:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_MISSING_DEP\", "
+
		    "\"data\": { "
+
		    "\"depname\": \"%s\", "
+
		    "\"depversion\": \"%s\""
+
		    "}}" ,
+
		    pkg_dep_name(ev->e_missing_dep.dep),
+
		    pkg_dep_version(ev->e_missing_dep.dep));
+
		break;
+
	case PKG_EVENT_NOREMOTEDB:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_NOREMOTEDB\", "
+
		    "\"data\": { "
+
		    "\"url\": \"%s\" "
+
		    "}}" ,
+
		    ev->e_remotedb.repo);
+
		break;
+
	case PKG_EVENT_NOLOCALDB:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_NOLOCALDB\", "
+
		    "\"data\": {} ");
+
		break;
+
	case PKG_EVENT_NEWPKGVERSION:
+
		sbuf_printf(msg, "{ \"type\": \"INFO_NEWPKGVERSION\", "
+
		    "\"data\": {} ");
+
		break;
+
	case PKG_EVENT_FILE_MISMATCH:
+
		pkg_get(ev->e_file_mismatch.pkg,
+
		    PKG_NAME, &name,
+
		    PKG_VERSION, &version);
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_FILE_MISMATCH\", "
+
		    "\"data\": { "
+
		    "\"pkgname\": \"%s\", "
+
		    "\"pkgversion\": \"%s\", "
+
		    "\"path\": \"%s\""
+
		    "}}",
+
		    name,
+
		    version,
+
		    sbuf_json_escape(buf, pkg_file_path(ev->e_file_mismatch.file)));
+
		break;
+
	case PKG_EVENT_PLUGIN_ERRNO:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_PLUGIN\", "
+
		    "\"data\": {"
+
		    "\"plugin\": \"%s\", "
+
		    "\"msg\": \"%s(%s): %s\","
+
		    "\"errno\": %d"
+
		    "}}",
+
		    pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
+
		    sbuf_json_escape(buf, ev->e_plugin_errno.func),
+
		    sbuf_json_escape(buf, ev->e_plugin_errno.arg),
+
		    sbuf_json_escape(buf, strerror(ev->e_plugin_errno.no)),
+
		    ev->e_plugin_errno.no);
+
		break;
+
	case PKG_EVENT_PLUGIN_ERROR:
+
		sbuf_printf(msg, "{ \"type\": \"ERROR_PLUGIN\", "
+
		    "\"data\": {"
+
		    "\"plugin\": \"%s\", "
+
		    "\"msg\": \"%s\""
+
		    "}}",
+
		    pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
+
		    sbuf_json_escape(buf, ev->e_plugin_error.msg));
+
		break;
+
	case PKG_EVENT_PLUGIN_INFO:
+
		sbuf_printf(msg, "{ \"type\": \"INFO_PLUGIN\", "
+
		    "\"data\": {"
+
		    "\"plugin\": \"%s\", "
+
		    "\"msg\": \"%s\""
+
		    "}}",
+
		    pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
+
		    sbuf_json_escape(buf, ev->e_plugin_info.msg));
+
		break;
+
	default:
+
		break;
+
	}
+
	sbuf_finish(msg);
+
	dprintf(eventpipe, "%s\n", sbuf_data(msg));
+
	sbuf_delete(msg);
+
	sbuf_delete(buf);
+
}
+

void
pkg_event_register(pkg_event_cb cb, void *data)
{
@@ -46,6 +331,7 @@ pkg_emit_event(struct pkg_event *ev)
	pkg_plugins_hook_run(PKG_PLUGIN_HOOK_EVENT, ev, NULL);
	if (_cb != NULL)
		_cb(_data, ev);
+
	pipeevent(ev);
}

void
@@ -88,6 +374,7 @@ pkg_emit_errno(const char *func, const char *arg)
	ev.type = PKG_EVENT_ERRNO;
	ev.e_errno.func = func;
	ev.e_errno.arg = arg;
+
	ev.e_errno.no = errno;

	pkg_emit_event(&ev);
}
@@ -110,9 +397,9 @@ pkg_emit_fetching(const char *url, off_t total, off_t done, time_t elapsed)

	ev.type = PKG_EVENT_FETCHING;
	ev.e_fetching.url = url;
-
        ev.e_fetching.total = total;
-
        ev.e_fetching.done = done;
-
        ev.e_fetching.elapsed = elapsed;
+
	ev.e_fetching.total = total;
+
	ev.e_fetching.done = done;
+
	ev.e_fetching.elapsed = elapsed;

	pkg_emit_event(&ev);
}
@@ -320,6 +607,7 @@ pkg_plugin_errno(struct pkg_plugin *p, const char *func, const char *arg)
	ev.e_plugin_errno.plugin = p;
	ev.e_plugin_errno.func = func;
	ev.e_plugin_errno.arg = arg;
+
	ev.e_plugin_errno.no = errno;

	pkg_emit_event(&ev);
}
modified libpkg/pkg_jobs.c
@@ -2,6 +2,7 @@
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
@@ -36,10 +37,6 @@
#include <stdlib.h>
#include <string.h>

-
#ifdef __DragonFly__
-
#define STAILQ_FOREACH_SAFE STAILQ_FOREACH_MUTABLE
-
#endif
-

#include "pkg.h"
#include "private/event.h"
#include "private/pkg.h"
@@ -62,7 +59,6 @@ pkg_jobs_new(struct pkg_jobs **j, pkg_jobs_t t, struct pkgdb *db)
	(*j)->type = t;
	(*j)->solved = false;
	(*j)->flags = PKG_FLAG_NONE;
-
	STAILQ_INIT(&(*j)->patterns);

	return (EPKG_OK);
}
@@ -85,8 +81,6 @@ pkg_jobs_set_repository(struct pkg_jobs *j, const char *name)
void
pkg_jobs_free(struct pkg_jobs *j)
{
-
	struct job_pattern *jp;
-

	if (j == NULL)
		return;

@@ -94,7 +88,7 @@ pkg_jobs_free(struct pkg_jobs *j)
		pkgdb_release_lock(j->db);

	HASH_FREE(j->jobs, pkg, pkg_free);
-
	LIST_FREE(&j->patterns, jp, free);
+
	LL_FREE(j->patterns, job_pattern, free);

	free(j);
}
@@ -114,7 +108,7 @@ pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc)
	jp->pattern = argv;
	jp->nb = argc;
	jp->match = match;
-
	STAILQ_INSERT_TAIL(&j->patterns, jp, next);
+
	LL_APPEND(j->patterns, jp);

	return (EPKG_OK);
}
@@ -131,7 +125,7 @@ jobs_solve_deinstall(struct pkg_jobs *j)
	if ((j->flags & PKG_FLAG_RECURSIVE) == PKG_FLAG_RECURSIVE)
		recursive = true;

-
	STAILQ_FOREACH(jp, &j->patterns, next) {
+
	LL_FOREACH(j->patterns, jp) {
		if ((it = pkgdb_query_delete(j->db, jp->match, jp->nb,
		    jp->pattern, recursive)) == NULL)
			return (EPKG_FATAL);
@@ -176,14 +170,23 @@ jobs_solve_upgrade(struct pkg_jobs *j)
	struct pkgdb_it *it;
	char *origin;
	bool all = false;
+
	bool pkgversiontest = false;
+
	unsigned flags = PKG_LOAD_BASIC;

	if ((j->flags & PKG_FLAG_FORCE) != 0)
		all = true;

-
	if ((it = pkgdb_query_upgrades(j->db, j->reponame, all)) == NULL)
+
	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) != 0)
+
		pkgversiontest = true;
+

+
	if ((j->flags & PKG_FLAG_WITH_DEPS) != 0)
+
		flags |= PKG_LOAD_DEPS;
+

+
	if ((it = pkgdb_query_upgrades(j->db, j->reponame, all,
+
	        pkgversiontest)) == NULL)
		return (EPKG_FATAL);

-
	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
+
	while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
		pkg_get(pkg, PKG_ORIGIN, &origin);
		HASH_ADD_KEYPTR(hh, j->jobs, origin, strlen(origin), pkg);
		pkg = NULL;
@@ -203,17 +206,21 @@ jobs_solve_install(struct pkg_jobs *j)
	char *origin;
	bool force = false;
	bool recursive = false;
+
	bool pkgversiontest = false;

-

-
	if ((j->flags & PKG_FLAG_FORCE) == PKG_FLAG_FORCE)
+
	if ((j->flags & PKG_FLAG_FORCE) != 0)
		force = true;

-
	if ((j->flags & PKG_FLAG_RECURSIVE) == PKG_FLAG_RECURSIVE)
+
	if ((j->flags & PKG_FLAG_RECURSIVE) != 0)
		recursive = true;

-
	STAILQ_FOREACH(jp, &j->patterns, next) {
+
	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) != 0)
+
		pkgversiontest = true;
+

+
	LL_FOREACH(j->patterns, jp) {
		if ((it = pkgdb_query_installs(j->db, jp->match, jp->nb,
-
		    jp->pattern, j->reponame, force, recursive)) == NULL)
+
		        jp->pattern, j->reponame, force, recursive,
+
			pkgversiontest)) == NULL)
			return (EPKG_FATAL);

		while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
@@ -239,10 +246,13 @@ jobs_solve_fetch(struct pkg_jobs *j)
	char *origin;
	unsigned flag = PKG_LOAD_BASIC;

+
	if ((j->flags & PKG_FLAG_UPGRADES_FOR_INSTALLED) != 0)
+
		return (jobs_solve_upgrade(j));
+

	if ((j->flags & PKG_FLAG_WITH_DEPS) != 0)
		flag |= PKG_LOAD_DEPS;

-
	STAILQ_FOREACH(jp, &j->patterns, next) {
+
	LL_FOREACH(j->patterns, jp) {
		if ((it = pkgdb_query_fetch(j->db, jp->match, jp->nb,
		    jp->pattern, j->reponame, flag)) == NULL)
			return (EPKG_FATAL);
@@ -355,7 +365,7 @@ pkg_jobs_install(struct pkg_jobs *j)
	struct pkg *newpkg = NULL;
	struct pkg *pkg_temp = NULL;
	struct pkgdb_it *it = NULL;
-
	STAILQ_HEAD(,pkg) pkg_queue;
+
	struct pkg *pkg_queue = NULL;
	char path[MAXPATHLEN + 1];
	const char *cachedir = NULL;
	int flags = 0;
@@ -364,8 +374,6 @@ pkg_jobs_install(struct pkg_jobs *j)
	    PKG_LOAD_DIRS;
	bool handle_rc = false;

-
	STAILQ_INIT(&pkg_queue);
-

	/* Fetch */
	if (pkg_jobs_fetch(j) != EPKG_OK)
		return (EPKG_FATAL);
@@ -401,9 +409,10 @@ pkg_jobs_install(struct pkg_jobs *j)
						goto cleanup; /* Bail out */
					}

-
					STAILQ_INSERT_TAIL(&pkg_queue, pkg, next);
-
					pkg_script_run(pkg,
-
					    PKG_SCRIPT_PRE_DEINSTALL);
+
					LL_APPEND(pkg_queue, pkg);
+
					if ((j->flags & PKG_FLAG_NOSCRIPT) == 0)
+
						pkg_script_run(pkg,
+
						    PKG_SCRIPT_PRE_DEINSTALL);
					pkg_get(pkg, PKG_ORIGIN, &origin);
					/*
					 * stop the different related services
@@ -435,8 +444,10 @@ pkg_jobs_install(struct pkg_jobs *j)
					goto cleanup; /* Bail out */
				}

-
				STAILQ_INSERT_TAIL(&pkg_queue, pkg, next);
-
				pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL);
+
				LL_APPEND(pkg_queue, pkg);
+
				if ((j->flags & PKG_FLAG_NOSCRIPT) == 0)
+
					pkg_script_run(pkg,
+
					    PKG_SCRIPT_PRE_DEINSTALL);
				pkg_get(pkg, PKG_ORIGIN, &origin);
				/*
				 * stop the different related services if the
@@ -458,15 +469,17 @@ pkg_jobs_install(struct pkg_jobs *j)
		} else {
			pkg_emit_install_begin(newpkg);
		}
-
		STAILQ_FOREACH(pkg, &pkg_queue, next)
+
		LL_FOREACH(pkg_queue, pkg)
			pkg_jobs_keep_files_to_del(pkg, newpkg);

-
		STAILQ_FOREACH_SAFE(pkg, &pkg_queue, next, pkg_temp) {
+
		LL_FOREACH_SAFE(pkg_queue, pkg, pkg_temp) {
			pkg_get(pkg, PKG_ORIGIN, &origin);
			if (strcmp(pkgorigin, origin) == 0) {
-
				STAILQ_REMOVE(&pkg_queue, pkg, pkg, next);
+
				LL_DELETE(pkg_queue, pkg);
				pkg_delete_files(pkg, 1);
-
				pkg_script_run(pkg, PKG_SCRIPT_POST_DEINSTALL);
+
				if ((j->flags & PKG_FLAG_NOSCRIPT) == 0)
+
					pkg_script_run(pkg,
+
					    PKG_SCRIPT_POST_DEINSTALL);
				pkg_delete_dirs(j->db, pkg, 0);
				pkg_free(pkg);
				break;
@@ -475,6 +488,8 @@ pkg_jobs_install(struct pkg_jobs *j)

		if ((j->flags & PKG_FLAG_FORCE) != 0)
			flags |= PKG_ADD_FORCE;
+
		if ((j->flags & PKG_FLAG_NOSCRIPT) != 0)
+
			flags |= PKG_ADD_NOSCRIPT;
		flags |= PKG_ADD_UPGRADE;
		if (automatic)
			flags |= PKG_ADD_AUTOMATIC;
@@ -489,7 +504,7 @@ pkg_jobs_install(struct pkg_jobs *j)
		else
			pkg_emit_install_finished(newpkg);

-
		if (STAILQ_EMPTY(&pkg_queue)) {
+
		if (pkg_queue == NULL) {
			pkgdb_transaction_commit(j->db->sqlite, "upgrade");
			pkgdb_transaction_begin(j->db->sqlite, "upgrade");
		}
@@ -517,6 +532,9 @@ pkg_jobs_deinstall(struct pkg_jobs *j)
	if ((j->flags & PKG_FLAG_FORCE) != 0)
		flags = PKG_DELETE_FORCE;

+
	if ((j->flags & PKG_FLAG_NOSCRIPT) != 0)
+
		flags |= PKG_DELETE_NOSCRIPT;
+

	while (pkg_jobs(j, &p) == EPKG_OK) {
		retcode = pkg_delete(p, j->db, flags);

modified libpkg/pkg_old.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,7 @@ pkg_old_load_from_path(struct pkg *pkg, const char *path)
	regmatch_t pmatch[2];
	int i;
	size_t size;
+
	char myarch[BUFSIZ];

	if (!is_dir(path))
		return (EPKG_FATAL);
@@ -72,19 +73,19 @@ pkg_old_load_from_path(struct pkg *pkg, const char *path)

	snprintf(fpath, MAXPATHLEN, "%s/+COMMENT", path);
	if (access(fpath, F_OK) == 0)
-
		pkg_set_from_file(pkg, PKG_COMMENT, fpath);
+
		pkg_set_from_file(pkg, PKG_COMMENT, fpath, true);

	snprintf(fpath, sizeof(fpath), "%s/+DESC", path);
	if (access(fpath, F_OK) == 0)
-
		pkg_set_from_file(pkg, PKG_DESC, fpath);
+
		pkg_set_from_file(pkg, PKG_DESC, fpath, false);

	snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", path);
	if (access(fpath, F_OK) == 0)
-
		pkg_set_from_file(pkg, PKG_MESSAGE, fpath);
+
		pkg_set_from_file(pkg, PKG_MESSAGE, fpath, false);

	snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", path);
	if (access(fpath, F_OK) == 0)
-
		pkg_set_from_file(pkg, PKG_MTREE, fpath);
+
		pkg_set_from_file(pkg, PKG_MTREE, fpath, false);

	for (i = 0; scripts[i] != NULL; i++) {
		snprintf(fpath, sizeof(fpath), "%s/%s", path, scripts[i]);
@@ -92,6 +93,9 @@ pkg_old_load_from_path(struct pkg *pkg, const char *path)
			pkg_addscript_file(pkg, fpath);
	}

+
	pkg_set(pkg, PKG_ARCH, pkg_get_myarch(myarch, BUFSIZ));
+
	pkg_set(pkg, PKG_MAINTAINER, "unknown");
+
	pkg_get_myarch(myarch, BUFSIZ);
	pkg_get(pkg, PKG_DESC, &desc);
	regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE);
	if (regexec(&preg, desc, 2, pmatch, 0) == 0) {
@@ -204,3 +208,132 @@ pkg_from_old(struct pkg *p)

	return (EPKG_OK);
}
+

+
int
+
pkg_register_old(struct pkg *pkg)
+
{
+
	FILE *fp;
+
	char *name, *version, *content, *buf;
+
	const char *pkgdbdir, *tmp;
+
	char path[MAXPATHLEN];
+
	struct sbuf *install_script = sbuf_new_auto();
+
	struct sbuf *deinstall_script = sbuf_new_auto();
+
	struct pkg_dep *dep = NULL;
+

+
	pkg_to_old(pkg);
+
	pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version);
+
	pkg_old_emit_content(pkg, &content);
+

+
	pkg_config_string(PKG_CONFIG_DBDIR, &pkgdbdir);
+
	snprintf(path, MAXPATHLEN, "%s/%s-%s", pkgdbdir, name, version);
+
	mkdir(path, 0755);
+

+
	snprintf(path, MAXPATHLEN, "%s/%s-%s/+CONTENTS", pkgdbdir, name, version);
+
	fp = fopen(path, "w");
+
	fputs(content, fp);
+
	fclose(fp);
+

+
	pkg_get(pkg, PKG_DESC, &buf);
+
	snprintf(path, MAXPATHLEN, "%s/%s-%s/+DESC", pkgdbdir, name, version);
+
	fp = fopen(path, "w");
+
	fputs(buf, fp);
+
	fclose(fp);
+

+
	pkg_get(pkg, PKG_COMMENT, &buf);
+
	snprintf(path, MAXPATHLEN, "%s/%s-%s/+COMMENT", pkgdbdir, name, version);
+
	fp = fopen(path, "w");
+
	fprintf(fp, "%s\n", buf);
+
	fclose(fp);
+

+
	pkg_get(pkg, PKG_MESSAGE, &buf);
+
	if (buf != NULL && *buf != '\0') {
+
		snprintf(path, MAXPATHLEN, "%s/%s-%s/+DISPLAY", pkgdbdir, name, version);
+
		fp = fopen(path, "w");
+
		fputs(buf, fp);
+
		fclose(fp);
+
	}
+

+
	sbuf_clear(install_script);
+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_PRE_INSTALL);
+
	if (tmp != NULL && *tmp != '\0') {
+
		if (sbuf_len(install_script) == 0)
+
			sbuf_cat(install_script, "#!/bin/sh\n\n");
+
		sbuf_printf(install_script,
+
		    "if [ \"$2\" = \"PRE-INSTALL\" ]; then\n"
+
		    "%s\n"
+
		    "fi\n",
+
		    tmp);
+
	}
+

+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_INSTALL);
+
	if (tmp != NULL && *tmp != '\0') {
+
		if (sbuf_len(install_script) == 0)
+
			sbuf_cat(install_script, "#!/bin/sh\n\n");
+
		sbuf_cat(install_script, tmp);
+
	}
+

+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_POST_INSTALL);
+
	if (tmp != NULL && *tmp != '\0') {
+
		if (sbuf_len(install_script) == 0)
+
			sbuf_cat(install_script, "#!/bin/sh\n\n");
+
		sbuf_printf(install_script,
+
		    "if [ \"$2\" = \"POST-INSTALL\" ]; then\n"
+
		    "%s\n"
+
		    "fi\n",
+
		    tmp);
+
	}
+
	if (sbuf_len(install_script) > 0) {
+
		sbuf_finish(install_script);
+
		snprintf(path, MAXPATHLEN, "%s/%s-%s/+INSTALL", pkgdbdir, name, version);
+
		fp = fopen(path, "w");
+
		fputs(sbuf_data(install_script), fp);
+
		fclose(fp);
+
	}
+

+
	sbuf_clear(deinstall_script);
+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_PRE_DEINSTALL);
+
	if (tmp != NULL && *tmp != '\0') {
+
		if (sbuf_len(deinstall_script) == 0)
+
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
+
		sbuf_printf(deinstall_script,
+
		    "if [ \"$2\" = \"DEINSTALL\" ]; then\n"
+
		    "%s\n"
+
		    "fi\n",
+
		    tmp);
+
	}
+

+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_DEINSTALL);
+
	if (tmp != NULL && *tmp != '\0') {
+
		if (sbuf_len(deinstall_script) == 0)
+
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
+
		sbuf_cat(deinstall_script, tmp);
+
	}
+

+
	tmp = pkg_script_get(pkg, PKG_SCRIPT_POST_DEINSTALL);
+
	if (tmp != NULL && tmp[0] != '\0') {
+
		if (sbuf_len(deinstall_script) == 0)
+
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
+
		sbuf_printf(deinstall_script,
+
		    "if [ \"$2\" = \"POST-DEINSTALL\" ]; then\n"
+
		    "%s\n"
+
		    "fi\n",
+
		    tmp);
+
	}
+
	if (sbuf_len(deinstall_script) > 0) {
+
		sbuf_finish(deinstall_script);
+
		snprintf(path, MAXPATHLEN, "%s/%s-%s/+DEINSTALL", pkgdbdir, name, version);
+
		fp = fopen(path, "w");
+
		fputs(sbuf_data(deinstall_script), fp);
+
		fclose(fp);
+
	}
+

+
	while (pkg_deps(pkg, &dep)) {
+
		snprintf(path, MAXPATHLEN, "%s/%s-%s/+REQUIRED_BY", pkgdbdir,
+
		    pkg_dep_name(dep), pkg_dep_version(dep));
+
		fp = fopen(path, "a");
+
		fprintf(fp, "%s-%s\n", name, version);
+
		fclose(fp);
+
	}
+

+
	return (EPKG_OK);
+
}
modified libpkg/pkg_ports.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -46,7 +46,7 @@
struct keyword {
	/* 64 is more than enough for this */
	char keyword[64];
-
	STAILQ_HEAD(, action) actions;
+
	struct action *actions;
	UT_hash_handle hh;
};

@@ -81,7 +81,7 @@ struct file_attr {

struct action {
	int (*perform)(struct plist *, char *, struct file_attr *);
-
	STAILQ_ENTRY(action) next;
+
	struct action *next;
};

static int setprefix(struct plist *, char *, struct file_attr *);
@@ -146,11 +146,18 @@ sbuf_append(struct sbuf *buf, __unused const char *comment, const char *str, ...
static int
setprefix(struct plist *p, char *line, struct file_attr *a)
{
+
	char *pkgprefix;
+

	/* if no arguments then set default prefix */
	if (line[0] == '\0')
		pkg_get(p->pkg, PKG_PREFIX, &p->prefix);
	else
		p->prefix = line;
+

+
	pkg_get(p->pkg, PKG_PREFIX, &pkgprefix);
+
	if (pkgprefix == NULL || *pkgprefix == '\0')
+
		pkg_set(p->pkg, PKG_PREFIX, line);
+

	p->slash = p->prefix[strlen(p->prefix) -1] == '/' ? "" : "/";

	free(a);
@@ -381,7 +388,7 @@ static int
comment_key(struct plist *p, char *line, struct file_attr *a)
{
	char *name, *version;
-
	if (strcmp(line, "DEPORIGIN:") == 0) {
+
	if (strncmp(line, "DEPORIGIN:", 10) == 0) {
		line += 10;
		name = p->pkgdep;
		version = strrchr(name, '-');
@@ -389,7 +396,7 @@ comment_key(struct plist *p, char *line, struct file_attr *a)
		version++;
		pkg_adddep(p->pkg, name, line, version, false);
		p->pkgdep = NULL;
-
	} else if (strcmp(line, "ORIGIN:") == 0) {
+
	} else if (strncmp(line, "ORIGIN:", 7) == 0) {
		line += 7;
		pkg_set(p->pkg, PKG_ORIGIN, line);
	}
@@ -524,142 +531,51 @@ unexec(struct plist *p, char *line, struct file_attr *a)
	return (meta_exec(p, line, a, true));
}

+
static struct keyact {
+
	const char *key;
+
	int (*action)(struct plist *, char *, struct file_attr *);
+
} keyacts[] = {
+
	{ "cwd", setprefix },
+
	{ "ignore", ignore_next },
+
	{ "comment", comment_key },
+
	{ "dirrm", dirrm },
+
	{ "dirrmtry", dirrmtry },
+
	{ "mode", setmod },
+
	{ "owner", setowner },
+
	{ "group", setgroup },
+
	{ "exec", exec },
+
	{ "unexec", unexec },
+
	/* old pkg compat */
+
	{ "name", name_key },
+
	{ "pkgdep", pkgdep },
+
	{ NULL, NULL },
+
};
+

static void
populate_keywords(struct plist *p)
{
	struct keyword *k;
	struct action *a;
+
	int i;

-
	/* @cwd */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "cwd", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = setprefix;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @ignore */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "ignore", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = ignore_next;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @comment */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "comment", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = comment_key;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @dirrm */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "dirrm", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = dirrm;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @dirrmtry */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "dirrmtry", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = dirrmtry;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @mode */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "mode", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = setmod;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @owner */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "owner", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = setowner;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @group */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "group", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = setgroup;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @exec */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "exec", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = exec;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @unexec */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "unexec", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = unexec;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* old pkg compat */
-

-
	/* @name */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "name", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = name_key;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
-

-
	/* @pkgdep */
-
	k = malloc(sizeof(struct keyword));
-
	a = malloc(sizeof(struct action));
-
	strlcpy(k->keyword, "pkgdep", sizeof(k->keyword));
-
	STAILQ_INIT(&k->actions);
-
	a->perform = pkgdep;
-
	STAILQ_INSERT_TAIL(&k->actions, a, next);
-
	HASH_ADD_STR(p->keywords, keyword, k);
+
	for (i = 0; keyacts[i].key != NULL; i++) {
+
		k = calloc(1, sizeof(struct keyword));
+
		a = malloc(sizeof(struct action));
+
		strlcpy(k->keyword, keyacts[i].key, sizeof(k->keyword));
+
		a->perform = keyacts[i].action;
+
		LL_APPEND(k->actions, a);
+
		HASH_ADD_STR(p->keywords, keyword, k);
+
	}
}

static void
keyword_free(struct keyword *k)
{
-
	struct action *a;
-

-
	LIST_FREE(&k->actions, a, free);
+
	LL_FREE(k->actions, action, free);

	free(k);
}

-
static void
-
plist_free(struct plist *p)
-
{
-
	struct keyword *k, *tmp;
-
	HASH_ITER(hh, p->keywords, k, tmp) {
-
		HASH_DEL(p->keywords, k);
-
		keyword_free(k);
-
	}
-
}

static int
parse_actions(yaml_document_t *doc, yaml_node_t *node, struct plist *p,
@@ -967,7 +883,7 @@ parse_keywords(struct plist *plist, char *keyword, char *line)

	HASH_FIND_STR(plist->keywords, keyword, k);
	if (k != NULL) {
-
		STAILQ_FOREACH(a, &k->actions, next) {
+
		LL_FOREACH(k->actions, a) {
			ret = a->perform(plist, line, attr);
			if (ret != EPKG_OK)
				return (ret);
@@ -999,7 +915,6 @@ ports_parse_plist(struct pkg *pkg, char *plist, const char *stage)
	char *plist_buf, *walk, *buf, *token;
	int ret = EPKG_OK;
	off_t sz = 0;
-
	struct hardlinks hardlinks = {NULL, 0, 0};
	struct plist pplist;

	assert(pkg != NULL);
@@ -1021,7 +936,7 @@ ports_parse_plist(struct pkg *pkg, char *plist, const char *stage)
	pplist.pkg = pkg;
	pplist.slash = "";
	pplist.ignore_next = false;
-
	pplist.hardlinks = &hardlinks;
+
	pplist.hardlinks = NULL;
	pplist.flatsize = 0;
	pplist.keywords = NULL;

@@ -1107,10 +1022,10 @@ ports_parse_plist(struct pkg *pkg, char *plist, const char *stage)
	flush_script_buffer(pplist.post_upgrade_buf, pkg,
	    PKG_SCRIPT_POST_UPGRADE);

-
	free(hardlinks.inodes);
+
	HASH_FREE(pplist.hardlinks, hardlinks, free);

	free(plist_buf);
-
	plist_free(&pplist);
+
	HASH_FREE(pplist.keywords, keyword, keyword_free);

	return (ret);
}
modified libpkg/pkg_repo.c
@@ -637,7 +637,7 @@ pkg_create_repo(char *path, bool force,
	thd_data.stop = false;
	thd_data.fts = fts;
	pthread_mutex_init(&thd_data.fts_m, NULL);
-
	STAILQ_INIT(&thd_data.results);
+
	thd_data.results = NULL;
	thd_data.thd_finished = 0;
	pthread_mutex_init(&thd_data.results_m, NULL);
	pthread_cond_init(&thd_data.has_result, NULL);
@@ -658,14 +658,14 @@ pkg_create_repo(char *path, bool force,
		lic_t licenselogic;

		pthread_mutex_lock(&thd_data.results_m);
-
		while ((r = STAILQ_FIRST(&thd_data.results)) == NULL) {
+
		while ((r = thd_data.results) == NULL) {
			if (thd_data.thd_finished == num_workers) {
				break;
			}
			pthread_cond_wait(&thd_data.has_result, &thd_data.results_m);
		}
		if (r != NULL) {
-
			STAILQ_REMOVE_HEAD(&thd_data.results, next);
+
			LL_DELETE(thd_data.results, thd_data.results);
			thd_data.num_results--;
			pthread_cond_signal(&thd_data.has_room);
		}
@@ -916,7 +916,7 @@ read_pkg_file(void *data)
		while (d->num_results >= d->max_results) {
			pthread_cond_wait(&d->has_room, &d->results_m);
		}
-
		STAILQ_INSERT_TAIL(&d->results, r, next);
+
		LL_APPEND(d->results, r);
		d->num_results++;
		pthread_cond_signal(&d->has_result);
		pthread_mutex_unlock(&d->results_m);
modified libpkg/pkgdb.c
@@ -6,6 +6,7 @@
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
 * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
+
 * Copyright (c) 2013 Gerald Pfeifer <gerald@pfeifer.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -169,7 +170,7 @@ pkgdb_get_reponame(struct pkgdb *db, const char *repo)
			reponame = repo;
		} else {
			/* default repository in multi-repos is 'default' */
-
			reponame = "default";
+
			reponame = "remote-default";
		}
	} else {
		if (repo != NULL && strcmp(repo, "repo") &&
@@ -250,8 +251,15 @@ pkgdb_regex(sqlite3_context *ctx, int argc, sqlite3_value **argv)

	re = (regex_t *)sqlite3_get_auxdata(ctx, 0);
	if (re == NULL) {
+
		int cflags;
+

+
		if (pkgdb_case_sensitive())
+
			cflags = REG_EXTENDED | REG_NOSUB;
+
		else
+
			cflags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
+

		re = malloc(sizeof(regex_t));
-
		if (regcomp(re, regex, REG_EXTENDED | REG_NOSUB) != 0) {
+
		if (regcomp(re, regex, cflags) != 0) {
			sqlite3_result_error(ctx, "Invalid regex\n", -1);
			free(re);
			return;
@@ -640,13 +648,6 @@ pkgdb_open_multirepos(const char *dbdir, struct pkgdb *db)
		const char *repo_name = pkg_config_kv_get(repokv,
		    PKG_CONFIG_KV_KEY);

-
		/* is it a reserved name? */
-
		if ((strcmp(repo_name, "repo") == 0) ||
-
		    (strcmp(repo_name, "main") == 0) ||
-
		    (strcmp(repo_name, "temp") == 0) ||
-
		    (strcmp(repo_name, "local") == 0))
-
			continue;
-

		/* is it already attached? */
		if (is_attached(db->sqlite, repo_name)) {
			pkg_emit_error("repository '%s' is already "
@@ -654,7 +655,7 @@ pkgdb_open_multirepos(const char *dbdir, struct pkgdb *db)
			continue;
		}

-
		snprintf(remotepath, sizeof(remotepath), "%s/%s.sqlite",
+
		snprintf(remotepath, sizeof(remotepath), "%s/repo-%s.sqlite",
		    dbdir, repo_name);

		if (access(remotepath, R_OK) != 0) {
@@ -663,7 +664,7 @@ pkgdb_open_multirepos(const char *dbdir, struct pkgdb *db)
			return (EPKG_ENODB);
		}

-
		ret = sql_exec(db->sqlite, "ATTACH '%s' AS '%s';",
+
		ret = sql_exec(db->sqlite, "ATTACH '%s' AS 'remote-%s';",
		    remotepath, repo_name);
		if (ret != EPKG_OK) {
			pkgdb_close(db);
@@ -688,7 +689,7 @@ pkgdb_open_multirepos(const char *dbdir, struct pkgdb *db)
		}

		/* check if default repository exists */
-
		if (!is_attached(db->sqlite, "default")) {
+
		if (!is_attached(db->sqlite, "remote-default")) {
			pkg_emit_error("no default repository defined");
			pkgdb_close(db);
			return (EPKG_FATAL);
@@ -700,18 +701,18 @@ pkgdb_open_multirepos(const char *dbdir, struct pkgdb *db)
static int
file_mode_insecure(const char *path, bool install_as_user)
{
-
	uid_t		euid;
-
	gid_t		egid;
+
	uid_t		fileowner;
+
	gid_t		filegroup;
	bool		bad_perms = false;
	bool		wrong_owner = false;
	struct stat	sb;

	if (install_as_user) {
-
		euid = geteuid();
-
		egid = getegid();
+
		fileowner = geteuid();
+
		filegroup = getegid();
	} else {
-
		euid = 0;
-
		egid = 0;
+
		fileowner = 0;
+
		filegroup = 0;
	}

	if (stat(path, &sb) != 0) {
@@ -723,21 +724,22 @@ file_mode_insecure(const char *path, bool install_as_user)
			return (EPKG_FATAL);
	}

-
	/* if euid == 0, root ownership and no group or other read
-
	   access.  if euid != 0, require no other read access and
-
	   group read access IFF the group ownership == egid */
+
	/* if fileowner == 0, root ownership and no group or other
+
	   read access.  if fileowner != 0, require no other read
+
	   access and group read access IFF the group ownership ==
+
	   filegroup */

-
	if ( euid == 0 ) {
+
	if ( fileowner == 0 ) {
		if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
			bad_perms = true;
-
		if (sb.st_uid != euid)
+
		if (sb.st_uid != fileowner)
			wrong_owner = true;
	} else {
		if ((sb.st_mode & S_IWOTH) != 0)
			bad_perms = true;
-
		if (sb.st_gid != egid && (sb.st_mode & S_IWGRP) != 0)
+
		if (sb.st_gid != filegroup && (sb.st_mode & S_IWGRP) != 0)
			bad_perms = true;
-
		if (sb.st_uid != 0 && sb.st_uid != euid && sb.st_gid != egid)
+
		if (sb.st_uid != 0 && sb.st_uid != fileowner && sb.st_gid != filegroup)
			wrong_owner = true;
	}

@@ -747,7 +749,9 @@ file_mode_insecure(const char *path, bool install_as_user)
		return (EPKG_INSECURE);
	}
	if (wrong_owner) {
-
		pkg_emit_error("%s wrong user or group ownership", path);
+
		pkg_emit_error("%s wrong user or group ownership"
+
			       " (expected %d/%d versus actual %d/%d)",
+
			       path, fileowner, filegroup, sb.st_uid, sb.st_gid);
		return (EPKG_INSECURE);
	}

@@ -755,17 +759,22 @@ file_mode_insecure(const char *path, bool install_as_user)
}

static int
-
database_access(unsigned mode, const char* dbdir, const char *dbname)
+
database_access(unsigned mode, const char* dbdir, const char *dbname,
+
		bool multirepo)
{
	char		 dbpath[MAXPATHLEN + 1];
	int		 retval;
	bool		 database_exists;
	bool		 install_as_user;

-
	if (dbname != NULL)
-
		snprintf(dbpath, sizeof(dbpath), "%s/%s.sqlite", dbdir,
-
			 dbname);
-
	else
+
	if (dbname != NULL) {
+
		if (multirepo)
+
			snprintf(dbpath, sizeof(dbpath), "%s/repo-%s.sqlite",
+
				 dbdir, dbname);
+
		else
+
			snprintf(dbpath, sizeof(dbpath), "%s/%s.sqlite",
+
				 dbdir, dbname);
+
	} else
		strlcpy(dbpath, dbdir, sizeof(dbpath));

	install_as_user = (getenv("INSTALL_AS_USER") != NULL);
@@ -853,16 +862,16 @@ pkgdb_access(unsigned mode, unsigned database)

	if ((mode & PKGDB_MODE_CREATE) != 0) 
		retval = database_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
-
					 dbdir, NULL);
+
					 dbdir, NULL, false);
	else
-
		retval = database_access(PKGDB_MODE_READ, dbdir, NULL);
+
		retval = database_access(PKGDB_MODE_READ, dbdir, NULL, false);
	if (retval != EPKG_OK)
		return (retval);

	/* Test local.sqlite, if required */

	if ((database & PKGDB_DB_LOCAL) != 0) {
-
		retval = database_access(mode, dbdir, "local");
+
		retval = database_access(mode, dbdir, "local", false);
		if (retval != EPKG_OK)
			return (retval);
	}
@@ -871,7 +880,7 @@ pkgdb_access(unsigned mode, unsigned database)
	   if in multirepos_enabled mode */

	if (!multirepos_enabled && (database & PKGDB_DB_REPO) != 0) {
-
		retval = database_access(mode, dbdir, "repo");
+
		retval = database_access(mode, dbdir, "repo", false);
		if (retval != EPKG_OK)
			return (retval);
	}
@@ -885,7 +894,7 @@ pkgdb_access(unsigned mode, unsigned database)
			reponame = pkg_config_kv_get(all_repos,
					 PKG_CONFIG_KV_KEY);

-
			retval = database_access(mode, dbdir, reponame);
+
			retval = database_access(mode, dbdir, reponame, true);
			if (retval != EPKG_OK)
				return (retval);
		}
@@ -1256,6 +1265,23 @@ pkgdb_it_free(struct pkgdb_it *it)
	free(it);
}

+
/* By default, MATCH_EXACT and MATCH_REGEX are case sensitive. */
+

+
static bool _case_sensitive_flag = true;
+

+
void
+
pkgdb_set_case_sensitivity(bool case_sensitive)
+
{
+
	_case_sensitive_flag = case_sensitive;
+
	return;
+
}
+

+
bool
+
pkgdb_case_sensitive(void)
+
{
+
	return (_case_sensitive_flag);
+
}
+

static const char *
pkgdb_get_pattern_query(const char *pattern, match_t match)
{
@@ -1270,11 +1296,20 @@ pkgdb_get_pattern_query(const char *pattern, match_t match)
		comp = "";
		break;
	case MATCH_EXACT:
-
		if (checkorigin == NULL)
-
			comp = " WHERE name = ?1 "
-
				"OR name || \"-\" || version = ?1";
-
		else
-
			comp = " WHERE origin = ?1";
+
		if (pkgdb_case_sensitive()) {
+
			if (checkorigin == NULL)
+
				comp = " WHERE name = ?1 "
+
					"OR name || \"-\" || version = ?1";
+
			else
+
				comp = " WHERE origin = ?1";
+
		} else {
+
			if (checkorigin == NULL)
+
				comp = " WHERE name = ?1 COLLATE NOCASE"
+
					"OR name || \"-\" || version = ?1"
+
					"COLLATE NOCASE";
+
			else
+
				comp = " WHERE origin = ?1 COLLATE NOCASE";
+
		}
		break;
	case MATCH_GLOB:
		if (checkorigin == NULL)
@@ -1308,7 +1343,10 @@ pkgdb_get_match_how(match_t match)
		how = NULL;
		break;
	case MATCH_EXACT:
-
		how = "%s = ?1";
+
		if (pkgdb_case_sensitive())
+
			how = "%s = ?1";
+
		else
+
			how = "%s = ?1 COLLATE NOCASE";			
		break;
	case MATCH_GLOB:
		how = "%s GLOB ?1";
@@ -2871,7 +2909,7 @@ cleanup:

struct pkgdb_it *
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
-
    const char *repo, bool force, bool recursive)
+
        const char *repo, bool force, bool recursive, bool pkgversiontest)
{
	sqlite3_stmt	*stmt = NULL;
	struct pkgdb_it	*it;
@@ -2879,8 +2917,10 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
	struct sbuf	*sql = NULL;
	const char	*how = NULL;
	const char	*reponame = NULL;
+
	bool             pkg_not_found = false;

-
	if ((it = pkgdb_query_newpkgversion(db, repo)) != NULL) {
+
	if (pkgversiontest && 
+
	    (it = pkgdb_query_newpkgversion(db, repo)) != NULL) {
		pkg_emit_newpkgversion();
		return (it);
	}
@@ -2979,13 +3019,20 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
		while (sqlite3_step(stmt) != SQLITE_DONE);

		/* report if package was not found in the database */
-
		if (sqlite3_changes(db->sqlite) == 0)
+
		if (sqlite3_changes(db->sqlite) == 0) {
			pkg_emit_package_not_found(pkgs[i]);
+
			pkg_not_found = true;
+
		}
	}

	sqlite3_finalize(stmt);
	sbuf_clear(sql);

+
	if (pkg_not_found) {
+
		sbuf_delete(sql);
+
		return (NULL);
+
	}
+

	/*
	 * Report and remove packages already installed and at the latest
	 * version and without option change
@@ -3080,7 +3127,8 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
}

struct pkgdb_it *
-
pkgdb_query_upgrades(struct pkgdb *db, const char *repo, bool all)
+
pkgdb_query_upgrades(struct pkgdb *db, const char *repo, bool all,
+
	bool pkgversiontest)
{
	sqlite3_stmt	*stmt = NULL;
	struct sbuf	*sql = NULL;
@@ -3088,7 +3136,8 @@ pkgdb_query_upgrades(struct pkgdb *db, const char *repo, bool all)
	struct pkgdb_it	*it;
	int		 ret;

-
	if ((it = pkgdb_query_newpkgversion(db, repo)) != NULL) {
+
	if (pkgversiontest &&
+
	    (it = pkgdb_query_newpkgversion(db, repo)) != NULL) {
		pkg_emit_newpkgversion();
		return (it);
	}
@@ -3431,7 +3480,7 @@ pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match,
	/*
	 * Working on multiple remote repositories
	 */
-
	if (multirepos_enabled && !strcmp(reponame, "default")) {
+
	if (multirepos_enabled && !strcmp(reponame, "remote-default")) {
		/* duplicate the query via UNION for all the attached
		 * databases */

@@ -3941,14 +3990,14 @@ pkgdb_query_fetch(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
		"FROM pkgjobs ORDER BY weight DESC;";

	const char	 main_sql[] = ""
-
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, "
-
			"flatsize, pkgsize, cksum, repopath) "
+
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, "
+
		        "newversion, newflatsize, pkgsize, cksum, repopath) "
			"SELECT id, origin, name, version, flatsize, "
			"pkgsize, cksum, path FROM '%s'.packages ";

	const char	deps_sql[] = ""
-
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, "
-
			"flatsize, pkgsize, cksum, repopath) "
+
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, "
+
		        "newversion, newflatsize, pkgsize, cksum, repopath) "
		"SELECT DISTINCT r.id, r.origin, r.name, r.version, "
			"r.flatsize, r.pkgsize, r.cksum, r.path "
		"FROM '%s'.packages AS r where r.origin IN "
modified libpkg/plugins.c
@@ -26,7 +26,6 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

-
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/stat.h>

@@ -60,10 +59,10 @@ struct pkg_plugin {
	struct plugin_hook *hooks;
	struct pkg_config *conf;
	struct pkg_config *conf_by_key;
-
	STAILQ_ENTRY(pkg_plugin) next;
+
	struct pkg_plugin *next;
};

-
static STAILQ_HEAD(, pkg_plugin) ph = STAILQ_HEAD_INITIALIZER(ph);
+
static struct pkg_plugin *plugins = NULL;

static int pkg_plugin_free(void);
static int pkg_plugin_hook_free(struct pkg_plugin *p);
@@ -100,9 +99,7 @@ plug_free(struct pkg_plugin *p)
static int
pkg_plugin_free(void)
{
-
	struct pkg_plugin *p = NULL;
-

-
	LIST_FREE(&ph, p, plug_free);
+
	LL_FREE(plugins, pkg_plugin, plug_free);

	return (EPKG_OK);
}
@@ -362,12 +359,10 @@ pkg_plugin_conf_add_list(struct pkg_plugin *p, int id, const char *key)
int
pkg_plugins(struct pkg_plugin **plugin)
{
-
	assert(&ph != NULL);
-
	
	if ((*plugin) == NULL)
-
		(*plugin) = STAILQ_FIRST(&ph);
+
		(*plugin) = plugins;
	else
-
		(*plugin) = STAILQ_NEXT((*plugin), next);
+
		(*plugin) = (*plugin)->next;

	if ((*plugin) == NULL)
		return (EPKG_END);
@@ -417,7 +412,7 @@ pkg_plugins_init(void)
		}
		pkg_plugin_set(p, PKG_PLUGIN_PLUGINFILE, pluginfile);
		if (init_func(p) == EPKG_OK) {
-
			STAILQ_INSERT_TAIL(&ph, p, next);
+
			LL_APPEND(plugins, p);
		} else {
			dlclose(p->lh);
			free(p);
deleted libpkg/private/gr_util.h
@@ -1,32 +0,0 @@
-
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
-
 * All rights reserved.
-
 * 
-
 * Redistribution and use in source and binary forms, with or without
-
 * modification, are permitted provided that the following conditions
-
 * are met:
-
 * 1. Redistributions of source code must retain the above copyright
-
 *    notice, this list of conditions and the following disclaimer
-
 *    in this position and unchanged.
-
 * 2. Redistributions in binary form must reproduce the above copyright
-
 *    notice, this list of conditions and the following disclaimer in the
-
 *    documentation and/or other materials provided with the distribution.
-
 * 
-
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 */
-

-
int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group *_old_gr);
-
void gr_fini(void);
-
int gr_init(const char *_dir, const char *_master);
-
int gr_lock(void);
-
int gr_mkdb(void);
-
int gr_tmp(int _mdf);
modified libpkg/private/ldconfig.h
@@ -30,7 +30,6 @@
#define LDCONFIG_H 1

#include <sys/cdefs.h>
-
#include <sys/queue.h>

extern int	insecure;	/* -i flag, needed here for elfhints.c */

modified libpkg/private/pkg.h
@@ -29,7 +29,6 @@
#define _PKG_PRIVATE_H

#include <sys/param.h>
-
#include <sys/queue.h>
#include <sys/sbuf.h>
#include <sys/types.h>

@@ -39,6 +38,7 @@
#include <openssl/md5.h>
#include <stdbool.h>
#include <uthash.h>
+
#include <utlist.h>

#include <yaml.h>
#include "private/utils.h"
@@ -60,6 +60,16 @@
	data = NULL;                               \
} while (0)

+
#define LL_FREE(head, type, free_func) do {   \
+
	struct type *l1, *l2;                 \
+
	LL_FOREACH_SAFE(head, l1, l2) {       \
+
		LL_DELETE(head, l1);          \
+
		if (free_func != NULL)        \
+
			free_func(l1);        \
+
	}                                     \
+
	head = NULL;                          \
+
} while (0)
+

#define HASH_NEXT(hash, data) do {            \
		if (data == NULL)             \
			data = hash;          \
@@ -71,15 +81,8 @@
			return (EPKG_OK);     \
	} while (0)

-
#define LIST_FREE(head, data, free_func) do { \
-
	while (!STAILQ_EMPTY(head)) { \
-
		data = STAILQ_FIRST(head); \
-
		STAILQ_REMOVE_HEAD(head, next); \
-
		free_func(data); \
-
	}  \
-
	} while (0)
-

extern pthread_mutex_t mirror_mtx;
+
extern int eventpipe;

struct pkg {
	struct sbuf	*fields[PKG_NUM_FIELDS];
@@ -105,7 +108,7 @@ struct pkg {
	lic_t		 licenselogic;
	pkg_t		 type;
	UT_hash_handle	 hh;
-
	STAILQ_ENTRY(pkg) next;
+
	struct pkg	*next;
};

struct pkg_dep {
@@ -160,24 +163,24 @@ struct pkg_jobs {
	pkg_flags	 flags;
	bool		 solved;
	const char *	 reponame;
-
	STAILQ_HEAD(,job_pattern) patterns;
+
	struct job_pattern *patterns;
};

struct job_pattern {
	char		**pattern;
	int		nb;
	match_t		match;
-
	STAILQ_ENTRY(job_pattern) next;
+
	struct job_pattern *next;
};

-
struct pkg_jobs_node {
+
/*struct pkg_jobs_node {
	struct pkg	*pkg;
	size_t		 nrefs;
-
	struct pkg_jobs_node	**parents; /* rdeps */
+
	struct pkg_jobs_node	**parents;
	size_t		 parents_len;
	size_t		 parents_cap;
	LIST_ENTRY(pkg_jobs_node) entries;
-
};
+
}; */

struct pkg_user {
	char		 name[MAXLOGNAME+1];
@@ -254,6 +257,7 @@ typedef enum {
int pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags);
#define PKG_DELETE_FORCE (1<<0)
#define PKG_DELETE_UPGRADE (1<<1)
+
#define PKG_DELETE_NOSCRIPT (1<<2)

int pkg_fetch_file_to_fd(const char *url, int dest, time_t t);
int pkg_repo_fetch(struct pkg *pkg);
modified libpkg/private/pkgdb.h
@@ -58,8 +58,8 @@ int pkgdb_transaction_rollback(sqlite3 *sqlite, const char *savepoint);

struct pkgdb_it *pkgdb_query_delete(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, int recursive);
struct pkgdb_it *pkgdb_query_autoremove(struct pkgdb *db);
-
struct pkgdb_it *pkgdb_query_upgrades(struct pkgdb *db, const char *reponame, bool all);
-
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, bool force, bool recursive);
+
struct pkgdb_it *pkgdb_query_upgrades(struct pkgdb *db, const char *reponame, bool all, bool pkgversiontest);
+
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, bool force, bool recursive, bool pkgversiontest);
struct pkgdb_it *pkgdb_query_fetch(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, unsigned flags);

int pkgdb_obtain_lock(struct pkgdb *db);
modified libpkg/private/thd_repo.h
@@ -27,7 +27,6 @@
#ifndef _PKG_THD_REPO_H
#define _PKG_THD_REPO_H

-
#include <sys/queue.h>
#include <sys/types.h>
#include <pthread.h>

@@ -37,7 +36,7 @@ struct pkg_result {
	char cksum[SHA256_DIGEST_LENGTH * 2 + 1];
	off_t size;
	int retcode; /* to pass errors */
-
	STAILQ_ENTRY(pkg_result) next;
+
	struct pkg_result *next;
};

struct thd_data {
@@ -57,7 +56,7 @@ struct thd_data {
	pthread_mutex_t results_m;
	pthread_cond_t has_result;
	pthread_cond_t has_room;
-
	STAILQ_HEAD(results, pkg_result) results;
+
	struct pkg_result *results;
	unsigned int num_results;
	int thd_finished;
};
modified libpkg/private/utils.h
@@ -31,6 +31,7 @@
#include <sys/types.h>
#include <sys/sbuf.h>
#include <sys/param.h>
+
#include <uthash.h>

#include <openssl/pem.h>
#include <openssl/sha.h>
@@ -41,10 +42,14 @@
#define ERROR_SQLITE(db) \
	pkg_emit_error("sqlite: %s (%s:%d)", sqlite3_errmsg(db), __FILE__, __LINE__)

+
#define HASH_FIND_INO(head,ino,out)                                          \
+
	HASH_FIND(hh,head,ino,sizeof(ino_t),out)
+
#define HASH_ADD_INO(head,ino,add)                                          \
+
	HASH_ADD(hh,head,ino,sizeof(ino_t),add)
+

struct hardlinks {
-
	ino_t *inodes;
-
	size_t len;
-
	size_t cap;
+
	ino_t inode;
+
	UT_hash_handle hh;
};

struct dns_srvinfo {
modified libpkg/scripts.c
@@ -129,13 +129,13 @@ pkg_script_run(struct pkg * const pkg, pkg_script type)
				    STDIN_FILENO);
				posix_spawn_file_actions_addclose(&action, stdin_pipe[1]);

-
				argv[0] = "sh";
+
				argv[0] = _PATH_BSHELL;
				argv[1] = "-s";
				argv[2] = NULL;

				use_pipe = 1;
			} else {
-
				argv[0] = "sh";
+
				argv[0] = _PATH_BSHELL;
				argv[1] = "-c";
				argv[2] = sbuf_get(script_cmd);
				argv[3] = NULL;
modified libpkg/update.c
@@ -80,12 +80,17 @@ pkg_update(const char *name, const char *packagesite, bool force)
	int fd, rc = EPKG_FATAL, ret;
	struct stat st;
	time_t t = 0;
-
	sqlite3 *sqlite;
-
	char *archreq = NULL;
+
	sqlite3 *sqlite = NULL;
+
	char *req = NULL;
	const char *myarch;
	int64_t res;
	const char *tmpdir;
+
	sqlite3_stmt *stmt;
+
	const char sql[] = ""
+
	    "INSERT OR REPLACE INTO repodata (key, value) "
+
	    "VALUES (\"packagesite\", ?1);";

+
	sqlite3_initialize();
	snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

	tmpdir = getenv("TMPDIR");
@@ -120,13 +125,53 @@ pkg_update(const char *name, const char *packagesite, bool force)
		}
	}

+
	if (t != 0) {
+
		if (sqlite3_open(repofile, &sqlite) != SQLITE_OK) {
+
			pkg_emit_error("Unable to open local database");
+
			rc = EPKG_FATAL;
+
			goto cleanup;
+
		}
+

+
		if (get_pragma(sqlite, "SELECT count(name) FROM sqlite_master "
+
		    "WHERE type='table' AND name='repodata';", &res) != EPKG_OK) {
+
			pkg_emit_error("Unable to query repository");
+
			rc = EPKG_FATAL;
+
			sqlite3_close(sqlite);
+
			goto cleanup;
+
		}
+
		if (res != 1)
+
			t = 0;
+
	}
+

+
	if (t != 0) {
+
		req = sqlite3_mprintf("select count(key) from repodata "
+
		    "WHERE key = \"packagesite\" and value = '%q'", packagesite);
+

+
		if (get_pragma(sqlite, req, &res) != EPKG_OK) {
+
			sqlite3_free(req);
+
			pkg_emit_error("Unable to query repository");
+
			rc = EPKG_FATAL;
+
			sqlite3_close(sqlite);
+
			goto cleanup;
+
		}
+
		sqlite3_free(req);
+
		if (res != 1)
+
			t = 0;
+
	}
+

+
	if (sqlite != NULL)
+
		sqlite3_close(sqlite);
+

	rc = pkg_fetch_file_to_fd(url, fd, t);
	close(fd);
	if (rc != EPKG_OK) {
		goto cleanup;
	}

-
	if (eaccess(repofile, W_OK) == -1) {
+
	/* If the repo.sqlite file exists, test that we can write to
+
	   it.  If it doesn't exist, assume we can create it */
+

+
	if (eaccess(repofile, F_OK) == 0 && eaccess(repofile, W_OK) == -1) {
		pkg_emit_error("Insufficient privilege to update %s\n",
			       repofile);
		rc = EPKG_ENOACCESS;
@@ -190,7 +235,6 @@ pkg_update(const char *name, const char *packagesite, bool force)
	}

	/* check is the repository is for valid architecture */
-
	sqlite3_initialize();

	if (sqlite3_open(repofile_unchecked, &sqlite) != SQLITE_OK) {
		unlink(repofile_unchecked);
@@ -201,10 +245,10 @@ pkg_update(const char *name, const char *packagesite, bool force)

	pkg_config_string(PKG_CONFIG_ABI, &myarch);

-
	archreq = sqlite3_mprintf("select count(arch) from packages "
+
	req = sqlite3_mprintf("select count(arch) from packages "
	    "where arch not GLOB '%q'", myarch);
-
	if (get_pragma(sqlite, archreq, &res) != EPKG_OK) {
-
		sqlite3_free(archreq);
+
	if (get_pragma(sqlite, req, &res) != EPKG_OK) {
+
		sqlite3_free(req);
		pkg_emit_error("Unable to query repository");
		rc = EPKG_FATAL;
		sqlite3_close(sqlite);
@@ -220,6 +264,36 @@ pkg_update(const char *name, const char *packagesite, bool force)
		goto cleanup;
	}

+
	/* register the packagesite */
+
	if (sql_exec(sqlite, "CREATE TABLE IF NOT EXISTS repodata ("
+
	    "   key TEXT UNIQUE NOT NULL,"
+
	    "   value TEXT NOT NULL"
+
	    ");") != EPKG_OK) {
+
		pkg_emit_error("Unable to register the packagesite in the "
+
		    "database");
+
		rc = EPKG_FATAL;
+
		sqlite3_close(sqlite);
+
		goto cleanup;
+
	}
+

+
	if (sqlite3_prepare_v2(sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(sqlite);
+
		rc = EPKG_FATAL;
+
		sqlite3_close(sqlite);
+
		goto cleanup;
+
	}
+

+
	sqlite3_bind_text(stmt, 1, packagesite, -1, SQLITE_STATIC);
+

+
	if (sqlite3_step(stmt) != SQLITE_DONE) {
+
		ERROR_SQLITE(sqlite);
+
		rc = EPKG_FATAL;
+
		sqlite3_close(sqlite);
+
		goto cleanup;
+
	}
+

+
	sqlite3_finalize(stmt);
+

	sqlite3_close(sqlite);
	sqlite3_shutdown();

deleted libpkg/usergroup.c
@@ -1,239 +0,0 @@
-
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
-
 * All rights reserved.
-
 * 
-
 * Redistribution and use in source and binary forms, with or without
-
 * modification, are permitted provided that the following conditions
-
 * are met:
-
 * 1. Redistributions of source code must retain the above copyright
-
 *    notice, this list of conditions and the following disclaimer
-
 *    in this position and unchanged.
-
 * 2. Redistributions in binary form must reproduce the above copyright
-
 *    notice, this list of conditions and the following disclaimer in the
-
 *    documentation and/or other materials provided with the distribution.
-
 * 
-
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 */
-

-
#include <sys/param.h>
-
#include <sys/types.h> /* needed type libutl.h on 8.X */
-

-
#include <grp.h>
-
#include <pwd.h>
-
#include <libutil.h>
-
#include <string.h>
-

-
#ifndef HAVE_GRUTILS
-
#include "private/gr_util.h"
-
#endif
-
#include "pkg.h"
-
#include "private/event.h"
-
#include "private/pkg.h"
-

-
int
-
pkg_add_user_group(struct pkg *pkg)
-
{
-
	struct pkg_group *g = NULL;
-
	struct pkg_user *u = NULL;
-
	struct group *gr = NULL;
-
	struct passwd *pw = NULL;
-
	int tfd, pfd;
-

-
	/* loop just to check group and users contains string */
-
	while (pkg_groups(pkg, &g) == EPKG_OK) {
-
		if (g->gidstr[0] == '\0') {
-
			/*
-
			 * old style group ignorring, this is created from
-
			 * scripts
-
			 */
-
			return (EPKG_OK);
-
		}
-
	}
-

-
	/* loop just to check group and users contains string */
-
	while (pkg_users(pkg, &u) == EPKG_OK) {
-
		if (u->uidstr[0] == '\0') {
-
			/*
-
			 * old style group ignorring, this is created from
-
			 * scripts
-
			 */
-
			return (EPKG_OK);
-
		}
-
	}
-

-
	g = NULL;
-
	u = NULL;
-

-
	while (pkg_groups(pkg, &g) == EPKG_OK) {
-
		char *gr_create_str, *tmp;
-

-
		/* simply create the group */
-
		if ((gr = getgrnam(pkg_group_name(g))) == NULL) {
-
			/* remove the members if any */
-
			if (g->gidstr[strlen(g->gidstr) - 1] == ':') {
-
				gr = gr_scan(g->gidstr);
-
			} else {
-
				gr_create_str = strdup(g->gidstr);
-
				tmp = strrchr(gr_create_str, ':');
-
				tmp++;
-
				tmp[0] = '\0';
-
				gr = gr_scan(gr_create_str);
-
				free(gr_create_str);
-
			}
-
		} else {
-
			/* no need to create the group */
-
			continue;
-
		}
-

-
		if (gr == NULL) {
-
			pkg_emit_error("Bad group line, ignoring");
-
			continue;
-
		}
-
		gr_init(NULL, NULL);
-
		if ((pfd = gr_lock()) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if ((tfd = gr_tmp(-1)) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if (gr_copy(pfd, tfd, gr, NULL) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if (gr_mkdb() == -1) {
-
			gr_fini();
-
			continue;
-
		}
-

-
		free(gr);
-
		gr_fini();
-
	}
-

-
	while (pkg_users(pkg, &u) == EPKG_OK) {
-

-
		if ((pw = getpwnam(pkg_user_name(u))) == NULL) {
-
			/* simply create the user */
-
			pw = pw_scan(u->uidstr, PWSCAN_WARN|PWSCAN_MASTER);
-
		} else {
-
			/* user already exists */
-
			continue;
-
		}
-

-
		pw_init(NULL, NULL);
-
		if ((pfd = pw_lock()) == -1) {
-
			pw_fini();
-
			continue;
-
		}
-
		if ((tfd = gr_tmp(-1)) == -1) {
-
			pw_fini();
-
			continue;
-
		}
-
		if (pw_copy(pfd, tfd, pw, NULL) == -1) {
-
			pw_fini();
-
			continue;
-
		}
-
		if (pw_mkdb(pkg_user_name(u)) == -1) {
-
			pw_fini();
-
		}
-
		pw_fini();
-
		if (strcmp(pw->pw_dir, "/nonexistent") &&
-
		    strcmp(pw->pw_dir, "/var/empty")) {
-
			/* now create the homedir if it doesn't exists */
-
			/* TODO: do it recursively */
-
			mkdir(pw->pw_dir, 0644);
-
			chown(pw->pw_dir, pw->pw_uid, pw->pw_gid);
-
		}
-
		free(pw);
-
	}
-

-
	/* now add members to groups if they also are listed in users */
-
	g = NULL;
-

-
	while (pkg_groups(pkg, &g) == EPKG_OK) {
-
		struct group *grlocal;
-
		struct group *grnew;
-
		int i, j;
-
		int nx = 0;
-

-
		if (g->gidstr[strlen(g->gidstr) - 1] == ':')
-
			continue; /* no members, next */
-

-
		gr = gr_scan(g->gidstr);
-
		grlocal = getgrnam(pkg_group_name(g));
-
		grnew = NULL;/* gr_dup(grlocal);*/
-

-
		u = NULL;
-
		for (i = 0; gr->gr_mem[i] != NULL; i++) {
-

-
			while (pkg_users(pkg, &u) == EPKG_OK) {
-
				if (strcmp(pkg_user_name(u), gr->gr_mem[i]))
-
					continue;
-

-
				/*
-
				 * check if the user is not already in the
-
				 * local group
-
				 */
-
				for (j = 0; grlocal->gr_mem[j] != NULL; j++) {
-
					if (!strcmp(grlocal->gr_mem[j],
-
					    gr->gr_mem[i]))
-
						break;
-
				}
-

-
				if (grlocal->gr_mem[j] != NULL)
-
					continue; /* already in the group */
-

-
				/* adding the user to the group */
-

-
				if (grnew == NULL) {
-
					nx = j - 1;
-
					grnew = gr_dup(grlocal);
-
				}
-

-
				if (nx == 0)
-
					grnew->gr_mem = NULL;
-
				nx++;
-
				grnew->gr_mem = reallocf(grnew->gr_mem,
-
				    sizeof(*grnew->gr_mem) * (nx + 1));
-
				grnew->gr_mem[nx - 1] =
-
				    __DECONST(char *, pkg_user_name(u));
-
				grnew->gr_mem[nx] = NULL;
-
			}
-
		}
-
		if (grnew == NULL) {
-
			continue;
-
		}
-
		gr_init(NULL, NULL);
-
		if ((pfd = gr_lock()) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if ((tfd = gr_tmp(-1)) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if (gr_copy(pfd, tfd, grnew, grlocal) == -1) {
-
			gr_fini();
-
			continue;
-
		}
-
		if (gr_mkdb() == -1) {
-
			gr_fini();
-
			continue;
-
		}
-

-
		free(grnew);
-
		gr_fini();
-
	}
-

-
	return (EPKG_OK);
-
}
modified libpkg/utils.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * All rights reserved.
 * 
@@ -66,8 +66,9 @@ sbuf_set(struct sbuf **buf, const char *str)
char *
sbuf_get(struct sbuf *buf)
{
+
	if (buf == NULL)
+
		return (__DECONST(char *, ""));

-
	assert(buf != NULL);
	if (sbuf_done(buf) == 0)
		sbuf_finish(buf);

@@ -389,21 +390,18 @@ is_conf_file(const char *path, char *newpath, size_t len)
	return (0);
}

-
bool is_hardlink(struct hardlinks *hl, struct stat *st)
+
bool
+
is_hardlink(struct hardlinks *hl, struct stat *st)
{
-
	size_t i;
+
	struct hardlinks *h;

-
	for (i = 0; i < hl->len; i++) {
-
		if (hl->inodes[i] == st->st_ino)
-
			return (false);
-
	}
-
	if (hl->cap <= hl->len) {
-
		hl->cap |= 1;
-
		hl->cap *= 2;
-
		hl->inodes = reallocf(hl->inodes,
-
				hl->cap * sizeof(ino_t));
-
	}
-
	hl->inodes[hl->len++] = st->st_ino;
+
	HASH_FIND_INO(hl, &st->st_ino, h);
+
	if (h != NULL)
+
		return false;
+

+
	h = malloc(sizeof(struct hardlinks));
+
	h->inode = st->st_ino;
+
	HASH_ADD_INO(hl, inode, h);

	return (true);
}
modified pkg/add.c
@@ -54,8 +54,8 @@ is_url(const char * const pattern)
void
usage_add(void)
{
-
	fprintf(stderr, "usage: pkg add <pkg-name>\n");
-
	fprintf(stderr, "       pkg add <protocol>://<path>/<pkg-name>\n\n");
+
	fprintf(stderr, "usage: pkg add [-I] <pkg-name>\n");
+
	fprintf(stderr, "       pkg add [-I] <protocol>://<path>/<pkg-name>\n\n");
	fprintf(stderr, "For more information see 'pkg help add'.\n");
}

@@ -67,11 +67,25 @@ exec_add(int argc, char **argv)
	char path[MAXPATHLEN + 1];
	char *file;
	int retcode;
+
	int ch;
	int i;
	int failedpkgcount = 0;
-
	struct pkg *p = NULL;
+
	pkg_flags f = PKG_FLAG_NONE;
+

+
	while ((ch = getopt(argc, argv, "I")) != -1) {
+
		switch (ch) {
+
		case 'I':
+
			f |= PKG_ADD_NOSCRIPT;
+
			break;
+
		default:
+
			usage_add();
+
			return (EX_USAGE);
+
		}
+
	}
+
	argc -= optind;
+
	argv += optind;

-
	if (argc < 2) {
+
	if (argc < 1) {
		usage_add();
		return (EX_USAGE);
	}
@@ -90,7 +104,7 @@ exec_add(int argc, char **argv)
		return (EX_IOERR);

	failedpkgs = sbuf_new_auto();
-
	for (i = 1; i < argc; i++) {
+
	for (i = 0; i < argc; i++) {
		if (is_url(argv[i]) == EPKG_OK) {
			snprintf(path, sizeof(path), "./%s", basename(argv[i]));
			if ((retcode = pkg_fetch_file(argv[i], path, 0)) != EPKG_OK)
@@ -111,10 +125,8 @@ exec_add(int argc, char **argv)
			}

		}
-
			
-
		pkg_open(&p, file);

-
		if ((retcode = pkg_add(db, file, 0)) != EPKG_OK) {
+
		if ((retcode = pkg_add(db, file, f)) != EPKG_OK) {
			sbuf_cat(failedpkgs, argv[i]);
			if (i != argc - 1)
				sbuf_printf(failedpkgs, ", ");
@@ -128,6 +140,7 @@ exec_add(int argc, char **argv)
	if(failedpkgcount > 0) {
		sbuf_finish(failedpkgs);
		printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, sbuf_data(failedpkgs));
+
		retcode = EPKG_FATAL;
	}
	sbuf_delete(failedpkgs);

modified pkg/check.c
@@ -233,7 +233,7 @@ check_summary(struct pkgdb *db, struct deps_head *dh)
void
usage_check(void)
{
-
	fprintf(stderr, "usage: pkg check [-Bdsr] [-vy] [-a | -gx <pattern>]\n\n");
+
	fprintf(stderr, "usage: pkg check [-Bdsr] [-vy] [-a | -gix <pattern>]\n\n");
	fprintf(stderr, "For more information see 'pkg help check'.\n");
}

@@ -261,24 +261,11 @@ exec_check(int argc, char **argv)

	struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh);

-
	while ((ch = getopt(argc, argv, "yagdBxsrv")) != -1) {
+
	while ((ch = getopt(argc, argv, "yagidBxsrv")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
-
		case 'x':
-
			match = MATCH_REGEX;
-
			break;
-
		case 'g':
-
			match = MATCH_GLOB;
-
			break;
-
		case 'y':
-
			yes = true;
-
			break;
-
		case 'd':
-
			dcheck = true;
-
			flags |= PKG_LOAD_DEPS;
-
			break;
		case 'B':
			pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
			if (!shlibs)
@@ -287,17 +274,33 @@ exec_check(int argc, char **argv)
			reanalyse_shlibs = true;
			flags |= PKG_LOAD_FILES;
			break;
-
		case 's':
-
			checksums = true;
-
			flags |= PKG_LOAD_FILES;
+
		case 'd':
+
			dcheck = true;
+
			flags |= PKG_LOAD_DEPS;
+
			break;
+
		case 'g':
+
			match = MATCH_GLOB;
+
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
			break;
		case 'r':
			recompute = true;
			flags |= PKG_LOAD_FILES;
			break;
+
		case 's':
+
			checksums = true;
+
			flags |= PKG_LOAD_FILES;
+
			break;
		case 'v':
			verbose = 1;
			break;
+
		case 'x':
+
			match = MATCH_REGEX;
+
			break;
+
		case 'y':
+
			yes = true;
+
			break;
		default:
			usage_check();
			return (EX_USAGE);
modified pkg/convert.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@ convert_to_old(void)
{
	struct pkgdb *db = NULL;
	struct pkg *pkg = NULL;
+
	struct pkg_dep *dep = NULL;
	struct pkgdb_it *it = NULL;
	char *content, *name, *version, *buf;
	const char *tmp;
@@ -56,8 +57,8 @@ convert_to_old(void)
	int query_flags = PKG_LOAD_DEPS | PKG_LOAD_FILES |
	    PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS |
	    PKG_LOAD_OPTIONS | PKG_LOAD_MTREE |
-
	    PKG_LOAD_USERS | PKG_LOAD_GROUPS;
-
	FILE *fp;
+
	    PKG_LOAD_USERS | PKG_LOAD_GROUPS | PKG_LOAD_RDEPS;
+
	FILE *fp, *rq;
	struct sbuf *install_script = sbuf_new_auto();
	struct sbuf *deinstall_script = sbuf_new_auto();

@@ -72,6 +73,7 @@ convert_to_old(void)
	}

	while (pkgdb_it_next(it, &pkg, query_flags) == EPKG_OK) {
+
		rq = NULL;
		pkg_to_old(pkg);
		pkg_old_emit_content(pkg, &content);
		pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version);
@@ -185,7 +187,15 @@ convert_to_old(void)
			fputs(sbuf_data(deinstall_script), fp);
			fclose(fp);
		}
-
		/* TODO  required_by */
+

+
		snprintf(path, MAXPATHLEN, "/var/db/pkg/%s-%s/+REQUIRED_BY", name, version);
+
		while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
+
			if (rq == NULL)
+
				rq = fopen(path, "w");
+
			fprintf(rq, "%s-%s\n", pkg_dep_name(dep), pkg_dep_version(dep));
+
		}
+
		if (rq != NULL)
+
			fclose(rq);
		printf("done.\n");

		free(content);
@@ -230,9 +240,8 @@ convert_from_old(void)
			pkg_old_load_from_path(p, path);
			pkg_from_old(p);
			pkg_get(p, PKG_NAME, &name, PKG_VERSION, &version);
-
			printf("Converting %s-%s...", name, version);
+
			printf("Converting %s-%s...\n", name, version);
			pkgdb_register_ports(db, p);
-
			printf("done\n");
		}
	}

@@ -261,7 +270,7 @@ exec_convert(int argc, char **argv)
	}

	if (revert)
-
		return (convert_from_old());
-
	else
		return (convert_to_old());
+
	else
+
		return (convert_from_old());
}
modified pkg/create.c
@@ -54,11 +54,11 @@ STAILQ_HEAD(pkg_head, pkg_entry);
void
usage_create(void)
{
-
	fprintf(stderr, "usage: pkg create [-n] [-f format] [-o outdir] "
+
	fprintf(stderr, "usage: pkg create [-On] [-f format] [-o outdir] "
		"[-p plist] [-r rootdir] -m manifestdir\n");
-
	fprintf(stderr, "       pkg create [-gnx] [-f format] [-o outdir] "
+
	fprintf(stderr, "       pkg create [-Ognx] [-f format] [-o outdir] "
		"[-r rootdir] pkg-name ...\n");
-
	fprintf(stderr, "       pkg create [-n] [-f format] [-o outdir] "
+
	fprintf(stderr, "       pkg create [-On] [-f format] [-o outdir] "
		"[-r rootdir] -a\n\n");
	fprintf(stderr, "For more information see 'pkg help create'.\n");
}
@@ -69,7 +69,6 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt,
{
	int i, ret = EPKG_OK, retcode = EPKG_OK;
	const char *name, *version;
-
#ifndef PKG_COMPAT
	struct pkg *pkg = NULL;
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
@@ -77,19 +76,16 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt,
	    PKG_LOAD_CATEGORIES | PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS |
	    PKG_LOAD_OPTIONS | PKG_LOAD_MTREE | PKG_LOAD_LICENSES |
	    PKG_LOAD_USERS | PKG_LOAD_GROUPS | PKG_LOAD_SHLIBS;
-
#endif
	struct pkg_head head = STAILQ_HEAD_INITIALIZER(head);
	struct pkg_entry *e = NULL;
	char pkgpath[MAXPATHLEN];
	const char *format = NULL;
	bool foundone;

-
#ifndef PKG_COMPAT
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
		pkgdb_close(db);
		return (EX_IOERR);
	}
-
#endif

	switch (fmt) {
	case TXZ:
@@ -107,7 +103,6 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt,
	}

	for (i = 0; i < argc || match == MATCH_ALL; i++) {
-
#ifndef PKG_COMPAT
		if (match == MATCH_ALL) {
			printf("Loading package list...\n");
			if ((it = pkgdb_query(db, NULL, match)) == NULL)
@@ -133,49 +128,6 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt,
		pkgdb_it_free(it);
		if (ret != EPKG_END)
			retcode++;
-
#else
-
		const char *dbdir = getenv("PKG_DBDIR");
-
		struct dirent *dp;
-
		DIR *d;
-

-
		if (dbdir == NULL)
-
			dbdir = "/var/db/pkg";
-

-
		foundone = false;
-
		if (match == MATCH_ALL) {
-
			if ((d = opendir(dbdir)) == NULL) {
-
				retcode++;
-
				goto cleanup;
-
			}
-
			while ((dp = readdir(d)) != NULL) {
-
				if (dp->d_type == DT_DIR) {
-
					if ((e = malloc(sizeof(struct pkg_entry))) == NULL)
-
						err(1, "malloc(pkg_entry)");
-
					e->pkg = NULL;
-
					pkg_new(&e->pkg, PKG_OLD_FILE);
-
					snprintf(pkgpath, MAXPATHLEN, "%s/%s", dbdir, dp->d_name);
-
					ret = pkg_old_load_from_path(e->pkg, pkgpath);
-
					STAILQ_INSERT_TAIL(&head, e, next);
-
					foundone = true;
-
				}
-
			}
-
			closedir(d);
-
			match = !MATCH_ALL;
-
		} else {
-
			struct stat st;
-
			snprintf(pkgpath, MAXPATHLEN, "%s/%s", dbdir, argv[i]);
-
			if (stat(pkgpath, &st) == 0 && S_ISDIR(st.st_mode)) {
-
				foundone = true;
-
				if ((e = malloc(sizeof(struct pkg_entry))) == NULL)
-
					err(1, "malloc(pkg_entry)");
-
				e->pkg = NULL;
-
				pkg_new(&e->pkg, PKG_OLD_FILE);
-
				ret = pkg_old_load_from_path(e->pkg, pkgpath);
-
				STAILQ_INSERT_TAIL(&head, e, next);
-
				foundone = true;
-
			}
-
		}
-
#endif
	}

	while (!STAILQ_EMPTY(&head)) {
@@ -203,9 +155,7 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt,
	}

cleanup:
-
#ifndef PKG_COMPAT
	pkgdb_close(db);
-
#endif

	return (retcode);
}
@@ -232,8 +182,9 @@ exec_create(int argc, char **argv)
	bool overwrite = true;
	pkg_formats fmt;
	int ch;
+
	bool old = false;

-
	while ((ch = getopt(argc, argv, "agxf:r:m:o:np:")) != -1) {
+
	while ((ch = getopt(argc, argv, "agxf:r:m:o:np:O")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
@@ -262,6 +213,9 @@ exec_create(int argc, char **argv)
		case 'p':
			plist = optarg;
			break;
+
		case 'O':
+
			old = true;
+
			break;
		}
	}
	argc -= optind;
@@ -276,11 +230,7 @@ exec_create(int argc, char **argv)
		outdir = "./";

	if (format == NULL) {
-
#ifdef PKG_COMPAT
-
		fmt = TBZ;
-
#else
-
		fmt = TXZ;
-
#endif
+
		fmt = old ? TBZ : TXZ;
	} else {
		if (format[0] == '.')
			++format;
@@ -294,19 +244,21 @@ exec_create(int argc, char **argv)
			fmt = TAR;
		else {
			warnx("unknown format %s, using txz", format);
-
#ifdef PKG_COMPAT
-
			fmt = TBZ;
-
#else
-
			fmt = TXZ;
-
#endif
+
			fmt = old ? TBZ : TXZ;
		}
	}

-
	if (manifestdir == NULL)
+
	if (manifestdir == NULL) {
+
		if (!old) {
+
			warnx("Can only create an old package format"
+
			    "out of a staged directory");
+
			return (EX_SOFTWARE);
+
		}
		return (pkg_create_matches(argc, argv, match, fmt, outdir,
		    rootdir, overwrite) == EPKG_OK ? EX_OK : EX_SOFTWARE);
-
	else
+
	} else {
		return (pkg_create_staged(outdir, fmt, rootdir, manifestdir,
-
		    plist) == EPKG_OK ? EX_OK : EX_SOFTWARE);
+
		    plist, old) == EPKG_OK ? EX_OK : EX_SOFTWARE);
+
	}
}

modified pkg/delete.c
@@ -40,8 +40,8 @@
void
usage_delete(void)
{
-
	fprintf(stderr, "usage: pkg delete [-fgnqRxy] <pkg-name> ...\n");
-
	fprintf(stderr, "       pkg delete [-nqy] -a\n\n");
+
	fprintf(stderr, "usage: pkg delete [-DfginqRxy] <pkg-name> ...\n");
+
	fprintf(stderr, "       pkg delete [-Dnqy] -a\n\n");
	fprintf(stderr, "For more information see 'pkg help delete'.\n");
}

@@ -62,11 +62,14 @@ exec_delete(int argc, char **argv)

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

-
	while ((ch = getopt(argc, argv, "afgnqRxy")) != -1) {
+
	while ((ch = getopt(argc, argv, "aDfginqRxy")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
+
		case 'D':
+
			f |= PKG_FLAG_NOSCRIPT;
+
			break;
		case 'f':
			f |= PKG_FLAG_FORCE;
			force = true;
@@ -74,6 +77,9 @@ exec_delete(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'n':
			f |= PKG_FLAG_DRY_RUN;
			dry_run = true;
modified pkg/event.c
@@ -54,7 +54,8 @@ event_callback(void *data, struct pkg_event *ev)

	switch(ev->type) {
	case PKG_EVENT_ERRNO:
-
		warn("%s(%s)", ev->e_errno.func, ev->e_errno.arg);
+
		warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg,
+
		    strerror(ev->e_errno.no));
		break;
	case PKG_EVENT_ERROR:
		warnx("%s", ev->e_pkg_error.msg);
@@ -200,7 +201,7 @@ event_callback(void *data, struct pkg_event *ev)
		break;
	case PKG_EVENT_NOT_FOUND:
		printf("Package '%s' was not found in "
-
		    "the repositories", ev->e_not_found.pkg_name);
+
		    "the repositories\n", ev->e_not_found.pkg_name);
		break;
	case PKG_EVENT_MISSING_DEP:
		fprintf(stderr, "missing dependency %s-%s",
@@ -225,8 +226,10 @@ event_callback(void *data, struct pkg_event *ev)
		    PKG_VERSION, &version);
		fprintf(stderr, "%s-%s: checksum mismatch for %s\n", name,
		    version, pkg_file_path(ev->e_file_mismatch.file));
+
		break;
	case PKG_EVENT_PLUGIN_ERRNO:
-
		warn("%s: %s(%s)", pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),ev->e_plugin_errno.func, ev->e_plugin_errno.arg);
+
		warnx("%s: %s(%s): %s", pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
+
		    ev->e_plugin_errno.func, ev->e_plugin_errno.arg, strerror(ev->e_plugin_errno.no));
		break;
	case PKG_EVENT_PLUGIN_ERROR:
		warnx("%s: %s", pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME), ev->e_plugin_error.msg);
modified pkg/fetch.c
@@ -1,5 +1,6 @@
/*-
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
@@ -42,54 +43,64 @@
void
usage_fetch(void)
{
-
	fprintf(stderr, "usage: pkg fetch [-r reponame] [-yqgxadL] <pkg-name> <...>\n\n");
+
	fprintf(stderr, "usage: pkg fetch [-r reponame] [-dgiLqxy] <pkg-name> <...>\n");
+
	fprintf(stderr, "       pkg fetch [-r reponame] [-dLqy] -a\n");
+
	fprintf(stderr, "       pkg fetch [-r reponame] [-dLqy] -u\n\n");
	fprintf(stderr, "For more information see 'pkg help fetch'.\n");
}

int
exec_fetch(int argc, char **argv)
{
-
	struct pkgdb *db = NULL;
-
	struct pkg_jobs *jobs = NULL;
-
	const char *reponame = NULL;
-
	int retcode = EX_SOFTWARE;
-
	int ch;
-
	bool force = false;
-
	bool yes;
-
	bool auto_update;
-
	unsigned mode;
-
	match_t match = MATCH_EXACT;
-
	pkg_flags f = PKG_FLAG_NONE;
+
	struct pkgdb	*db = NULL;
+
	struct pkg_jobs	*jobs = NULL;
+
	const char	*reponame = NULL;
+
	int		 ch;
+
	int		 retcode = EX_SOFTWARE;
+
	bool		 auto_update;
+
	bool		 force = false;
+
	bool		 upgrades_for_installed = false;
+
	bool		 yes;
+
	unsigned	 mode;
+
	match_t		 match = MATCH_EXACT;
+
	pkg_flags	 f = PKG_FLAG_NONE;

	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);
	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

-
	while ((ch = getopt(argc, argv, "ygxr:qaLd")) != -1) {
+
	while ((ch = getopt(argc, argv, "adgiLqr:uxy")) != -1) {
		switch (ch) {
-
		case 'y':
-
			yes = true;
-
			break;
		case 'a':
			match = MATCH_ALL;
			break;
+
		case 'd':
+
			f |= PKG_FLAG_WITH_DEPS;
+
			force = true;
+
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
-
		case 'x':
-
			match = MATCH_REGEX;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
			break;
-
		case 'r':
-
			reponame = optarg;
+
		case 'L':
+
			auto_update = false;
			break;
		case 'q':
			quiet = true;
			break;
-
		case 'L':
-
			auto_update = false;
+
		case 'r':
+
			reponame = optarg;
			break;
-
		case 'd':
-
			f |= PKG_FLAG_WITH_DEPS;
-
			force = true;
+
		case 'u':
+
			f |= PKG_FLAG_UPGRADES_FOR_INSTALLED;
+
			upgrades_for_installed = true;
+
			break;
+
		case 'x':
+
			match = MATCH_REGEX;
+
			break;
+
		case 'y':
+
			yes = true;
			break;
		default:
			usage_fetch();
@@ -99,7 +110,12 @@ exec_fetch(int argc, char **argv)
	argc -= optind;
	argv += optind;
	
-
	if (argc < 1 && match != MATCH_ALL) {
+
	if (argc < 1 && match != MATCH_ALL && !upgrades_for_installed) {
+
		usage_fetch();
+
		return (EX_USAGE);
+
	}
+

+
        if (match == MATCH_ALL && upgrades_for_installed) {
		usage_fetch();
		return (EX_USAGE);
	}
@@ -113,12 +129,23 @@ exec_fetch(int argc, char **argv)
		mode = PKGDB_MODE_READ;

	retcode = pkgdb_access(mode, PKGDB_DB_REPO);
+

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privilege to access repo catalogue");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK)
		return (EX_IOERR);

+
	if (upgrades_for_installed) {
+
		retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
+

+
		if (retcode == EPKG_ENOACCESS) {
+
			warnx("Insufficient privilege to access package DB");
+
			return (EX_NOPERM);
+
		} else if (retcode != EPKG_OK)
+
			return (EX_IOERR);
+
	}
+

	/* first update the remote repositories if needed */
	if (auto_update && (retcode = pkgcli_update(false)) != EPKG_OK)
		return (retcode);
@@ -131,7 +158,8 @@ exec_fetch(int argc, char **argv)

	pkg_jobs_set_flags(jobs, f);

-
	if (pkg_jobs_add(jobs, match, argv, argc) != EPKG_OK)
+
	if (!upgrades_for_installed &&
+
	    pkg_jobs_add(jobs, match, argv, argc) != EPKG_OK)
		goto cleanup;

	if (pkg_jobs_solve(jobs) != EPKG_OK)
modified pkg/info.c
@@ -50,7 +50,7 @@ usage_info(void)
{
	fprintf(stderr, "usage: pkg info <pkg-name>\n");
	fprintf(stderr, "       pkg info -a\n");
-
	fprintf(stderr, "       pkg info [-BDdefgIklOqRrsx] <pkg-name>\n");
+
	fprintf(stderr, "       pkg info [-BDdefgiIklOqRrsx] <pkg-name>\n");
	fprintf(stderr, "       pkg info [-BDdfIlqRrs] -F <pkg-file>\n\n");
	fprintf(stderr, "For more information see 'pkg help info'.\n");
}
@@ -83,7 +83,7 @@ exec_info(int argc, char **argv)
	bool origin_search = false;

	/* TODO: exclusive opts ? */
-
	while ((ch = getopt(argc, argv, "aDegxEIdrklBsqopOfF:R")) != -1) {
+
	while ((ch = getopt(argc, argv, "aDegixEIdrklBsqopOfF:R")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
@@ -98,6 +98,9 @@ exec_info(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
modified pkg/install.c
@@ -45,7 +45,7 @@ void
usage_install(void)
{
	fprintf(stderr,
-
	    "usage: pkg install [-AfgLnqRxy] [-r reponame] <pkg-name> ...\n\n");
+
	    "usage: pkg install [-AfgIiLnqRxy] [-r reponame] <pkg-name> ...\n\n");
	fprintf(stderr, "For more information see 'pkg help install'.\n");
}

@@ -63,12 +63,12 @@ exec_install(int argc, char **argv)
	match_t match = MATCH_EXACT;
	bool dry_run = false;
	nbactions = nbdone = 0;
-
	pkg_flags f = PKG_FLAG_NONE;
+
	pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);

-
	while ((ch = getopt(argc, argv, "AfgLnqRr:xy")) != -1) {
+
	while ((ch = getopt(argc, argv, "AfgIiLnqRr:xy")) != -1) {
		switch (ch) {
		case 'A':
			f |= PKG_FLAG_AUTOMATIC;
@@ -79,6 +79,12 @@ exec_install(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'I':
+
			f |= PKG_FLAG_NOSCRIPT;
+
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'L':
			auto_update = false;
			break;
modified pkg/lock.c
@@ -48,9 +48,9 @@ static bool yes = false; /* Assume yes answer to questions */
void
usage_lock(void)
{
-
	fprintf(stderr, "usage: pkg lock [-gqxy] <pkg-name>\n");
+
	fprintf(stderr, "usage: pkg lock [-giqxy] <pkg-name>\n");
	fprintf(stderr, "       pkg lock [-qy] -a\n");
-
	fprintf(stderr, "       pkg unlock [-gqxy] <pkg-name>\n");
+
	fprintf(stderr, "       pkg unlock [-giqxy] <pkg-name>\n");
	fprintf(stderr, "       pkg unlock [-qy] -a\n");
	fprintf(stderr, "For more information see 'pkg help lock'.\n");
}
@@ -137,7 +137,7 @@ exec_lock_unlock(int argc, char **argv, enum action action)

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

-
	while ((ch = getopt(argc, argv, "agqxy")) != -1) {
+
	while ((ch = getopt(argc, argv, "agiqxy")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
@@ -145,6 +145,9 @@ exec_lock_unlock(int argc, char **argv, enum action action)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'q':
			quiet = true;
			break;
modified pkg/pkg-add.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd June 12, 2012
+
.Dd January 25, 2013
.Dt PKG-ADD 8
.Os
.Sh NAME
@@ -23,8 +23,10 @@
.Nd Registers a package and installs it on the system
.Sh SYNOPSIS
.Nm
+
.Op Fl I
.Ar <pkg-name>
.Nm
+
.Op Fl I
.Ar <protocol>://<path>/<pkg-name>
.Sh DESCRIPTION
.Nm
@@ -34,6 +36,14 @@ When installing from a remote source you need to specify
the protocol to use when fetching the package.
.Pp
Currently supported protocols are FTP, HTTP and HTTPS.
+
.Sh OPTIONS
+
The following options are supported by
+
.Nm :
+
.Bl -tag -width I1
+
.It Fl I
+
If any installation scripts (pre-install or post-install) exist for a given
+
package, do not execute them.
+
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm .
modified pkg/pkg-check.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-CHECK 8
.Os
.Sh NAME
@@ -25,7 +25,7 @@
.Nm
.Op Fl Bdsr
.Op Fl vy
-
.Op Fl a | gx Ar <pattern>
+
.Op Fl a | gix Ar <pattern>
.Sh DESCRIPTION
.Nm
.Fl B
@@ -55,6 +55,12 @@ Assume yes when asked for confirmation before installing missing dependencies.
Be verbose.
.It Fl a
Process all packages.
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pattern
+
case insensitive.
.It Fl g
Treat
.Ar <pattern>
modified pkg/pkg-delete.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 25, 2013
.Dt PKG-DELETE 8
.Os
.Sh NAME
@@ -23,10 +23,10 @@
.Nd deletes packages from the database and the system
.Sh SYNOPSIS
.Nm
-
.Op Fl fgnqRxy
+
.Op Fl DfginqRxy
.Ar <pkg-name> ...
.Nm
-
.Op Fl nqy
+
.Op Fl Dnqy
.Fl a
.Sh DESCRIPTION
.Nm
@@ -55,10 +55,18 @@ The following options are supported by
.Bl -tag -width F1
.It Fl a
Deletes all installed packages from the system and empties the database.
+
.It Fl D
+
If a deinstallation script exists for a given package, do not execute it.
.It Fl f
Forces packages to be removed despite leaving unresolved dependencies.
.It Fl g
Treat the package names as shell glob patterns.
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
.It Fl n
Dry run mode.
The list of packages to delete is always printed, but no packages are
modified pkg/pkg-fetch.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 25, 2013
.Dt PKG-FETCH 8
.Os
.Sh NAME
@@ -24,9 +24,17 @@
.Sh SYNOPSIS
.Nm
.Op Fl r Ar reponame
-
.Op Fl yqgxadL
+
.Op Fl dgiLqxy
.Ar <pkg-name>
.Op ...
+
.Nm
+
.Op Fl r Ar reponame
+
.Op Fl dLqy
+
.Fl a
+
.Nm
+
.Op Fl r Ar reponame
+
.Op Fl dLqy
+
.Fl u
.Sh DESCRIPTION
.Nm
is used to download binary packages from a remote repository.
@@ -44,8 +52,22 @@ The following options are supported by
.Bl -tag -width F1
.It Fl a
Fetch all packages.
-
.It Fl y
-
Assume yes when asked for confirmation before fetching packages.
+
.It Fl d
+
Fetch the package and its dependencies as well.
+
.It Fl g
+
Treat
+
.Ar <pkg-name>
+
as a shell glob pattern.
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
+
.It Fl L
+
Skip updating the repository catalogues with
+
.Xr pkg-update 8 .
+
Use the local cache only.
.It Fl q
Quiet mode.
Show less output.
@@ -55,22 +77,16 @@ Fetches packages from the given
if multiple repo support is enabled.
See
.Xr pkg.conf 5 .
-
.It Fl g
-
Treat
-
.Ar <pkg-name>
-
as a shell glob pattern.
+
.It Fl u
+
Fetch all available updates for the currently installed packages. 
.It Fl x
Treat
.Ar <pkg-name>
as a regular expression according to the "modern" or "extended" syntax
of
.Xr re_format 7 .
-
.It Fl L
-
Skip updating the repository catalogues with
-
.Xr pkg-update 8 .
-
Use the local cache only.
-
.It Fl d
-
Fetch the package and its dependencies as well.
+
.It Fl y
+
Assume yes when asked for confirmation before fetching packages.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
modified pkg/pkg-info.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-INFO 8
.Os
.Sh NAME
@@ -27,7 +27,7 @@
.Nm
.Fl a
.Nm
-
.Op Fl BDdefgIklOqRrsx
+
.Op Fl BDdefgiIklOqRrsx
.Ar <pkg-name>
.Nm
.Op Fl BDdfIlqRrs
@@ -58,6 +58,11 @@ Show the pkg-message for matching packages.
Treat
.Ar <pkg-name>
as a shell glob pattern.
+
.It Fl i
+
Make the default or the regular expression
+
.Fl ( x )
+
.Ar pkg-name
+
matching case insensitive.
.It Fl x
Treat
.Ar <pkg-name>
modified pkg/pkg-install.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 25, 2013
.Dt PKG-INSTALL 8
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Nd installs packages from remote package repositories
.Sh SYNOPSIS
.Nm
-
.Op Fl AfgLnqRxy
+
.Op Fl AfgIiLnqRxy
.Op Fl r Ar reponame
.Ar <pkg-origin> ...
.Sh DESCRIPTION
@@ -115,6 +115,16 @@ For more information please refer to
Force the reinstallation of the package if already installed.
.It Fl g
Treat the package names as shell glob patterns.
+
.It Fl I
+
If any installation scripts (pre-install or post-install) exist for a given
+
package, do not execute them.  When a package is updated, deinstallation
+
scripts (pre-deinstall or post-deinstall) are not run either.
+
.It Fl i
+
Make the standard or the regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
.It Fl L
Skip updating the repository catalogues with
.Xr pkg-update 8 .
modified pkg/pkg-lock.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-LOCK 8
.Os
.Sh NAME
@@ -27,13 +27,13 @@
.Op Fl qy
.Fl a
.Nm
-
.Op Fl gqxy
+
.Op Fl giqxy
.Ar <pkg-name>
.Nm "pkg unlock"
.Op Fl qy
.Fl a
.Nm "pkg unlock"
-
.Op Fl gqxy
+
.Op Fl giqxy
.Ar <pkg-name>
.Sh DESCRIPTION
.Nm
@@ -76,6 +76,11 @@ Lock or unlock all installed packages.
Treat
.Ar <pkg-name>
as a shell glob pattern.
+
.It Fl i
+
Make the default or the regular expression
+
.Fl ( x )
+
.Ar pkg-name
+
matching case insensitive.
.It Fl q
Operate quietly: do not output anything other than confirmatory questions.
.It Fl x
modified pkg/pkg-query.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-QUERY 8
.Os
.Sh NAME
@@ -32,7 +32,7 @@
.Nm
.Fl e Ao evaluation-condition Ac Ao query-format Ac
.Nm
-
.Op Fl gx
+
.Op Fl gix
.Ao query-format Ac Ao pattern Ac Ao ... Ac
.Sh DESCRIPTION
.Nm
@@ -50,6 +50,12 @@ See EVALUATION FORMAT for details.
.It Fl F Ar pkg-name
Display information only for the package file
.Ar pkg-name
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
.It Fl g
Treat
.Ao pattern Ac
modified pkg/pkg-rquery.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-RQUERY 8
.Os
.Sh NAME
@@ -33,7 +33,7 @@
.Op Fl r Ar reponame
.Ao query-format Ac
.Nm
-
.Op Fl gx
+
.Op Fl gix
.Op Fl r Ar reponame
.Ao query-format Ac Ao pattern Ac Ao ... Ac
.Sh DESCRIPTION
@@ -59,6 +59,12 @@ See
Treat
.Ao pattern Ac
as a glob pattern.
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
.It Fl x
Treat
.Ao pattern Ac
modified pkg/pkg-search.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd July 11, 2012
+
.Dd January 20, 2013
.Dt PKG-SEARCH 8
.Os
.Sh NAME
@@ -23,14 +23,14 @@
.Nd search package repository catalogues
.Sh SYNOPSIS
.Nm
-
.Op Fl egx
+
.Op Fl egix
.Op Fl r Ar repo
.Op Fl S Ar search
.Op Fl L Ar label
.Op Fl Q Ar query-modifier
.Ar pattern
.Nm
-
.Op Fl cDdefgopqx
+
.Op Fl cDdefgiopqx
.Op Fl r Ar repo
.Ar pattern
.Sh DESCRIPTION
@@ -83,6 +83,14 @@ Treat
.Ar pattern
as a shell globbing expression.
The glob pattern must match the entire field being seached.
+
.It Fl i
+
Make the exact
+
.Fl ( e )
+
or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pattern
+
case insensitive.
.It Fl L Ar label
Select which identifying label is printed for each matched package,
unless
modified pkg/pkg-set.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-SET 8
.Os
.Sh NAME
@@ -27,24 +27,33 @@
.Op Fl A Op Ar 01
.Op Fl o Ar <oldorigin>:<neworigin>
.Op Fl y
-
.Op Fl xg
+
.Op Fl gix
.Ar <pkg-name>
.Sh DESCRIPTION
.Nm
-
is used to modify information concerning installed packages, should be used with
-
caution
+
is used to modify information concerning installed packages.
+
.Nm
+
should always be used with caution.
.Sh OPTIONS
The following options are supported by
.Nm :
.Bl -tag -width F1
-
.It Fl y
-
Assume yes when asked for confirmation before package autoremoval.
-
.It Fl a
-
Match on all installed packages.
.It Fl A Op 01
-
Set automatic flag to the package: 0 is not automatic, 1 is automatic.
+
Set automatic flag for the package: 0 is not automatic, 1 is automatic.
This affects the operation of
.Xr pkg-autoremove 8 .
+
.It Fl a
+
Match all installed packages.
+
.It Fl g
+
Match
+
.Ar pkg-name
+
as a globbing expression.
+
.It Fl i
+
Make the standard or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
.It Fl o Op <oldorigin>:<neworigin>
Change the port origin of a given dependency from
.Ar oldorigin
@@ -60,12 +69,19 @@ Also see
and
.Sx EXAMPLES .
.It Fl x
-
Assume pkg-name is a regular expression according to the "modern" or
-
"extended" syntax of
+
Match
+
.Ar pkg-name
+
as a regular expression according to the "modern" or "extended" syntax of
.Xr re_format 7 .
-
.It Fl g
-
Assume pkg-name is a glob
+
.It Fl y
+
Assume yes rather than asking for confirmation before package autoremoval.
.El
+
.Pp
+
If neither the
+
.Fl g
+
nor
+
.Fl x
+
options are used, the default is to match pkg-name exactly.
.Sh FILES
See
.Xr pkg.conf 5 .
modified pkg/pkg-upgrade.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd May 16, 2012
+
.Dd January 25, 2013
.Dt PKG-UPGRADE 8
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Nd performs upgrades of package software distributions
.Sh SYNOPSIS
.Nm
-
.Op Fl fLnqy
+
.Op Fl fILnqy
.Op Fl r Ar reponame
.Sh DESCRIPTION
.Nm
@@ -53,6 +53,10 @@ The following options are supported by
.Bl -tag -width F1
.It Fl f
Force reinstalling/upgrading the whole set of packages
+
.It Fl I
+
If any installation scripts (pre-install or post-install) or deinstallation
+
scripts (pre-deinstall or post-deinstall) exist for a given package, do not
+
execute them.
.It Fl L
Skip updating the repository catalogues with
.Xr pkg-update 8 .
modified pkg/pkg-version.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd October 15, 2012
+
.Dd January 20, 2013
.Dt PKG-VERSION 8
.Os
.Sh NAME
@@ -27,7 +27,7 @@
.Op Fl hoqvU
.Op Fl l Ar limchar
.Op Fl L Ar limchar
-
.Op Fl xge Ar pattern
+
.Op Fl egix Ar pattern
.Op Fl r Ar reponame
.Op Fl O Ar origin
.Op Ar index
@@ -118,13 +118,21 @@ flag.
Displays the packages which status flag does not match the one
specified by
.Ar limchar
+
.It Fl i
+
Make the exact
+
.Fl ( e )
+
or regular expression
+
.Fl ( x )
+
matching against
+
.Ar pattern
+
case insensitive.
.It Fl x Ar pattern
Only display the packages that match the regular expression.
Uses the "modern" or "extended" syntax of
.Xr re_format 7 .
.It Fl g Ar pattern
Only display the packages that match the glob expression.
-
.It Fl g Ar string
+
.It Fl e Ar string
Only display the packages that exactly match the string.
.It Fl O Ar origin
Display only the packages which origin matches
modified pkg/query.c
@@ -805,7 +805,7 @@ usage_query(void)
	fprintf(stderr, "       pkg query [-a] <query-format>\n");
	fprintf(stderr, "       pkg query -F <pkg-name> <query-format>\n");
	fprintf(stderr, "       pkg query -e <evaluation> <query-format>\n");
-
	fprintf(stderr, "       pkg query [-gx] <query-format> <pattern> <...>\n\n");
+
	fprintf(stderr, "       pkg query [-gix] <query-format> <pattern> <...>\n\n");
	fprintf(stderr, "For more information see 'pkg help query.'\n");
}

@@ -827,7 +827,7 @@ exec_query(int argc, char **argv)
	struct sbuf *sqlcond = NULL;
	const unsigned int q_flags_len = (sizeof(accepted_query_flags)/sizeof(accepted_query_flags[0]));

-
	while ((ch = getopt(argc, argv, "agxF:e:")) != -1) {
+
	while ((ch = getopt(argc, argv, "agixF:e:")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
@@ -835,6 +835,9 @@ exec_query(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
modified pkg/register.c
@@ -1,5 +1,5 @@
/*-
-
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
 * All rights reserved.
@@ -66,7 +66,7 @@ static const char * const scripts[] = {
void
usage_register(void)
{
-
	fprintf(stderr, "usage: pkg register [-ld] [-i <input-path>]"
+
	fprintf(stderr, "usage: pkg register [-Old] [-i <input-path>]"
	                " -m <metadatadir> -f <plist-file>\n\n");
	fprintf(stderr, "For more information see 'pkg help register'.\n");
}
@@ -95,26 +95,16 @@ exec_register(int argc, char **argv)

	bool legacy = false;
	bool developer = false;
+
	bool old = false;

	int i;
-
	int ret = EPKG_OK, retcode;
-

-
	retcode = pkgdb_access(PKGDB_MODE_READ  |
-
			       PKGDB_MODE_WRITE |
-
			       PKGDB_MODE_CREATE,
-
			       PKGDB_DB_LOCAL);
-
	if (retcode == EPKG_ENOACCESS) {
-
		warnx("Insufficient privilege to register packages");
-
		return (EX_NOPERM);
-
	} else if (retcode != EPKG_OK)
-
		return (EX_IOERR);
-
	else
-
		retcode = EX_OK;
+
	int ret = EPKG_OK, retcode = EX_OK;
+


	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	pkg_new(&pkg, PKG_INSTALLED);
-
	while ((ch = getopt(argc, argv, "f:m:i:ld")) != -1) {
+
	while ((ch = getopt(argc, argv, "f:m:i:ldO")) != -1) {
		switch (ch) {
		case 'f':
			if ((plist = strdup(optarg)) == NULL)
@@ -135,6 +125,9 @@ exec_register(int argc, char **argv)
		case 'l':
			legacy = true;
			break;
+
		case 'O':
+
			old = true;
+
			break;
		default:
			printf("%c\n", ch);
			usage_register();
@@ -142,6 +135,20 @@ exec_register(int argc, char **argv)
		}
	}

+
	if (!old) {
+
		retcode = pkgdb_access(PKGDB_MODE_READ  |
+
				       PKGDB_MODE_WRITE |
+
				       PKGDB_MODE_CREATE,
+
				       PKGDB_DB_LOCAL);
+
		if (retcode == EPKG_ENOACCESS) {
+
			warnx("Insufficient privilege to register packages");
+
			return (EX_NOPERM);
+
		} else if (retcode != EPKG_OK)
+
			return (EX_IOERR);
+
		else
+
			retcode = EX_OK;
+
	}
+

	if (plist == NULL)
		errx(EX_USAGE, "missing -f flag");

@@ -154,15 +161,15 @@ exec_register(int argc, char **argv)
	}

	snprintf(fpath, sizeof(fpath), "%s/+DESC", mdir);
-
	pkg_set_from_file(pkg, PKG_DESC, fpath);
+
	pkg_set_from_file(pkg, PKG_DESC, fpath, false);

	snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", mdir);
	if (access(fpath, F_OK) == 0)
-
		 pkg_set_from_file(pkg, PKG_MESSAGE, fpath);
+
		 pkg_set_from_file(pkg, PKG_MESSAGE, fpath, false);

	snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", mdir);
	if (access(fpath, F_OK) == 0)
-
		pkg_set_from_file(pkg, PKG_MTREE, fpath);
+
		pkg_set_from_file(pkg, PKG_MTREE, fpath, false);

	for (i = 0; scripts[i] != NULL; i++) {
		snprintf(fpath, sizeof(fpath), "%s/%s", mdir, scripts[i]);
@@ -196,12 +203,9 @@ exec_register(int argc, char **argv)

	free(plist);

-
#ifndef PKG_COMPAT
-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (!old && pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
		return (EX_IOERR);
	}
-
#else
-
#endif

	pkg_analyse_files(db, pkg);

@@ -225,19 +229,21 @@ exec_register(int argc, char **argv)
		free(input_path);
	}

-
#ifndef PKG_COMPAT
-
	if (pkgdb_register_ports(db, pkg) != EPKG_OK)
-
		retcode = EX_SOFTWARE;
-
#else
-
#endif
+
	if (old) {
+
		if (pkg_register_old(pkg) != EPKG_OK)
+
			retcode = EX_SOFTWARE;
+
	} else {
+
		if (pkgdb_register_ports(db, pkg) != EPKG_OK)
+
			retcode = EX_SOFTWARE;
+
	}

	pkg_get(pkg, PKG_MESSAGE, &message);
	if (message != NULL && !legacy)
		printf("%s\n", message);

-
#ifndef PKG_COMPAT
-
	pkgdb_close(db);
-
#endif
+
	if (!old)
+
		pkgdb_close(db);
+

	pkg_free(pkg);

	return (retcode);
modified pkg/rquery.c
@@ -70,7 +70,7 @@ usage_rquery(void)
	fprintf(stderr, "usage: pkg rquery [-r reponame] <query-format> <pkg-name>\n");
	fprintf(stderr, "       pkg rquery [-a] [-r reponame] <query-format>\n");
	fprintf(stderr, "       pkg rquery -e <evaluation> [-r reponame] <query-format>\n");
-
	fprintf(stderr, "       pkg rquery [-gx] [-r reponame] <query-format> <pattern> <...>\n\n");
+
	fprintf(stderr, "       pkg rquery [-gix] [-r reponame] <query-format> <pattern> <...>\n\n");
	fprintf(stderr, "For more information see 'pkg help rquery.'\n");
}

@@ -94,7 +94,7 @@ exec_rquery(int argc, char **argv)
	const char *reponame = NULL;
	bool onematched = false;

-
	while ((ch = getopt(argc, argv, "agxe:r:")) != -1) {
+
	while ((ch = getopt(argc, argv, "agixe:r:")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
@@ -102,6 +102,9 @@ exec_rquery(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
modified pkg/search.c
@@ -206,9 +206,9 @@ usage_search(void)
{
	int i, n;

-
	fprintf(stderr, "usage: pkg search [-egx] [-r repo] [-S search] "
+
	fprintf(stderr, "usage: pkg search [-egix] [-r repo] [-S search] "
	    "[-L label] [-M mod]... <pkg-name>\n");
-
	fprintf(stderr, "       pkg search [-cDdefgopqx] [-r repo] "
+
	fprintf(stderr, "       pkg search [-cDdefgiopqx] [-r repo] "
	    "<pattern>\n\n");
	n = fprintf(stderr, "       Search and Label options:");
	for (i = 0; search_label[i].option != NULL; i++) {
@@ -243,7 +243,7 @@ exec_search(int argc, char **argv)
	struct pkg *pkg = NULL;
	bool atleastone = false;

-
	while ((ch = getopt(argc, argv, "cDdefgL:opqQ:r:S:sx")) != -1) {
+
	while ((ch = getopt(argc, argv, "cDdefgiL:opqQ:r:S:sx")) != -1) {
		switch (ch) {
		case 'c':	/* Same as -S comment */
			search = search_label_opt("comment");
@@ -263,6 +263,9 @@ exec_search(int argc, char **argv)
		case 'g':
			match = MATCH_GLOB;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'L':
			label = search_label_opt(optarg);
			break;
modified pkg/set.c
@@ -41,7 +41,7 @@
void
usage_set(void)
{
-
	fprintf(stderr, "usage: pkg set [-a] [-A [01]] [-o <oldorigin>:<neworigin>] [-y] [-gx] <pkg-name>\n\n");
+
	fprintf(stderr, "usage: pkg set [-a] [-A [01]] [-o <oldorigin>:<neworigin>] [-y] [-gix] <pkg-name>\n\n");
	fprintf(stderr, "For more information see 'pkg help set'. \n");
}

@@ -53,8 +53,7 @@ exec_set(int argc, char **argv)
	struct pkg *pkg = NULL;
	int ch;
	int i;
-
	bool yes_flag = false;
-
	bool yes = yes_flag;
+
	bool yes;
	match_t match = MATCH_EXACT;
	int newautomatic = -1;
	bool automatic = false;
@@ -67,20 +66,10 @@ exec_set(int argc, char **argv)
	unsigned int sets = 0;
	int retcode;

-
	while ((ch = getopt(argc, argv, "ayA:kxgo:")) != -1) {
+
	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
+

+
	while ((ch = getopt(argc, argv, "A:agio:xy")) != -1) {
		switch (ch) {
-
		case 'y':
-
			yes_flag = true;
-
			break;
-
		case 'a':
-
			match = MATCH_ALL;
-
			break;
-
		case 'x':
-
			match = MATCH_REGEX;
-
			break;
-
		case 'g':
-
			match = MATCH_GLOB;
-
			break;
		case 'A':
			sets |= AUTOMATIC;
			newautomatic = strtonum(optarg, 0, 1, &errstr);
@@ -89,6 +78,15 @@ exec_set(int argc, char **argv)
				    "Expecting 0 or 1, got: %s (%s)",
				    optarg, errstr);
			break;
+
		case 'a':
+
			match = MATCH_ALL;
+
			break;
+
		case 'g':
+
			match = MATCH_GLOB;
+
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'o':
			sets |= ORIGIN;
			loads |= PKG_LOAD_DEPS;
@@ -110,6 +108,12 @@ exec_set(int argc, char **argv)
				    "Bad origin format, got: %s", optarg);
			}
			break;
+
		case 'x':
+
			match = MATCH_REGEX;
+
			break;
+
		case 'y':
+
			yes = true;
+
			break;
		default:
			if (oldorigin != NULL)
				free(oldorigin);
@@ -145,12 +149,8 @@ exec_set(int argc, char **argv)

	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
		return (EX_IOERR);
-

-
	if (!yes_flag)
-
		pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes_flag);
-

+
 
	if (oldorigin != NULL) {
-
		yes = yes_flag;
		match = MATCH_ALL;
		if ((it = pkgdb_query(db, oldorigin, MATCH_EXACT)) == NULL) {
			pkgdb_close(db);
@@ -183,6 +183,8 @@ exec_set(int argc, char **argv)
	}
	i = 0;
	do {
+
		bool save_yes = yes;
+

		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
			free(oldorigin);
			pkgdb_close(db);
@@ -190,7 +192,6 @@ exec_set(int argc, char **argv)
		}

		while (pkgdb_it_next(it, &pkg, loads) == EPKG_OK) {
-
			yes = yes_flag;
			if ((sets & AUTOMATIC) == AUTOMATIC) {
				pkg_get(pkg, PKG_AUTOMATIC, &automatic);
				if (automatic == newautomatic)
@@ -204,6 +205,7 @@ exec_set(int argc, char **argv)
				}
				if (yes)
					pkgdb_set(db, pkg, PKG_SET_AUTOMATIC, newautomatic);
+
				yes = save_yes;
			}
			if ((sets & ORIGIN) == ORIGIN) {
				struct pkg_dep *d = NULL;
modified pkg/update.c
@@ -50,6 +50,7 @@ pkgcli_update(bool force) {
	bool multi_repos = false;
	struct pkg_config_kv *repokv = NULL;
	int retcode = EPKG_FATAL;
+
	char name[MAXPATHLEN];

	if (!quiet)
		printf("Updating repository catalogue\n");
@@ -82,7 +83,8 @@ pkgcli_update(bool force) {
			repo_name = pkg_config_kv_get(repokv, PKG_CONFIG_KV_KEY);
			packagesite = pkg_config_kv_get(repokv, PKG_CONFIG_KV_VALUE);

-
			retcode = pkg_update(repo_name, packagesite, force);
+
			snprintf(name, MAXPATHLEN, "repo-%s.sqlite", repo_name);
+
			retcode = pkg_update(name, packagesite, force);
			if (retcode == EPKG_UPTODATE) {
				if (!quiet)
					printf("%s repository catalogue is "
modified pkg/upgrade.c
@@ -37,7 +37,7 @@
void
usage_upgrade(void)
{
-
	fprintf(stderr, "usage: pkg upgrade [-fLnqy] [-r reponame]\n\n");
+
	fprintf(stderr, "usage: pkg upgrade [-fILnqy] [-r reponame]\n\n");
	fprintf(stderr, "For more information see 'pkg help upgrade'.\n");
}

@@ -54,7 +54,7 @@ exec_upgrade(int argc, char **argv)
	bool dry_run = false;
	bool auto_update;
	nbactions = nbdone = 0;
-
	pkg_flags f = PKG_FLAG_NONE;
+
	pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);
@@ -65,6 +65,9 @@ exec_upgrade(int argc, char **argv)
		case 'f':
			f |= PKG_FLAG_FORCE;
			break;
+
		case 'I':
+
			f |= PKG_FLAG_NOSCRIPT;
+
			break;
		case 'L':
			auto_update = false;
			break;
modified pkg/utils.c
@@ -629,9 +629,14 @@ print_jobs_summary(struct pkg_jobs *jobs, const char *msg, ...)
			dlsize += pkgsize;
			snprintf(path, MAXPATHLEN, "%s/%s", cachedir, pkgrepopath);
			if (stat(path, &st) != -1)
-
				dlsize -= st.st_size;
+
				oldsize = st.st_size;
+
			else
+
				oldsize = 0;
+
			dlsize -= oldsize;

-
			printf("\t%s-%s\n", name, version);
+
			humanize_number(size, sizeof(size), pkgsize, "B", HN_AUTOSCALE, 0);
+

+
			printf("\t%s-%s (%ld%% of %s)\n", name, newversion, 100 - (100 * oldsize)/pkgsize, size);
			break;
		}
	}
modified pkg/version.c
@@ -57,7 +57,7 @@ struct index_entry {
void
usage_version(void)
{
-
	fprintf(stderr, "usage: pkg version [-IPR] [-hoqvU] [-l limchar] [-L limchar] [[-X] -s string]\n");
+
	fprintf(stderr, "usage: pkg version [-IPR] [-hoqvU] [-l limchar] [-L limchar] [-egix pattern]\n");
	fprintf(stderr, "                   [-r reponame] [-O origin] [index]\n");
	fprintf(stderr, "       pkg version -t <version1> <version2>\n");
	fprintf(stderr, "       pkg version -T <pkgname> <pattern>\n\n");
@@ -174,7 +174,7 @@ exec_version(int argc, char **argv)

	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);

-
	while ((ch = getopt(argc, argv, "hIPRUoqvl:L:x:g:e:O:r:tT")) != -1) {
+
	while ((ch = getopt(argc, argv, "hIPRUoqvl:L:ix:g:e:O:r:tT")) != -1) {
		switch (ch) {
		case 'h':
			usage_version();
@@ -208,6 +208,9 @@ exec_version(int argc, char **argv)
			opt |= VERSION_NOSTATUS;
			limchar = *optarg;
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'x':
			match = MATCH_REGEX;
			pattern = optarg;
deleted pkg_compat/Makefile
@@ -1,16 +0,0 @@
-
PROG=	pkg_compat
-

-
SRCS=	pkg_compat.c register.c create.c
-

-
CFLAGS=	-I${.CURDIR}/../libpkg \
-
	-I${.CURDIR}/../pkg \
-
	-DPKG_COMPAT=yes
-

-
.PATH:	${.CURDIR}/../pkg
-

-
LDFLAGS=	-L${.OBJDIR}/../libpkg -lpkg
-

-
NO_MAN=	yes
-
WARNS=	6
-

-
.include <bsd.prog.mk>
deleted pkg_compat/pkg_compat.c
@@ -1,76 +0,0 @@
-
/*
-
 * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
-
 * All rights reserved.
-
 * 
-
 * Redistribution and use in source and binary forms, with or without
-
 * modification, are permitted provided that the following conditions
-
 * are met:
-
 * 1. Redistributions of source code must retain the above copyright
-
 *    notice, this list of conditions and the following disclaimer
-
 *    in this position and unchanged.
-
 * 2. Redistributions in binary form must reproduce the above copyright
-
 *    notice, this list of conditions and the following disclaimer in the
-
 *    documentation and/or other materials provided with the distribution.
-
 * 
-
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 */
-

-
#include <sys/types.h>
-
#include <sys/param.h>
-

-
#include <stdbool.h>
-
#include <stdio.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <sysexits.h>
-
#include <unistd.h>
-

-
#include <err.h>
-

-
#include <pkg.h>
-
#include "pkgcli.h"
-

-
/* -i stagedir -l legacy -f tmpplist -m metadir */
-

-
struct pkg *pkg;
-

-
static void
-
usage() {
-
	fprintf(stderr, "usage: %s register [-ld] [-i <input-path>]"
-
	    " -m <metadatadir> -f <plist-file>\n", getprogname());
-
	fprintf(stderr, "usage: %s create [-n] [-f format] [-o outdir] "
-
	    "[-p plist] [-r rootdir] -m manifestdir\n", getprogname());
-

-
	exit(EX_USAGE);
-
}
-

-
int
-
main(int argc, char **argv)
-
{
-
	const char *cmd;
-

-
	if (argc < 2)
-
		usage();
-

-
	cmd = argv[1];
-
	argc--;
-
	argv++;
-

-
	if (strcmp(cmd, "register") == 0)
-
		return (exec_register(argc, argv));
-
	else if (strcmp(cmd, "create") == 0)
-
		return (exec_create(argc, argv));
-

-
	usage();
-
	/* NOT REACHED */
-
	return (EXIT_FAILURE);
-
}
modified ports/pkg2ng
@@ -1,133 +1,3 @@
#!/bin/sh

-
: "${PORTSDIR:=/usr/ports}"
-

-
export PKG_OLD_NOWARN=yes
-

-
if [ $( id -u ) -ne 0 ]
-
then
-
	echo "This program needs to be run as root"
-
	return 77	# EX_PERM
-
fi
-

-
: ${ARCH=$(uname -m)}
-
failed_pkgs=""
-
MOVED=0
-
PKGDB="$(make -C ${PORTSDIR}/ports-mgmt/pkg -VPKG_DBDIR)"
-
PKGBAK="$PKGDB.bak"
-

-
for PKG in $( pkg_info -Ea )
-
do
-
	DB="${PKGDB}/${PKG}"
-

-
	# Work around lingering portmaster distfiles showing "corruption"
-
	if [ ! -e "${DB}/+CONTENTS" ] && [ "$(/bin/ls ${DB})" = "distfiles" ]; then
-
		continue
-
	fi
-

-
	DESC="${DB}/+DESC"
-
	if [ ! -e "${PKGBAK}" ]; then
-
		echo "Creating backup pkg_info(1) database directory in ${PKGBAK}."
-
		mkdir -p ${PKGBAK}
-
	fi
-

-
	ORIGIN=$(pkg_info -qo ${PKG})
-
	# register a package only if it's not registered already
-
	if pkg info -e ${ORIGIN}; then
-
		echo "${PKG} is already registered."
-
		if [ -e ${DB} ]; then
-
			mv ${DB} ${PKGBAK}/${PKG}
-
			MOVED=1
-
		fi
-
		continue
-
	fi
-
	PREFX=$(pkg_info -qp ${PKG})
-
	if [ -d ${PORTSDIR}/${ORIGIN} ]; then
-
		MAINTAINER=$( make -C ${PORTSDIR}/${ORIGIN} -V MAINTAINER )
-
		CATEGORIES=$( make -C ${PORTSDIR}/${ORIGIN} -V CATEGORIES | sed -e "s/ /,/g")
-
		LICENSES=$( make -C ${PORTSDIR}/${ORIGIN} -V LICENSE | sed -e "s/ /,/g")
-
		LICLOGIC=$(make -C ${PORTSDIR}/${ORIGIN} -V LICENSE_COMB )
-
		OPTIONS=$(make -C ${PORTSDIR}/${ORIGIN} showconfig | awk 'BEGIN{ line=""; }!/^=/ { gsub(/=/,": ",$1); gsub(/:$/,"",$1); line=line" "$1","; } END{print line}')
-
		USERS=$(make -C ${PORTSDIR}/${ORIGIN} -V USERS | sed -e "s/ /,/g")
-
		GROUPS=$(make -C ${PORTSDIR}/${ORIGIN} -V GROUPS | sed -e "s/ /,/g")
-
	else
-
		MAINTAINER="unknown"
-
		CATEGORIES=${ORIGIN%/*}
-
	fi
-

-
	# +CONTENTS
-
	MDIR=$(mktemp -d /tmp/pkg2ngXXXXX)
-
	test -f ${DB}/+DISPLAY && cp -f ${DB}/+DISPLAY ${MDIR}
-
	test -f ${DB}/+MTREE_DIRS && cp -f ${DB}/+MTREE_DIRS ${MDIR}
-
	test -f ${DB}/+DESC && cp -f ${DB}/+DESC ${MDIR}
-
	MANIFEST=${MDIR}/+MANIFEST
-
	PLIST=${MDIR}/plist
-
	cp -f ${DB}/+INSTALL ${MDIR} 2>/dev/null
-
	echo "name: ${PKG%-*}" >> ${MANIFEST}
-
	echo "version: ${PKG##*-}" >> ${MANIFEST}
-
	echo "origin: ${ORIGIN}" >> ${MANIFEST}
-
	echo "comment: |" >> ${MANIFEST}
-
	echo -n "  " >> ${MANIFEST}
-
	cat ${DB}/+COMMENT >> ${MANIFEST}
-
	echo "maintainer: ${MAINTAINER}" >> ${MANIFEST}
-
	echo "prefix: ${PREFX##* }" >> ${MANIFEST}
-
	echo "licenselogic: ${LICLOGIC:-single}" >> ${MANIFEST}
-
	test -n "${LICENSES}" && echo "licenses: [${LICENSES}]" >> ${MANIFEST}
-
	echo "deps:" >> ${MANIFEST}
-
	pkg_info -qr ${PKG} | while read ignore dep; do
-
		deporigin=$(pkg_info -qo ${dep})
-
		echo -e "  ${dep%-*}: { origin: \"${deporigin}\", version: \"${dep##*-}\"}" >> ${MANIFEST}
-
	done
-
	egrep -v "^@(name|pkgdep|ignore|conflicts|display)" ${DB}/+CONTENTS >> ${PLIST}
-
	test -n "${CATEGORIES}" && echo "categories: [${CATEGORIES}]" >> ${MANIFEST}
-
	test -n "${OPTIONS}" && echo "options: {${OPTIONS}}" >> ${MANIFEST}
-
	test -n "${USERS}" && echo "users: [${USERS}]" >> ${MANIFEST}
-
	test -n "${GROUPS}" && echo "groups: [${GROUPS}]" >> ${MANIFEST}
-

-
	pkg register -l -m ${MDIR} -f ${PLIST} ${CMD_ARGS}
-
	if [ $? -ne 0 ]; then
-
		echo "Registration of ${PKG} failed." >&2
-
		cat ${MANIFEST}
-
		failed_pkgs="${failed_pkgs} ${PKG}"
-
	else
-
		rm -rf ${MANIFEST}
-
	fi
-

-
	rm -rf ${MDIR}
-
done
-

-
if [ ${MOVED} -eq 1 ]; then
-
	echo "Moved old package database to ${PKGBAK}."
-
fi
-

-
if [ -n "${failed_pkgs}" ]; then
-
	echo "" >&2
-
	echo "!!! Some packages failed to register !!!" >&2
-
	echo "Please fix them by upgrading them or removing them" >&2
-
	echo "or rerun \"PERMISSIVE=yes pkg2ng\" if you *really* must" >&2
-
	echo "Failed packages: ${failed_pkgs}" >&2
-
else
-
	for PKG in $( pkg_info -Ea ); do
-
		DB="${PKGDB}/${PKG}"
-
		# Ignore package dirs that only have portmaster 'distfiles' in them
-
		if [ -e ${DB} ] && [ "$(/bin/ls ${DB})" != "distfiles" ]; then
-
			cp -pr ${DB} ${PKGBAK}/${PKG}
-
			# Remove only the files documented in
-
			# pkg_add(1), then remove ${DB} only if empty
-
			for f in +COMMENT +CONTENTS +DEINSTALL +DESC \
-
                                 +DISPLAY +INSTALL +MTREE_DIRS \
-
			         +POST-DEINSTALL +POST-INSTALL  +REQUIRE \
-
                                 +REQUIRED_BY ;
-
			do
-
			    rm -f ${DB}/$f
-
			done
-
			rmdir ${DB} 2>/dev/null || true
-
			MOVED=1
-
		fi
-
	done
-
	echo "Conversion has been successfully finished"
-
	echo "Your old packages database has been moved to: ${PKGBAK}."
-
fi
-

-
# Delete the portupgrade pkgdb to avoid discrepencies. It will be auto recreated.
-
rm -f /var/db/pkg/pkgdb.db > /dev/null 2>&1
+
pkg convert