/* Copy the directory structure, but not the files */ #include #include #include #include #include #include #include #include using namespace std; static void usage() { fprintf (stderr ,"copytree source-directory target-directory\n" "\n" "All sub-directory in source-directory are created\n" "with the same permission/ownership in target-directory.\n"); } static int copytree (const char *src, const char *dst) { int ret = -1; DIR *d = opendir (src); if (d == NULL){ fprintf (stderr,"Can't open directory %s (%s)\n",src,strerror(errno)); }else{ struct dirent *ent; ret = 0; while ((ent=readdir(d))!=NULL){ struct stat64 st; string srctmp = string(src) + '/' + ent->d_name; string dsttmp = string(dst) + '/' + ent->d_name; const char *dtmp = dsttmp.c_str(); if (stat64 (srctmp.c_str(),&st)==-1){ // If this is symlink pointing nowhere, we copy the link if (lstat64(srctmp.c_str(),&st)==-1){ // Very strange. The entry exist in the directory but // even lstat fails. The system is broken, better bug off. fprintf (stderr,"Can't stat file %s (%s)\n",srctmp.c_str() ,strerror(errno)); ret = -1; break; }else if (S_ISLNK(st.st_mode)){ char lpath[PATH_MAX]; int len = readlink (srctmp.c_str(),lpath,sizeof(lpath)-1); if (len > 0){ lpath[len] = '\0'; unlink (dtmp); if (symlink(lpath,dtmp)==-1){ fprintf (stderr,"Can't symlink %s -> %s (%s)\n" ,dtmp,lpath,strerror(errno)); ret = -1; break; } }else{ fprintf (stderr,"Can't readlink %s (%s)\n",srctmp.c_str() ,strerror(errno)); ret = -1; break; } }else{ // Really strange. stat failed, but not lstat fprintf (stderr,"Can't stat file %s, but can lstat, but not symlink\n" ,srctmp.c_str()); ret = -1; break; } }else if (S_ISDIR(st.st_mode) && strcmp(ent->d_name,".")!=0 && strcmp(ent->d_name,"..")!=0){ // Is is a directory or a symlink char lpath[PATH_MAX]; int len = readlink (srctmp.c_str(),lpath,sizeof(lpath)); struct stat64 dst; if (len > 0){ lpath[len] = '\0'; unlink (dtmp); if (symlink(lpath,dtmp)==-1){ fprintf (stderr,"Can't create symlink %s -> %s (%s)\n" ,lpath,dtmp,strerror(errno)); ret = -1; } }else if (lstat64(dtmp,&dst)!=-1){ if (S_ISDIR(dst.st_mode)){ // Already there if (chown (dtmp,st.st_uid,st.st_gid)==-1){ fprintf (stderr,"Can't chown directory %s (%s)\n" ,dtmp,strerror(errno)); ret = -1; }else if (chmod (dtmp,st.st_mode)==-1){ fprintf (stderr,"Can't chmod sub-directory %s (%s)\n" ,dtmp,strerror(errno)); ret = -1; }else{ ret = copytree (srctmp.c_str(),dtmp); } }else if(S_ISLNK(dst.st_mode)){ }else{ fprintf (stderr,"%s already exist but is not a directory nor a symlink\n" ,dtmp); ret = -1; } }else{ if (mkdir (dtmp,st.st_mode)==-1){ fprintf (stderr,"Can't create sub-directory %s (%s)\n" ,dtmp,strerror(errno)); ret = -1; }else if (chown (dtmp,st.st_uid,st.st_gid)==-1){ fprintf (stderr,"Can't chown directory %s (%s)\n" ,dtmp,strerror(errno)); ret = -1; }else{ ret = copytree (srctmp.c_str(),dtmp); } } } } closedir (d); } return ret; } int main (int argc, char *argv[]) { int ret = -1; if (argc != 3){ usage(); }else{ umask(0); ret = copytree (argv[1],argv[2]); } return ret; }