/*
 * c.file
 *
 * File handling functions
 *
 * $Log: file,v $
 * Revision 1.7  1998/09/28 15:55:10  joseph
 * Changed file_exists to take a const char *
 *
 * Revision 1.6  1998/06/16 18:29:38  joseph
 * Added recalculation of fetch portion for base href & redirections
 * Added processing of base href in fetch and rewrite
 * Moved file_truncate from rewrite to file
 * Logging of urls with unknown schemes
 * Errorlog file kept open across whole fetch
 * Log routines may handle effects of *close better.
 * Invalid chars in urls and hostnames replaced with ~'s on filesystem
 * Rewrite recovers from zero length log file
 * Removed permfail, softfail states as not used
 * Removed some unused bits from url structures
 * Changed proxy code to handle dotless hostnames okay.
 * Version to 0.06a.
 *
 * Revision 1.5  1998/05/28 22:26:30  joseph
 * Altered to compile with debugging changes
 *
 * Revision 1.4  1998/05/28 19:41:11  joseph
 * Changed all printf()'s to debug_printf(())'s
 *
 * Revision 1.3  1998/05/12 19:29:18  jogu
 * file_readtimestamp now returns failure if file does not exist
 *
 * Revision 1.2  1998/04/05 11:34:53  jogu
 * Added file_exists
 *
 * Revision 1.1  1998/03/21 20:30:21  jogu
 * Created from c.http. File handling functions.
 *
 *
 */

#include <stdio.h>
#include <string.h>

#include "swis.h"
#include "wimplib.h"
#include "debug.h"

#include "macros.h"
#include "file.h"


int file_settype(char *name, int type)
{
  _kernel_oserror *e;
  if ( (e=_swix(OS_File, _INR(0,2), 18,name,type)) != NULL )
  {
    debug_printf(("**** File_settype failed(%s)!\n",e->errmess));
    return -1;
  }

  return 0;
}

static int time_leapyear(int year)
{
  int yr; // contains year within century
  yr = year % 100;
  year -= yr; // contains century

  if ( yr == 0 ) // if xx00
    return ( ( year % 4 ) == 0 );

  return ( ( yr % 4 ) == 0 );
}

static int time_days_in_year( int year )
{
  if ( time_leapyear( year ) ) return 366;
  return 365;
}

static int time_days_in_month(int month,int year)
{
  static const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  if ( month < 1 || month > 12 ) return -1;
  if ( month == 2 && time_leapyear( year ) )
    return 29;
  return days[ month - 1 ];
}

static int time_timet_to_riscos( time_t t, char *riscos )
{
  static int ords[7];
  int offset;

  ords[0]=0;       // usec
  ords[1]=t % 60;  // secs
  t/=60;
  ords[2]=t % 60;  // mins
  t/=60;
  ords[3]=t % 24;  // hours
  t/=24;

  // t now contains days since 1970

  ords[6]=1970; // base year for time
  while ( t >= time_days_in_year( ords[6] ) )
  {
    t -= time_days_in_year( ords[6] );
    ords[6]++;
  }

  ords[5]=1; // first month
  while ( t >= time_days_in_month( ords[5], ords[6] ) )
  {
    t -= time_days_in_month( ords[5], ords[6] );
    ords[5]++;
  }
  ords[4] = t + 1; // answers contains number of days into month

  /* convert our ordinals to a 5 byte time */
  E_CHECKRETURN( _swix( Territory_ConvertOrdinalsToTime, _INR(0,2), -1, riscos, ords ), -1 );

  /* convert Time back to UTC */
  E_CHECKRETURN( _swix( Territory_ReadCurrentTimeZone, _OUT(1), &offset ), -1 );
  *( (int *) riscos ) += offset;

  return 0;
}

int file_readstamp( const char *filename, char *stamp )
{
  int load, exec, objtype;
  /* read load & exec address */
  E_CHECKRETURN( _swix( OS_File, _INR(0,1) | _OUT(0) | _OUTR(2,3), 17, filename, &objtype, &load, &exec ), -1 );
  if ( objtype == 0 ) return -1; /* object not found */

//  debug_printf(( "Stamp is: load = %x, exec = %x\n", load, exec ));
  memcpy( stamp, &exec, 4);
  stamp[4] = load & 0xFF;
/*  {
    char date[30];
    const char timeformat[]="%W3, %DY %M3 %CE%YR %24:%MI:%SE %TZ";
    _swix( Territory_ConvertDateAndTime, _INR(0,4), -1, stamp, date, sizeof date, timeformat );
//    debug_printf(("Stamp is : '%s'\n",date));
  } */
  return 0;
}

int file_setstamp( const char *filename, char *riscos )
{
  unsigned int load;
  unsigned int exec;
  {
    char date[30];
    const char timeformat[]="%W3, %DY %M3 %CE%YR %24:%MI:%SE %TZ";
    _swix( Territory_ConvertDateAndTime, _INR(0,4), -1, riscos, date, sizeof date, timeformat );
//    debug_printf(("Setting stamp to : '%s'\n",date));
//    debug_printf(("Setting stamp to : '%x,%x,%x,%x,%x'\n",riscos[0],riscos[1],riscos[2],riscos[3],riscos[4]));
  }

  /* read exec, set load + exec */
  E_CHECKRETURN( _swix(OS_File, _INR(0,1) | _OUT(2), 17, filename, &load), -1 );

  if ( load & 0xFFF00000 != 0xFFF00000 )
    load = 0xFFFD0000; /* if untyped, type to data */

  memcpy( &exec, riscos, 4 );
  load = (load & 0xFFFFFF00) | riscos[4];
//  debug_printf(( "Setting stamp, load = %x, exec = %x\n", load, exec ));

  E_CHECKRETURN( _swix(OS_File, _INR(0,2), 2, filename, load), -1 );
  E_CHECKRETURN( _swix(OS_File, _INR(0,3), 3, filename, 0, exec), -1 );
//  debug_printf(( "Set stamp, load = %x, exec = %x\n", load, exec ));

//  file_readstamp( filename, riscos );

  return 0;
}

int file_setstampunix( const char *filename, time_t stamp )
{
  char riscos[5];

//  debug_printf(("Setting time for %s to %s",filename,ctime(&stamp)));

  if ( time_timet_to_riscos( stamp, riscos ) < 0 ) return -1;

  return file_setstamp( filename, riscos );
}

int file_exists( const char *name )
{
  int type;

  if (_swix(OS_File, _INR(0,1) | _OUT(0), 17, name, &type)) return 0;

  if (type == 1) return 1; /* it's a file */

  return 0;
}


_kernel_oserror *file_truncate( char *name, long length )
{
  int fhan;

  if ( _swix( OS_Find, _INR(0,2) | _OUT(0), 0xC0+3+4+8, name, NULL, &fhan ) )
  {
    debug_printf(("Error from OS_Find"));
  }
  else
  {
    _kernel_oserror *fail;
    fail = _swix( OS_Args, _INR(0,2), 3, fhan, length ); /* set extent */
    _swix( OS_Find, _INR(0,2), 0, fhan, NULL ); /* close file */
    if (fail)
      return fail;
  }

  return NULL;
}
