OSDN Git Service

Fix a bug: Could not extract 2G over files.
[lha/lha.git] / src / util.c
index da01caa..cb1047f 100644 (file)
@@ -1,11 +1,11 @@
 /* ------------------------------------------------------------------------ */
-/* LHa for UNIX                                                                                                                        */
-/*                             util.c -- LHarc Util                                                                            */
-/*                                                                                                                                                     */
-/*             Modified                        Nobutaka Watazaki                                                       */
-/*                                                                                                                                                     */
-/*     Ver. 1.14       Source All chagned                              1995.01.14      N.Watazaki              */
-/*  Ver. 1.14e  Support for sfx archives               1999.05.28      T.Okamoto       */
+/* LHa for UNIX                                                             */
+/*              util.c -- LHarc Util                                        */
+/*                                                                          */
+/*      Modified                Nobutaka Watazaki                           */
+/*                                                                          */
+/*  Ver. 1.14   Source All chagned              1995.01.14  N.Watazaki      */
+/*  Ver. 1.14e  Support for sfx archives        1999.05.28  T.Okamoto       */
 /* ------------------------------------------------------------------------ */
 #include "lha.h"
 /*
  */
 #include <errno.h>
 
-/* ------------------------------------------------------------------------ */
-extern unsigned short crc;
-extern int      quiet;
-/* ------------------------------------------------------------------------ */
-long
-copyfile(f1, f2, size, crc_flg)        /* return: size of source file */
-       FILE           *f1;
-       FILE           *f2;
-       long            size;
-       int             crc_flg;/* 0: no crc, 1: crc check, 2: extract, 3:
-                                * append */
+off_t
+copyfile(f1, f2, size, text_flg, crcp)  /* return: size of source file */
+    FILE *f1;
+    FILE *f2;
+    off_t size;
+    int text_flg;               /* 0: binary, 1: read text, 2: write text */
+    unsigned int *crcp;
 {
-       unsigned short  xsize;
-       char           *buf;
-       long            rsize = 0;
-
-       buf = (char *)xmalloc(BUFFERSIZE);
-       crc = 0;
-       if ((crc_flg == 2 || crc_flg) && text_mode)
-               init_code_cache();
-       while (size > 0) {
-               /* read */
-               if (crc_flg == 3 && text_mode) {
-                       xsize = fread_txt(buf, BUFFERSIZE, f1);
-                       if (xsize == 0)
-                               break;
-                       if (ferror(f1)) {
-                               fatal_error("file read error");
-                       }
-               }
-               else {
-                       xsize = (size > BUFFERSIZE) ? BUFFERSIZE : size;
-                       if (fread(buf, 1, xsize, f1) != xsize) {
-                               fatal_error("file read error");
-                       }
-               }
-               /* write */
-               if (f2) {
-                       if (crc_flg == 2 && text_mode) {
-                               if (fwrite_txt(buf, xsize, f2)) {
-                                       fatal_error("file write error");
-                               }
-                       }
-                       else {
-                               if (fwrite(buf, 1, xsize, f2) != xsize) {
-                                       fatal_error("file write error");
-                               }
-                       }
-               }
-               /* calculate crc */
-               if (crc_flg) {
-                       calccrc(buf, xsize);
-               }
-               rsize += xsize;
-               if (crc_flg != 3 || !text_mode)
-                       size -= xsize;
-       }
-       free(buf);
-       return rsize;
+    unsigned short  xsize;
+    char *buf;
+    off_t rsize = 0;
+
+    if (!text_mode)
+        text_flg = 0;
+
+    buf = (char *)xmalloc(BUFFERSIZE);
+    if (crcp)
+        INITIALIZE_CRC(*crcp);
+    if (text_flg)
+        init_code_cache();
+    while (size > 0) {
+        /* read */
+        if (text_flg & 1) {
+            xsize = fread_txt(buf, BUFFERSIZE, f1);
+            if (xsize == 0)
+                break;
+            if (ferror(f1)) {
+                fatal_error("file read error");
+            }
+        }
+        else {
+            xsize = (size > BUFFERSIZE) ? BUFFERSIZE : size;
+            if (fread(buf, 1, xsize, f1) != xsize) {
+                fatal_error("file read error");
+            }
+            if (size < xsize)
+                size = 0;
+            else
+                size -= xsize;
+        }
+
+        /* write */
+        if (f2) {
+            if (text_flg & 2) {
+                if (fwrite_txt(buf, xsize, f2)) {
+                    fatal_error("file write error");
+                }
+            }
+            else {
+                if (fwrite(buf, 1, xsize, f2) != xsize) {
+                    fatal_error("file write error");
+                }
+            }
+        }
+
+        /* calculate crc */
+        if (crcp) {
+            *crcp = calccrc(*crcp, buf, xsize);
+#ifdef NEED_INCREMENTAL_INDICATOR
+            put_indicator(xsize);
+#endif
+        }
+        rsize += xsize;
+    }
+    free(buf);
+    return rsize;
 }
 
