/* Optional Netatalk/libatalk AFP metadata backend helpers. */
#include "net.h"
#include "config.h"
#include "nwatalk.h"
#include "tools.h"

#include <string.h>

#if NETATALK_SUPPORT
#include <errno.h>
#include <sys/stat.h>
#include <atalk/adouble.h>
#endif

int nwatalk_backend_available(void)
{
#if NETATALK_SUPPORT
  return(1);
#else
  return(0);
#endif
}

#if NETATALK_SUPPORT
static int nwatalk_open_adouble(const char *path, struct adouble *ad)
{
  int result;

  if (!path || !*path) return(-0x9c); /* invalid path */

  ad_init_old(ad, AD_VERSION, 0);

  result = ad_open(ad, path,
                   ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDONLY |
                   ADFLAGS_NOHF | ADFLAGS_NORF);
  if (result < 0) {
    return(-0x9c);
  }

  return(0);
}
#endif

int nwatalk_get_finder_info(const char *path, uint8 *finder_info,
                            int finder_info_len)
{
#if NETATALK_SUPPORT
  struct adouble ad;
  void *entry;
  int result;

  if (!finder_info || finder_info_len < NWATALK_FINDER_INFO_LEN) {
    return(-0x9c);
  }

  memset(finder_info, 0, finder_info_len);

  result = nwatalk_open_adouble(path, &ad);
  if (result < 0) return(result);

  entry = ad_entry(&ad, ADEID_FINDERI);
  if (entry && ad_getentrylen(&ad, ADEID_FINDERI) >= NWATALK_FINDER_INFO_LEN) {
    memcpy(finder_info, entry, NWATALK_FINDER_INFO_LEN);
  }

  ad_close(&ad, 0);
  return(0);
#else
  (void)path;
  (void)finder_info;
  (void)finder_info_len;
  return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}

int nwatalk_get_resource_fork_size(const char *path, uint32 *resource_size)
{
#if NETATALK_SUPPORT
  struct adouble ad;
  off_t size;
  int result;

  if (!resource_size) return(-0x9c);
  *resource_size = 0;

  result = nwatalk_open_adouble(path, &ad);
  if (result < 0) return(result);

  size = ad_size(&ad, ADEID_RFORK);
  if (size > 0) {
    if (size > 0xffffffffUL) size = 0xffffffffUL;
    *resource_size = (uint32)size;
  }

  ad_close(&ad, 0);
  return(0);
#else
  (void)path;
  (void)resource_size;
  return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}


int nwatalk_get_entry_id(const char *path, uint32 *entry_id)
{
#if NETATALK_SUPPORT
  struct adouble ad;
  struct stat stbuff;
  uint32_t id;
  int result;

  if (!entry_id) return(-0x9c);
  *entry_id = 0;
  if (!path || !*path) return(-0x9c);

  if (stat(path, &stbuff)) return(-0x9c);

  result = nwatalk_open_adouble(path, &ad);
  if (result < 0) return(result);

  id = ad_getid(&ad, stbuff.st_dev, stbuff.st_ino, 0, NULL);
  if (id) *entry_id = (uint32)id;

  ad_close(&ad, 0);
  return(id ? 0 : -0x9c);
#else
  (void)path;
  (void)entry_id;
  return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}
