/* 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.
*/
/*
 * AtFStk -- Attribute Filesystem Toolkit Library
 *
 * attrs.c -- AtFS toolkit library
 *
 * Author: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: attrs.c[7.0] Fri Jun 25 16:38:51 1993 andy@cs.tu-berlin.de frozen $
 */

#include "atfs.h"
#include "atfstk.h"

/*=======
 * name
 *=======*/

EXPORT char *atFileClassExt (aso)
     Af_key *aso;
{
  static char classStr[4];
  char    *strPtr = classStr;
  mode_t  mode;
  Af_user *locker;

  classStr[0] = classStr[1] = classStr[2] = classStr[3] = '\0';

  mode = af_retnumattr (aso, AF_ATTMODE);

  if (S_ISDIR (mode))
    *strPtr++ = '/';
#ifdef S_ISLNK
  else if (S_ISLNK (mode))
    *strPtr++ = '@';
#endif
#ifdef S_ISSOCK
  else if (S_ISSOCK (mode))
    *strPtr++ = '=';
#endif
  else if ((mode & S_IXUSR) || (mode & S_IXGRP) || (mode & S_IXOTH))
    *strPtr++ = '*';

  if (af_retnumattr (aso, AF_ATTSTATE) == AF_DERIVED)
    *strPtr++ = '$'; /* derived object */
  else {
    locker = af_testlock (aso);
    if (locker->af_username[0])
      *strPtr++ = '^';
  }
  return (classStr);
}

/*===============
 * version status
 *===============*/

LOCAL struct {
  char *name;
  int  code;
} statusTable[] = {
  { "busy", AF_BUSY },
  { "b", AF_BUSY },
  { "saved", AF_SAVED },
  { "save", AF_SAVED },
  { "s", AF_SAVED },
  { "proposed", AF_PROPOSED },
  { "prop", AF_PROPOSED },
  { "p", AF_PROPOSED },
  { "published", AF_PUBLISHED },
  { "publishd", AF_PUBLISHED },
  { "publ", AF_PUBLISHED },
  { "P", AF_PUBLISHED },
  { "accessed", AF_ACCESSED },
  { "acce", AF_ACCESSED },
  { "a", AF_ACCESSED },
  { "frozen", AF_FROZEN },
  { "froz", AF_FROZEN },
  { "f", AF_FROZEN },
  { (char *)0x0, AF_NOSTATE }
};

EXPORT int atScanStatus (statusStr)
     char *statusStr;
{
  int i;
  register char *strPtr;

  if (!(strcmp (statusStr, "P")))
    return (AF_PUBLISHED);

  strPtr = statusStr;
  while ((*strPtr = tolower (*strPtr))) strPtr++;

  for (i = 0; statusTable[i].name; i++)
    if (!(strcmp (statusStr, statusTable[i].name)))
      return (statusTable[i].code);

  return (AF_NOSTATE);
}

EXPORT char *atWriteStatus (aso, verbose)
     Af_key *aso;
     int verbose;
{
  switch (af_retnumattr (aso, AF_ATTSTATE))
    {
    case AF_BUSY:
      return verbose ? "busy    " : "b";
    case AF_SAVED:
      return verbose ? "saved   " : "s";
    case AF_PROPOSED:
      return verbose ? "proposed" : "p";
    case AF_PUBLISHED:
      return verbose ? "publishd" : "P";
    case AF_ACCESSED:
      return verbose ? "accessed" : "a";
    case AF_FROZEN:
      return verbose ? "frozen  " : "f";
    case AF_DERIVED:
      return verbose ? "derived " : "d";
    default:
      return verbose ? "none    " : "n";
    }
}

EXPORT int atIsDerived (aso)
     Af_key *aso;
{
  if (af_retnumattr (aso, AF_ATTSTATE) == AF_DERIVED)
    return (TRUE);
  return (FALSE);
}

/*=======
 * mode
 *=======*/

EXPORT char *atWriteMode (aso)
     Af_key *aso;
{
  static char fileMode[12];
  mode_t mode = af_retnumattr (aso, AF_ATTMODE);

  (void) sprintf(fileMode, " %c%c%c%c%c%c%c%c%c",
		 (mode & S_IRUSR) ? 'r' : '-',
		 (mode & S_IWUSR) ? 'w' : '-',
		 (mode & S_IXUSR) ? 'x' : '-',
		 (mode & S_IRGRP) ? 'r' : '-',
		 (mode & S_IWGRP) ? 'w' : '-',
		 (mode & S_IXGRP) ? 'x' : '-',
		 (mode & S_IROTH) ? 'r' : '-',
		 (mode & S_IWOTH) ? 'w' : '-',
		 (mode & S_IXOTH) ? 'x' : '-');

  if (S_ISDIR(mode))
    fileMode[0] =  'd';
  else if (S_ISCHR(mode))
    fileMode[0] = 'c';
  else if (S_ISBLK(mode))
    fileMode[0] = 'b';
  else if (S_ISREG(mode))
    fileMode[0] = '-';
#ifdef S_ISLNK
  else if (S_ISLNK(mode))
    fileMode[0] = 'l';
#endif
#ifdef S_ISSOCK
  else if (S_ISSOCK(mode))
    fileMode[0] = 's';
#endif
  
  if (mode & S_ISUID)
    fileMode[3] = 's';
  if (mode & S_ISGID)
    fileMode[6] = 's';
#ifdef S_ISVTX
  if (mode & S_ISVTX)
    fileMode[9] = 't';
#endif

  return (fileMode);
}

/*=================
 *  atWriteDate
 *=================*/

#define HALF_YEAR_MAX_SECS 15897600 /* 184 days */
#define HALF_YEAR_MIN_SECS 15638400 /* 181 days */

EXPORT char *atWriteDate (aso, date)
     Af_key *aso;
     char    *date;
{
  static char resultTime[16];
  time_t asoTime, curTime;
  int timeDiff, dateType;
  char *asoTimeString = af_retattr (aso, date);

  if (!asoTimeString[0]) {
    /* time not available */
    strcpy (resultTime, "            ");
    return (resultTime);
  }
    
  asoTime = af_rettimeattr (aso, date);
  curTime = time (&curTime);

  timeDiff = curTime - asoTime;

  if (timeDiff < HALF_YEAR_MIN_SECS)
    dateType = 0; /* Month Day Time */
  else if (timeDiff > HALF_YEAR_MAX_SECS)
    dateType = 1; /* Month Day Year */
  else {
    dateType = 0;
    /* ToDo: do closer examination */
  }

  resultTime[12] = '\0';
  switch (dateType) {
  case 0:
    strncpy (resultTime, &asoTimeString[4], 12);
    break;
  case 1:
    strncpy (resultTime, &asoTimeString[4], 7);
    strncpy (&resultTime[7], &asoTimeString[19], 5);
    break;
  }
  return (resultTime);
}

/*=================
 *  atWriteName
 *=================*/


EXPORT char *atWriteName (aso, path)
     Af_key *aso;
     char   *path;
{
  static char name[PATH_MAX];

  if (!path)
    path = "";

  if (af_retnumattr (aso, AF_ATTSTATE) == AF_BUSY)
    sprintf (name, "%s%s%s", path, *path ? "/" : "", af_retattr (aso, AF_ATTUNIXNAME));
  else
    sprintf (name, "%s%s%s", path, *path ? "/" : "", af_retattr (aso, AF_ATTBOUND));

  return (name);
}
