2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
useful function for deleting a whole directory tree
Copyright ( C ) Andrew Tridgell 2003
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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2006-01-03 18:40:05 +03:00
# include "libcli/raw/libcliraw.h"
# include "libcli/libcli.h"
2003-08-13 05:53:07 +04:00
struct delete_state {
2004-08-04 17:23:35 +04:00
struct smbcli_tree * tree ;
2003-08-13 05:53:07 +04:00
int total_deleted ;
BOOL failed ;
} ;
/*
callback function for torture_deltree ( )
*/
2004-11-30 08:37:57 +03:00
static void delete_fn ( struct clilist_file_info * finfo , const char * name , void * state )
2003-08-13 05:53:07 +04:00
{
struct delete_state * dstate = state ;
char * s , * n ;
if ( strcmp ( finfo - > name , " . " ) = = 0 | |
strcmp ( finfo - > name , " .. " ) = = 0 ) return ;
n = strdup ( name ) ;
n [ strlen ( n ) - 1 ] = 0 ;
asprintf ( & s , " %s%s " , n , finfo - > name ) ;
2004-11-30 08:37:57 +03:00
if ( finfo - > attrib & FILE_ATTRIBUTE_READONLY ) {
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_setatr ( dstate - > tree , s , 0 , 0 ) ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 2 , ( " Failed to remove READONLY on %s - %s \n " ,
2004-08-04 17:23:35 +04:00
s , smbcli_errstr ( dstate - > tree ) ) ) ;
2003-08-13 05:53:07 +04:00
}
}
2004-11-30 08:37:57 +03:00
if ( finfo - > attrib & FILE_ATTRIBUTE_DIRECTORY ) {
2003-08-13 05:53:07 +04:00
char * s2 ;
asprintf ( & s2 , " %s \\ * " , s ) ;
2004-08-04 17:23:35 +04:00
smbcli_unlink ( dstate - > tree , s2 ) ;
smbcli_list ( dstate - > tree , s2 ,
2003-08-13 05:53:07 +04:00
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ,
delete_fn , state ) ;
free ( s2 ) ;
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_rmdir ( dstate - > tree , s ) ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 2 , ( " Failed to delete %s - %s \n " ,
2004-08-04 17:23:35 +04:00
s , smbcli_errstr ( dstate - > tree ) ) ) ;
2003-08-13 05:53:07 +04:00
dstate - > failed = True ;
}
dstate - > total_deleted + + ;
} else {
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( dstate - > tree , s ) ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 2 , ( " Failed to delete %s - %s \n " ,
2004-08-04 17:23:35 +04:00
s , smbcli_errstr ( dstate - > tree ) ) ) ;
2003-08-13 05:53:07 +04:00
dstate - > failed = True ;
}
dstate - > total_deleted + + ;
}
free ( s ) ;
free ( n ) ;
}
/*
recursively descend a tree deleting all files
returns the number of files deleted , or - 1 on error
*/
2004-08-04 17:23:35 +04:00
int smbcli_deltree ( struct smbcli_tree * tree , const char * dname )
2003-08-13 05:53:07 +04:00
{
char * mask ;
struct delete_state dstate ;
2004-02-08 03:51:07 +03:00
dstate . tree = tree ;
2003-08-13 05:53:07 +04:00
dstate . total_deleted = 0 ;
dstate . failed = False ;
/* it might be a file */
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_OK ( smbcli_unlink ( tree , dname ) ) ) {
2003-08-13 05:53:07 +04:00
return 1 ;
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_EQUAL ( smbcli_nt_error ( tree ) , NT_STATUS_OBJECT_NAME_NOT_FOUND ) | |
NT_STATUS_EQUAL ( smbcli_nt_error ( tree ) , NT_STATUS_OBJECT_PATH_NOT_FOUND ) | |
NT_STATUS_EQUAL ( smbcli_nt_error ( tree ) , NT_STATUS_NO_SUCH_FILE ) ) {
2003-08-13 05:53:07 +04:00
return 0 ;
}
asprintf ( & mask , " %s \\ * " , dname ) ;
2004-08-04 17:23:35 +04:00
smbcli_unlink ( dstate . tree , mask ) ;
smbcli_list ( dstate . tree , mask ,
2003-08-13 05:53:07 +04:00
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ,
delete_fn , & dstate ) ;
free ( mask ) ;
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_rmdir ( dstate . tree , dname ) ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 2 , ( " Failed to delete %s - %s \n " ,
2004-08-04 17:23:35 +04:00
dname , smbcli_errstr ( dstate . tree ) ) ) ;
2003-08-13 05:53:07 +04:00
return - 1 ;
}
dstate . total_deleted + + ;
if ( dstate . failed ) {
return - 1 ;
}
return dstate . total_deleted ;
}