New memory management subsystem.

This commit is contained in:
Robert Kiraly 2021-04-15 17:09:54 -07:00
parent 1801ca9c74
commit 9b4288cf9c
35 changed files with 2576 additions and 106 deletions

View File

@ -12,7 +12,8 @@ CC ?= gcc
#CC ?= tcc
#CC ?= musl-tcc
CFLAGS += -O2 -pedantic -g -Wall -Wextra
CPPFLAGS += -DVERSION=$(VERSION) -D_FORTIFY_SOURCE=2
# CPPFLAGS += -DVERSION=$(VERSION) -D_FORTIFY_SOURCE=2
CPPFLAGS += -DVERSION=$(VERSION)
LDFLAGS += -lm
BIN ?= slidescript

0
src/compression.c Executable file → Normal file
View File

0
src/enc.c Executable file → Normal file
View File

259
src/eprintf.c Normal file
View File

@ -0,0 +1,259 @@
/* ------------------------------------------------------------ */
/* file information */
/* ------------------------------------------------------------ */
// Filename: eprintf.c
// Purpose: TTY and error-message routines
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
/* ------------------------------------------------------------ */
/* header files */
/* ------------------------------------------------------------ */
/* The "EPRINTF_P" definition used below suppresses some of the */
/* prototypes in "x3file.h" locally. This allows us to imple- */
/* ment variable-length argument lists in a non-standard (but */
/* generally portable) fashion. */
#define EPRINTF_P /* see explanation above */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "inc/eprintf.h"
/* ------------------------------------------------------------ */
/* functions */
/* ------------------------------------------------------------ */
/* Function: V_FUNC init_tty(NO_PARAM) */
/* Summary: Initializes the UX3 TTY flags. */
/* ------------------------------------------------------------ */
/* "init_tty()" sets three global character variables as fol- */
/* lows: */
/* */
/* tty_in -- standard input stream TTY mode */
/* tty_out -- standard output stream TTY mode */
/* tty_err -- standard error stream TTY mode */
/* TTY modes are determined by the standard library function */
/* "isatty()". */
/* E.g., "init_tty()" sets these three flags true if and only */
/* if the associated streams are console devices. */
/* The global character variable "tty_set" flags the TTY */
/* initialization status. "tty_set" is true if "init_tty()" */
/* has been called previously. */
/* ------------------------------------------------------------ */
V_FUNC init_tty (NO_PARAM)
{
tty_in = isatty (0); /* standard-input TTY flag */
tty_out = isatty (1); /* standard-output TTY flag */
tty_err = isatty (2); /* standard-error TTY flag */
tty_set = TRUE; /* TTY initialization flag */
}
/* ------------------------------------------------------------ */
/* "eprintf(s,...)" accepts a "printf()"-style argument list, */
/* writes the specified message to the standard error stream, */
/* and flushes the stream. */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC eprintf (s,a,b,c,d,e,f,g,h,i,j)
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
fflush (stdout); /* flush standard output stream */
fprintf (stderr, /* print message to the */
s,a,b,c,d,e,f,g,h,i,j); /* standard error stream */
fflush (stderr); /* flush standard error stream */
}
/* ------------------------------------------------------------ */
/* "eprintf2(s,...)" accepts a "printf()"-style argument list, */
/* writes the specified message to the standard error stream, */
/* and flushes the stream. */
/* If the standard output and standard error TTY modes are */
/* different, "eprintf2()" will write the message to the */
/* standard output stream as well. TTY modes are determined by */
/* the standard library function "isatty()". */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC eprintf2 (s,a,b,c,d,e,f,g,h,i,j)
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
fflush (stdout); /* flush standard output stream */
fprintf (stderr, /* print message to the */
s,a,b,c,d,e,f,g,h,i,j); /* standard error stream */
fflush (stderr); /* flush standard error stream */
if (!tty_set) init_tty(); /* initialize TTY mode flags */
if (tty_out == tty_err) /* split the error stream? */
{ /* no */
return; /* done - exit */
}
fprintf (stdout, /* print message to the stan- */
s,a,b,c,d,e,f,g,h,i,j); /* dard output stream */
fflush (stdout); /* flush standard output stream */
}
/* ------------------------------------------------------------ */
/* "z_msg(t_flag,pf,s,...)" accepts the following arguments: */
/* */
/* t_flag -- terminate-caller flag */
/* pf -- prefix-string pointer */
/* s, ... -- "printf()"-style argument list */
/* "z_msg()" writes the specified "printf()"-style message to */
/* the standard error stream, appends a newline, and flushes */
/* the stream. */
/* If the standard output and standard error TTY modes are */
/* different, "z_msg()" will write the message to the standard */
/* output stream as well. TTY modes are determined by the */
/* standard library function "isatty()". */
/* If the prefix-string pointer "pf" is not NULL, "z_msg()" */
/* prepends the specified string to the message produced. */
/* If the terminate-caller flag "t_flag" is true (nonzero), */
/* "z_msg()" terminates the caller upon completion. */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
MODPRIV V_FUNC z_msg(t_flag,pf,s,a,b,c,d,e,f,g,h,i,j)
int t_flag; /* terminate-caller flag */
char *pf; /* prefix pointer (or NULL) */
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
if ((pf != NULLCP) && (*pf != CH_EOS)) eprintf2 ("%s",pf);
eprintf2 (s,a,b,c,d,e,f,g,h,i,j);
eprintf2 ("\n"); /* append a newline */
if (t_flag) exit (ONE); /* terminate the caller */
}
/* ------------------------------------------------------------ */
/* "x_warn(s,...)" accepts a "printf()"-style argument list */
/* and writes an warning message based on the argument list to */
/* the standard error stream. */
/* If the standard output and standard error TTY modes are */
/* different, "x_warn()" will write the message to the standard */
/* output stream as well. TTY modes are determined by the */
/* standard library function "isatty()". */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC x_warn(s,a,b,c,d,e,f,g,h,i,j)
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
z_msg (FALSE, "Warning: ", s,a,b,c,d,e,f,g,h,i,j);
}
/* ------------------------------------------------------------ */
/* "x_error(s,...)" accepts a "printf()"-style argument list, */
/* writes an error message based on the argument list to the */
/* standard error stream, and terminates the caller. */
/* If the standard output and standard error TTY modes are */
/* different, "x_error()" will write the message to the */
/* standard output stream as well. TTY modes are determined by */
/* the standard library function "isatty()". */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC x_error(s,a,b,c,d,e,f,g,h,i,j)
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
z_msg (TRUE, "Error: ", s,a,b,c,d,e,f,g,h,i,j);
}
/* ------------------------------------------------------------ */
/* "x_panic(s,...)" accepts a "printf()"-style argument list, */
/* writes an error message based on the argument list to the */
/* standard error stream, and terminates the caller. */
/* If the standard output and standard error TTY modes are */
/* different, "x_panic" will write the message to the standard */
/* output stream as well. TTY modes are determined by the */
/* standard library function "isatty()". */
/* "x_panic" is called primarily to handle internal consistency */
/* errors. */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC x_panic (s,a,b,c,d,e,f,g,h,i,j)
char *s; /* format string */
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
{
z_msg (TRUE, "Internal error: ",
s,a,b,c,d,e,f,g,h,i,j);
}
/* ------------------------------------------------------------ */
/* "n_panic(n)" prints an error message of the following form */
/* and terminates the caller: */
/* */
/* Internal error: #123 */
/* The integer "n" is used for the "#..." portion of the */
/* message. */
/* "n_panic()" writes the message to the standard error stream. */
/* If the standard output and standard error TTY modes are */
/* different, "n_panic()" will write the message to the stan- */
/* dard output stream as well. TTY modes are determined by the */
/* standard library function "isatty()". */
/* "n_panic()" is called primarily to handle internal con- */
/* sistency errors. */
/* This function may be system-dependent. */
/* ------------------------------------------------------------ */
V_FUNC n_panic(n)
REG_VAR int n; /* "panic" number */
{
x_panic ("#%d",n,0,0,0,0,0,0,0,0,0);
}

0
src/inc/compression.h Executable file → Normal file
View File

0
src/inc/config.h Executable file → Normal file
View File

0
src/inc/deps.h Executable file → Normal file
View File

0
src/inc/enc.h Executable file → Normal file
View File

45
src/inc/eprintf.h Normal file
View File

@ -0,0 +1,45 @@
/* ------------------------------------------------------------ */
/* file information */
/* ------------------------------------------------------------ */
// Filename: eprintf.h
// Purpose: TTY and error-message routines
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
/* ------------------------------------------------------------ */
/* header file setup */
/* ------------------------------------------------------------ */
#ifndef _EPRINTF_H /* skip this file if loaded */
#define _EPRINTF_H 1 /* flag this file */
#include "x3basic.h"
/* ------------------------------------------------------------ */
/* TTY (console mode) flags */
/* ------------------------------------------------------------ */
UX3_EXT char tty_in; /* standard-input TTY flag */
UX3_EXT char tty_out; /* standard-output TTY flag */
UX3_EXT char tty_err; /* standard-error TTY flag */
UX3_EXT char tty_set; /* TTY initialization flag */
/* ------------------------------------------------------------ */
/* function prototypes */
/* ------------------------------------------------------------ */
V_PROTO init_tty (NO_PARAM);
#ifndef EPRINTF_P /* see comments in "eprintf.c" */
/*VARARGS*/ V_PROTO eprintf (argp2 (char *, ...));
/*VARARGS*/ V_PROTO eprintf2 (argp2 (char *, ...));
/*VARARGS*/ V_PROTO x_panic (argp2 (char *, ...));
/*VARARGS*/ V_PROTO x_error (argp2 (char *, ...));
/*VARARGS*/ V_PROTO x_warn (argp2 (char *, ...));
#endif /* endif not EPRINTF_P */
/* ------------------------------------------------------------ */
/* wrap it up */
/* ------------------------------------------------------------ */
#endif /* endif _EPRINTF_H */

0
src/inc/inset.h Executable file → Normal file
View File

0
src/inc/lexer.h Executable file → Normal file
View File

0
src/inc/math.h Executable file → Normal file
View File

0
src/inc/md5.h Executable file → Normal file
View File

0
src/inc/network.h Executable file → Normal file
View File

0
src/inc/pipe.h Executable file → Normal file
View File

0
src/inc/sbyteswap.h Executable file → Normal file
View File

0
src/inc/search.h Executable file → Normal file
View File

6
src/inc/tar.h Executable file → Normal file
View File

@ -26,6 +26,12 @@ THE SOFTWARE
#ifndef __TAR__
#define __TAR__
#include "x3mem.h"
UX3_EXT QLIST QM_TAR [ONE]; // Dynamic-memory QLIST
extern void tar_free_pool (void);
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif

0
src/inc/util.h Executable file → Normal file
View File

0
src/inc/vars.h Executable file → Normal file
View File

275
src/inc/x3basic.h Normal file
View File

@ -0,0 +1,275 @@
/* ------------------------------------------------------------ */
/* file information */
/* ------------------------------------------------------------ */
// Filename: x3basic.h
// Purpose: UX3 basic definitions
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
/* ------------------------------------------------------------ */
/* header file setup */
/* ------------------------------------------------------------ */
#ifndef _X3BASIC_H /* skip this file if loaded */
#define _X3BASIC_H 1 /* flag this file */
/* ------------------------------------------------------------ */
/* basic definitions */
/* ------------------------------------------------------------ */
#ifndef ZERO
#define ZERO 0
#endif // Endif ZERO
#ifndef ONE
#define ONE 1
#endif // Endif ONE
#ifndef FALSE
#define FALSE 0
#endif // Endif FALSE
#ifndef TRUE
#define TRUE 1
#endif // Endif TRUE
#ifndef CH_EOS
#define CH_EOS '\0'
#endif // Endif CH_EOS
#ifndef x3u_char
#define x3u_char unsigned char
#endif
#ifndef x3u_int
#define x3u_int unsigned int
#endif
#ifndef x3u_long
#define x3u_long unsigned long
#endif
#ifndef MODPRIV // Module-private
#define MODPRIV static
#endif // Endif MODPRIV
#ifndef MODPUB // Module-public
#define MODPUB
#endif // Endif MODPUB
#ifndef REG_VAR
#define REG_VAR
#endif // Endif NULL_PTR
/* ------------------------------------------------------------ */
/* "erase item" macro functions */
/* ------------------------------------------------------------ */
/* If "dp" is a data pointer (of any type) and "nb" is a short */
/* or long integer, "b_clr(dp,nb)" clears "nb" bytes to zero, */
/* starting with the first byte pointed to by "dp". */
/* Note: "nb" may use any integer data type, but the value of */
/* "nb" should fit into an unsigned integer. */
#define b_clr(dp,nb) \
{ \
REG_VAR char *cp = (char *) (dp); \
REG_VAR u_int x = (u_int) (nb); \
while (x-- > ZERO) *cp++ = CH_EOS; \
}
/* ------------------------------------------------------------ */
/* If "a[]" is an array, "a_clr(a)" clears the array (bytewise) */
/* to zero. "a[]" must be an array and not a pointer. The */
/* array must have a known fixed size. */
#define a_clr(a) b_clr ((char *) (&((a)[0])),sizeof(a))
/* ------------------------------------------------------------ */
/* If "p" is a pointer to a structure or variable, "p_clr(p)" */
/* clears the structure or variable. The pointer object must */
/* have a known fixed size. */
#define p_clr(p) b_clr ((char *) (p),sizeof(*p))
/* ------------------------------------------------------------ */
/* If "x" is a variable (and not an array), "v_clr(x)" clears */
/* the variable (bytewise) to zero. The variable must have a */
/* known fixed size. */
#define v_clr(x) b_clr ((char *) (&(x)),sizeof(x))
/* ------------------------------------------------------------ */
/* handle "void" data type */
/* ------------------------------------------------------------ */
/* The following five symbols provide a portable interface to */
/* the "void" data type. These five symbols are translated */
/* appropriately for systems which don't support the "void" */
/* type. */
/* (a) V_FUNC -- defines a void function */
/* (b) V_PROTO -- declares a void function */
/* (c) NO_PARAM -- void function parameter type */
/* (d) V_CAST -- void typecast */
/* (e) V_OBJ -- void pointer object */
/* ------------------------------------------------------------ */
/* V_FUNC may be used to declare a void function in the follow- */
/* ing context: */
/* */
/* V_FUNC function-definition(...) { ... } */
/* V_FUNC should not be used in function declarations or */
/* function prototypes. */
/* ------------------------------------------------------------ */
/* V_PROTO may be used to declare a void function in the */
/* following two contexts: */
/* */
/* V_PROTO function-declaration(); */
/* V_PROTO function-prototype(...); */
/* V_PROTO should not be used in function definitions. */
/* ------------------------------------------------------------ */
/* NO_PARAM may be used to declare a void function argument; */
/* for example, */
/* */
/* int foo(NO_PARAM) { ... } */
/* NO_PARAM may be used in function declarations, in function */
/* definitions, and in function prototypes. */
/* ------------------------------------------------------------ */
/* "V_OBJ *" translates into the appropriate void-pointer data */
/* type; for example, */
/* */
/* V_OBJ *malloc (argp1 (u_int)); */
/* ------------------------------------------------------------ */
/* V_CAST translates into a "void" typecast; for example, */
/* */
/* char *strcpy (argp2(char *,char *)); */
/* V_CAST strcpy (s,t); */
/* ------------------------------------------------------------ */
/* if "void" is not supported */
#ifdef NO_VOID /* "void" type is not supported */
#define NO_PARAM /* void parameter type (empty) */
#define V_CAST /* void typecast (no effect) */
#define V_FUNC /* void function definition */
#define V_OBJ char /* void pointer object */
#define V_PROTO extern /* void function declaration */
#endif /* endif "void not supported" */
/* ------------------------------------------------------------ */
/* if "void" is supported */
#ifndef NO_VOID /* "void" type is supported */
#ifdef NO_PROTO /* prototypes are not supported */
#define NO_PARAM /* void parameter type (empty) */
#else /* prototypes are supported */
#define NO_PARAM void /* void parameter type */
#endif /* endif NO_PARAM */
#endif /* endif "void is supported" */
#ifndef NO_VOID /* "void" type is supported */
#define V_CAST (void) /* void typecast */
#define V_FUNC void /* void function definition */
#define V_OBJ void /* void pointer object */
#define V_PROTO void /* void function declaration */
#endif /* endif "void is supported" */
/* ------------------------------------------------------------ */
/* ANSI prototype setup */
/* ------------------------------------------------------------ */
/* The following "argp#(...)" macros may be used in ANSI */
/* function prototypes. "#" should be replaced with the number */
/* of function arguments; e.g.: */
/* */
/* V_OBJ *malloc (argp1(u_int)); */
/* char *strcpy (argp2(char *,char *)); */
/* The "argp#(...)" macros discard their arguments on systems */
/* which do not support ANSI prototypes. */
/* The "ellipse" construct "..." counts as one argument. */
/* ------------------------------------------------------------ */
#ifdef NO_PROTO
#define argp0()
#define argp1(a)
#define argp2(a,b)
#define argp3(a,b,c)
#define argp4(a,b,c,d)
#define argp5(a,b,c,d,e)
#define argp6(a,b,c,d,e,f)
#define argp7(a,b,c,d,e,f,g)
#define argp8(a,b,c,d,e,f,g,h)
#define argp9(a,b,c,d,e,f,g,h,i)
#else
#define argp0() NO_PARAM
#define argp1(a) a
#define argp2(a,b) a,b
#define argp3(a,b,c) a,b,c
#define argp4(a,b,c,d) a,b,c,d
#define argp5(a,b,c,d,e) a,b,c,d,e
#define argp6(a,b,c,d,e,f) a,b,c,d,e,f
#define argp7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
#define argp8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
#define argp9(a,b,c,d,e,f,g,h,i) a,b,c,d,e,f,g,h,i
#endif
/* ------------------------------------------------------------ */
/* null pointers of various types */
/* ------------------------------------------------------------ */
/* Note: NULLXP is a null function pointer. */
#ifndef NULLXP
#define NULL_PTR ((void *) ZERO)
#define NULLCP ((char *) ZERO)
#define NULLFP ((FILE *) ZERO)
#define NULLVP ((V_OBJ *) ZERO)
#define NULLXP ((int (*)()) ZERO)
#endif // Endif NULLXP
/* ------------------------------------------------------------ */
/* resolve global variables */
/* ------------------------------------------------------------ */
#ifdef RES_UX3 /* resolve external variables? */
#define UX3_EXT /* yes */
#else /* no */
#define UX3_EXT extern /* variables are externals */
#endif
#ifdef VMS /* VMS host */
#undef UX3_EXT
#ifdef RES_UX3 /* resolve externals? */
#define UX3_EXT globaldef
#else /* don't resolve externals */
#define UX3_EXT globalref
#endif /* endif RES_UX3 */
#endif /* endif VMS */
/* ------------------------------------------------------------ */
/* wrap it up */
/* ------------------------------------------------------------ */
#endif // Endif _X3BASIC_H

