/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
 */
/*
 * AtFS -- Attribute Filesystem
 *
 * afsattrs.c - reading and writing special attributes
 *
 * Author: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: afsattrs.c[7.0] Fri Jun 25 14:32:12 1993 andy@cs.tu-berlin.de frozen $
 */

#include "atfs.h"

/*====================================================================
 *      af_chowner -- change owner
 *====================================================================*/

EXPORT int af_chowner (key, owner)
     Af_key  *key;
     Af_user *owner;
{
  /* not yet implemented (chowner) */
  FAIL ("chowner", "", AF_EACCES, ERROR);
}

/*====================================================================
 *      af_chauthor -- return author
 *====================================================================*/

EXPORT int af_chauthor (key, author)
     Af_key  *key;
     Af_user *author;
{
  uid_t uid;
  gid_t gid;

  if (afAccessAso (key, AF_ATTRS))
    FAIL ("chauthor", "", AF_EINVKEY, ERROR);
  if (af_checkperm (key, AF_OWNER) == ERROR)
    return (ERROR);

  if (VATTR(key).af_state == AF_DERIVED)
    FAIL ("chauthor", "", AF_EDERIVED, ERROR);

  if (VATTR(key).af_state == AF_BUSY) {
    if ((uid = af_getuid (author->af_username, author->af_userhost, author->af_userdomain)) == (uid_t) -1)
      FAIL ("chauthor", "", AF_EINVUSER, ERROR);
    if ((gid = af_getgid (author->af_username, author->af_userhost, author->af_userdomain)) == (gid_t) -1)
      FAIL ("chauthor", "", AF_EINVUSER, ERROR);
    if (chown (key->af_ldes->af_busyfilename, (int) uid, (int) gid) == ERROR)
      FAIL ("chauthor", "chown", AF_ESYSERR, ERROR);
  }
  else {
    VATTR(key).af_auname = af_entersym (author->af_username);
    VATTR(key).af_auhost = af_enterhost (author->af_userhost);
    VATTR(key).af_audomain = af_enterdomain (author->af_userdomain);
  }
  if (afUpdateAso (key, AF_CHANGE) == ERROR)
    return (ERROR);
  return (AF_OK);
}

/*====================================================================
 *    af_chmod -- change mode
 *====================================================================*/

EXPORT int af_chmod (key, mode)
     Af_key *key;
     int    mode;
{
  if (afAccessAso (key, AF_ATTRS))
    FAIL ("chmod", "", AF_EINVKEY, ERROR);

  if (af_checkperm (key, AF_OWNER | AF_AUTHOR) == ERROR)
    return (ERROR);

  if (VATTR(key).af_state == AF_BUSY) {
    if (chmod (key->af_ldes->af_busyfilename, mode) == ERROR)
      FAIL ("chmod", "chmod", AF_ESYSERR, ERROR);
  }
  else {
    VATTR(key).af_mode &= ~07777;
    VATTR(key).af_mode |= mode & 07777;
  }
 
  if (afUpdateAso (key, AF_CHANGE) == ERROR)
	return (ERROR);

  return (AF_OK);
}

/*====================================================================
 *    af_snote -- set note (write note text)
 *====================================================================*/

EXPORT int af_snote (key, buf)
     Af_key *key;
     char   *buf;
{
  register int  len;
  char internalbuf[1];

  internalbuf[0] = '\0';

  if (afAccessAso (key, AF_DATA))
    FAIL ("snote", "", AF_EINVKEY, ERROR);

  if (VATTR(key).af_state == AF_BUSY)
    FAIL ("snote", "", AF_EBUSY, ERROR);

  if (VATTR(key).af_state == AF_DERIVED)
    FAIL ("snote", "", AF_EDERIVED, ERROR);

  if (af_checkperm (key, AF_LOCKHOLDER | AF_AUTHOR | AF_OWNER) == ERROR)
    FAIL ("snote", "", AF_EACCES, ERROR);

  if (!buf) /* if buf is a nil pointer */
    buf = internalbuf;

  len = strlen(buf) + sizeof (char); /* length of string plus nullbyte */
  if (len > VATTR(key).af_notesize) {
    if ((VATTR(key).af_note = af_malloc (key->af_ldes, (unsigned) (len * sizeof (char)))) == NULL)
      return (ERROR);
  }
  /* change datasize in header */
  key->af_ldes->af_datasize -= VATTR(key).af_notesize;
  key->af_ldes->af_datasize += len;

  strncpy (VATTR(key).af_note, buf, len);
  VATTR(key).af_notesize = len;

  /* save changes */
  if (afUpdateAso (key, AF_CHANGE) == ERROR)
    return (ERROR);
  return (AF_OK);
}

/*====================================================================
 *    af_rnote -- get pointer to note (read only)
 *====================================================================*/

EXPORT char *af_rnote (key)
     Af_key *key;
{
  register char *note;

  if (afAccessAso (key, AF_DATA))
    FAIL ("rnote", "", AF_EINVKEY, NULL);

  if (VATTR(key).af_state == AF_BUSY)
    FAIL ("rnote", "", AF_EBUSY, NULL);

  if (VATTR(key).af_state == AF_DERIVED)
    FAIL ("rnote", "", AF_EDERIVED, NULL);

  if (VATTR(key).af_notesize != 0) {
    if ((note = malloc ((unsigned) VATTR(key).af_notesize)) == NULL)
      FAIL ("rnote", "malloc", AF_ESYSERR, NULL);
    strcpy (note, VATTR(key).af_note);
    /* replace newline by nullbyte */
    note[VATTR(key).af_notesize-1] = '\0';
  }
  else {
    if ((note = malloc ((unsigned) sizeof (char))) == NULL)
      FAIL ("rnote", "malloc", AF_ESYSERR, NULL);
    note[0] = '\0';
  }

  return (note);
}
