/*-
 * Copyright (c) 2001, 2003 Allan Saddi <allan@saddi.com>
 * 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.
 * 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 ALLAN SADDI AND HIS 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 ALLAN SADDI OR HIS 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.
 *
 * $Id: statpack.h 354 2003-02-23 23:37:13Z asaddi $
 */

#ifndef _STATPACK_H
#define _STATPACK_H

#include "sha1.h"

#define PACK16(data, buf) do { \
  (buf)[0] = (uint8_t) (((uint16_t) (data)) >> 8); \
  (buf)[1] = (uint8_t) ((uint16_t) (data)); \
} while (0)

#define UNPACK16(buf) \
  ((((uint16_t) (buf)[0]) << 8) | ((uint16_t) (buf)[1]))

#define PACK32(data, buf) do { \
  (buf)[0] = (uint8_t) (((uint32_t) (data)) >> 24); \
  (buf)[1] = (uint8_t) (((uint32_t) (data)) >> 16); \
  (buf)[2] = (uint8_t) (((uint32_t) (data)) >> 8); \
  (buf)[3] = (uint8_t) ((uint32_t) (data)); \
} while (0)

#define UNPACK32(buf) \
  ((((uint32_t) (buf)[0]) << 24) | (((uint32_t) (buf)[1]) << 16) | \
  (((uint32_t) (buf)[2]) << 8) | ((uint32_t) (buf)[3]))

#define PACK64(data, buf) do { \
  (buf)[0] = (uint8_t) (((uint64_t) (data)) >> 56); \
  (buf)[1] = (uint8_t) (((uint64_t) (data)) >> 48); \
  (buf)[2] = (uint8_t) (((uint64_t) (data)) >> 40); \
  (buf)[3] = (uint8_t) (((uint64_t) (data)) >> 32); \
  (buf)[4] = (uint8_t) (((uint64_t) (data)) >> 24); \
  (buf)[5] = (uint8_t) (((uint64_t) (data)) >> 16); \
  (buf)[6] = (uint8_t) (((uint64_t) (data)) >> 8); \
  (buf)[7] = (uint8_t) ((uint64_t) (data)); \
} while (0)

#define UNPACK64(buf) \
  ((((uint64_t) (buf)[0]) << 56) | (((uint64_t) (buf)[1]) << 48) | \
  (((uint64_t) (buf)[2]) << 40) | (((uint64_t) (buf)[3]) << 32) | \
  (((uint64_t) (buf)[4]) << 24) | (((uint64_t) (buf)[5]) << 16) | \
  (((uint64_t) (buf)[6]) << 8) | ((uint64_t) (buf)[7]))

/* The horror, the horror. */

#if SIZEOF_STAT_ST_MODE == 2
#define ST_MODE_FMT "%u"
#define ST_MODE_CAST (unsigned int)
#define ST_MODE_PACK PACK16
#define ST_MODE_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_MODE == 4
#define ST_MODE_FMT "%u"
#define ST_MODE_CAST (unsigned int)
#define ST_MODE_PACK PACK32
#define ST_MODE_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_MODE == 8
#define ST_MODE_FMT "%llu"
#define ST_MODE_CAST (unsigned long long)
#define ST_MODE_PACK PACK64
#define ST_MODE_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_MODE is 0!
#endif

#if SIZEOF_STAT_ST_INO == 2
#define ST_INO_FMT "%u"
#define ST_INO_CAST (unsigned int)
#define ST_INO_PACK PACK16
#define ST_INO_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_INO == 4
#define ST_INO_FMT "%u"
#define ST_INO_CAST (unsigned int)
#define ST_INO_PACK PACK32
#define ST_INO_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_INO == 8
#define ST_INO_FMT "%llu"
#define ST_INO_CAST (unsigned long long)
#define ST_INO_PACK PACK64
#define ST_INO_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_INO is 0!
#endif

#if SIZEOF_STAT_ST_NLINK == 2
#define ST_NLINK_FMT "%u"
#define ST_NLINK_CAST (unsigned int)
#define ST_NLINK_PACK PACK16
#define ST_NLINK_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_NLINK == 4
#define ST_NLINK_FMT "%u"
#define ST_NLINK_CAST (unsigned int)
#define ST_NLINK_PACK PACK32
#define ST_NLINK_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_NLINK == 8
#define ST_NLINK_FMT "%llu"
#define ST_NLINK_CAST (unsigned long long)
#define ST_NLINK_PACK PACK64
#define ST_NLINK_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_NLINK is 0!
#endif

