/************************************************************
**
** Application: SyncDiscs
**
** Title:       c.getdir
**
*************************************************************/

/*
*
* Copyright (c) 2017, David Pilling and Chris Johnson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * 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.
*   * Neither the name of the copyright holder nor the names of their
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
* HOLDER 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.
*
*/

/* Include files */
/* from standard clib */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>



#include "Tasklib:swis.h"
#include "Tasklib:h.os"
#include "Tasklib:h.flex"
#include "Tasklib:h.fsx"
#include "Tasklib:h.etc"
#include "Tasklib:h.bits"
#include "Tasklib:h.wimp"
#include "Tasklib:h.wos"


/* from application */
#include "h.zstring"
#include "h.arcs"
#include "h.syncdiscs"
#include "h.getdir"



/************************************************************/

static int acmpfn(const void * p1, const void * p2)
{

 return(cstrcmp(zstringptr(((heads*)p1)->name),zstringptr(((heads*)p2)->name)));

}


/************************************************************/

static os_error * alphasortdir(heads * base, int start, int limit)
{

  qsort(base+start, limit-start, sizeof(heads), acmpfn);
  return (NULL);
}






/************************************************************/

typedef os_error * (*insertfn)(int acn, int ind, int fn, heads ** base);

static os_error * opendirsub(int acn, int ind, int * fnp,
                                             heads ** base, insertfn insfn)
{
  os_error * err;
  int        fn;
// char     * p;
  fxstat     f;
  int        eof;
  int        object;
  int        s;
  char       arcpath[NAMELEN];
  char       tbuf[NAMELEN + 48];


//  err=NULL;
 
  err = filepath(arcpath, acn, ind);
  if (!err)
  {
    err = fs_exists(arcpath, &object);
 //   if(object!=2); /* err=&mb_sfserr_CatNotFound; */
   
    if (!err)
    {
     
     // p=arcpath+strlen(arcpath);
      fn = *fnp;
      fs_startscan();
     
//      if (err)  make_errlog_entry (303, err->errmess);
     
      if (!err)
      {
        while (1)
        {
          err = fs_nextitem(arcpath, &f, NULL, &eof);
          if (err)
          {
            make_errlog_entry (304, err->errmess);
            sprintf (tbuf, "   Directory: %s", arcpath);
            make_errlog_entry (0, tbuf);
            sprintf (tbuf, "   Object: %s", f.name);
            make_errlog_entry (0, tbuf);
            break;
          }
          if (eof) break;
       
          if (f.f.object)
          {
            err = insfn(acn, ind, fn, base);
            if (err)
            {
              make_errlog_entry (305, err->errmess);
              break;
            }
        
        
            err = zcreatestring(f.name, &s);
            if (err)
            {
              make_errlog_entry (306, err->errmess);
              break;
            }
        
            (*base)[fn].name = s;
        
            (*base)[fn].dirn = (f.f.object==2)?DFLAT:DNFILE;
            (*base)[fn].load = f.f.load;
            (*base)[fn].exec = f.f.exec;
            (*base)[fn].acc = f.f.acc;
            (*base)[fn].length = f.f.length;
        
            fn++;
          }
          if(err) break;
        }
      
        if(!err)
        {
          alphasortdir(*base, *fnp, fn);
          if (err) make_errlog_entry (307, err->errmess);
        }
      
      
        *fnp = fn;
      }
    }
  }
  return (err);
}





/************************************************************/

#define HCHUNK (16*sizeof(heads))

/*
 * get the contents of directory specified by ind and fill into a temp
 * buffer.
 */

static os_error * getdirfn(int acn, int ind, int fn, heads ** base)
{
  os_error * err;
 
  if(!*base) err = flex_alloc((flex_ptr)base,HCHUNK);
  else       err = flex_chunk((flex_ptr)base,sizeof(heads)*(fn+1),HCHUNK);
  if(!err)   memset((*base)+fn, 0, sizeof(heads));
 
  return (err);
  USE(acn);
  USE(ind);
}


/************************************************************/

os_error * getdir(int acn, int ind, heads ** hdr, int * size)
{
  *hdr = NULL;
  *size = 0;
  return (opendirsub(acn, ind, size, hdr, getdirfn));
}




/************************************************************/

/*
 * get the contents of directory specified by ind and insert entries into
 * the main file header structure.
 */

static os_error * opendirfn(int acn, int ind, int fn, heads ** base)
{
  return (insentry(acn, fn, ind, 1));
  USE(base);
}


/************************************************************/

os_error * opendir(int acn, int ind)
{
  os_error * err;
  int        fn;
 
  if (ind >= 0)
  {
    arc[acn].hdr[ind].dirn = 0;
  }
  fn = ind + 1;                    /* nb is OK for fmain == -1 */
  err = opendirsub (acn, ind, &fn, &arc[acn].hdr, opendirfn);
  if (err) make_errlog_entry (302, err->errmess);
 
  if(ind >= 0 && err) arc[acn].hdr[ind].dirn = DFLAT;
 
  return(err);
}





/************************************************************/

os_error * loaddir(char * path, int * acnp)
{
  os_error * err;
  int        arcn;
 
  err = getarchandle(&arcn);
  if (err)  make_errlog_entry (300, err->errmess);
  if (!err)
  {
    *acnp = arcn;
  
    arc[arcn].path = path;
  
    err = opendir(arcn,-1);
    if (err)  make_errlog_entry (301, err->errmess);
  }
 
  return (err);
}





/*************  End of c.getdir  ***********************/