333
src/inc/x3mem.h Normal file
View File

@ -0,0 +1,333 @@
/* ------------------------------------------------------------ */
/* file information */
/* ------------------------------------------------------------ */
// Filename: x3mem.h
// Purpose: Memory management
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
/* ------------------------------------------------------------ */
/* header file setup */
/* ------------------------------------------------------------ */
#ifndef _X3MEM_H /* skip this file if loaded */
#define _X3MEM_H 1 /* flag this file */
#include <stdio.h>
#include <stdlib.h>
#include "x3basic.h"
#include "eprintf.h"
/* ------------------------------------------------------------ */
/* basic definitions */
/* ------------------------------------------------------------ */
#ifndef x3u_int
#define x3u_int unsigned int
#endif
#ifndef x3u_long
#define x3u_long unsigned long
#endif
#ifndef V_OBJ
#define V_OBJ void
#endif
/* ------------------------------------------------------------ */
/* X3MEM package - overview */
/* ------------------------------------------------------------ */
/* The X3MEM package includes the public functions listed be- */
/* low. For more information, see the functions themselves. */
/* ------------------------------------------------------------ */
/* QLIST support functions: (*) = macro function */
/* 1. chk_qm0() -- checks a "qmalloc()" storage pointer */
/* 2. chk_qma() -- checks an entire QLIST */
/* (*) 3. chk_qmp() -- generic version of "chk_qm0()" */
/* 4. qcalloc() -- allocates and clears memory */
/* 5. qmalloc() -- allocates memory */
/* 6. qrealloc() -- re-allocates memory */
/* 7. qfree() -- frees allocated memory */
/* 8. qflush() -- frees an entire QLIST */
/* 9. sys_mem() -- returns amount of free system memory */
/* (*) 10. xqfree() -- generic version of "qfree()" */
/* ------------------------------------------------------------ */
/* Simplified QLIST interface layer: */
/* 11. sqCalloc() -- similar to "calloc()" */
/* 12. sqChkHeap() -- checks the entire "sq..." heap */
/* 13. sqChkPtr() -- checks an "sq..." storage pointer */
/* 14. sqFlush() -- frees all "sq..." storage */
/* 15. sqFree() -- frees one "sq..." storage block */
/* 16. sqMalloc() -- similar to "malloc()" */
/* 17. sqRealloc() -- similar to "realloc()" */
/* ------------------------------------------------------------ */
/* QLIST pointers - explanation */
/* ------------------------------------------------------------ */
/* The X3MEM functions support multiple dynamic-memory allo- */
/* cation lists. The "qmalloc()" function, for example, */
/* allocates memory from a specified allocation list, and the */
/* "qfree()" function returns memory to the associated list. */
/* Multiple-allocation lists provide greater control over */
/* memory allocation; e.g., the caller can free up one list in */
/* its entirety without disturbing other lists. */
/* Additionally, the use of multiple allocation lists can */
/* reduce the fragmentation problems which occur on virtual- */
/* memory systems when free lists have grown large. */
/* Allocation lists are specified by QLIST pointers; to create */
/* a new allocation list, the user simply defines a new (empty) */
/* QLIST structure. */
/* If a program does not require multiple allocation lists, the */
/* predefined general-purpose list "QM_GEN" may be used. */
/* ------------------------------------------------------------ */
/* QMALLOC structure definitions */
/* ------------------------------------------------------------ */
/* alignment data type */
#ifdef QMSA /* stand-alone version */
#ifndef DEF_ALIGN /* set default alignment type */
#define DEF_ALIGN unsigned int
#endif
#endif /* endif "QMSA" */
#ifdef DEF_ALIGN /* is alignment type defined? */
typedef DEF_ALIGN QM_ALIGN; /* use specified alignment type */
#else /* use default alignment type */
typedef long QM_ALIGN; /* "long-integer" alignment */
#endif /* endif DEF_ALIGN */
/* size of an alignment unit */
#define QMASIZE (sizeof(QM_ALIGN))
/* ------------------------------------------------------------ */
/* "size" data type */
#define QM_SIZE_T unsigned int
/* ------------------------------------------------------------ */
/* QMALLOC memory block header */
union qm_header
{
QM_ALIGN qm_d; /* align the block header */
struct /* begin header proper (qm_h) */
{
union /* begin multi-use portion */
{ /* see explanation below */
union qm_header *n0_free;
struct qlist *q0_owner;
}
qm_x; /* end multi-use portion */
QM_SIZE_T q0_chk; /* consistency-check value */
QM_SIZE_T q0_size; /* block size */
}
qm_h; /* end header proper (qm_h) */
};
typedef union qm_header QM_HDR; /* typedef the block header */
/* ------------------------------------------------------------ */
/* simplify the structure */
#define nxt_free qm_h.qm_x.n0_free
#define qa_size qm_h.q0_size
#define qm_chk qm_h.q0_chk
#define qm_owner qm_h.qm_x.q0_owner
/* ------------------------------------------------------------ */
/* QM_HDR structure */
/* The "QM_HDR" structure defines a block of dynamic memory. */
/* The block is aligned on a "QM_ALIGN" boundary, and begins */
/* with a header of type "QM_HDR". The rest of the block is */
/* used for storage. */
/* "qa_size" is the total size of the memory block (including */
/* the header itself) in "QM_ALIGN" alignment units (i.e., */
/* units of QMASIZE bytes). */
/* "nxt_free" and "qm_owner" are context-dependent. See the */
/* discussion of the QLIST structure below for additional */
/* information. */
/* "qm_chk" is used internally for consistency checking. */
/* ------------------------------------------------------------ */
/* QLIST structure */
struct qlist
{
QM_HDR *qm_free; /* QLIST free list */
QM_HDR *qm_sysmem; /* QLIST system-memory list */
QM_SIZE_T qm_block; /* allocation blocking factor */
char qm_nofree; /* non-freeable flag */
};
typedef struct qlist QLIST; /* typedef the list header */
/* null structure pointer */
#define NULL_QLS ((QLIST *) ZERO)
/* ------------------------------------------------------------ */
/* QLIST free-list */
/* The "qm_free" field for a QLIST points to a list of free */
/* memory blocks associated with the QLIST. Each free block */
/* begins with a "QM_HDR" block header. The free blocks are */
/* linked together by the "nxt_free" field in the "QM_HDR" */
/* header. Blocks are allocated from this list by "qmalloc()" */
/* and freed onto the list by "qfree()". */
/* When "qmalloc()" allocates a block from a free-list, it */
/* points the "qm_owner" field in the header to the QLIST from */
/* which the block was obtained. "qfree()" uses this field */
/* subsequently when the block is freed. */
/* The memory blocks in the free list are carved out of a */
/* lower-level system memory chain, which is discussed in the */
/* next section. */
/* ------------------------------------------------------------ */
/* QLIST system-memory list */
/* The "qm_sysmem" field for a QLIST points to a list of low- */
/* level "system memory" blocks associated with the QLIST. */
/* Each system memory block begins with a "QM_HDR" block head- */
/* er. The system memory blocks are linked together by the */
/* "nxt_free" field in the "QM_HDR" header. */
/* This linked list contains all of the dynamic storage */
/* currently associated with a QLIST (on the "qm_free" free */
/* list or not). The blocks in this list are obtained from the */
/* operating system. */
/* "qmalloc()" carves the storage portion of each system memory */
/* block up into sub-blocks, writes "QM_HDR" headers onto the */
/* sub-blocks, and uses these secondary headers to build */
/* higher-level (qm_free) allocation lists. */
/* ------------------------------------------------------------ */
/* allocation blocking factor */
/* The "malloc"-based version of "qmalloc()" uses the standard */
/* library routine "malloc()" to allocate dynamic memory at the */
/* system level. */
/* The "stand-alone" version of "qmalloc()" uses an internal */
/* utility routine to allocate dynamic memory at the system */
/* level. */
/* The "qm_block" field in a QLIST header specifies the minimum */
/* amount of memory (in bytes) to be requested for the QLIST */
/* per system-level memory allocation call. */
/* If the "qm_block" field is not set, a reasonable default */
/* value is used. */
/* If the host system has virtual memory, setting "qm_block" */
/* as follows may improve performance: */
/* */
/* qm_block <- system memory page size minus total size of all */
/* system-level storage headers. */
/* ------------------------------------------------------------ */
/* misc. global variables */
/* ------------------------------------------------------------ */
/* "QM_GEN" is intended for use as a general-purpose QLIST. */
/* Note: Since "QM_GEN[]" is an array, "QM_GEN" serves both as */
/* a QLIST pointer and as the QLIST entry itself. */
UX3_EXT QLIST QM_GEN [ONE]; /* general-purpose QLIST */
/* ------------------------------------------------------------ */
/* "qm_retsys" is a flag used by the "qflush()" function. See */
/* "qflush()" for additional information. */
UX3_EXT char qm_retsys; /* "qflush()" flag */
/* ------------------------------------------------------------ */
/* macro functions */
/* ------------------------------------------------------------ */
/* "chk_qmp(xp)" checks the pointer "xp" and terminates the */
/* caller with an error message if "xp" is not a valid */
/* "qmalloc()" storage pointer. "xp" may be a pointer of any */
/* type; "chk_qmp()" typecasts the pointer appropriately. */
/* Note: A valid storage pointer becomes invalid if the */
/* associated storage is freed. */
/* "chk_qmp()" is a macro interface to the function "chk_ */
/* qm0()". See the description of "chk_qm0()" for additional */
/* information. */
/* ------------------------------------------------------------ */
#define chk_qmp(xp) chk_qm0 ((V_OBJ *) (xp))
/* ------------------------------------------------------------ */
/* The macro function "xqfree()" is equivalent to the non-macro */
/* function "qfree()", with the distinction that "xqfree()" */
/* typecasts its argument appropriately. See the description */
/* of "qfree()" for additional information. */
/* ------------------------------------------------------------ */
#define xqfree(p) qfree ((V_OBJ *) (p))
/* ------------------------------------------------------------ */
/* X3MEM function prototypes */
/* ------------------------------------------------------------ */
V_PROTO chk_qm0 (argp1 (V_OBJ *));
V_PROTO chk_qma (argp1 (QLIST *));
V_OBJ *qcalloc (argp3 (QLIST *,x3u_int,x3u_int));
V_PROTO qflush (argp1 (QLIST *));
V_PROTO qfree (argp1 (V_OBJ *));
V_OBJ *qmalloc (argp2 (QLIST *,int));
V_OBJ *qrealloc (argp2 (V_OBJ *,int));
long sys_mem (argp0 ());
/* ------------------------------------------------------------ */
V_OBJ *sqCalloc (argp2 (x3u_int, x3u_int));
V_PROTO sqChkHeap (argp0 ());
V_PROTO sqChkPtr (argp2 (V_OBJ *, char *));
V_PROTO sqFlush (argp0 ());
V_PROTO sqFree (argp1 (V_OBJ *));
V_OBJ *sqMalloc (argp1 (x3u_int));
V_OBJ *sqRealloc (argp2 (V_OBJ *, x3u_int));
/* ------------------------------------------------------------ */
/* wrap it up */
/* ------------------------------------------------------------ */
#endif /* endif _X3MEM_H */