#if SIZEOF_STAT_ST_UID == 2
#define ST_UID_FMT "%u"
#define ST_UID_CAST (unsigned int)
#define ST_UID_PACK PACK16
#define ST_UID_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_UID == 4
#define ST_UID_FMT "%u"
#define ST_UID_CAST (unsigned int)
#define ST_UID_PACK PACK32
#define ST_UID_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_UID == 8
#define ST_UID_FMT "%llu"
#define ST_UID_CAST (unsigned long long)
#define ST_UID_PACK PACK64
#define ST_UID_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_UID is 0!
#endif

#if SIZEOF_STAT_ST_GID == 2
#define ST_GID_FMT "%u"
#define ST_GID_CAST (unsigned int)
#define ST_GID_PACK PACK16
#define ST_GID_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_GID == 4
#define ST_GID_FMT "%u"
#define ST_GID_CAST (unsigned int)
#define ST_GID_PACK PACK32
#define ST_GID_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_GID == 8
#define ST_GID_FMT "%llu"
#define ST_GID_CAST (unsigned long long)
#define ST_GID_PACK PACK64
#define ST_GID_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_GID is 0!
#endif

#if SIZEOF_STAT_ST_SIZE == 2
#define ST_SIZE_FMT "%u"
#define ST_SIZE_CAST (unsigned int)
#define ST_SIZE_PACK PACK16
#define ST_SIZE_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_SIZE == 4
#define ST_SIZE_FMT "%u"
#define ST_SIZE_CAST (unsigned int)
#define ST_SIZE_PACK PACK32
#define ST_SIZE_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_SIZE == 8
#define ST_SIZE_FMT "%llu"
#define ST_SIZE_CAST (unsigned long long)
#define ST_SIZE_PACK PACK64
#define ST_SIZE_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_SIZE is 0!
#endif

#if SIZEOF_STAT_ST_ATIME == 2
#define ST_ATIME_FMT "%u"
#define ST_ATIME_CAST (unsigned int)
#define ST_ATIME_PACK PACK16
#define ST_ATIME_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_ATIME == 4
#define ST_ATIME_FMT "%u"
#define ST_ATIME_CAST (unsigned int)
#define ST_ATIME_PACK PACK32
#define ST_ATIME_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_ATIME == 8
#define ST_ATIME_FMT "%llu"
#define ST_ATIME_CAST (unsigned long long)
#define ST_ATIME_PACK PACK64
#define ST_ATIME_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_ATIME is 0!
#endif

#if SIZEOF_STAT_ST_MTIME == 2
#define ST_MTIME_FMT "%u"
#define ST_MTIME_CAST (unsigned int)
#define ST_MTIME_PACK PACK16
#define ST_MTIME_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_MTIME == 4
#define ST_MTIME_FMT "%u"
#define ST_MTIME_CAST (unsigned int)
#define ST_MTIME_PACK PACK32
#define ST_MTIME_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_MTIME == 8
#define ST_MTIME_FMT "%llu"
#define ST_MTIME_CAST (unsigned long long)
#define ST_MTIME_PACK PACK64
#define ST_MTIME_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_MTIME is 0!
#endif

#if SIZEOF_STAT_ST_CTIME == 2
#define ST_CTIME_FMT "%u"
#define ST_CTIME_CAST (unsigned int)
#define ST_CTIME_PACK PACK16
#define ST_CTIME_UNPACK UNPACK16
#elif SIZEOF_STAT_ST_CTIME == 4
#define ST_CTIME_FMT "%u"
#define ST_CTIME_CAST (unsigned int)
#define ST_CTIME_PACK PACK32
#define ST_CTIME_UNPACK UNPACK32
#elif SIZEOF_STAT_ST_CTIME == 8
#define ST_CTIME_FMT "%llu"
#define ST_CTIME_CAST (unsigned long long)
#define ST_CTIME_PACK PACK64
#define ST_CTIME_UNPACK UNPACK64
#else
#error SIZEOF_STAT_ST_CTIME is 0!
#endif

#define DB_RECORD_SIZE \
  (SIZEOF_STAT_ST_MODE + \
   SIZEOF_STAT_ST_INO + \
   SIZEOF_STAT_ST_NLINK + \
   SIZEOF_STAT_ST_UID + \
   SIZEOF_STAT_ST_GID + \
   SIZEOF_STAT_ST_SIZE + \
   SIZEOF_STAT_ST_ATIME + \
   SIZEOF_STAT_ST_MTIME + \
   SIZEOF_STAT_ST_CTIME + \
   SHA1_HASH_SIZE)

#endif /* !_STATPACK_H */