-/* ------------------------------------------------------------------------ */
 int
 encode_stored_crc(ifp, ofp, size, original_size_var, write_size_var)
-       FILE           *ifp, *ofp;
-       long            size;
-       long           *original_size_var;
-       long           *write_size_var;
+    FILE *ifp, *ofp;
+    off_t size;
+    off_t *original_size_var;
+    off_t *write_size_var;
 {
-       int             save_quiet;
-
-       save_quiet = quiet;
-       quiet = 1;
-       size = copyfile(ifp, ofp, size, 3);
-       *original_size_var = *write_size_var = size;
-       quiet = save_quiet;
-       return crc;
+    int save_quiet;
+    unsigned int crc;
+
+    save_quiet = quiet;
+    quiet = 1;
+    size = copyfile(ifp, ofp, size, 1, &crc);
+    *original_size_var = *write_size_var = size;
+    quiet = save_quiet;
+    return crc;
 }
 
-/* ------------------------------------------------------------------------ */
-/*     convert path delimit
-       erreturns *filename                                                                                                             */
-/* ------------------------------------------------------------------------ */
-unsigned char  *
-convdelim(path, delim)
-       unsigned char  *path;
-       unsigned char   delim;
-{
-       unsigned char   c;
-       unsigned char  *p;
-#ifdef MULTIBYTE_FILENAME
-       int             kflg;
-
-       kflg = 0;
-#endif
-       for (p = path; (c = *p) != 0; p++) {
-#ifdef MULTIBYTE_FILENAME
-               if (kflg) {
-                       kflg = 0;
-               }
-               else if (MULTIBYTE_FIRST_P(c)) {
-                       kflg = 1;
-               }
-               else
-#endif
-               if (c == '\\' || c == '/' || c == LHA_PATHSEP) {
-                       *p = delim;
-                       path = p + 1;
-               }
-       }
-       return path;
-}
-
-/* ------------------------------------------------------------------------ */
 /* If TRUE, archive file name is msdos SFX file name. */
 boolean
 archive_is_msdos_sfx1(name)
-       char           *name;
+    char *name;
 {
-       int             len = strlen(name);
+    int len = strlen(name);
 
-       return ((len >= 4) &&
-               (strucmp(".COM", name + len - 4) == 0 ||
-                strucmp(".EXE", name + len - 4) == 0)) ||
-               ((len >= 2) &&
-                (strucmp(".x", name + len - 2) == 0));
-}
+    if (len >= 4) {
+        if (strcasecmp(".COM", name + len - 4) == 0 ||
+            strcasecmp(".EXE", name + len - 4) == 0)
+            return 1;
+    }
 
-/* ------------------------------------------------------------------------ */
-/* skip SFX header */
-boolean
-skip_msdos_sfx1_code(fp)
-       FILE           *fp;
-{
-       unsigned char   buffer[MAXSFXCODE];
-       unsigned char  *p, *q;
-       int             n;
-
-       n = fread(buffer, sizeof(char), MAXSFXCODE, fp);
-
-       for (p = buffer + 2, q = buffer + n - /* 5 */ (I_HEADER_LEVEL+1)-2; p < q; p++) {
-               /* found "-l??-" keyword (as METHOD type string) */
-               if (p[0] == '-' && p[1] == 'l' && p[4] == '-') {
-                       /* size and checksum validate check */
-                       if ( (p[I_HEADER_LEVEL-2] == 0 || p[I_HEADER_LEVEL-2] == 0)
-                               && p[I_HEADER_SIZE-2] > 20
-                               && p[I_HEADER_CHECKSUM-2] == calc_sum(p, p[-2])) {
-                                       fseek(fp, ((p - 2) - buffer) - n, SEEK_CUR);
-                               return TRUE;
-                       } else if (p[I_HEADER_LEVEL-2] == 2 && p[I_HEADER_SIZE-2] >= 24
-                                          && p[I_ATTRIBUTE-2] == 0x20) {
-                               fseek(fp, ((p - 2) - buffer) - n, SEEK_CUR);
-                               return TRUE;
-                       }
-               }
-       }
-
-       fseek(fp, -n, SEEK_CUR);
-       return FALSE;
+    if (len >= 2 && strcasecmp(".x", name + len - 2) == 0)
+        return 1;
+
+    return 0;
 }
 
 /*
  * strdup(3)
  */
