/* This file is part of Lcrzo.
*/

/*-------------------------------------------------------------*/
int lcrzo_file_open_write(const char *filename,
			lcrzo_bool mustbeanexistentfile,
			lcrzo_bool mustbeanewfile,
			lcrzo_file *pfile)
{ int ret, fd;
  lcrzo_int16 language;
  struct stat st1, st2;
  lcrzo_bool fileexists;

  /*parameters verification*/
  if (filename==NULL) return(LCRZO_ERR_PANULLPTR);
  lcrzo_bool_verifbof(mustbeanewfile);
  lcrzo_bool_verifbof(mustbeanexistentfile);
  if (mustbeanewfile&&mustbeanexistentfile)
  { lcrzo_er(lcrzo_global_get_language(&language));
    if (language==LCRZO_GLOBAL_LANG_FR)
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("Ne pas affecter mustbeanewfile et mustbeanexistentfile"));
    }
    else
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("Cannot set mustbeanewfile and mustbeanexistentfile"));
    }
    return(LCRZO_ERR_SPFILESECURITY);
  }
  
  lcrzo_er(lcrzo_priv_dir_eventually_create_parent(filename));
  
  /*before opening, we verify if the file seems OK*/
  ret=lcrzo_priv_filename_stat_get(filename, &st1);
  if (ret!=LCRZO_ERR_OK)
  { /*unknown error*/
    if (errno!=ENOENT) return(ret);
    errno=0;
    fileexists=0;
  }
  else
  { fileexists=1;
    lcrzo_er(lcrzo_priv_stat_forbidslink(st1));
    lcrzo_er(lcrzo_priv_stat_forbidsnotreg(st1));
  }

  /*error cases*/
  if ( mustbeanewfile && fileexists )
  { lcrzo_er(lcrzo_global_get_language(&language));
    if (language==LCRZO_GLOBAL_LANG_FR)
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("Nouveau fichier voulu, mais il existe deja"));
    }
    else
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("We want a new file, but file exists"));
    }
    return(LCRZO_ERR_SPFILESECURITY);
  }
  if ( mustbeanexistentfile && !fileexists )
  { lcrzo_er(lcrzo_global_get_language(&language));
    if (language==LCRZO_GLOBAL_LANG_FR)
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("Fichier existant voulu, mais il n'existe pas"));
    }
    else
    { lcrzo_er(lcrzo_priv_global_set_errmsglcrzo("We want an existent file, but file doesn't exists"));
    }
    return(LCRZO_ERR_SPFILESECURITY);
  }
  
  /*open*/
  if (fileexists)
  { fd=LAURENT_open(filename, (O_WRONLY|O_BINARY) & (~O_CREAT));
    if (fd==-1) return(LCRZO_ERR_FUOPEN);
    /*verify if the characteristics are the same*/
    lcrzo_efr(lcrzo_priv_fd_stat_get(fd, &st2), LAURENT_close(fd));
    lcrzo_efr(lcrzo_priv_stat_forbidschange(st1, st2), LAURENT_close(fd));
    /*truncate the file*/
#if defined LCRZODEF_SYSTEM_Unix
    ret=ftruncate(fd, 0);
    if (ret==-1) { LAURENT_close(fd); return(LCRZO_ERR_FUFTRUNCATE); }
#elif defined LCRZODEF_SYSTEM_Windows
    ret=_chsize(fd, 0);
    if (ret==-1) { LAURENT_close(fd); return(LCRZO_ERR_FUCHSIZE); }
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif
  }
  else
  { fd=LAURENT_open3(filename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0600);
    if (fd==-1) return(LCRZO_ERR_FUOPEN);
  }

  /*eventually close the file descriptor*/
  if (pfile==NULL)
  { ret=LAURENT_close(fd);
    if ( ret == -1 ) return(LCRZO_ERR_FUCLOSE);
  }
  else
  { pfile->fd=fd;
    pfile->canclosefd=LCRZO_TRUE;
    pfile->openforreading=LCRZO_FALSE;
    pfile->openforwriting=LCRZO_TRUE;
    pfile->dataend=LCRZO_FALSE;
    pfile->storeddata=NULL;
    pfile->storeddatasize=0;
  }

  return(LCRZO_ERR_OK);
}

