/* Do not remove the headers from this file! see /USAGE for more info. */
//:COMMAND
//USAGE: findfile <target>
// findfile -u
//
//Find any file containing the specified target within its name.
//
//The system relies on a database of filenames for speed.
//To rebuild that database, use a -u flag.
inherit CMD;
#define ITERS_PER_CALL 2
#define DATA_FILE "/data/find.codes"
#define TMP_DATA_FILE "/data/find.tmp"
mixed array stack;
string path;
int building_database = 0;
private void end_building()
{
cp(TMP_DATA_FILE,DATA_FILE);
rm(TMP_DATA_FILE);
printf("Locate DB build done.\n");
building_database = 0;
}
private void do_building()
{
int i = ITERS_PER_CALL;
string array this_dir;
while(i--)
{
string new_path;
if(!sizeof(stack))
{
end_building();
return;
}
if(intp(stack[0]))
{
/* hit the sentinel. pop up one directory level */
stack = stack[1..];
path = split_path(path)[0];
i++;
continue;
}
new_path = path + stack[0]+"/";
stack = stack[1..];
this_dir = get_dir(new_path+"*",-1);
if(arrayp(this_dir))
{
int w;
if( (w = member_array(".", get_dir(new_path+"*"))) != -1 )
this_dir = this_dir[0..(w-1)] + this_dir[(w+2)..];
} else
continue;
/* prepend the dir and write into the file */
map(this_dir,(:write_file(TMP_DATA_FILE,
join_path($(new_path),$1[0])+"\n"):));
/* filter out just the dirs and extract the names */
this_dir = map(filter(this_dir, (:$1[1] == -2:)), (:$1[0]:));
/* push onto stack w/ a sentinel to go up the dir tree */
if(sizeof(this_dir))
{
stack = this_dir + ({0}) + stack;
path = new_path;
}
}
call_out((:do_building:), 2);
}
private void begin_database_build()
{
stack = ({""});
path = "";
if(is_file(TMP_DATA_FILE) && !rm(TMP_DATA_FILE))
{
out("You don't have permission to do that.\n");
return;
}
do_building();
building_database = 1;
}
private void main(mixed * arg, mapping flags)
{
string find;
string outstr;
if (!arg[0] && !flags["u"])
{
out( "Syntax: findfile <string>\n");
return;
}
if(flags["u"])
{
if(building_database)
{
out("Already building database.\n");
return;
}
out("Building database... This takes a while.\n");
begin_database_build();
return;
} else {
/* arg[0] is an array of strings. use just the first */
find = arg[0];
ed_start(DATA_FILE);
outstr = ed_cmd(sprintf("1,$g#%s#p", find));
if( !sizeof(outstr))
out( "No matching files found.\n");
else
out( outstr );
ed_cmd("q");
return;
}
}