📄 archive.c
字号:
} } /* check permissions. This uses the users real id, so the user can not get access to files that are usually not accessible, even if sitback is running suid root to allow access to a device. Skip links already reported as bad symlinks */ if(know_this_is_symlink==0) { if(access(filename,R_OK)) { UI__Warning("Bad permissions on '%s'\n",filename); return -1; } } /*if the filename is a directory, dive into it and get info for all files and directory's here*/ if(S_ISDIR(info.st_mode)) { /* check permissions */ if(access(filename,R_OK | X_OK)) { UI__Warning("Bad permissions on '%s'\n",filename); return -1; } /*if descend=0, then just return 0, this is in fact a valid directory*/ debug("'%s' is a directory\n",filename); if(!descend) return 0; debug("descending into '%s'\n",filename); /*write this directory into the archive-list*/ if(archivelist!=NULL) { fprintf(archivelist,"%s,%ld\n",filename,info.st_size); conf__archive_size+=info.st_size; } /* to be able to detect a looping directory symlink (which tar handles fine), we do a lstat also on the file. a looping symlink would bring us into a burning spin towards the ground..! */ if(lstat(filename,&linfo)) { UI__Warning("Unable to lstat() if '%s' is a symlink.\n",filename); debug("lstat failed for '%s'\n",filename); return -1; } else { if(S_ISLNK(linfo.st_mode)) { debug("lstat() reports '%s' as a directory symlink\n",filename); if(conf__follow_symlinks==0) return 0; /* check for repeated visits to a inode, unless we are already checking a location */ debug("stop_ino=%lu info.st_ino=%lu\n",stop_ino,linfo.st_ino); debug("stop_dev=%lu info.st_dev=%lu\n",stop_dev,linfo.st_dev); strcpy(linkpath,filename); debug("linkpath='%s'\n",linkpath); if((p=strrchr(linkpath,'/'))!=NULL) { if(p!=linkpath) *p='\0'; } debug("Truncated linkpath '%s'\n",linkpath); memset(tmp_linkpath,'\0',4096); readlink(filename,tmp_linkpath,4095-strlen(linkpath)); debug("linkname='%s'\n",tmp_linkpath); if(tmp_linkpath[0]=='/') strcpy(linkpath,tmp_linkpath); else { strcat(linkpath,"/"); strcat(linkpath,tmp_linkpath); } debug("Full linkpath '%s'\n",linkpath); if(stop_ino!=0 && stop_dev!=0 && stop_ino==linfo.st_ino && stop_dev==linfo.st_dev) { debug("stop_ino and stop_dev matches current inode on current device, returning an error\n"); return -1; } if(stop_ino==0 && stop_dev==0) { /* Check that this symlink does not loop */ debug("Checking that this is not a looping symlink\n"); if(__stat_location(linkpath,NULL,NULL,1,linfo.st_ino,linfo.st_dev)) { UI__Warning("Warning: %s is a looping symlink\n",filename); debug("'%s' is a looping symlink\n",filename); log("'%s' is a looping symlink\n",filename); return -1; } } } } /*we dont know how much buffer-space is needed for the file-names as we descend along the paths found in the filelist, so we allocate a initial buffer and realloc it later if needed*/ if((location=(char*) malloc(1025))==NULL) { errcode=11; sprintf(strn,"Unable to create temporary memory buffer for filenames\n"); UI__Warning(strn); return -1; } /*open a DIR-stream for this directory*/ if((dir=opendir(filename))==NULL) { free(location); log("Unable to list content of directory '%s'.",filename); fprintf(excludelist,"%s\n",filename); return 0; } /*check all entry's*/ errno=0; while((entry=readdir(dir))!=NULL) { /*check for error's*/ if(errno!=0) { closedir(dir); free(location); errcode=16; sprintf(strn,"Unable to get directory entry\n"); UI__Warning(strn); sprintf(strn,"System say's: %s\n",strerror(errno)); UI__Warning(strn); return -1; } /*dont check . and ..*/ debug("got direntry '%s'\n",entry->d_name); if(strcmp(entry->d_name,".") && strcmp(entry->d_name,"..")) { /*check buffer size*/ if(location_length<strlen(entry->d_name)+strlen(filename)+1) { if((location=(char*) realloc(location,strlen(entry->d_name)+strlen(filename)+2))==NULL) { closedir(dir); errcode=11; UI__Warning("Unable to extend temporary buffer for filenames\n"); return -1; } location_length=strlen(entry->d_name)+strlen(filename)+1; debug("location buffer reallocated, new size is %d bytes\n",location_length); } /*compose new path*/ if(strcmp(filename,"/")) sprintf(location,"%s/%s",filename,entry->d_name); else /* root directory */ sprintf(location,"/%s",entry->d_name); /*check that location*/ if(__stat_location(location,archivelist,excludelist,1,stop_ino,stop_dev)==-1) { free(location); /*errcode has been set by the failing function*/ /*error message has been given by the failing function*/ return -1; } } /*forget about any errors that is not critical*/ errno=0; } /*done searching this directory*/ closedir(dir); /*no more use for the location buffer*/ if(location!=NULL) free(location); } else if((S_ISREG(info.st_mode) || S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode) || S_ISFIFO(info.st_mode)) && conf__special_files) { /*include fileinfo into the archive-list*/ debug("'%s' is a file\n",filename); if(archivelist!=NULL) { fprintf(archivelist,"%s,%ld\n",filename,info.st_size); conf__archive_size+=info.st_size; } } else if(S_ISREG(info.st_mode)) { /*include fileinfo into the archive-list*/ debug("'%s' is a file\n",filename); if(archivelist!=NULL) { fprintf(archivelist,"%s,%ld\n",filename,info.st_size); conf__archive_size+=info.st_size; } } /*report invalid file-types. Actually, tar will most likely include them, but it makes no sense to backup those files unless it is a rescue backup of the entire system, but there are better way's to do this..*/ else if(S_ISFIFO(info.st_mode)) { debug("'%s' is a FIFO\n",filename); if(excludelist!=NULL) { log("'%s' is a FIFO. Not included in the archive.",filename); fprintf(excludelist,"%s\n",filename); } } else if(S_ISLNK(info.st_mode)) { if(know_this_is_symlink) { debug("'%s' is a bad symlink\n",filename); know_this_is_symlink=0; } else { debug("'%s' is a link\n",filename); UI__Warning("'%s' is reported as a link, even though we asked for the target file or directory. Will not be included in archive.\n",filename); if(excludelist!=NULL) fprintf(excludelist,"%s\n",filename); /* there must be something weird with this file */ } } else if(S_ISSOCK(info.st_mode)) { debug("'%s' is a socket\n",filename); if(excludelist!=NULL) { log("'%s' is a socket. Not included in the archive.",filename); fprintf(excludelist,"%s\n",filename); } } else if(S_ISCHR(info.st_mode)) { debug("'%s' is a character device file\n",filename); if(excludelist!=NULL) { log("'%s' is a character device file. Not included in the archive.",filename); fprintf(excludelist,"%s\n",filename); } } else if(S_ISBLK(info.st_mode)) { debug("'%s' is a block device file\n",filename); if(excludelist!=NULL) { log("'%s' is a block device file. Not included in the archive.",filename); fprintf(excludelist,"%s\n",filename); } } /* leaving __stat_location() */ debug("__stat_location return from \"%s\"\n",filename); /*no problems*/ return 0;}/******************************************************************** int ArchiveName() Use the archive-name given in the script or on the command-line. If no archive-name is given, generate default name. arguments: none return: -1 on error 0 on success********************************************************************/int ArchiveName(){ FILE *file; struct tm *currtime; time_t timep; /*get time and date only once to ensure that the dates and times in the default archivename and in the sitback.archivename file is the same*/ timep=time(NULL); currtime=localtime(&timep); /*check for archive-name*/ if(conf__archive_name[0]=='\0') { sprintf(conf__archive_name,"%02d%02d%04d",currtime->tm_mon+1,currtime->tm_mday,currtime->tm_year+1900); debug("No archive-name. Using default name \"%s\"\n",conf__archive_name); } /*write the archivename-file*/ if((file=fopen("sitback.archivename","w"))==NULL) { UI__Warning("Unable to write sitback.archivename\n"); return -1; } fprintf(file,"%s\n",conf__archive_name); /*write the date of creation*/ fprintf(file,"%02d/%02d-%04d\n",currtime->tm_mon+1,currtime->tm_mday,currtime->tm_year+1900); /*write the time of creation*/ fprintf(file,"%02d:%02d\n",currtime->tm_hour,currtime->tm_min); /*write info about this sitback*/ fprintf(file,"%s\n",VERSION); /*close the archivename-file*/ fclose(file); /*no problems*/ return 0;}/******************************************************************** int TestLocation(char *location) Test if the location is a valid file or directory. Actually, this is just wrapper-code for the local defined __stat_location function. arguments: none return: -1 on error 0 on success********************************************************************/int TestLocation(char *location){ debug("TestLocation('%s')\n",location); if(access(location,0)) { debug("Target '%s' does not exists\n"); return -1; } return __stat_location(location,NULL,NULL,0,0,0);}/******************************************************************** int ArchiveId() Write the archive-id file arguments: none return: -1 on error 0 on success********************************************************************/int ArchiveId(){ time_t timep; struct tm *currtime; /*If we got no archive-id, make one*/ if(conf__archive_oldid[0]=='\0') { /*create a default archive-id*/ timep=time(NULL); currtime=localtime(&timep); sprintf(conf__archive_oldid,"%02d%02d%04d%02d%02d" ,currtime->tm_mon+1 ,currtime->tm_mday
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -