/* misc.c
 *
 * Copyright (C) 1996-2014 Timo Kokkonen
 * All Rights Reserved.
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>


#include "jpegoptim.h"


int delete_file(const char *name)
{
  int retval;

  if (!name) return -1;
  if (verbose_mode > 1 && !quiet_mode) fprintf(stderr,"deleting: %s\n",name);
  if ((retval=unlink(name)) && !quiet_mode) 
    warn("error removing file: %s",name);

  return retval;
}


long file_size(FILE *fp)
{
  struct stat buf;

  if (!fp) return -1;
  if (fstat(fileno(fp),&buf)) return -2;
  return (long)buf.st_size;
}


int is_directory(const char *pathname)
{
  struct stat buf;

  if (!pathname) return 0;
  if (stat(pathname,&buf) != 0) return 0;
  if (S_ISDIR(buf.st_mode)) return 1;
  return 0;
}


int is_file(const char *filename, struct stat *st)
{
 struct stat buf;

 if (!filename) return 0;
 if (lstat(filename,&buf) != 0) return 0;
 if (st) *st=buf;
 if (S_ISREG(buf.st_mode)) return 1;
 return 0;
}


int file_exists(const char *pathname)
{
  struct stat buf;

  if (!pathname) return 0;
  if (stat(pathname,&buf) != 0) return 0;
  return 1;
}


int rename_file(const char *old_path, const char *new_path)
{
  if (!old_path || !new_path) return -1;
#ifdef WIN32
  if (file_exists(new_path)) delete_file(new_path);
#endif
  return rename(old_path,new_path);
}


#define COPY_BUF_SIZE  (256*1024)

int copy_file(const char *srcfile, const char *dstfile)
{
  FILE *in,*out;
  unsigned char buf[COPY_BUF_SIZE];
  int r,w;
  int err=0;

  if (!srcfile || !dstfile) return -1;

  in=fopen(srcfile,"rb");
  if (!in) {
    warn("failed to open file for reading: %s", srcfile);
    return -2;
  }
  out=fopen(dstfile,"wb");
  if (!out) {
    fclose(in);
    warn("failed to open file for writing: %s", dstfile);
    return -3;
  }


  do {
    r=fread(buf,1,sizeof(buf),in);
    if (r > 0) {
      w=fwrite(buf,1,r,out);
      if (w != r) {
	err=1;
	warn("error writing to file: %s", dstfile);
	break;
      }
    } else {
      if (ferror(in)) {
	  err=2;
	  warn("error reading file: %s", srcfile);
	  break;
      }
    }
  } while (!feof(in));

  fclose(out);
  fclose(in);
  return err;
}


char *splitdir(const char *pathname, char *buf, int buflen)
{
  char *s = NULL;
  int size = 0;

  if (!pathname || !buf || buflen < 2) return NULL;

  if ((s = strrchr(pathname,DIR_SEPARATOR_C))) size = (s-pathname)+1;
  if (size >= buflen) return NULL;
  if (size > 0) memcpy(buf,pathname,size);
  buf[size]=0;

  return buf;
}

char *splitname(const char *pathname, char *buf, int buflen)
{
  const char *s = NULL;
  int size = 0;

  if (!pathname || !buf || buflen < 2) return NULL;

  if ((s = strrchr(pathname,DIR_SEPARATOR_C))) {
    s++;
  } else {
    s=pathname;
  }

  size=strlen(s);
  if (size >= buflen) return NULL;
  if (size > 0) memcpy(buf,s,size);
  buf[size]=0;

  return buf;
}

void fatal(const char *format, ...)
{
  va_list args;

  fprintf(stderr, PROGRAMNAME ": ");
  va_start(args,format);
  vfprintf(stderr, format, args);
  va_end(args);
  fprintf(stderr,"\n");
  fflush(stderr);

  exit(3);
}

void warn(const char *format, ...)
{
  va_list args;

  if (quiet_mode) return;

  fprintf(stderr, PROGRAMNAME ": ");
  va_start(args,format);
  vfprintf(stderr, format, args);
  va_end(args);
  fprintf(stderr,"\n");
  fflush(stderr);
}


/* eof */
