#include #include #include #include #include #include #include //#include #include #include #include #include //======================================= #define BUFSIZE 512 //size of chunk to be read #define PERM 0644 //file permission for new file #define _PC_PATH_MAX_1 80 void check_cmd_line(int argc, char** argv, char* flag, char* arg1, char* arg2); int copyfile (char *name1, char * name2, char* flag); void synfiles(char *file1, char *file2, char *flag); //char* getEndingName(char * pathname); void syncDir (char *name1, char* name2, char *flag); void copy_subdir(char* dir1, char* dir2, char* flag); char find_same_subdir(char* subdir, char* dirk); //int match (const char * s1, const char * s2); int find_entry (char *dirname, char *fileName); int isDir (char *name); int fileTyping (char *pathname); char IsOverWriteFile(char* file2, char* flag); char IsCreateFile(char* file2, char* flag); void Disp_Replaced_by(char* file1, char* file2, char* flag); void Disp_Added_to(char* file1, char* file2, char* flag); void GetDirFile(char* fullname, char* dirname, char* filename); void ModifyTime(char* file1, char* file2); int testRight(uid_t userid); uid_t getowner(char *pathname); uid_t euid, ruid; //======================================= int main(int argc, char *argv[]) { char flag[4]; char arg1[80],arg2[80], arg_temp[80]; int i; int ff; uid_t f1_id, f2_id, f1_id1, f1_id2, f2_id1, f2_id2; int t1, t2; euid=geteuid(); ruid=getuid(); ////////////////////////////////// //printf("effective user id is: %ld\n", euid); //printf("real user id is: %ld\n", ruid); ////////////////////////////////////// ff=testRight(ruid); if(ff == 0) { printf("Not authorized\n"); exit(1); } for(i=0; i<4; i++) flag[i]=0; strcpy(arg1,""); strcpy(arg2,""); check_cmd_line(argc,argv,flag,arg1,arg2); // get the owners of arg1 f1_id=getowner(arg1); if(f1_id == -1) {printf("error getting owner of %s. Neither effective nor real user can access it. \n", arg1); exit(-1); } // get the owner of arg2 f2_id=getowner(arg2); if(f2_id == -1) {printf("error getting owner of %s. Neither effective nore real user can access it. \n", arg2); exit(-2); } if(euid!=ruid) {if (f1_id==f2_id) {printf("Error: two files or directories must be owned by two user! \n"); exit(-1); } if((f1_id !=euid && f1_id != ruid) || (f2_id !=euid && f2_id != ruid)) { printf("Error: Both two files or directories must be owned by group member! \n"); exit(-3); } if(f1_id!=euid) {strcpy(arg_temp,arg1); strcpy(arg1, arg2); strcpy(arg2, arg_temp); } } else {printf("Error: teamsync must be used for case where euid and ruid are different!\n\n"); exit(-2); } //check arg1 and arg2 seteuid(euid); t1=isDir(arg1); seteuid(ruid); t2=isDir(arg2); //two directories exist and their name are different if( (t1==1) && (t2==1) && (strcmp(arg1, arg2)!=0)) syncDir(arg1, arg2, flag); //two files exist else if((t1==0) && (t2==0) && (strcmp(arg1, arg2)!=0)) {char f1[80]; char f2[80]; char dir1[80]; char dir2[80]; GetDirFile(arg1, dir1, f1); GetDirFile(arg2, dir2, f2); if(strcmp(f1,f2)==0) synfiles(arg1, arg2, flag); } else {printf("Command line argument wrong! \n"); exit(1); } } //============================================================ void check_cmd_line(int argc, char** argv, char* flag, char* arg1, char* arg2) { int op_n; if(argc > 7) { printf("Command line arguments too many!\n"); exit(-1); } if(argc < 3) { printf("Command line arguments too little!\n"); exit(1); } /* treat option */ op_n=argc-3; while(op_n > 0) { op_n--; argv++; if( (strcmp(*argv,"-q")==0) && (flag[0]==0) ) flag[0]='q'; else if( (strcmp(*argv,"-r")==0) && (flag[1]==0) ) flag[1]='r'; else if( (strcmp(*argv,"-c")==0) && (flag[2]==0) ) flag[2]='c'; else if( (strcmp(*argv,"-i")==0) && (flag[3]==0) ) flag[3]='i'; else { printf("Command line arguments wrong!\n"); exit(1); } } argv++; strcpy(arg1,*argv); argv++; strcpy(arg2,*argv); } //============================================================ int isDir(char *name) {int i; i= fileTyping(name); return i; } //============================================================ int fileTyping (char *pathname) {struct stat s; int retval; retval = stat(pathname, &s); if(retval == -1) {printf("stat failed %s ! \n", pathname); return -1;} if (S_ISREG(s.st_mode)) return 0; if(S_ISDIR(s.st_mode)) return 1; else return -1; } //========================================================= //file1 and file2 are given by their path name void synfiles (char *file1, char *file2, char* flag) {int copyfs; int filedes1, filedes2; struct stat statFile1, statFile2; time_t time1, time2; uid_t f1_id, f2_id; uid_t temp1, temp2, myid; char dir1[80], dir2[80], f1[80], f2[80]; seteuid(euid); f1_id=getowner(file1); seteuid(ruid); f2_id=getowner(file2); // open file 1 and get its time of last modification seteuid(euid); /******* if((filedes1=open(file1, O_RDONLY))==-1) {printf("File 1: error %d\n", errno); exit (-1); } ****/ if (stat(file1, &statFile1)==-1) {printf("Couldn't stat %s\n", file1); exit(-2); } else time1=statFile1.st_mtime; // open files 2 and set its time of last modification seteuid(ruid); /********* if((filedes2=open(file2, O_RDONLY))==-1) {printf("File 2: error %d\n", errno); exit (-3); } *****/ if(stat(file2, &statFile2)==-1) {printf("Could not fstat %s\n", file2); exit(-4); } time2=statFile2.st_mtime; //if file1 is newer than file2 if(time1>time2) {char f=IsOverWriteFile(file2,flag); if( f != 0 ) {copyfs=copyfile(file1, file2, flag); //file1 overwrite file2 if( copyfs == 0 ) //success {ModifyTime(file1,file2); //file1_t to file2_t Disp_Replaced_by(file1,file2,flag); //dips.. } else if (copyfs < 0) printf("Error copying file.\n"); else { } } } //if file1 is older than file2 else if(time1 will not be copied to: directory owned by <%d>\n", dir1, f1_id); printf("<%s> will not be copied from: directory owned by <%d>\n", dir2, f2_id); } } //if file1 and file2 is the same age else if(flag[0] != 'q') printf("%s:%s: same age!\n", file1, file2); } //=================================================================== //This piece of code is from text book "Unix System Programming", p20 //copy name1 to name2. name1 and name2 are full names int copyfile(char *name1, char *name2, char* flag) { int infile, outfile; ssize_t nread; char buffer[BUFSIZE]; int opd; char f1[50],f2[50],d1[80],d2[80]; uid_t d1_id,f1_id,d2_id,f2_id; uid_t t_id; seteuid(euid); GetDirFile(name1,d1,f1); f1_id=getowner(name1); if(f1_id != euid) {if(flag[0] != 'q') printf("%s will not be copied: file owned by %d\n",f1,f1_id); return(1); } seteuid(ruid); opd=open(name2,O_RDWR); if(opd != -1) //file name2 exists { GetDirFile(name2,d2,f2); f2_id=getowner(name2); if((f2_id >= 0) && (f2_id != ruid)) {if(flag[0] != 'q') printf("%s will not be copied to: file owned by %d\n", f2, f2_id); return(1); } } seteuid(euid); if((infile=open(name1, O_RDONLY))==(-1)) return(-1); seteuid(ruid); if((outfile=open(name2, O_WRONLY|O_CREAT|O_TRUNC, PERM))==-1) {close(infile); return(-2); } seteuid(euid); //now read from name1 BUFSIZE chars at a time while ((nread=read(infile, buffer, BUFSIZE) )>0) { //write buffer to the output file seteuid(ruid); if (write(outfile, buffer, nread)d_ino==0) continue; if(strcmp(dir->d_name,".")==0 || strcmp(dir->d_name,"..")==0) continue; strcpy(fullfilename1,dir1); strcat(fullfilename1,dir->d_name); strcpy(fullfilename2, dir2); strcat(fullfilename2,dir->d_name); seteuid(euid); if(isDir(fullfilename1)!=0) {if(flag[1] == 'r') {char ff=find_same_subdir(dir->d_name,dir2); if(ff != 0) //same subdir in dir1,dir2 {strcat(fullfilename1, "/"); strcat(fullfilename2, "/"); syncDir(fullfilename1, fullfilename2, flag); //recursive } else //subdir in dir1, no in dir2 copy_subdir(fullfilename1, fullfilename2, flag); } } else {if(find_entry(dir2, dir->d_name)==1) // file does exist in directory 2 synfiles(fullfilename1, fullfilename2, flag); else // no file with same name in directory 2 {int cpfs; char f=IsCreateFile(fullfilename2,flag); if(f != 0 ) {//fname1 overwrite fname2 cpfs=copyfile(fullfilename1, fullfilename2, flag); if(cpfs == 0 ) //success {ModifyTime(fullfilename1,fullfilename2); //fname1_t to fname2_t Disp_Added_to(fullfilename1,fullfilename2,flag); //dips.. } else if(cpfs < 0 ) printf("Error copying files.\n"); else { } } } } } closedir(dp); dp=NULL; } //===================================================== void copy_subdir(char* dir1, char* dir2, char* flag) {static DIR *dp=NULL; struct dirent *dir; char sdir1[80],sdir2[80]; int cpfs; seteuid(ruid); mkdir(dir2, 0744); seteuid(euid); if((dp=opendir(dir1))==NULL) printf("error opening directory!\n"); while(dir=readdir(dp)) { if(strcmp(dir->d_name,".")==0 || strcmp(dir->d_name,"..")==0) continue; strcpy(sdir1,dir1); strcat(sdir1,"/"); strcat(sdir1,dir->d_name); strcpy(sdir2,dir2); strcat(sdir2,"/"); strcat(sdir2,dir->d_name); seteuid(euid); if(isDir(sdir1)!=0) //sdir1 is a full name for a dir copy_subdir(sdir1, sdir2, flag); //recursive else {char f=IsCreateFile(sdir2, flag); if(f != 0) {cpfs=copyfile(sdir1, sdir2, flag); //sdir1 overwrite sdir2 if( cpfs == 0 ) //success {ModifyTime(sdir1,sdir2); //sdir1_t to sdir2_t Disp_Added_to(sdir1,sdir2,flag); //dips.. } else if( cpfs < 0 ) printf("Error copying file. \n"); else { } } } } closedir(dp); } //======================================================== //subdir is not full name, dirk is full name //found, return 1; no found, return 0 char find_same_subdir(char* subdir, char* dirk) {char fullfilename2[60]; static DIR *dp=NULL; struct dirent *dir; seteuid(ruid); if((dp=opendir(dirk))==NULL) printf("error opening directory!\n"); while(dir=readdir(dp)) { strcpy(fullfilename2,dirk); strcat(fullfilename2,"/"); strcat(fullfilename2,dir->d_name); if(isDir(fullfilename2)) { if( strcmp(dir->d_name,subdir) == 0 ) { closedir(dp); return 1; } } } closedir(dp); return 0; } //=========================================================== //this piece of code from text book by Keith et al. p 71) //fileName is the ending name of the file int find_entry (char *dirname, char *fileName) {DIR *dp=NULL; struct dirent *dir; seteuid(ruid); if(dp!=NULL) closedir(dp); dp=opendir(dirname); if(dp==NULL) return(0); dir=readdir(dp); while(dir) {if(dir->d_ino==0) continue; if(strcmp(dir->d_name, fileName)==0) {closedir(dp); // seteuid(euid); // printf("the current effective user id is: %ld \n", geteuid()); return (1); } dir=readdir(dp); } closedir(dp); dp=NULL; //seteuid(euid); return 0; } //======================================================== //get dirname and filename from fullname void GetDirFile(char* fullname, char* dirname, char* filename) { char *pdest; char str[100]; strcpy(str,fullname); pdest=strrchr(str,'/'); if(pdest == NULL) //no '/' in str { strcpy(filename,str); strcpy(dirname,""); } else { strcpy(filename,pdest+1); *(pdest+1)=0; strcpy(dirname,str); } } //======================================================== //prompt,ask(-c/-i). overwrite? return 1; no, return 0 char IsOverWriteFile(char* file2, char* flag) { //flag: -c, -i char f=1; char str[40]; if(flag[2]=='c' || flag[3]=='i') { printf("%s exists, overwrite? (y/n/x) ",file2); gets(str); if( strlen(str)==1 && (str[0]=='y' || str[0]=='Y') ) f=1; else if( strlen(str)==1 && (str[0]=='n' || str[0]=='N') ) f=0; else if( strlen(str)==1 && (str[0]=='x' || str[0]=='X') ) exit(1); else f=0; } return f; } //======================================================== //prompt,ask(-i). Create? return 1; no, return 0 char IsCreateFile(char* file2, char* flag) { //flag: -i char f=1; char str[40]; if(flag[3]=='i') { printf("Create %s? (y/n/x) ",file2); gets(str); if( strlen(str)==1 && (str[0]=='y' || str[0]=='Y') ) f=1; else if( strlen(str)==1 && (str[0]=='n' || str[0]=='N') ) f=0; else if( strlen(str)==1 && (str[0]=='x' || str[0]=='X') ) exit(1); else f=0; } return f; } //======================================================== //file1,file2 full filename void Disp_Replaced_by(char* file1, char* file2, char* flag) { struct stat statbuf1; time_t t1; seteuid(euid); stat(file1, &statbuf1); t1=statbuf1.st_mtime; if(flag[0] != 'q') printf("%s replaced by %s: %s\n",file2,file1,asctime(localtime(&t1))); } //======================================================== //file1,file2 full filename //disp: filename(of file2) Added to dirname(of file2) void Disp_Added_to(char* file1, char* file2, char* flag) { struct stat statbuf1; time_t t1; char dirname[80]; char filename[80]; seteuid(euid); stat(file1, &statbuf1); t1=statbuf1.st_mtime; GetDirFile(file2, dirname, filename); if(flag[0] != 'q') printf("%s added to %s: %s\n",filename,dirname,asctime(localtime(&t1))); } //======================================================== //file2_t to file1_t. file1,file2: full filename void ModifyTime(char* file1, char* file2) { struct utimbuf times; struct stat statbuf1; time_t t1m,t1a; seteuid(euid); stat(file1, &statbuf1); t1m=statbuf1.st_mtime; t1a=statbuf1.st_atime; seteuid(ruid); times.modtime=t1m; times.actime=t1a; utime (file2, ×); seteuid(euid); } //======================================================== int testRight (uid_t userid) { uid_t user_ID[10]; //number of team <= 10 int i; char *fr; FILE * fp; char temp[15]; // make sure the file to be opened exist if((fp=fopen("syncteam","r"))==NULL) { printf("Error opening user file: syncteam.\n"); exit(1); } i=0; while(1) { fr=fgets(temp, 15, fp); user_ID[i]=atoi(temp); if(fr == NULL) break; if(userid == user_ID[i]) return 1; //found i++; } return 0; //no found } //======================================================== uid_t getowner (char *pathname) { struct stat s; seteuid(euid); if (stat(pathname, &s)==0) return s.st_uid; else {seteuid(ruid); if (stat(pathname, &s)==0) return s.st_uid; } return -1; } //========================================================