-
-/* ------------------------------------------------------------------------ */
 #ifndef HAVE_STRDUP
-char           *
+char *
 strdup(buf)
-       char           *buf;
+    const char *buf;
 {
-       char           *p;
+    char *p;
 
-       if ((p = (char *) malloc(strlen(buf) + 1)) == NULL)
-               return NULL;
-       strcpy(p, buf);
-       return p;
+    if ((p = (char *) malloc(strlen(buf) + 1)) == NULL)
+        return NULL;
+    strcpy(p, buf);             /* ok */
+    return p;
 }
 #endif
 
 /*
  * memmove( char *dst , char *src , size_t cnt )
  */
-
-/* ------------------------------------------------------------------------ */
 #ifndef HAVE_MEMMOVE
-void           *
+void *
 memmove(dst, src, cnt)
-       register char  *dst, *src;
-       register int    cnt;
-{
-       if (dst == src)
-               return dst;
-       if (src > dst) {
-               while (--cnt >= 0)
-                       *dst++ = *src++;
-       }
-       else {
-               dst += cnt;
-               src += cnt;
-               while (--cnt >= 0)
-                       *--dst = *--src;
-       }
-       return dst;
-}
-#endif
-
-/*
- * rename - change the name of file 91.11.02 by Tomohiro Ishikawa
- * (ishikawa@gaia.cow.melco.CO.JP) 92.01.20 little modified (added #ifdef) by
- * Masaru Oki 92.01.28 added mkdir() and rmdir() by Tomohiro Ishikawa
- */
-
-#if !defined(HAVE_FTRUNCATE) && !defined(_MINIX) && HAVE_LINK
-
-/* ------------------------------------------------------------------------ */
-int
-rename(from, to)
-       const char *from, *to;
+    register char *dst, *src;
+    register int cnt;
 {
-       struct stat     s1, s2;
-       extern int      errno;
-
-       if (stat(from, &s1) < 0)
-               return (-1);
-       /* is 'FROM' file a directory? */
-       if ((s1.st_mode & S_IFMT) == S_IFDIR) {
-               errno = ENOTDIR;
-               return (-1);
-       }
-       if (stat(to, &s2) >= 0) {       /* 'TO' exists! */
-               /* is 'TO' file a directory? */
-               if ((s2.st_mode & S_IFMT) == S_IFDIR) {
-                       errno = EISDIR;
-                       return (-1);
-               }
-               if (unlink(to) < 0)
-                       return (-1);
-       }
-       if (link(from, to) < 0)
-               return (-1);
-       if (unlink(from) < 0)
-               return (-1);
-       return (0);
-}
-#endif                         /* !HAVE_FTRUNCATE */
-/* ------------------------------------------------------------------------ */
-
-#if !HAVE_MKDIR && HAVE_WORKING_FORK
-#ifndef        MKDIRPATH
-#define        MKDIRPATH       "/bin/mkdir"
-#endif
-#ifndef        RMDIRPATH
-#define        RMDIRPATH       "/bin/rmdir"
-#endif
-int
-rmdir(path)
-       char           *path;
-{
-       int             stat, rtn = 0;
-       char           *cmdname;
-       if ((cmdname = (char *) malloc(strlen(RMDIRPATH) + 1 + strlen(path) + 1))
-           == 0)
-               return (-1);
-       strcpy(cmdname, RMDIRPATH);
-       *(cmdname + strlen(RMDIRPATH)) = ' ';
-       strcpy(cmdname + strlen(RMDIRPATH) + 1, path);
-       if ((stat = system(cmdname)) < 0)
-               rtn = -1;       /* fork or exec error */
-       else if (stat) {        /* RMDIR command error */
-               errno = EIO;
-               rtn = -1;
-       }
-       free(cmdname);
-       return (rtn);
-}
-
-/* ------------------------------------------------------------------------ */
-int
-mkdir(path, mode)
-       char           *path;
-       int             mode;
-{
-       int             child, stat;
-       char           *cmdname, *cmdpath = MKDIRPATH;
-       if ((cmdname = (char *) strrchr(cmdpath, '/')) == (char *) 0)
-               cmdname = cmdpath;
-       if ((child = fork()) < 0)
-               return (-1);    /* fork error */
-       else if (child) {       /* parent process */
-               while (child != wait(&stat))    /* ignore signals */
-                       continue;
-       }
-       else {                  /* child process */
-               int             maskvalue;
-               maskvalue = umask(0);   /* get current umask() value */
-               umask(maskvalue | (0777 & ~mode));      /* set it! */
-               execl(cmdpath, cmdname, path, (char *) 0);
-               /* never come here except execl is error */
-               return (-1);
-       }
-       if (stat != 0) {
-               errno = EIO;    /* cannot get error num. */
-               return (-1);
-       }
-       return (0);
+    if (dst == src)
+        return dst;
+    if (src > dst) {
+        while (--cnt >= 0)
+            *dst++ = *src++;
+    }
+    else {
+        dst += cnt;
+        src += cnt;
+        while (--cnt >= 0)
+            *--dst = *--src;
+    }
+    return dst;
 }
 #endif
 
