/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- main
- parse_comline
- parse_task
- do_tree
- do_task
- delete_all_files
- move_all_files
- file_days
- adjust_path
- create_base_dir
- app_out
- term_app
- set_date
- usage
/* daymvdel - A program that moves or deletes files in directories
or directory trees according to file age. Rick Smereka,
Copyright (C) 2005-2006.
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
Program syntax:
daymvdel [-q] [-l[ log_file]] [-n] [-c] task_list_file
Where 'task_list_file' is a ASCII file containing a list of directories and
what to do in each directory. The task list is in the following format for
a delete operation:
d[s][a] numdays fname source_path
The task list is in the following format for the move operation:
m[s][a] numdays fname source_path dest_path
The first option is an 'm' for move or 'd' for delete. One of these
two must be present. The option 's' includes subdirectories and the
option 'a' stand for 'all or nothing' which means move or delete all
files as long as every file meets the age requirement. If any file
does not meet this requirement, delete or move none of the files.
The parameter 'numdays' is the file age in days, 'fname' indicates
which files to consider (the wildcards '*' and '?' may be used),
'source_path' is source directory path and 'dest_path' (required
only for a move operation) is the destination directory path.
Any task line parameter that contains spaces must be quoted.
In addition to the normal move or delete operation, you can apply
the 't'ree command that will perform the move or delete operation to each
subdirectory underneath the specified tree. The task list line syntax
along with the 't'ree command is:
Delete operation:
td[s][a] numdays fname source_path[ except...]
Move operation:
tm[s][a] numdays fname source_path dest_path[ except...]
The 't' signifies a 'tree' move or delete. The 't' should be the first
character on the line. Most of the task line is the same as the normal
move or delete with the addition of the optional exception directories.
Any directory listed as an exception (they may be more than one listed),
will be excluded from the move or delete operation when it is encountered.
Exception directories (like all paths in this program) must be specified
in absolute form.
The command line option 'q' will suppress all console message output
(quiet), the 'l' (el) option will output all messages to either the default
log destination/file or the supplied destination/file, the 'n'
option will report only without taking any action and the 'c' option
will automatically create the destination base directory tree for the
move operation. Note that the option/switch character is based on the
platform and may be not the hyphen.
This program uses the 'dscan' directory scanning API, the 'armtree'
directory tree removal API and the 'path' API.
Original version for Linux, Windows and DOS. Dec/2005, Rick Smereka
Added 'tree' task processing. Jan/2006, Rick Smereka
Modified 'all or nothing' processing by creating functions
'delete_all_files' and 'move_all_files'. Sep/2006, Rick Smereka */
#include "stdhead.h"
#ifndef OS_DOS
#include "flsocket.h"
#endif
#include "dscan.h"
#include "armtree.h"
#include "path.h"
#ifdef IPC_TCP
#include "socloc.h"
#include "sloc.h"
#include "slconfig.h"
#include "sliocode.h"
#endif
#define APPNAME "daymvdel"
#define VERSION "1.10-2006.09.03"
#define DEFAULT_LOG_FILE "daymvdel.log"
#define DIRS_NULL ((struct dirs *)NULL)
// operation codes
#define OPCODE_DELETE 0
#define OPCODE_MOVE 1
// global data
char c_log_file[128];
char c_task_file[128];
char today[9];
char line[BUFSIZE];
int console_output = TRUE;
int log_output = FALSE;
int take_action = TRUE;
// int take_action = FALSE;
int move_do_base_dir = FALSE;
int line_num = 0;
int line_parms = 0;
FILE *in;
// dirs link list structure
struct dirs
{
char *dir; // single absolute directory path
struct dirs *next; // pointer to next node
};
// task structure
struct
{
int opcode; // operation code
int do_subs; // should subdirectories be included?
int all; // all or nothing?
int tree; // 'tree' task?
int numdays; // age in days
char fpat[128]; // file name pattern to match
char path[BUFSIZE]; // path to operate on
char dest_path[BUFSIZE]; // destination path (for moving)
struct dirs *dhead; // head of dirs list
} task;
#ifdef OS_WIN32
WSADATA wsaData;
#endif
// function prototypes
int main(int, char **);
int parse_comline(int, char **);
int parse_task(void);
void do_tree(void);
void do_task(void);
int delete_all_files(void);
int move_all_files(void);
int file_days(char *, int *);
int adjust_path(char *);
int create_base_dir(char *, int);
void app_out(char *,...);
void term_app(void);
void set_date(void);
void usage(void);
int main(int argc, char **argv)
{
char mes[128], mname[] = "main";
int ret, lstatus;
if (argc == 1)
{
usage();
return(0);
}
// parse command line
if (!parse_comline(argc, argv))
return(0);
// build logo string based on platform
#ifndef OS_UNIX
// non-Unix
app_out("%s for %s Version %s", APPNAME, PLATFORM_STRING,
VERSION);
#else
// Unix
app_out("%s for %s Version %s", APPNAME, SUB_PLATFORM_STRING,
VERSION);
#endif
app_out("By Rick Smereka, Copyright (c) 2005-2006");
app_out("%s comes with ABSOLUTELY NO WARRANTY", APPNAME);
app_out("This is free software, and you are welcome to redistribute it");
app_out("under certain conditions; see 'gpl.txt' for information.");
// open task list file
if ((in = fopen(c_task_file, "r")) == (FILE *)NULL)
{
app_out("unable to open input task list file '%s'", c_task_file);
return(0);
}
app_out("task list file is '%s'", c_task_file);
(void)flag_2_logic_string(move_do_base_dir, mes);
app_out("create base directory structure during move op is %s", mes);
(void)flag_2_logic_string(log_output, mes);
app_out("logging is %s, log destination is '%s'", mes, c_log_file);
(void)flag_2_logic_string(console_output, mes);
app_out("console output is %s", mes);
if (!take_action)
app_out("in analysis mode only, no action taken (delete or move)");
set_date();
get_rec(in, line);
line_num++;
while(!feof(in))
{
if (parse_task())
if (task.tree)
do_tree();
else
do_task();
get_rec(in, line);
line_num++;
}
app_out("%s:%s:program complete", APPNAME, mname);
term_app();
return(0);
}
int parse_comline(int c_count, char **c_parm)
{
/* Parse the command line for parameters. Function
returns 'TRUE' if no error was detected, 'FALSE'
otherwise. */
char mname[] = "parse_comline";
int parms = 1, done = FALSE;
// set default log file
strcpy(c_log_file, DEFAULT_LOG_FILE);
c_task_file[0] = EOS;
while(!done)
{
if (c_parm[parms][0] == SWITCH_CHAR)
{
switch(toupper(c_parm[parms][1]))
{
case 'L':
if (strlen(c_parm[parms]) > 2)
printf("%s:%s:extraneous input with log switch, "
"ignoring\n", APPNAME, mname);
parms++;
if (c_count > parms)
if (c_parm[parms][0] != SWITCH_CHAR)
{
strcpy(c_log_file, c_parm[parms]);
parms++;
}
log_output = TRUE;
break;
case 'Q':
console_output = FALSE;
parms++;
break;
case 'N':
take_action = FALSE;
parms++;
break;
case 'C':
move_do_base_dir = TRUE;
parms++;
break;
default:
printf("%s:%s:unknown switch[%s], program abort\n",
APPNAME, mname, c_parm[parms]);
return(FALSE);
};
}
else
{
strcpy(c_task_file, c_parm[parms]);
parms++;
}
if (parms >= c_count)
done = TRUE;
}
if (!strlen(c_task_file))
{
printf("%s:%s:task list file name is missing,program abort\n",
APPNAME, mname);
return(FALSE);
}
if (log_output)
if (logman_start(c_log_file, APPNAME))
{
printf("%s:%s:error starting logging,program abort\n", APPNAME, mname);
return(FALSE);
}
return(TRUE);
}
int parse_task(void)
{
/* Parse task and load into 'task' structure. Function returns
'TRUE' upon success, 'FALSE' upon error or a comment line. */
char mname[] = "parse_task";
char tline[BUFSIZE], wrd[BUFSIZE], ch;
int len, i;
trim(line, tline);
// ignore blank lines
if (!strlen(line))
return(FALSE);
// ignore comment lines ('#' as first non-blank char)
if (tline[0] == '#')
return(FALSE);
// re-initialize task structure
task.do_subs = task.all = task.tree = FALSE;
task.path[0] = task.fpat[0] = task.dest_path[0] = EOS;
task.dhead = DIRS_NULL;
task.numdays = 0;
line_parms = command_words(tline);
// there must be at least four command words on the line
if (line_parms < 4)
{
app_out("%s:line[%d]:**error:insufficient number of parameters", mname,
line_num);
return(FALSE);
}
// first command word consists of the operation code and options
if (!command_word(tline, wrd, 1))
{
app_out("%s:line[%d]:internal error word[1]", mname, line_num);
return(FALSE);
}
// each character is an operation code or an option
len = strlen(wrd);
for(i =0; i < len; i++)
{
ch = toupper(wrd[i]);
switch(ch)
{
case 'D':
task.opcode = OPCODE_DELETE;
break;
case 'M':
task.opcode = OPCODE_MOVE;
break;
case 'T':
task.tree = TRUE;
break;
case 'S':
task.do_subs = TRUE;
break;
case 'A':
task.all = TRUE;
break;
default:
app_out("%s:line[%d]:**error:unknown operation code/option[%c]",
mname, line_num, ch);
return(FALSE);
};
}
// if move operation, must be five words on the line
if (task.opcode == OPCODE_MOVE)
if (line_parms < 5)
{
app_out("%s:line[%d]:**error:insufficient number of parameters", mname,
line_num);
return(FALSE);
}
// word two s/b the age in days
if (!command_word(tline, wrd, 2))
{
app_out("%s:line[%d]:internal error word[2]", mname, line_num);
return(FALSE);
}
if (!qatoi(wrd, &i))
{
app_out("%s:line[%d]:**error:number of days is non-numeric",
mname, line_num);
return(FALSE);
}
if (i <= 0)
{
app_out("%s:line[%d]:**error:number of days is out of range(s/b >0)",
mname, line_num);
return(FALSE);
}
task.numdays = i;
// word three is the file name pattern to match
if (!command_word(tline, task.fpat, 3))
{
app_out("%s:line[%d]:internal error word[3]", mname, line_num);
return(FALSE);
}
// 'all or nothing' option must be used with all files ('*' or '*.*')
if (task.all)
if (strcmp(task.fpat, "*") && strcmp(task.fpat, "*.*"))
{
app_out("%s:line[%d]:must specify all files with 'all or nothing'",
mname, line_num);
return(FALSE);
}
// word four is the path to operate on
if (!command_word(tline, wrd, 4))
{
app_out("%s:line[%d]:internal error word[4]", mname, line_num);
return(FALSE);
}
if (!isdirectory(wrd))
{
app_out("%s:line[%d]:**error:'%s' is not a directory", mname,
line_num, wrd);
return(FALSE);
}
strcpy(task.path, wrd);
// word five is the move destination path
if (task.opcode == OPCODE_MOVE)
{
if (!command_word(tline, wrd, 5))
{
app_out("%s:line[%d]:internal error word[5]", mname, line_num);
return(FALSE);
}
if (!move_do_base_dir)
if (!isdirectory(wrd))
{
app_out("%s:line[%d]:**error:'%s' is not a directory", mname,
line_num, wrd);
return(FALSE);
}
strcpy(task.dest_path, wrd);
}
return(TRUE);
}
void do_tree(void)
{
/* Process a 'tree' task. Locate all directories in the specified
source directory structure and load these into the 'dirs' link
list excluding the exception directories. For each directory in
the 'dirs' link list, process a task. */
struct dirs *ot, *rov;
char mname[] = "do_tree", pfname[BUFSIZE], wrd[BUFSIZE], odest_path[BUFSIZE];
int ret, size, done, ex_start, i;
get_ftime(pfname);
app_out("%s:%s:starting tree task '%s'", mname, pfname, line);
ex_start = ((task.opcode == OPCODE_DELETE) ? 4 : 5) + 1;
strcpy(odest_path, task.dest_path);
// locate all sub-directories
ret = dscan_findfirst(task.path, "*", "d", pfname);
size = sizeof(struct dirs);
// add all sub-directories to the link list
while(ret)
{
// app_out("%s:found dir '%s'", mname, pfname);
// exclude the directory if in the exclude list
if (line_parms >= ex_start)
{
for(i = ex_start; i <= line_parms; i++)
{
if (!command_word(line, wrd, i))
{
app_out("%s[%d]:exit:internal error getting exception", mname,
line_num);
return;
}
// Windoze and DOS compare case insensitive
#ifdef OS_WIN32
if (!stricmp(wrd, pfname))
#endif
#ifdef OS_DOS
if (!stricmp(wrd, pfname))
#endif
// Unix/Linux/FreeBSD compare case sensitive
#ifdef OS_UNIX
if (!strcmp(wrd, pfname))
#endif
{
app_out("%s:dir '%s' in exception list,ignoring", mname, wrd);
ret = dscan_findnext(pfname);
break;
}
}
}
if (!ret)
break;
// add each directory found to the 'dirs' link list
if ((ot = (struct dirs *)malloc(size)) == DIRS_NULL)
{
app_out("%s[%d]:exit:alloc fail[ot]", mname, line_num);
return;
}
if ((ot->dir = (char *)malloc(strlen(pfname) + 1)) == (char *)NULL)
{
free(ot);
app_out("%s[%d]:exit:alloc fail[ot->dir]", mname, line_num);
return;
}
ot->next = DIRS_NULL;
strcpy(ot->dir, pfname);
done = FALSE;
if (task.dhead == DIRS_NULL)
task.dhead = ot;
else
{
// insert new entry at end of link list
rov = task.dhead;
while(!done)
{
if (rov->next == DIRS_NULL)
{
rov->next = ot;
done = TRUE;
}
else
rov = rov->next;
}
}
ret = dscan_findnext(pfname);
}
/* app_out("%s:debug dirs", mname);
rov = task.dhead;
while(rov != DIRS_NULL)
{
app_out("%s:dir '%s'", mname, rov->dir);
rov = rov->next;
} */
/* load each directory from link list into source path ('task.path'),
and process it */
rov = task.dhead;
while(rov != DIRS_NULL)
{
strcpy(task.path, rov->dir);
/* if task is move, alter the destination path by adding the
last directory name onto it */
if (task.opcode == OPCODE_MOVE)
{
ret = ll_words(rov->dir, PATH_SEP);
if (ll_word(rov->dir, wrd, ret, PATH_SEP))
{
i = strlen(odest_path) + 1 + strlen(wrd);
sprintf(pfname, "%s%c%s", odest_path, PATH_SEP, wrd);
pfname[i] = EOS;
/* app_out("%s:old dest=%s,new_dest=%s", mname, task.dest_path,
pfname); */
strcpy(task.dest_path, pfname);
}
}
do_task();
rov = rov->next;
}
// de-allocate entire link list
rov = task.dhead;
while(rov != DIRS_NULL)
{
free(rov->dir);
ot = rov->next;
free(rov);
rov = ot;
}
}
void do_task(void)
{
// Perform task/operation.
char mname[] = "do_task";
char pfname[BUFSIZE], dest_name[BUFSIZE];
int done = FALSE, ret, days, mindays = 32760, fcount = 0;
get_ftime(pfname);
if (task.opcode == OPCODE_DELETE)
app_out("%s[%s]:starting delete task '%s'", mname, pfname, task.path);
else
app_out("%s[%s]:starting move task '%s', '%s'", mname, pfname, task.path,
task.dest_path);
while(!done)
{
if (!file_days(pfname, &days))
{
done = TRUE;
continue;
}
fcount++;
// if 'all or none', detect minimum number of days
if (task.all)
{
if (days < mindays)
{
mindays = days;
// app_out("%s:new mindays=%d", mname, mindays);
}
}
else
{
// perform operation if greater than number of days specified
if (days > task.numdays)
{
if (task.opcode == OPCODE_DELETE)
{
if (take_action)
{
unlink(pfname);
app_out("%s:'%s' deleted", mname, pfname);
}
else
app_out("%s:'%s' should be deleted", mname, pfname);
}
if (task.opcode == OPCODE_MOVE)
{
strcpy(dest_name, pfname);
if (adjust_path(dest_name))
if (take_action)
{
// create destination base directory if requested
if (move_do_base_dir)
if (!create_base_dir(dest_name, TRUE))
{
app_out("%s:exit:bad rc[FALSE] from "
"create_base_dir,file skipped", mname);
continue;
}
if (!filecopy(pfname, dest_name))
app_out("%s:bad rc[FALSE] from filecopy[%s]", mname,
pfname);
else
{
unlink(pfname);
app_out("%s:file moved to '%s'", mname, dest_name);
}
}
}
}
}
}
// if tree is empty, do nothing
if (!fcount)
{
app_out("%s:dir tree is empty,ignoring", mname);
return;
}
// perform operation if 'all or none' and greater than number of days
if (task.all)
{
if (mindays > task.numdays)
{
if (task.opcode == OPCODE_DELETE)
{
if (take_action)
{
if (!delete_all_files())
app_out("%s:bad rc[0] from delete_all_files", mname);
}
else
app_out("%s:newest file is %d day(s) old,should perform "
"operation", mname, mindays);
}
else
{
// move 'all or none'
if (take_action)
{
if (!move_all_files())
app_out("%s:bad rc[0] from move_all_files", mname);
}
else
app_out("%s:newest file is %d day(s) old,should perform "
"operation", mname, mindays);
}
}
else
app_out("%s:newest file is %d day(s) old,should not perform operation",
mname, mindays);
}
get_ftime(pfname);
app_out("%s:%s:completed task", mname, pfname);
}
int delete_all_files(void)
{
/* Delete all files from the source directory task(path).
If subdirectories are also specified, the entire
directory tree will be deleted. Returns 'TRUE' upon
success, 'FALSE' otherwise. */
char pfname[128], flags[4], mname[] = "delete_all_files";
int ret, pos = 0;
// prepare flags for 'dscan'
flags[0] = 'f';
pos = 1;
#ifdef OS_UNIX
// add sybbolic link detection if running under Unix/Linux/BSD
flags[pos++] = 'l';
#endif
if (task.do_subs)
flags[pos++] = 's';
flags[pos] = EOS;
// initialize 'dscan'
if ((ret = dscan_findfirst(task.path, task.fpat, flags, pfname)) == 0)
{
app_out("%s:no files to delete", mname);
return(FALSE);
}
while(ret)
{
unlink(pfname);
ret = dscan_findnext(pfname);
}
if (task.do_subs)
if (!rmtree(task.path))
{
app_out("%s:bad rc[FALSE] from rmtree deleting directory "
"tree '%s'", mname, task.path);
return(FALSE);
}
return(TRUE);
}
int move_all_files(void)
{
/* Move all files from the source directory(task.path) to the
destination directory(task.dest_path). If subdirectories are
also specified, the entire source directory tree will be
deleted after all the files have been moved. Function
returns 'TRUE' upon success, 'FALSE' otherwise. */
char src_name[128], dest_name[128], flags[4], mname[] = "move_all_files";
int pos, ret;
// prepare flags for 'dscan'
flags[0] = 'f';
pos = 1;
#ifdef OS_UNIX
// add sybbolic link detection if running under Unix/Linux/BSD
flags[pos++] = 'l';
#endif
if (task.do_subs)
flags[pos++] = 's';
flags[pos] = EOS;
// initialize 'dscan'
if ((ret = dscan_findfirst(task.path, task.fpat, flags, src_name)) == 0)
{
app_out("%s:no files to move", mname);
return(FALSE);
}
while(ret)
{
strcpy(dest_name, src_name);
if (!adjust_path(dest_name))
{
app_out("%s:bad rc[0] from adjust_path[%s,%s]", mname, src_name,
dest_name);
return(FALSE);
}
if (move_do_base_dir)
if (!create_base_dir(dest_name, TRUE))
{
app_out("%s:exit:bad rc[0] from create_base_dir[%s,%s]",
mname, src_name, dest_name);
return(FALSE);
}
// app_out("%s:src_name=%s,dest_name=%s", mname, src_name, dest_name);
// use rename to move the file
if (!qrename(src_name, dest_name))
{
app_out("%s:bad rc[0] from qrename[%s,%s]", mname, src_name,
dest_name);
return(FALSE);
}
ret = dscan_findnext(src_name);
}
if (task.do_subs)
if (!rmtree(task.path))
{
app_out("%s:bad rc[FALSE] from rmtree deleting directory "
"tree '%s'", mname, task.path);
return(FALSE);
}
return(TRUE);
}
int file_days(char *fname, int *days)
{
/* Get the next file and calculate age in days. Function returns
the code from 'dscan'. */
struct stat statbuf;
struct tm *tmbuf;
char mname[] = "file_days";
char flags[5], chfdate[9];
static int did_init = FALSE;
int pos, ret, year, mon;
if (!did_init)
{
// prepare flags for 'dscan'
flags[0] = 'f';
pos = 1;
#ifdef OS_UNIX
// add sybbolic link detection if running under Unix/Linux
flags[pos++] = 'l';
#endif
if (task.do_subs)
flags[pos++] = 's';
flags[pos] = EOS;
did_init = TRUE;
// initialize 'dscan'
ret = dscan_findfirst(task.path, task.fpat, flags, fname);
}
else
ret = dscan_findnext(fname);
if (!ret)
{
did_init = FALSE;
return(ret);
}
// stat the file
#ifdef OS_UNIX
if (lstat(fname, &statbuf) != 0)
#else
if (stat(fname, &statbuf) != 0)
#endif
{
app_out("%s:bad rc from stat[%s]", mname, fname);
return(FALSE);
}
// get time of last modification to file and convert to struct 'tm'
tmbuf = localtime(&statbuf.st_mtime);
// date in 'yyyymmdd' format for 'datdif'
year = tmbuf->tm_year + 1900;
mon = tmbuf->tm_mon + 1;
sprintf(chfdate, "%d%02d%02d", year, mon, tmbuf->tm_mday);
// calc the number of days difference
if (!datdif(today, chfdate, days))
{
app_out("%s:bad rc from datdif[%s]", fname);
return(FALSE);
}
// app_out("%s:%s=%s,days=%d", mname, fname, chfdate, *days);
return(ret);
}
int adjust_path(char *pfname)
{
/* Adjust source path to destination path for the move operation.
Function returns 'TRUE' upon success, 'FALSE' otherwise. */
char mname[] = "adjust_path";
char tk_drive, tk_path[BUFSIZE], wrd[BUFSIZE];
char pf_drive, pf_path[BUFSIZE], pf_name[BUFSIZE];
char tkd_drive, tkd_path[BUFSIZE], tkd_name[BUFSIZE], tmp[BUFSIZE];
int tk_nwords, pf_nwords, i, j;
// split task path, current source path and destination path into parts
if (!path_split(task.path, FALSE, &tk_drive, tk_path, (char *)NULL))
{
app_out("%s:exit[FALSE]:bad rc from path_split[task.path]", mname);
return(FALSE);
}
if (!path_split(pfname, TRUE, &pf_drive, pf_path, pf_name))
{
app_out("%s:exit[FALSE]:bad rc from path_split[pfname]", mname);
return(FALSE);
}
if (!path_split(task.dest_path, FALSE, &tkd_drive, tkd_path, tkd_name))
{
app_out("%s:exit[FALSE]:bad rc from path_split[task.dest_path]", mname);
return(FALSE);
}
// get the number of directories in the task and current source paths
tk_nwords = ll_words(tk_path, PATH_SEP);
pf_nwords = ll_words(pf_path, PATH_SEP);
// copy each extra directory name into the destination path
for(i = tk_nwords + 1, j = ll_words(tkd_path, PATH_SEP) + 1; i <= pf_nwords;
i++, j++)
{
if (!ll_word(pf_path, wrd, i, PATH_SEP))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from ll_word[%d]", mname, i);
return(FALSE);
}
if (!ll_wordput(tkd_path, tmp, wrd, j, PATH_SEP))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from ll_wordput[%s]", mname,
wrd);
return(FALSE);
}
strcpy(tkd_path, tmp);
}
// copy file name
strcpy(tkd_name, pf_name);
// assemble/join new path
if (!path_join(tkd_drive, tkd_path, tkd_name, pfname))
{
app_out("%s:exit[FALSE]:bad rc from path_join[FALSE]", mname);
return(FALSE);
}
// app_out("%s:dest is '%s'", mname, pfname);
return(TRUE);
}
int create_base_dir(char *pfname, int has_fname)
{
/* Create the top-level base directory for the move operation.
The flag 'has_fname' is used to indicate whether the path
('pfname') has a file name in it.
Function returns 'TRUE' upon success, 'FALSE' otherwise. */
char mname[] = "create_base_dir";
char drive, path[BUFSIZE], fname[BUFSIZE];
char wrk[BUFSIZE], tmp[BUFSIZE], wrd[BUFSIZE];
int i, nwords;
if (pfname == (char *)NULL || !strlen(pfname))
{
app_out("%s:exit[FALSE]:null or empty[pfname]", mname);
return(FALSE);
}
if (!path_split(pfname, has_fname, &drive, path, fname))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from path_split", mname);
return(FALSE);
}
if ((nwords = ll_words(path, PATH_SEP)) == 0)
{
app_out("%s:exit[FALSE]:path contains no directories", mname);
return(FALSE);
}
wrk[0] = EOS;
for(i = 1; i <= nwords; i++)
{
if (!ll_word(path, wrd, i, PATH_SEP))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from ll_word[%d]", mname, i);
return(FALSE);
}
// assemble path
if (!ll_wordput(wrk, tmp, wrd, i, PATH_SEP))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from ll_wordput[%d]", mname, i);
return(FALSE);
}
if (!path_join(drive, tmp, (char *)NULL, wrk))
{
app_out("%s:exit[FALSE]:bad rc[FALSE] from path_join[%d]", mname, i);
return(FALSE);
}
// app_out("%s:path=%s", mname, wrk);
if (!isdirectory(wrk))
#ifdef OS_UNIX
if (mkdir(wrk, S_IRWXU) == -1)
#endif
#ifdef OS_WIN32
if (mkdir(wrk) == -1)
#endif
#ifdef OS_DOS
if (mkdir(wrk) == -1)
#endif
{
app_out("%s:exit[FALSE]:bad rc from mkdir[-1,%d]", mname, i);
return(FALSE);
}
strcpy(wrk, tmp);
}
return(TRUE);
}
void app_out(char *fmt,...)
{
// Output a message to the console and/or the log file.
va_list argptr;
char *mes, mname[] = "app_out";
int ret;
// if no output, return
if (!console_output && !log_output)
return;
va_start(argptr, fmt);
if ((mes = (char *)malloc(BUFSIZE)) == (char *)NULL)
{
logman("%s:%s:alloc fail[mes]", APPNAME, mname);
return;
}
// format message
memset(mes, 0, BUFSIZE);
vsprintf(mes, fmt, argptr);
if (log_output)
logman_nf(mes);
if (!log_output && console_output)
printf("%s\n", mes);
free(mes);
}
void term_app(void)
{
// Prepare to terminate the application. Shutdown all IPC API's.
if (log_output)
logman_end();
#ifdef IPC_TCP
// with TCP IPC method
sloc_term_api();
#ifdef OS_WIN32
// under Windoze
WSACleanup();
#endif
#endif
}
void set_date(void)
{
// Obtain current date and set 'today' string.
time_t tod;
struct tm *tmbuf;
int year, mon, day;
tod = time(NULL);
tmbuf = localtime(&tod);
year = tmbuf->tm_year + 1900;
mon = tmbuf->tm_mon + 1;
day = tmbuf->tm_mday;
sprintf(today, "%d%02d%02d", year, mon, day);
}
void usage(void)
{
// Display program usage.
printf("usage:%s [%cq] [%cl[ log_file]] [%cn] [%cc] task_list_file\n",
APPNAME, SWITCH_CHAR, SWITCH_CHAR, SWITCH_CHAR, SWITCH_CHAR);
}