/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- unique
- exist
- numrecs
- get_nrec
- get_rec
- zcreate
- isdirectory
- filecopy
- qrename
- write_dos_line
- write_unix_line
/* File I/O function library module,
Rick Smereka, Copyright (C) 1995-2005.
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, get a copy via the Internet at
http://gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
You can contact the author via email at rsmereka@future-lab.com
Original DOS version Feb/95, Rick Smereka
Port to QNX V4.23a Dec/97, Rick Smereka
Changed the 'unique' function to create a file in the
indicated directory. Also changed the return type to
'int' to indicate the success or failure of the file
name generation. Dec/97, Rick Smereka
Added function 'qrename' specific to QNX. This function
attempts to perform a normal rename. If that failes with
a 'EXDEV' 'errno' (cannot move across devices), an OS
copy is performed. Nov/98, Rick Smereka
Ported to 32bit Windows under CodeWarrior V4.
Ported to HP-UX under GNU C 2.8.1.
Jan/99, Rick Smereka
Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka
Changed function 'isdirectory' to compile on all
platforms and use the POSIX system call 'opendir'.
Feb/2001, Rick Smereka
Changed function 'filecopy' to use standard stream I/O
funtion calls ('fopen', 'fread', 'fwrite' and 'fclose').
Mar/2001, Rick Smereka
Corrected bug in 'zcreate' where an already existing file
was truncated. Nov/2001, Rick Smereka
Ported to Debian Linux. Nov/2002, Rick Smereka
Added functions 'write_dos_line' and 'write_unix_line'.
Dec/2002, Rick Smereka
Changed function 'unique' to use a sequential number for the
file name instead of a random number. Jan/2005, Rick Smereka
Added a check for a proper directory name in function 'unique'.
Fixed 'ifdef' in function 'qrename'. Mar/2005, Rick Smereka */
#include "stdhead.h"
int unique(char *dir, char *fname)
{
/* Create a unique file name. Uniquness will be tested in the
directory 'dir'. Do not end 'dir' with a path separator.
'dir' can be a null string but not a NULL pointer.
Name of the new file is returned in 'fname' minus the
directory name. */
static long fcount = 0L;
int dir_len, total_len, ex = TRUE;
char *total_f;
char rname[13];
if (dir == (char *)NULL)
return(FALSE);
dir_len = strlen(dir);
if (dir_len && dir[dir_len - 1] == PATH_SEP)
return(FALSE);
if (dir_len && !isdirectory(dir))
return(FALSE);
if (fname == (char *)NULL)
return(FALSE);
/* calculate length of total string required */
total_len = dir_len + 14;
/* allocate total file name string */
if ((total_f = (char *)malloc(total_len)) == (char *)NULL)
return(FALSE);
while(ex)
{
if (fcount > 99999999L)
fcount = 0L;
sprintf(rname, "%08ld.tmp", fcount++);
if (dir_len)
sprintf(total_f, "%s%c%s", dir, PATH_SEP, rname);
else
strcpy(total_f, rname);
ex = exist(total_f);
}
free(total_f);
strcpy(fname, rname);
return(TRUE);
}
int exist(char *file)
{
/* Test for file existance. Under Unix/QNX, the POSIX
'access' function is used. Since CodeWarrior does not
support this function and DOS directory functions are
also not supported, we test for file existance by
attempting to open the file. Note that the Unix/QNX
version makes no assumption on the read/write status
of the file whereas the Windows 32bit version specifically
opens the file for read. Function returns 'TRUE' upon success,
'FALSE' otherwise. */
#ifdef OS_DOS
struct ffblk dconst;
struct ffblk *dta = &dconst;
#endif
#ifdef OS_WIN32
FILE *in;
#endif
if (!strlen(file))
return(FALSE);
#ifdef OS_WIN32
if ((in = fopen(file, "r")) == (FILE *)NULL)
return(FALSE);
fclose(in);
return(TRUE);
#endif
#ifdef OS_UNIX
if (!access(file, F_OK))
return(TRUE);
return(FALSE);
#endif
#ifdef OS_DOS
if (!findfirst(file, dta, FA_NORMAL))
return(TRUE);
return(FALSE);
#endif
}
int numrecs(FILE *fi)
{
/* Count the number of records in a file. */
char *buf;
int numrec = 0;
if ((buf = (char *)malloc(BUFSIZE + 1)) == NULL)
return(0);
rewind(fi);
get_rec(fi, buf);
while(!feof(fi))
{
numrec++;
get_rec(fi, buf);
}
rewind(fi);
free(buf);
return(numrec);
}
void get_nrec(int recno, FILE *fi, char *buf)
{
/* Read the 'recno' record from 'fi' into 'buf' and strip any
line feeds. 'Buf' will contain zero bytes on failure.
'Buf' must be statically allocated by the caller to an
appropriate size. */
int i;
char *ptr;
rewind(fi);
for(i = 0; i < recno; i++)
{
fgets(buf, BUFSIZE, fi);
if (feof(fi))
{
buf[0] = EOS;
return;
}
}
if ((ptr = strchr(buf, EOL)) != NULL)
*ptr = EOS;
}
void get_rec(FILE *fi, char *buf)
{
/* Read a record from 'fi' into 'buf' and strip any
line feeds. */
char *ptr;
fgets(buf, BUFSIZE, fi);
if ((ptr = strchr(buf, EOL)) != NULL)
*ptr = EOS;
}
int zcreate(char *fname)
{
/* Create a zero byte file called 'fname'. It is an
error if the file already exists. Function
returns TRUE on success, FALSE otherwise. */
FILE *fi;
if (fname == (char *)NULL || !strlen(fname))
return(FALSE);
if (exist(fname))
return(FALSE);
if ((fi = fopen(fname,"w")) == (FILE *)NULL)
return(FALSE);
fclose(fi);
return(TRUE);
}
int isdirectory(char *path)
{
/* Check for 'path' being a directory. Function uses the
POSIX standard 'opendir' system call. Function returns
'TRUE' if the 'path' resolves to a directory, 'FALSE'
otherwise. */
DIR *dir;
if (path == NULL || !strlen(path))
return(FALSE);
if ((dir = opendir(path)) == NULL)
return(FALSE);
closedir(dir);
return(TRUE);
}
int filecopy(char *src, char *dest)
{
/* Copy a file from 'src' to 'dest'. If 'dest' file
exists, it will be overwritten. A 32kb buffer is
used to copy the data. Function returns 'TRUE'
upon success, 'FALSE' otherwise. */
FILE *in, *out;
int bufsiz, ret, done = FALSE;
char *ptr;
if (!strlen(src) || !strlen(dest))
return(FALSE);
bufsiz = 32760;
if ((ptr = (char *)malloc(bufsiz)) == (char *)NULL)
return(FALSE);
if ((in = fopen(src, "rb")) == NULL)
{
free(ptr);
return(FALSE);
}
if ((out = fopen(dest, "wb")) == NULL)
{
fclose(in);
free(ptr);
return(FALSE);
}
/* swap until end of file or error */
do
{
ret = fread(ptr, 1, bufsiz, in);
/* trap read errors */
if (ferror(in))
{
fclose(in);
fclose(out);
free(ptr);
return(FALSE);
}
if (fwrite(ptr, 1, ret, out) != ret)
{
fclose(in);
fclose(out);
free(ptr);
return(FALSE);
}
/* if we read less than a buffer size, assume done */
if (ret < bufsiz)
done = TRUE;
}
while(!done);
fclose(in);
fclose(out);
free(ptr);
return(TRUE);
}
int qrename(char *src, char *dest)
{
/* Rename a file. This version will rename a file
anywhere (same directory, different directory on
same volume, different directory on different
disk/volume). Function returns 'TRUE' upon
success, 'FALSE' otherwise. Dec/98,
Rick Smereka */
int lensrc, lendest;
#ifdef OS_UNIX
int ret;
#endif
// reasonableness checks
if (src == (char *)NULL || dest == (char *)NULL)
return(FALSE);
lensrc = strlen(src);
lendest = strlen(dest);
if (!lensrc || !lendest)
return(FALSE);
// first, attempt a normal 'rename'
if (!rename(src, dest))
return(TRUE);
#ifdef OS_UNIX
ret = errno;
if (ret != EXDEV)
return(FALSE);
#endif
// normal rename failed, use copy
if (!filecopy(src, dest))
return(FALSE);
// delete source file
(void)unlink(src);
return(TRUE);
}
int write_dos_line(FILE *out, char *buf)
{
/* Write a text line with DOS/Windoze line delimiters (cr/lf).
The file 'out' must have been opened for binary output.
Function returns 'TRUE' if the line was successfully
written, 'FALSE' otherwise. */
char *fbuf;
int len;
if (out == (FILE *)NULL || buf == (char *)NULL)
return(FALSE);
len = strlen(buf);
if ((fbuf = (char *)malloc(len + 3)) == (char *)NULL)
return(FALSE);
sprintf(fbuf, "%s%c%c", buf, (unsigned char)EOLL,
(unsigned char)EOL);
if (fwrite(fbuf, 1, len + 2, out) != len + 2)
{
free(fbuf);
return(FALSE);
}
free(fbuf);
return(TRUE);
}
int write_unix_line(FILE *out, char *buf)
{
/* Write a text line with a Unix line delimiter (lf).
The file 'out' must have been opened for binary output.
Function returns 'TRUE' if the line was successfully
written, 'FALSE' otherwise. */
char *fbuf;
int len;
if (out == (FILE *)NULL || buf == (char *)NULL)
return(FALSE);
len = strlen(buf);
if ((fbuf = (char *)malloc(len + 2)) == (char *)NULL)
return(FALSE);
sprintf(fbuf, "%s%c", buf, (unsigned char)EOL);
if (fwrite(fbuf, 1, len + 1, out) != len + 1)
{
free(fbuf);
return(FALSE);
}
free(fbuf);
return(TRUE);
}