 /*
  * Khoros: $Id: write_compr.c,v 1.3 1992/03/20 23:40:50 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: write_compr.c,v 1.3 1992/03/20 23:40:50 dkhoros Exp $";
#endif

 /*
  * $Log: write_compr.c,v $
 * Revision 1.3  1992/03/20  23:40:50  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.

 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

/*
    write_compressed.c - Write Khoros data in encoded format.

    Written: Scott Wilson
    Date:     21-Apr-89

    Modified: 13-Apr-91 Scott Wilson and Mark Young - Rearranged command
              execution so that the Apollo will work,
              1991 Mark Young - Changed all I/O calls to kxxxxx()
*/

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "vinclude.h"	
#include "vencode.h"	

write_compressed(fd,data,size,cmd)
int fd;     /* File descriptor to write to */
char *data; /* Pointer to the data to be written in encoded format */
int size;   /* Byte count of data block to be written (prior to encoding) */
char *cmd;  /* Command to be used for encoding process */
  {
    char command[256];  /* Command buffer */
    char *tmpfile;  /* Name of temporary file */
    char *buf;
    FILE *file;
    int  fdtmp;
    int len;
    struct stat stbuf;

    /* See of the size of the write request is zero. If so, just return.
       This emulates the behavior of write() when called with a size
       of zero */
    if (size == 0)
      {
        return(size);
      }

    tmpfile=vtempnam("vwcXXXXXX");
    sprintf(command,"%s > %s", cmd, tmpfile);
    if ((file = popen(command, "w")) == NULL)
      {
        fprintf(stderr,"write_compressed: Unable to open process\n");
        return(0);
      }
    if (fwrite(data,1,size,file) != size)
      {
        fprintf(stderr,"write_compressed: Unable to write source data\n");
        pclose(file);
        return(0);
      }
    pclose(file);

    /* Go grab the size in bytes of the resulting file */
    if (stat(tmpfile,&stbuf) != 0)
      {
        fprintf(stderr,"write_compressed: Unable to obtain stats on temp file\n");
        kunlink(tmpfile);
        return(0);
      }
    len = stbuf.st_size;

    /* See if the byte count is zero. If so, then the encode process failed */
    if (len == 0) 
      {
        fprintf(stderr,"write_compressed: the encoding command %s was not found!\n",cmd);
        kunlink(tmpfile);
        return(0);
      }

    /* All apparently went well. At this point, check the size of the result.
       If larger than the original, write a data block with zeros
       in the first eight bytes, followed by the original data. Otherwise
       (i.e. compression occurred) write the result byte count in ASCII
       in the first eight bytes, followed by the result data. */
    if (len >= size)			/* Result larger than original! */
      {
        if (kwrite(fd,"00000000",8) != 8)	/* Zero size field */
          {
            fprintf(stderr,"write_compressed: unable to write size field\n");
            kunlink(tmpfile);
            return(0);
          }
        if (kwrite(fd,data,size) != size)		/* Rest of data */
          {
            fprintf(stderr,"write_compressed: unable to write data\n");
            kunlink(tmpfile);
            return(0);
          }
        kunlink(tmpfile);
      }
    else
      {
        sprintf(command,"%08d",len);
        if (kwrite(fd,command,8) != 8)
          {
            fprintf(stderr,"write_compressed: unable to write size field\n");
            return(0);
          }
        /* Now malloc enough space for the new data, open the file,
           and read it */
        buf = malloc(len);
        if (buf == NULL)
          {
            fprintf(stderr,"write_compressed: Not enough memory for buffer!\n");
            return(0);
          }
        else
          { 
            fdtmp = kopen(tmpfile,O_RDONLY,0444);
            if (block_read(fdtmp,buf,len) != len)
              {
                fprintf(stderr,"write_compressed: unable to load compressed data\n");
                kclose(fdtmp);
                kunlink(tmpfile);
                free(buf);
                return(0);
              }
            kclose(fdtmp);
            kunlink(tmpfile);
            if (kwrite(fd,buf,len) != len)
              {
                fprintf(stderr,"write_compressed: Unable to write output data\n");
                free(buf);
                return(0);
              }
            free(buf);
          }
      }
    return(size);
  }