2
src/inset.c Executable file → Normal file
View File

@ -8,6 +8,7 @@
#include "inc/deps.h"
#include "inc/inset.h"
#include "inc/lexer.h"
#include "inc/tar.h"
#include "inc/vars.h"
#include "inc/util.h"
@ -75,6 +76,7 @@ char *parse_bq(char *string)
strcat (varbuffer, "\n");
variable_pointer = process_line(varbuffer);
tar_free_pool();
if(variable_pointer == NULL)
syn_error("ss:error:backquoted function must return string!");

3
src/lexer.c Executable file → Normal file
View File

@ -346,7 +346,6 @@ char *process_line(char *line)
return retbuf;
}
/* COMPRESSION AND DECOMPRESSION */
else if(strncmp("decompress",tok_srch,10) == 0)
{
@ -354,6 +353,7 @@ char *process_line(char *line)
struct tar_t *archive = NULL;
int fd;
tar_free_pool();
tok_srch = strtok(NULL, "\"");
if(tok_srch == NULL)
{
@ -430,6 +430,7 @@ char *process_line(char *line)
struct tar_t *archive = NULL;
int fd;
tar_free_pool();
tok_srch = strtok(NULL, "\"");
if(tok_srch == NULL)
{

4
src/main.c Executable file → Normal file
View File

@ -11,6 +11,7 @@
#include "inc/util.h"
#include "inc/lexer.h"
#include "inc/pipe.h"
#include "inc/tar.h"
#include "inc/vars.h"
int main(int argc, char **argv)
@ -62,6 +63,7 @@ int main(int argc, char **argv)
pipechk = get_cmd_count();
return_dat = process_line(spipe[0].command);
tar_free_pool();
// Blank line, getting up outta here.
if(return_dat == NULL) continue;
@ -74,6 +76,8 @@ int main(int argc, char **argv)
set_var(varc, "PIPE", return_dat);
// Process functions based on previous pipe return
return_dat = process_line(spipe[ii].command);
tar_free_pool();
// set PIPE var back to NULL after use, keep the struct clean
set_var(varc, "\0", "\0");
// Check to see if there's anything to even display

0
src/math.c Executable file → Normal file
View File

0
src/md5.c Executable file → Normal file
View File

0
src/network.c Executable file → Normal file
View File

0
src/pipe.c Executable file → Normal file
View File

0
src/search.c Executable file → Normal file
View File

339
src/tar.c Executable file → Normal file
View File

@ -27,12 +27,16 @@ static int iszeroed(char * buf, size_t size);
// make directory recursively
static int recursive_mkdir(const char * dir, const unsigned int mode);
int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
if (fd < 0){
int tar_read (const int fd,
struct tar_t **archive, const char verbosity)
{
if (fd < 0)
{
ERROR("Bad file descriptor");
}
if (!archive || *archive){
if (!archive || *archive)
{
ERROR("Bad archive");
}
@ -42,9 +46,11 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
struct tar_t ** tar = archive;
char update = 1;
for(count = 0; ; count++){
*tar = malloc(sizeof(struct tar_t));
if (update && (read_size(fd, (*tar) -> block, 512) != 512)){
for(count = 0; ; count++)
{
*tar = qmalloc (QM_TAR, sizeof (struct tar_t));
if (update && (read_size(fd, (*tar) -> block, 512) != 512))
{
V_PRINT(stderr, "Error: Bad read. Stopping");
tar_free(*tar);
*tar = NULL;
@ -53,8 +59,10 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
update = 1;
// if current block is all zeros
if (iszeroed((*tar) -> block, 512)){
if (read_size(fd, (*tar) -> block, 512) != 512){
if (iszeroed((*tar) -> block, 512))
{
if (read_size(fd, (*tar) -> block, 512) != 512)
{
V_PRINT(stderr, "Error: Bad read. Stopping");
tar_free(*tar);
*tar = NULL;
@ -62,12 +70,14 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
}
// check if next block is all zeros as well
if (iszeroed((*tar) -> block, 512)){
if (iszeroed((*tar) -> block, 512))
{
tar_free(*tar);
*tar = NULL;
// skip to end of record
if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1)){
if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
@ -82,13 +92,17 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
// skip over data and unfilled block
unsigned int jump = oct2uint((*tar) -> size, 11);
if (jump % 512){
if (jump % 512)
{
jump += 512 - (jump % 512);
}
// move file descriptor
offset += 512 + jump;
if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1)){
if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
@ -99,12 +113,19 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
return count;
}
int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
if (fd < 0){
int tar_write (const int fd,
struct tar_t ** archive,
const size_t filecount,
const char * files[],
const char verbosity)
{
if (fd < 0)
{
ERROR("Bad file descriptor");
}
if (!archive){
if (!archive)
{
ERROR("Bad archive");
}
@ -113,64 +134,101 @@ int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, con
// if there is old data
struct tar_t ** tar = archive;
if (*tar){
if (*tar)
{
// skip to last entry
while (*tar && (*tar) -> next){
while (*tar && (*tar) -> next)
{
tar = &((*tar) -> next);
}
// get offset past final entry
unsigned int jump = 512 + oct2uint((*tar) -> size, 11);
if (jump % 512){
if (jump % 512)
{
jump += 512 - (jump % 512);
}
// move file descriptor
offset = (*tar) -> begin + jump;
if (lseek(fd, offset, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, offset, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
tar = &((*tar) -> next);
}
// write entries first
if (write_entries(fd, tar, archive, filecount, files, &offset, verbosity) < 0){
if (write_entries (fd, tar, archive,
filecount, files, &offset, verbosity) < 0)
{
WRITE_ERROR("Failed to write entries");
}
// write ending data
if (write_end_data(fd, offset, verbosity) < 0){
if (write_end_data(fd, offset, verbosity) < 0)
{
ERROR("Failed to write end data");
}
// clear original names from data
tar = archive;
while (*tar){
while (*tar)
{
memset((*tar) -> name, 0, 100);
tar = &((*tar) -> next);
}
return offset;
}
void tar_free(struct tar_t * archive){
while (archive){
static void *woof (void *bark)
{
return (bark);
}
void tar_free (struct tar_t *archive)
{
// Silence "gcc"
(void) woof ((void *) archive);
#ifdef NOTDEF
while (archive)
{
struct tar_t * next = archive -> next;
free(archive);
archive = next;
}
#endif
}
int tar_ls(FILE * f, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity){
if (!verbosity){
void tar_free_pool (void)
{
qflush (QM_TAR);
}
int tar_ls (FILE * f,
struct tar_t * archive,
const size_t filecount,
const char * files[],
const char verbosity)
{
if (!verbosity)
{
return 0;
}
if (filecount && !files){
if (filecount && !files)
{
ERROR("Non-zero file count provided, but file list is NULL");
}
while (archive){
if (ls_entry(f, archive, filecount, files, verbosity) < 0){
while (archive)
{
if (ls_entry(f, archive, filecount, files, verbosity) < 0)
{
return -1;
}
archive = archive -> next;
@ -179,23 +237,35 @@ int tar_ls(FILE * f, struct tar_t * archive, const size_t filecount, const char
return 0;
}
int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity){
int tar_extract (const int fd,
struct tar_t * archive,
const size_t filecount,
const char * files[],
const char verbosity)
{
int ret = 0;
// extract entries with given names
if (filecount){
if (!files){
if (filecount)
{
if (!files)
{
ERROR("Received non-zero file count but got NULL file list");
}
while (archive){
for(size_t i = 0; i < filecount; i++){
if (!strncmp(archive -> name, files[i], MAX(strlen(archive -> name), strlen(files[i])))){
if (lseek(fd, archive -> begin, SEEK_SET) == (off_t) (-1)){
while (archive)
{
for(size_t i = 0; i < filecount; i++)
{
if (!strncmp(archive -> name, files[i], MAX(strlen(archive -> name), strlen(files[i]))))
{
if (lseek(fd, archive -> begin, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
if (extract_entry(fd, archive, verbosity) < 0){
if (extract_entry(fd, archive, verbosity) < 0)
{
ret = -1;
}
break;
@ -205,15 +275,19 @@ int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, co
}
}
// extract all
else{
else
{
// move offset to beginning
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
// extract each entry
while (archive){
if (extract_entry(fd, archive, verbosity) < 0){
while (archive)
{
if (extract_entry(fd, archive, verbosity) < 0)
{
ret = -1;
}
archive = archive -> next;
@ -223,17 +297,24 @@ int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, co
return ret;
}
int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
if (!filecount){
int tar_update (const int fd,
struct tar_t ** archive,
const size_t filecount,
const char * files[],
const char verbosity)
{
if (!filecount)
{
return 0;
}
if (filecount && !files){
if (filecount && !files)
{
ERROR("Non-zero file count provided, but file list is NULL");
}
// buffer for subset of files that need to be updated
char ** newer = calloc(filecount, sizeof(char *));
char ** newer = qcalloc (QM_TAR, filecount, sizeof(char *));
struct stat st;
int count = 0;
@ -241,79 +322,97 @@ int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, co
// check each source to see if it was updated
struct tar_t * tar = *archive;
for(int i = 0; i < (int)filecount; i++){
for(int i = 0; i < (int)filecount; i++)
{
// make sure original file exists
if (lstat(files[i], &st)){
if (lstat(files[i], &st))
{
all = 0;
RC_ERROR("Could not stat %s: %s", files[i], strerror(rc));
}
// find the file in the archive
struct tar_t * old = exists(tar, files[i], 1);
newer[count] = calloc(strlen(files[i]) + 1, sizeof(char));
newer[count] = qcalloc (QM_TAR,
strlen (files [i]) + 1, sizeof (char));
// if there is an older version, check its timestamp
if (old){
if (st.st_mtime > oct2uint(old -> mtime, 11)){
if (old)
{
if (st.st_mtime > oct2uint(old -> mtime, 11))
{
strncpy(newer[count++], files[i], strlen(files[i]));
V_PRINT(stdout, "%s", files[i]);
}
}
// if there is no older version, just add it
else{
else
{
strncpy(newer[count++], files[i], strlen(files[i]));
V_PRINT(stdout, "%s", files[i]);
}
}
// update listed files only
if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0){
if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0)
{
ERROR("Unable to update archive");
}
// cleanup
for(int i = 0; i < count; i++){
free(newer[i]);
for(int i = 0; i < count; i++)
{
// free(newer[i]);
}
free(newer);
// free(newer);
return all?0:-1;
}
int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
if (fd < 0){
int tar_remove (const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity)
{
if (fd < 0)
{
return -1;
}
// archive has to exist
if (!archive || !*archive){
if (!archive || !*archive)
{
ERROR("Got bad archive");
}
if (filecount && !files){
if (filecount && !files)
{
ERROR("Non-zero file count provided, but file list is NULL");
}
if (!filecount){
if (!filecount)
{
V_PRINT(stderr, "No entries specified");
return 0;
}
// get file permissions
struct stat st;
if (fstat(fd, &st)){
if (fstat(fd, &st))
{
RC_ERROR("Unable to stat archive: %s", strerror(rc));
}
// reset offset of original file
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
// find first file to be removed that does not exist
int ret = 0;
for(int i = 0; i < (int)filecount; i++){
if (!exists(*archive, files[i], 0)){
for(int i = 0; i < (int)filecount; i++)
{
if (!exists(*archive, files[i], 0))
{
ERROR("'%s' not found in archive", files[i]);
}
}
@ -322,46 +421,58 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
unsigned int write_offset = 0;
struct tar_t * prev = NULL;
struct tar_t * curr = *archive;
while(curr){
while(curr)
{
// get original size
int total = 512;
if ((curr -> type == REGULAR) || (curr -> type == NORMAL) || (curr -> type == CONTIGUOUS)){
if ((curr -> type == REGULAR) || (curr -> type == NORMAL) || (curr -> type == CONTIGUOUS))
{
total += oct2uint(curr -> size, 11);
if (total % 512){
if (total % 512)
{
total += 512 - (total % 512);
}
}
const int match = check_match(curr, filecount, files);
if (match < 0){
if (match < 0)
{
ERROR("Match failed");
}
else if (!match){
else if (!match)
{
// if the old data is not in the right place, move it
if (write_offset < read_offset){
if (write_offset < read_offset)
{
int got = 0;
while (got < total){
while (got < total)
{
// go to old data
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Cannot seek: %s", strerror(rc));
}
char buf[512];
// copy chunk out
if (read_size(fd, buf, 512) != 512){// guarenteed 512 octets
if (read_size(fd, buf, 512) != 512)
{// guaranteed 512 octets
ERROR("Read error");
}
// go to new position
if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Cannot seek: %s", strerror(rc));
}
// write data in
if (write_size(fd, buf, 512) != 512){
if (write_size(fd, buf, 512) != 512)
{
RC_ERROR("Write error: %s", strerror(rc));
}
@ -371,35 +482,43 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
write_offset += 512;
}
}
else{
else
{
read_offset += total;
write_offset += total;
// skip past data
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1))
{
RC_ERROR("Cannot seek: %s", strerror(rc));
}
}
prev = curr;
curr = curr -> next;
}
else{// if name matches, skip the data
struct tar_t * tmp = curr;
if (!prev){
else
{// if name matches, skip the data
// struct tar_t * tmp = curr;
if (!prev)
{
*archive = curr -> next;
if (*archive){
if (*archive)
{
(*archive) -> begin = 0;
}
}
else{
else
{
prev -> next = curr -> next;
if (prev -> next){
if (prev -> next)
{
prev -> next -> begin = curr -> begin;
}
}
curr = curr -> next;
free(tmp);
// free(tmp);
// next read starts after current entry
read_offset += total;
@ -407,40 +526,50 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
}
// resize file
if (ftruncate(fd, write_offset) < 0){
if (ftruncate(fd, write_offset) < 0)
{
RC_ERROR("Could not truncate file: %s", strerror(rc));
}
// add end data
if (write_end_data(fd, write_offset, verbosity) < 0){
if (write_end_data(fd, write_offset, verbosity) < 0)
{
V_PRINT(stderr, "Error: Could not close file");
}
return ret;
}
int tar_diff(FILE * f, struct tar_t * archive, const char verbosity){
int tar_diff (FILE * f, struct tar_t * archive, const char verbosity)
{
struct stat st;
while (archive){
while (archive)
{
V_PRINT(f, "%s", archive -> name);
// if not found, print error
if (lstat(archive -> name, &st)){
if (lstat(archive -> name, &st))
{
int rc = errno;
fprintf(f, "Could not ");
if (archive -> type == SYMLINK){
if (archive -> type == SYMLINK)
{
fprintf(f, "readlink");
}
else{
else
{
fprintf(f, "stat");
}
fprintf(f, " %s: %s", archive -> name, strerror(rc));
}
else{
if (st.st_mtime != oct2uint(archive -> mtime, 11)){
else
{
if (st.st_mtime != oct2uint(archive -> mtime, 11))
{
fprintf(f, "%s: Mod time differs", archive -> name);
}
if (st.st_size != oct2uint(archive -> size, 11)){
if (st.st_size != oct2uint(archive -> size, 11))
{
fprintf(f, "%s: Mod time differs", archive -> name);
}
}
@ -450,7 +579,8 @@ int tar_diff(FILE * f, struct tar_t * archive, const char verbosity){
return 0;
}
int print_entry_metadata(FILE * f, struct tar_t * entry){
int print_entry_metadata(FILE * f, struct tar_t * entry)
{
if (!entry){
return -1;
}
@ -740,7 +870,7 @@ int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
ERROR("Attempted to extract entry with empty name");
}
char * path = calloc(len + 1, sizeof(char));
char * path = qcalloc (QM_TAR, len + 1, sizeof(char));
strncpy(path, entry -> name, len);
// remove file from path
@ -749,10 +879,10 @@ int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
if (recursive_mkdir(path, DEFAULT_DIR_MODE) < 0){
V_PRINT(stderr, "Could not make directory %s", path);
free(path);
// free(path);
return -1;
}
free(path);
// free(path);
// create file
const unsigned int size = oct2uint(entry -> size, 11);
@ -851,7 +981,7 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
if ((*tar) -> type == DIRECTORY){
// save parent directory name (source will change)
const size_t len = strlen((*tar) -> name);
char * parent = calloc(len + 1, sizeof(char));
char * parent = qcalloc (QM_TAR, len + 1, sizeof(char));
strncpy(parent, (*tar) -> name, len);
// add a '/' character to the end
@ -879,7 +1009,8 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
// if not special directories . and ..
const size_t sublen = strlen(dir -> d_name);
if (strncmp(dir -> d_name, ".", sublen) && strncmp(dir -> d_name, "..", sublen)){
char * path = calloc(len + sublen + 2, sizeof(char));
char * path = qcalloc (QM_TAR,
len + sublen + 2, sizeof(char));
sprintf(path, "%s/%s", parent, dir -> d_name);
// recursively write each subdirectory
@ -892,12 +1023,12 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
tar = &((*tar) -> next);
}
free(path);
// free(path);
}
}
closedir(d);
free(parent);
// free(parent);
tar = &((*tar) -> next);
}
@ -1064,7 +1195,7 @@ int recursive_mkdir(const char * dir, const unsigned int mode){
return 0;
}
char * path = calloc(len + 1, sizeof(char));
char * path = qcalloc (QM_TAR, len + 1, sizeof(char));
strncpy(path, dir, len);
// remove last '/'
@ -1089,6 +1220,6 @@ int recursive_mkdir(const char * dir, const unsigned int mode){
EXIST_ERROR("Could not create directory %s: %s", path, strerror(rc));
}
free(path);
// free(path);
return 0;
}

0
src/util.c Executable file → Normal file
View File

0
src/vars.c Executable file → Normal file
View File

18
src/x3basic.c Normal file
View File

@ -0,0 +1,18 @@
/* ------------------------------------------------------------ */
/* file information */
/* ------------------------------------------------------------ */
// Filename: x3basic.c
// Purpose: Resolve UX3 global variables
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
/* ------------------------------------------------------------ */
/* header files */
/* ------------------------------------------------------------ */
#define RES_UX3 1 /* resolve UX3 global variables */
#include "inc/x3basic.h"
#include "inc/eprintf.h"
#include "inc/x3mem.h"
#include "inc/tar.h"

1395
src/x3mem.c Normal file

File diff suppressed because it is too large Load Diff