-/*
- * strucmp modified: Oct 29 1991 by Masaru Oki
- */
-
 #ifndef HAVE_STRCASECMP
-static int
-my_toupper(n)
-       register int    n;
-{
-       if (n >= 'a' && n <= 'z')
-               return n & (~('a' - 'A'));
-       return n;
-}
+/* public domain rewrite of strcasecmp(3) */
+
+#include <ctype.h>
 
-/* ------------------------------------------------------------------------ */
 int
-strucmp(s, t)
-       register char  *s, *t;
+strcasecmp(p1, p2)
+    const char *p1, *p2;
 {
-       while (my_toupper(*s++) == my_toupper(*t++))
-               if (!*s || !*t)
-                       break;
-       if (!*s && !*t)
-               return 0;
-       return 1;
+    while (*p1 && *p2) {
+       if (toupper(*p1) != toupper(*p2))
+           return toupper(*p1) - toupper(*p2);
+       p1++;
+       p2++;
+    }
+    return strlen(p1) - strlen(p2);
 }
 #endif
 
-/* ------------------------------------------------------------------------ */
 #ifndef HAVE_MEMSET
 /* Public Domain memset(3) */
-char           *
+char *
 memset(s, c, n)
-       char           *s;
-       int             c, n;
+    char *s;
+    int c;
+    size_t n;
 {
-       char           *p = s;
-       while (n--)
-               *p++ = (char) c;
-       return s;
+    char *p = s;
+
+    while (n--)
+        *p++ = (char) c;
+    return s;
 }
 #endif
 
@@ -400,6 +230,9 @@ xsnprintf(dest, size, fmt, va_alist)
 char *
 xstrchr(const char *s, int c)
 {
+    if (c == 0)
+        return s + strlen(s);
+
     while (*s) {
         if ((unsigned char)*s == (unsigned char)c)
             return (char*)s;
@@ -454,9 +287,49 @@ xmemrchr(const char *s, int c, size_t n)
 }
 #endif
 
-/* Local Variables: */
-/* mode:c */
-/* tab-width:4 */
-/* compile-command:"gcc -c util.c" */
-/* End: */
-/* vi: set tabstop=4: */
+#ifndef HAVE_BASENAME
+char *
+basename(char *s)
+{
+    int len;
+    char *t;
+
+    if (!s || *s == 0)
+        return ".";
+
+    /* strip trailing slashs */
+    t = s + strlen(s) - 1;
+    while (s != t && *t == '/')
+        *t-- = '\0';
+    if (s == t)
+        return s;
+
+    t = strrchr(s, '/');
+    if (t)
+        return t + 1;
+    else
+        return s;
+
+}
+#endif
+
+/* This function is similar to strncpy() but `dst' is always
+   terminated by '\0'. Return the copied string length. */
+int
+str_safe_copy(char *dst, const char *src, int dstsz)
+{
+    int i;
+
+    if (dstsz < 1) return 0;
+
+    for (i = 0; i < dstsz; i++) {
+       if ((dst[i] = src[i]) == '\0')
+           return i;
+    }
+
+    /* here is i == dstsz */
+    dst[--i] = '\0';   /* if eliminated this line,
+                          this function was same as strncpy(). */
+
+    return i;
+}