Logo Search packages:      
Sourcecode: yencode version File versions

output.c

/**************************************************************************************************
      $Header: /pub/cvsroot/yencode/src/output.c,v 1.11 2002/03/10 16:25:52 bboy Exp $

      Copyright (C) 2002  Don Moore <bboy@bboy.net>

      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at Your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "y.h"

extern int opt_keep_paths;


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      USERMSG
      Simple routine to standardize output for decoding errors.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
usermsg(
      const char *output_filename,
      const char *input_filename,
      int input_part_number,
      int total_part_number,
      char *error_message,
      const char *fmt, ...
)
{
      va_list     ap;
      char        msg[BUFSIZ];

      if (fmt)
      {
            va_start(ap, fmt);
            vsnprintf(msg, sizeof(msg), fmt, ap);
            va_end(ap);
      }
      else *msg = '\0';

      if (output_filename)
            fprintf(stderr, "%s: ", output_filename);
      if (input_filename)
            fprintf(stderr, "%s%s", input_filename, input_part_number ? " " : ": ");
      if (input_part_number)
      {
            if (total_part_number)
                  fprintf(stderr, "(%d/%d): ", input_part_number, total_part_number);
            else
                  fprintf(stderr, "(%d): ", input_part_number);
      }
      if (error_message)
            fprintf(stderr, "%s%s", error_message, *msg ? ": " : "");
      if (*msg)
            fprintf(stderr, "%s", msg);
      fputc('\n', stderr);
}     
/*--- decerr() ----------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      COPY_FILE_PERMS
      Copies owner, group, and permissions from 'src' to 'dest'.
      Returns 0 on success, -1 on error.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static int
copy_file_perms(const char *srcfile, const char *destfile)
{
      struct stat src, dest;

      if (stat(srcfile, &src))
            return WarnERR("%s", srcfile);
      if (stat(destfile, &dest))
            return WarnERR("%s", destfile);
      if (chown(destfile, src.st_uid, src.st_gid))
            return WarnERR("%s", destfile);
      return (chmod(destfile, src.st_mode));
}
/*--- copy_file_perms() -------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      CREATE_PATHS
      Creates paths for an output file.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void
create_paths(const char *filename)
{
      char  name[PATH_MAX], path[PATH_MAX];
      char  *c, *ns;
      struct stat st;

      strncpy(name, filename, sizeof(name)-1);

      /* Find last component (filename) and remove it, leaving the path part of the filename */
      if (!(c = strrchr(name, '/')))
            return;
      *c = '\0';

      /* Traverse through paths, creating dirs */
      *path = '\0';
      ns = name;
      while ((c = strsep(&ns, "/")))
      {
            strncat(path, c, sizeof(path)-strlen(path)-1);
            strncat(path, "/", sizeof(path)-strlen(path)-1);
            if (stat(path, &st))
            {
                  if (errno != ENOENT)
                        ErrERR("%s", path);
                  if (mkdir(path, 0755))
                        ErrERR("%s", path);
                  continue;
            }
            if (!S_ISDIR(st.st_mode))
                  Err(_("path component `%s' exists but is not a directory"), path);
      }
}
/*--- create_paths() ----------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      Open an output file.  If file exists, user will be prompted to overwrite unless `overwrite'
      is nonzero.  Returns the file pointer on success, NULL on error.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
FILE *
open_output_file(const char *output_filename, int overwrite, const char *input_filename)
{
      struct stat st;
      FILE  *fp;
      static int overwrite_all = 0;                                           // Has user requested the [A]ll option?
      static int overwrite_none = 0;                                          // Has user requested the [N]one option?

      if (opt_keep_paths)
            create_paths(output_filename);

      if (input_filename && !strcmp(output_filename, input_filename))
      {
            fprintf(stderr, "%s: %s (`%s')", output_filename, _("input and output filenames are identical"), input_filename);
            return (NULL);
      }

      if (!stat(output_filename, &st))
      {
            if (!S_ISREG(st.st_mode))
            {
                  fprintf(stderr, "%s: %s\n", output_filename, _("file exists and is not a regular file, will not overwrite"));
                  return (NULL);
            }
            if (overwrite_none)
            {
                  fprintf(stderr, "%s: %s\n", output_filename, _("not overwriting file"));
                  return (NULL);
            }
            if (!overwrite && !overwrite_all)
            {
                  char input[5];

                  if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO))
                  {
                        fprintf(stderr, "%s: %s\n", output_filename, _("not overwriting file"));
                        return (NULL);
                  }
                  for (;;)
                  {
                        printf("%s `%s'? [y]es, [n]o, [A]ll, [N]one: ", _("Overwrite"), output_filename);
                        fflush(stdout);
                        fgets(input, sizeof(input)-1, stdin);
                        strtrim(input);
                        if (input[1] != '\0')
                              continue;
                        if (*input == 'y' || *input == 'n' || *input == 'A' || *input == 'N')
                              break;
                  }

                  switch (*input)
                  {
                        case 'N':
                              overwrite_none = 1;
                              /* FALLTHROUGH */
                        case 'n':
                              fprintf(stderr, "%s: %s\n", output_filename, _("not overwriting file"));
                              return (NULL);

                        case 'A':
                              overwrite_all = 1;
                              break;
                  }
            }
      }

      if (!(fp = fopen(output_filename, "wb")))
            ErrERR("%s", output_filename);

      /* Copy permissions from input file to output file */
      if (input_filename)
            copy_file_perms(input_filename, output_filename);

      return (fp);
}
/*--- open_output_file() ------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      RENAME_OUTPUT_FILE
      If an error occurs, renames the output file according to the yEnc spec.  The string specified
      will be placed (in parentheses - UGH) in between the filename and its extension.
      If the rename succeeds, a pointer to a static buffer containing the new filename is returned.
      If the rename fails, NULL is returned.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
char *
rename_output_file(const char *filename, const char *errmsg)
{
      char  *ext;
      char  base[PATH_MAX];
      static char renameto[PATH_MAX];

      strncpy(base, filename, sizeof(base)-1);
      if ((ext = strrchr(base, '.')))
      {
            *(ext++) = '\0';
#if WANT_STRICT_COMPLIANCE
            snprintf(renameto, sizeof(renameto), "%s(%s).%s", base, errmsg, ext);
#else
            if (strstr(errmsg, "crc"))
                  snprintf(renameto, sizeof(renameto), "%s.bad-crc.%s", base, ext);
            else if (strstr(errmsg, "size"))
                  snprintf(renameto, sizeof(renameto), "%s.bad-size.%s", base, ext);
            else
                  snprintf(renameto, sizeof(renameto), "%s.bad-%s.%s", base, errmsg, ext);
#endif
      }
      else
      {
#if WANT_STRICT_COMPLIANCE
            snprintf(renameto, sizeof(renameto), "%s(%s)", base, errmsg);
#else
            if (strstr(errmsg, "crc"))
                  snprintf(renameto, sizeof(renameto), "%s.bad-crc", base);
            else if (strstr(errmsg, "size"))
                  snprintf(renameto, sizeof(renameto), "%s.bad-size", base);
            else
                  snprintf(renameto, sizeof(renameto), "%s.bad-%s", base, errmsg);
#endif
      }

      if (rename(filename, renameto) == 0)
            return (renameto);
      else
            return (NULL);
}
/*--- rename_output_file() ----------------------------------------------------------------------*/

/* vi:set ts=3: */

Generated by  Doxygen 1.6.0   Back to index