分区复制1

本文介绍了一个基于文件系统的分区复制程序,该程序能够实现源设备到目标设备的文件及目录结构复制,并保留原始文件权限和时间戳等属性。

/*******************************************************/
fastcopy.c
基于文件系统的分区复制
/*******************************************************/
#include "beinclude.h"

int     pathlen;
char    buf[BUFSIZE];
struct  aa finfo;

int main(int ac, char *av[]){
        char    cmd[50];
        char    *srcdev,*decdev;
        struct  stat st;
        //DIR   *sdir=NULL, *ddir=NULL;
        //struct        dirent diret, *diret_ptr;
        if (ac < 2){
                printf("the operate to less /n");
                return -1;
        }
        memset(cmd, 0x00, sizeof(cmd));
        srcdev = av[1];
        decdev = av[2];
 sprintf(cmd, "mount %s /data/sdev",av[1]);
        system(cmd);
        memset(cmd, 0x00, sizeof(cmd));
        sprintf(cmd, "mount %s /data/ddev",av[2]);
        system(cmd);

        lstat(DEVS, &st);
        if (!S_ISDIR(st.st_mode)){
                printf("%s errpo@@@/n",DEVS);
                return -1;
        }
        //if (ddir = opendir())
        pathlen = strlen(srcdev);
        if (scan_dir(DEVS, DEVD, &st) >= 0){
                system("umount /data/sdev");
                system("umount /data/ddev");
        }
        return 0;
}

int scan_dir(char *s, char *d, struct stat *fstat){
        int     retval = 0;
        int     rest;
        struct  dirent diret, *diret_ptr;
        char    filename[PATH_MAX],dfilename[PATH_MAX];
        DIR   *sdir=NULL, *ddir=NULL ,*sdirbak=NULL, *ddirbak=NULL;

        if (!S_ISDIR(fstat->st_mode)){
                printf("***%s is not a directy",s);
                return -1;
        }
        //ddir = opendir(d);
        //printf("######### s:%s ############# d:%s ##############/n",s,d);
        if ((sdir = opendir(s)) == NULL){
                printf("opendir %s error: %s/n",s, strerror(errno));
                return (-1);
        }
        if ((ddir = opendir(d)) == NULL){
                fprintf(stderr,"opendir %s error:%s/n",d,strerror(errno));
                return (-1);
        }
        sdirbak = sdir;
        ddirbak = ddir;
  while(!(retval = readdir_r(sdir, &diret, &diret_ptr)) ){
                struct stat dirinfo;
                int     filelen;

                if (diret_ptr == NULL){
                        printf("readdir_r:%s   error /n",diret.d_name);
                        break;
                }
                if ( (strncmp(diret.d_name, ".", PATH_MAX) == 0) ||
                        (strncmp(diret.d_name, "..", PATH_MAX) == 0)){
                        //retval = readdir_r(sdir, &diret, &diret_ptr);
                        continue;
                }
                filelen = strlen(diret.d_name);
                if (filelen+pathlen > PATH_MAX){
                        printf("file name too long/n");
                }
                printf("@@@@ current dire:%s @@@@ /n",diret.d_name);
                if (strcmp(s, "/")){
                        sprintf(filename,"%s/%s",s,diret.d_name);
                        sprintf(dfilename,"%s/%s",d,diret.d_name);
                }else  {
                        sprintf(filename,"/%s",diret.d_name);
                        sprintf(dfilename,"/%s",diret.d_name);
                }
     lstat(filename, &dirinfo);
                memset(&finfo, 0x00, sizeof(&finfo));
                memset(dfilename, 0x00, sizeof(dfilename));
                sprintf(finfo.name, "%s",diret.d_name);
                sprintf(dfilename,"%s/%s",d,diret.d_name);
                printf("w:%s/n/n",dfilename);
                //memcpy(&finfo->fstat, &dirinfo, sizeof(dirinfo) );
                if (S_ISDIR(dirinfo.st_mode)){
                        printf("################It is a direct: %s  /n", filename);
                        if (readops(filename, &dirinfo, dfilename) < 0){
                                printf("read directory %s error /n",filename);
                        }
                        rest = scan_dir(filename, dfilename, &dirinfo);
                        if (rest < 0){
                                printf("scan %s failed /n",filename);
                        }
                        continue;
                }
                else {
                        printf("%s not a directory /n",filename);
                        if (readops(filename, &dirinfo, dfilename) < 0){
                                printf("read reg file:%s error /n",filename);
                        }
                }
    }
        while (closedir(sdirbak) != 0);
        while (closedir(ddirbak) != 0);
        return 0;

}
int readops(char *fname, struct stat *info, char *dname){
        int     red;
        int     rfd,wfd;
        if(!S_ISREG(info->st_mode)){
                if (S_ISDIR(info->st_mode)){
                        //mkdir(dname, 0644);
                        mkdir(dname, info->st_mode);
                }else if (S_ISFIFO(info->st_mode)){
                        //mkfifo(dname, 0644);
                        mkdir(dname, info->st_mode);
                }else if (S_ISSOCK(info->st_mode)){
                        mknod(dname, info->st_mode, info->st_rdev);
                }else if ((S_ISBLK(info->st_mode))||(S_ISCHR(info->st_mode))){
                        mknod(dname, info->st_mode, info->st_rdev);
                }else if (S_ISLNK(info->st_mode)){
                        readlink(fname, buf, BUFSIZE);
                        symlink(buf, fname);
                }
                rebak_mod(dname, info);
                return 0;
        }
       if ((rfd = open(fname, O_RDONLY|O_NONBLOCK)) == -1){
                printf("open %s error:%s",fname,strerror(errno) );
                return -1;
        }
        if ((wfd = open(dname, O_WRONLY|O_CREAT|O_TRUNC)) == -1){
                printf("open write file %s error:%s /n",dname,strerror(errno));
                return -1;
        }
 do{
                red = read(rfd, buf, BUFSIZE);
                printf("readed :%d /n",red);
                if(red < 0){
                        perror("read error: ");
                        break;
                }else if(red == 0){
                        printf("read over /n");
                        break;
                }
                write(wfd, buf, red);

        }while(1);
        //if (red < 0)
        //      return -1;
        close(rfd);
        close(wfd);
        rebak_mod(dname, info);
        sync();
        return 0;

}
int rebak_mod(char *fname, struct stat *bakmod){
        struct utimbuf timebak;
        int ret;
        if (S_ISLNK(bakmod->st_mode)){
                ret = lchown(fname, bakmod->st_uid, bakmod->st_gid);
        }
        else
                ret = chown(fname, bakmod->st_uid, bakmod->st_gid);
        if (ret < 0){
                printf("can not change file:%s's owner/n",fname);
        }
        if (!S_ISLNK(bakmod->st_mode)){
                ret = chmod(fname, bakmod->st_mode);
        }
        if (ret < 0 ){
                printf("can not change file:%s mode/n",fname);
        }
        timebak.actime = bakmod->st_atime;
        timebak.modtime = bakmod->st_mtime;
        if (utime(fname, &timebak) < 0){
                printf("can not change file:%s time/n",fname);
        }
        return 0;
}

