129 lines
2.8 KiB
C
129 lines
2.8 KiB
C
/*
|
|
** copy_attrs.h - copy BeFS attributes from one file to another
|
|
**
|
|
** Jan. 11, 1998 Chris Herborth (chrish@qnx.com)
|
|
**
|
|
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
|
|
** redistribute, steal, or otherwise manipulate this code. No restrictions
|
|
** at all. If you laugh at this code, you can't use it.
|
|
*/
|
|
|
|
#include <support/Errors.h>
|
|
#ifndef NO_DEBUG
|
|
#include <assert.h>
|
|
#define ASSERT(cond) assert(cond)
|
|
#else
|
|
#define ASSERT(cond) ((void)0)
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <kernel/fs_attr.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "copy_attrs.h"
|
|
|
|
static const char *rcs_version_id = "$Id$";
|
|
|
|
/* ----------------------------------------------------------------------
|
|
** Copy file attributes from src_file to dst_file.
|
|
*/
|
|
|
|
status_t copy_attrs( const char *dst_file, const char *src_file )
|
|
{
|
|
int dst_fd, src_fd;
|
|
status_t retval = B_OK;
|
|
DIR *fa_dir = NULL;
|
|
struct dirent *fa_ent = NULL;
|
|
char *buff = NULL;
|
|
struct attr_info fa_info;
|
|
off_t read_bytes, wrote_bytes;
|
|
|
|
ASSERT( dst_file != NULL );
|
|
ASSERT( src_file != NULL );
|
|
|
|
/* Attempt to open the files.
|
|
*/
|
|
src_fd = open( src_file, O_RDONLY );
|
|
if( src_fd < 0 ) {
|
|
return B_FILE_NOT_FOUND;
|
|
}
|
|
|
|
dst_fd = open( dst_file, O_WRONLY );
|
|
if( dst_fd < 0 ) {
|
|
close( src_fd );
|
|
return B_FILE_NOT_FOUND;
|
|
}
|
|
|
|
/* Read the attributes, and write them to the destination file.
|
|
*/
|
|
fa_dir = fs_fopen_attr_dir( src_fd );
|
|
if( fa_dir == NULL ) {
|
|
retval = B_IO_ERROR;
|
|
goto close_return;
|
|
}
|
|
|
|
fa_ent = fs_read_attr_dir( fa_dir );
|
|
while( fa_ent != NULL ) {
|
|
retval = fs_stat_attr( src_fd, fa_ent->d_name, &fa_info );
|
|
if( retval != B_OK ) {
|
|
/* TODO: Print warning message?
|
|
*/
|
|
goto read_next_attr;
|
|
}
|
|
|
|
if( fa_info.size > (off_t)UINT_MAX ) {
|
|
/* TODO: That's too big. Print a warning message? You could
|
|
** copy it in chunks...
|
|
*/
|
|
goto read_next_attr;
|
|
}
|
|
|
|
if( fa_info.size > (off_t)0 ) {
|
|
buff = malloc( (size_t)fa_info.size );
|
|
if( buff == NULL ) {
|
|
/* TODO: Can't allocate memory for this attribute. Warning?
|
|
*/
|
|
goto read_next_attr;
|
|
}
|
|
|
|
read_bytes = fs_read_attr( src_fd, fa_ent->d_name, fa_info.type,
|
|
0, buff, fa_info.size );
|
|
if( read_bytes != fa_info.size ) {
|
|
/* TODO: Couldn't read entire attribute. Warning?
|
|
*/
|
|
goto free_attr_buff;
|
|
}
|
|
|
|
wrote_bytes = fs_write_attr( dst_fd, fa_ent->d_name, fa_info.type,
|
|
0, buff, fa_info.size );
|
|
if( wrote_bytes != fa_info.size ) {
|
|
/* TODO: Couldn't write entire attribute. Warning?
|
|
*/
|
|
;
|
|
}
|
|
|
|
free_attr_buff:
|
|
free( buff );
|
|
|
|
retval = B_OK;
|
|
}
|
|
|
|
/* Read the next entry.
|
|
*/
|
|
read_next_attr:
|
|
fa_ent = fs_read_attr_dir( fa_dir );
|
|
}
|
|
|
|
close_return:
|
|
close( dst_fd );
|
|
close( src_fd );
|
|
|
|
return retval;
|
|
}
|
|
|