diff -ur aide-0.10/include/db_config.h aide-0.10-new/include/db_config.h --- aide-0.10/include/db_config.h 2004-02-25 19:34:30.000000000 -0500 +++ aide-0.10-new/include/db_config.h 2004-02-25 22:59:53.000000000 -0500 @@ -133,6 +133,7 @@ #define DB_ACL (1<<20) /* "acl" */ #define DB_CHECKMASK (1<<21) /* "checkmask"*/ #define DB_SIZEG (1<<22) /* "unknown" */ +#define DB_CHECKINODE (1<<23) /* "checkinode"*/ #define DB_HASHES (DB_MD5|DB_SHA1|DB_RMD160|DB_TIGER|DB_CRC32|DB_HAVAL| \ DB_GOST|DB_CRC32B) diff -ur aide-0.10/include/db.h aide-0.10-new/include/db.h --- aide-0.10/include/db.h 2003-01-16 05:37:34.000000000 -0500 +++ aide-0.10-new/include/db.h 2004-04-08 11:34:41.000000000 -0400 @@ -50,6 +50,8 @@ #define NODE_TRAVERSE (1<<9) #define NODE_CHECKED (1<<10) +#define NODE_MOVED_OUT (1<<11) +#define NODE_MOVED_IN (1<<12) #endif Only in aide-0.10-new/include: db.h~ diff -ur aide-0.10/src/aide.c aide-0.10-new/src/aide.c --- aide-0.10/src/aide.c 2004-02-25 19:35:39.000000000 -0500 +++ aide-0.10-new/src/aide.c 2004-02-25 23:00:18.000000000 -0500 @@ -316,6 +316,7 @@ do_groupdef("p",DB_PERM); do_groupdef("i",DB_INODE); + do_groupdef("I",DB_CHECKINODE); do_groupdef("n",DB_LNKCOUNT); do_groupdef("u",DB_UID); do_groupdef("g",DB_GID); diff -ur aide-0.10/src/commandconf.c aide-0.10-new/src/commandconf.c --- aide-0.10/src/commandconf.c 2003-11-04 10:39:48.000000000 -0500 +++ aide-0.10-new/src/commandconf.c 2004-04-08 09:42:08.000000000 -0400 @@ -421,7 +421,7 @@ if((attr&DB_CTIME) && (check_dboo(db_ctime)!=RETFAIL)){ conf->db_out_order[conf->db_out_size++]=db_ctime; } - if((attr&DB_INODE) && (check_dboo(db_inode)!=RETFAIL)){ + if((attr&DB_INODE||attr&DB_CHECKINODE) && (check_dboo(db_inode)!=RETFAIL)){ conf->db_out_order[conf->db_out_size++]=db_inode; } if((attr&DB_LNKCOUNT) && (check_dboo(db_lnkcount)!=RETFAIL)){ diff -ur aide-0.10/src/compare_db.c aide-0.10-new/src/compare_db.c --- aide-0.10/src/compare_db.c 2003-11-04 10:39:48.000000000 -0500 +++ aide-0.10-new/src/compare_db.c 2004-04-08 11:35:51.000000000 -0400 @@ -816,17 +816,31 @@ /* Node was added to twice and discovered to be not changed*/ }else if(!(node->checked&DB_OLD)&&(node->checked&DB_NEW)){ /* File is in new db but not old. (ADDED) */ - stat[2]++; - node->checked|=NODE_ADDED; + /* unless it was moved in */ + if(!(node->checked&NODE_MOVED_IN)){ + stat[2]++; + node->checked|=NODE_ADDED; + } }else if((node->checked&DB_OLD)&&!(node->checked&DB_NEW)){ /* File is in old db but not new. (REMOVED) */ - stat[3]++; - node->checked|=NODE_REMOVED; + /* unless it was moved out */ + if(!(node->checked&NODE_MOVED_OUT)) { + stat[3]++; + node->checked|=NODE_REMOVED; + } }else if((node->checked&DB_OLD)&&(node->checked&DB_NEW)&& (node->old_data!=NULL)&&(node->new_data!=NULL)){ /* File is in both db's and the data is still there. (CHANGED) */ - stat[4]++; - node->checked|=NODE_CHANGED; + if(!(node->checked&(NODE_MOVED_IN|NODE_MOVED_OUT))){ + stat[4]++; + node->checked|=NODE_CHANGED; + }else if(!(node->checked&NODE_MOVED_IN)) { + stat[2]++; + node->checked|=NODE_ADDED; + }else if(!(node->checked&NODE_MOVED_OUT)) { + stat[3]++; + node->checked|=NODE_REMOVED; + } } } } diff -ur aide-0.10/src/do_md.c aide-0.10-new/src/do_md.c --- aide-0.10/src/do_md.c 2003-01-16 05:37:34.000000000 -0500 +++ aide-0.10-new/src/do_md.c 2004-04-08 09:51:44.000000000 -0400 @@ -239,7 +239,7 @@ void fs2db_line(struct AIDE_STAT_TYPE* fs,db_line* line) { - if(DB_INODE&line->attr){ + if(DB_INODE&line->attr||DB_CHECKINODE&line->attr){ line->inode=fs->st_ino; } else { line->inode=0; diff -ur aide-0.10/src/gen_list.c aide-0.10-new/src/gen_list.c --- aide-0.10/src/gen_list.c 2003-11-04 10:39:48.000000000 -0500 +++ aide-0.10-new/src/gen_list.c 2004-04-08 10:43:45.000000000 -0400 @@ -175,6 +175,44 @@ return depth; } +/* This function returns a node with the same inode value as the 'file' */ +/* The only place it is used is in add_file_to_tree() function */ +static seltree* get_seltree_inode(seltree* tree, db_line* file, int db) +{ + seltree* node=NULL; + list* r=NULL; + char* tmp=NULL; + + if(tree==NULL){ + return NULL; + } + + /* found the match */ + if((db == DB_NEW && + tree->new_data != NULL && + file->inode == tree->new_data->inode) || + (db == DB_OLD && + tree->old_data != NULL && + file->inode == tree->old_data->inode)) { + return tree; + } + + /* tmp is the directory of the file->filename */ + tmp=strgetndirname(file->filename,treedepth(tree)+1); + for(r=tree->childs;r;r=r->next){ + /* We are interested only in files with the same regexp specification */ + if(strlen(tmp) == strlen(file->filename) || + strncmp(((seltree*)r->data)->path,tmp,strlen(tmp)+1)==0){ + node=get_seltree_inode((seltree*)r->data,file,db); + if(node!=NULL){ + break; + } + } + } + free(tmp); + return node; +} + seltree* get_seltree_node(seltree* tree,char* path) { seltree* node=NULL; @@ -481,7 +519,7 @@ } - if(DB_INODE&fil->attr){ + if(DB_INODE&fil->attr||DB_CHECKINODE&fil->attr){ fil->inode=fs.st_ino; } else { fil->inode=0; @@ -1018,6 +1056,47 @@ node->new_data=NULL; } } + + /* Do verification if file was moved only if we are asked for it. + * old and new data are NULL only if file present in both DBs + * and has not been changed. + */ + if((file->attr & DB_CHECKINODE) && + (node->old_data!=NULL || node->new_data!=NULL)) { + /* Check if file was moved (same inode, different name in the other DB)*/ + db_line *oldData; + db_line *newData; + seltree* moved_node=get_seltree_inode(tree,file,db==DB_OLD?DB_NEW:DB_OLD); + + if(moved_node == NULL || moved_node == node) { + /* There's mo match for inode or it matches the node with the same name. + * In first case we don't have a match to compare with. + * In the second - we already compared those files. */ + return; + } + + if(db == DB_NEW) { + newData = node->new_data; + oldData = moved_node->old_data; + } else { + newData = moved_node->new_data; + oldData = node->old_data; + } + + localignorelist=(oldData->attr^newData->attr); + if (localignorelist!=0) { + error(5,"File %s in databases has different attributes, %i,%i\n", + oldData->filename,oldData->attr,newData->attr); + } + + localignorelist|=ignorelist; + + /* Free the data if same else leave as is for report_tree */ + if(compare_dbline(oldData, newData, localignorelist)==RETOK){ + node->checked |= db==DB_NEW ? NODE_MOVED_IN : NODE_MOVED_OUT; + moved_node->checked |= db==DB_NEW ? NODE_MOVED_OUT : NODE_MOVED_IN; + } + } } int check_rxtree(char* filename,seltree* tree,int* attr)