/*********************************************************************
*binclude.h
*********************************************************************/
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <unistd.h>
#include <dirent.h>
#include <utime.h>

#include <pthread.h>

#include <sys/ipc.h>


#define DEVS "/data/sdev"
#define DEVD "/data/ddev"
#ifndef PATH_MAX
#define PATH_MAX        256
#endif

#define BUFSIZE         1024*1024
typedef struct aa{

        struct stat statbak;
        char    name[NAME_MAX];
        int     flags;
}g_file_inf;

在Linux系统中复制磁盘分区可以通过多种工具和方法实现,以下是几种常见的技术手段: ### 使用 `dd` 命令进行逐块复制 `dd` 是一个非常强大的命令行工具,可以用于复制文件、转换数据以及备份和恢复磁盘分区。其基本语法如下: ```bash dd if=源设备路径 of=目标设备路径 bs=块大小 ``` 例如,将 `/dev/sda1` 分区复制到另一个磁盘的 `/dev/sdb1` 上,可以使用以下命令: ```bash dd if=/dev/sda1 of=/dev/sdb1 bs=4M ``` - `if` 表示输入文件(或设备),这里是 `/dev/sda1`。 - `of` 表示输出文件(或设备),这里是 `/dev/sdb1`。 - `bs` 指定每次读取和写入的数据块大小,通常设置为 4MB (`4M`) 可以提高效率。 此方法适用于完全镜像整个分区,包括空闲空间[^2]。 ### 使用 `rsync` 进行文件级复制 如果只需要复制分区中的文件而不是整个分区结构,则可以使用 `rsync` 工具。它可以在本地或远程同步文件,并保留权限、时间戳等属性。假设要将 `/dev/sda1` 挂载点 `/mnt/source` 的内容复制到 `/mnt/target`,可以执行: ```bash rsync -av /mnt/source/ /mnt/target/ ``` - `-a` 表示归档模式,启用递归复制并保持所有文件属性。 - `-v` 显示详细的复制过程。 这种方法适合于需要灵活控制复制内容的情况,且不会复制未使用的空间。 ### 使用 `partclone` 或 `Clonezilla` 对于更专业的场景,尤其是大规模部署或灾难恢复,可以考虑使用专门的分区克隆工具如 `partclone` 或 `Clonezilla`。这些工具能够高效地复制和恢复分区,支持压缩和网络传输等功能。 #### 安装与使用 `partclone` 安装 `partclone`: ```bash sudo apt-get install partclone ``` 使用 `partclone` 复制分区: ```bash sudo partclone.ext4 -c -s /dev/sda1 -o /path/to/image.img ``` 然后将镜像恢复到目标分区: ```bash sudo partclone.ext4 -r -s /path/to/image.img -o /dev/sdb1 ``` ### 注意事项 - **确保目标分区足够大**:无论是使用 `dd` 还是其他工具,目标分区的容量必须大于或等于源分区的实际使用空间。 - **备份重要数据**:操作前应备份关键数据,防止意外丢失。 - **检查设备名称正确性**:错误指定设备可能导致数据覆盖,造成不可逆损失。 通过以上方法,可以根据具体需求选择合适的工具来完成 Linux 系统中的分区复制任务。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值