/* shared_val1 = --unused-- */ enum backup_state_ret restore_state_complete_v1 (struct backup_info *info, void *data, unsigned size, unsigned *consumed) { if (size > 0) { fprintf (stderr, "Extra blocks at end of restore???"); } if (info->state != bsComplete) { /* Go ahead and print it to stderr - this is really a development message */ fprintf (stderr, "State machine missing states\n"); } if (restore_cleanup_parts (info) < 0) return bsError; if (restore_make_swap (info) < 0) return bsError; if (restore_fixup_vol_list (info) < 0) return bsError; if (restore_fixup_zone_maps (info) < 0) return bsError; mfsvol_cleanup (info->vols); info->vols = 0; info->mfs = mfs_init (info->devs[0].devname, info->ndevs > 1? info->devs[1].devname: NULL, O_RDWR); if (!info->mfs || mfs_has_error (info->mfs)) return bsError; if (restore_fudge_inodes (info) < 0) return bsError; if (restore_fudge_transactions (info) < 0) return bsError; #if HAVE_SYNC /* Make sure changes are committed to disk */ sync (); #endif return bsNextState; }
int mainloop(struct fuse_args *args,const char* mp,int mt,int fg) { struct fuse_session *se; struct fuse_chan *ch; struct rlimit rls; int piped[2]; char s; int err; int i; md5ctx ctx; uint8_t md5pass[16]; if (mfsopts.passwordask && mfsopts.password==NULL && mfsopts.md5pass==NULL) { mfsopts.password = getpass("MFS Password:"******"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } p++; if (*p>='0' && *p<='9') { md5pass[i]+=(*p-'0'); } else if (*p>='a' && *p<='f') { md5pass[i]+=(*p-'a'+10); } else if (*p>='A' && *p<='F') { md5pass[i]+=(*p-'A'+10); } else { fprintf(stderr,"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } p++; } if (*p) { fprintf(stderr,"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } memset(mfsopts.md5pass,0,strlen(mfsopts.md5pass)); } if (mfsopts.delayedinit) { fs_init_master_connection(mfsopts.bindhost,mfsopts.masterhost,mfsopts.masterport,mfsopts.meta,mp,mfsopts.subfolder,(mfsopts.password||mfsopts.md5pass)?md5pass:NULL,mfsopts.donotrememberpassword,1); } else { if (fs_init_master_connection(mfsopts.bindhost,mfsopts.masterhost,mfsopts.masterport,mfsopts.meta,mp,mfsopts.subfolder,(mfsopts.password||mfsopts.md5pass)?md5pass:NULL,mfsopts.donotrememberpassword,0)<0) { return 1; } } memset(md5pass,0,16); if (fg==0) { openlog(STR(APPNAME), LOG_PID | LOG_NDELAY , LOG_DAEMON); } else { #if defined(LOG_PERROR) openlog(STR(APPNAME), LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER); #else openlog(STR(APPNAME), LOG_PID | LOG_NDELAY, LOG_USER); #endif } i = mfsopts.nofile; while (1) { rls.rlim_cur = i; rls.rlim_max = i; if (setrlimit(RLIMIT_NOFILE,&rls)<0) { i /= 2; if (i<1000) { break; } } else { break; } } if (i != (int)(mfsopts.nofile)) { fprintf(stderr,"can't set open file limit to %d\n",mfsopts.nofile); if (i>=1000) { fprintf(stderr,"open file limit set to: %d\n",i); } } setpriority(PRIO_PROCESS,getpid(),mfsopts.nice); #ifdef MFS_USE_MEMLOCK if (mfsopts.memlock) { rls.rlim_cur = RLIM_INFINITY; rls.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_MEMLOCK,&rls)<0) { mfsopts.memlock=0; } } #endif piped[0] = piped[1] = -1; if (fg==0) { if (pipe(piped)<0) { fprintf(stderr,"pipe error\n"); return 1; } err = fork(); if (err<0) { fprintf(stderr,"fork error\n"); return 1; } else if (err>0) { close(piped[1]); err = read(piped[0],&s,1); if (err==0) { s=1; } return s; } close(piped[0]); s=1; } #ifdef MFS_USE_MEMLOCK if (mfsopts.memlock) { if (mlockall(MCL_CURRENT|MCL_FUTURE)==0) { syslog(LOG_NOTICE,"process memory was successfully locked in RAM"); } } #endif /* glibc malloc tuning */ #ifdef MFS_USE_MALLOPT if (mfsopts.limitarenas) { if (!getenv("MALLOC_ARENA_MAX")) { syslog(LOG_NOTICE,"setting glibc malloc arena max to 8"); mallopt(M_ARENA_MAX, mfsopts.limitarenas); } if (!getenv("MALLOC_ARENA_TEST")) { syslog(LOG_NOTICE,"setting glibc malloc arena test to 1"); mallopt(M_ARENA_TEST, 1); } } else { syslog(LOG_NOTICE,"setting glibc malloc arenas turned off"); } #endif /* glibc malloc tuning */ syslog(LOG_NOTICE,"monotonic clock function: %s",monotonic_method()); syslog(LOG_NOTICE,"monotonic clock speed: %"PRIu32" ops / 10 mili seconds",monotonic_speed()); conncache_init(200); chunkloc_cache_init(); symlink_cache_init(); negentry_cache_init(mfsopts.negentrycacheto); // dir_cache_init(); fs_init_threads(mfsopts.ioretries); if (masterproxy_init(mfsopts.proxyhost)<0) { fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } // fs_term(); // negentry_cache_term(); // symlink_cache_term(); // chunkloc_cache_term(); // return 1; if (mfsopts.meta==0) { csdb_init(); delay_init(); read_data_init(mfsopts.readaheadsize*1024*1024,mfsopts.readaheadleng,mfsopts.readaheadtrigger,mfsopts.ioretries); write_data_init(mfsopts.writecachesize*1024*1024,mfsopts.ioretries); } ch = fuse_mount(mp, args); if (ch==NULL) { fprintf(stderr,"error in fuse_mount\n"); if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } if (mfsopts.meta) { mfs_meta_init(mfsopts.debug,mfsopts.entrycacheto,mfsopts.attrcacheto); se = fuse_lowlevel_new(args, &mfs_meta_oper, sizeof(mfs_meta_oper), (void*)piped); } else { mfs_init(mfsopts.debug,mfsopts.keepcache,mfsopts.direntrycacheto,mfsopts.entrycacheto,mfsopts.attrcacheto,mfsopts.xattrcacheto,mfsopts.groupscacheto,mfsopts.mkdircopysgid,mfsopts.sugidclearmode,1,mfsopts.fsyncbeforeclose,mfsopts.noxattrs,mfsopts.noposixlocks,mfsopts.nobsdlocks); //mfsopts.xattraclsupport); se = fuse_lowlevel_new(args, &mfs_oper, sizeof(mfs_oper), (void*)piped); } if (se==NULL) { fuse_unmount(mp,ch); fprintf(stderr,"error in fuse_lowlevel_new\n"); portable_usleep(100000); // time for print other error messages by FUSE if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } // fprintf(stderr,"check\n"); fuse_session_add_chan(se, ch); if (fuse_set_signal_handlers(se)<0) { fprintf(stderr,"error in fuse_set_signal_handlers\n"); fuse_session_remove_chan(ch); fuse_session_destroy(se); fuse_unmount(mp,ch); if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } if (mfsopts.debug==0 && fg==0) { setsid(); setpgid(0,getpid()); if ((i = open("/dev/null", O_RDWR, 0)) != -1) { (void)dup2(i, STDIN_FILENO); (void)dup2(i, STDOUT_FILENO); (void)dup2(i, STDERR_FILENO); if (i>2) close (i); } } if (mt) { err = fuse_session_loop_mt(se); } else { err = fuse_session_loop(se); } if (err) { if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { syslog(LOG_ERR,"pipe write error: %s",strerr(errno)); } close(piped[1]); } } fuse_remove_signal_handlers(se); fuse_session_remove_chan(ch); fuse_session_destroy(se); fuse_unmount(mp,ch); if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return err ? 1 : 0; }
int copy_main (int argc, char **argv) { char source_a[PATH_MAX], source_b[PATH_MAX]; char dest_a[PATH_MAX], dest_b[PATH_MAX]; char *tmp; struct backup_info *info_b, *info_r; int opt, loop, thresh = 0, threshopt = 0; unsigned int varsize = 0, swapsize = 0; unsigned int bflags = BF_BACKUPVAR, rflags = 0; int quiet = 0; int bswap = 0; int expand = 0; int expandscale = 2; tivo_partition_direct (); while ((opt = getopt (argc, argv, "hqf:L:tTaspxr:v:S:lbBzE")) > 0) { switch (opt) { case 'q': quiet++; break; case 's': bflags |= BF_SHRINK; break; case 'E': bflags |= BF_TRUNCATED; break; case 'f': if (threshopt) { fprintf (stderr, "%s: -f and -%c cannot be used together\n", argv[0], threshopt); return 1; } threshopt = loop; thresh = strtoul (optarg, &tmp, 10); if (*tmp) { fprintf (stderr, "%s: Non integer argument to -f\n", argv[0]); return 1; } break; case 'L': if (threshopt) { fprintf (stderr, "%s: -l and -%c cannot be used together\n", argv[0], threshopt); return 1; } threshopt = loop; thresh = strtoul (optarg, &tmp, 10); thresh *= 1024 * 2; bflags |= BF_THRESHSIZE; if (*tmp) { fprintf (stderr, "%s: Non integer argument to -L\n", argv[0]); return 1; } break; case 't': bflags |= BF_THRESHTOT; break; case 'T': bflags |= BF_STREAMTOT; break; case 'a': if (threshopt) { fprintf (stderr, "%s: -a and -%c cannot be used together\n", argv[0], threshopt); return 1; } threshopt = loop; thresh = ~0; break; case 'v': bflags &= ~BF_BACKUPVAR; varsize = strtoul (optarg, &tmp, 10); varsize *= 1024 * 2; if (tmp && *tmp) { fprintf (stderr, "%s: Integer argument expected for -v.\n", argv[0]); return 1; } break; case 'S': swapsize = strtoul (optarg, &tmp, 10); swapsize *= 1024 * 2; if (tmp && *tmp) { fprintf (stderr, "%s: Integer argument expected for -s.\n", argv[0]); return 1; } break; case 'z': rflags |= RF_ZEROPART; break; case 'b': if (bswap != 0) { fprintf (stderr, "%s: Only one byte swapping option (-b/-B) allowed.\n", argv[0]); return 1; } bswap = -1; break; case 'B': if (bswap != 0) { fprintf (stderr, "%s: Only one byte swapping option (-b/-B) allowed.\n", argv[0]); return 1; } bswap = 1; break; case 'p': rflags |= RF_BALANCE; break; case 'l': rflags |= RF_NOFILL; break; case 'x': expand = 1; break; case 'r': expandscale = strtoul (optarg, &tmp, 10); if (tmp && *tmp) { fprintf (stderr, "%s: Integer argument expected for -r.\n", argv[0]); return 1; } if (expandscale < 0 || expandscale > 4) { fprintf (stderr, "%s: Scale value for -r must be in the range 0 to 4.\n", argv[0]); return 1; } break; default: copy_usage (argv[0]); return 1; } } // Split out the drive names source_a[0] = 0; source_b[0] = 0; dest_a[0] = 0; dest_b[0] = 0; if (argc - optind < 4) { if (optind < argc) { get_drives (argv[optind++], source_a, source_b); } if (optind < argc) { get_drives (argv[optind++], dest_a, dest_b); } } else { // Special case for convenience - 2 source and 2 target named strcpy (source_a, argv[optind++]); strcpy (source_b, argv[optind++]); strcpy (dest_a, argv[optind++]); strcpy (dest_b, argv[optind++]); } if (optind < argc || !*source_a || !*dest_a) { copy_usage (argv[0]); return 1; } if (expand > 0) rflags |= RF_NOFILL; info_b = init_backup (source_a, source_b, bflags); // Try to continue anyway despite error. if (bflags & BF_TRUNCATED && backup_has_error (info_b)) { backup_perror (info_b, "WARNING"); fprintf (stderr, "Attempting copy anyway\n"); backup_check_truncated_volume (info_b); if (info_b && backup_has_error (info_b)) { backup_perror (info_b, "Copy source"); return 1; } } if (info_b && backup_has_error (info_b)) { backup_perror (info_b, "Copy source"); fprintf (stderr, "To attempt copy anyway, try again with -E. -s is implied by -E.\n"); return 1; } info_r = init_restore (rflags); if (info_r && restore_has_error (info_r)) { restore_perror (info_r, "Copy target"); return 1; } if (!info_b || !info_r) { fprintf (stderr, "%s: Copy failed to start. Make sure you specified the right\ndevices, and that the drives are not locked.\n", argv[0]); return 1; } else { unsigned starttime; char buf[BUFSIZE]; unsigned int curcount = 0; int nread, nwrit; if (threshopt) backup_set_thresh (info_b, thresh); if (varsize) restore_set_varsize (info_r, varsize); if (swapsize) restore_set_swapsize (info_r, swapsize); if (bswap) restore_set_bswap (info_r, bswap); if (quiet < 2) fprintf (stderr, "Scanning source drive. Please wait a moment.\n"); if (backup_start (info_b) < 0) { if (backup_has_error (info_b)) backup_perror (info_b, "Copy source"); else fprintf (stderr, "Copy source failed.\n"); return 1; } // Fill the buffer up to start. Restore needs some information to bootstrap // the process. while (curcount < BUFSIZE && (nread = backup_read (info_b, buf, BUFSIZE - curcount)) > 0) { curcount += nread; } if (curcount < BUFSIZE) { if (backup_has_error (info_b)) backup_perror (info_b, "Copy source"); else fprintf (stderr, "Copy source failed.\n"); return 1; } nread = curcount; nwrit = restore_write (info_r, buf, nread); if (nwrit < 0) { if (restore_has_error (info_r)) restore_perror (info_r, "Copy target"); else fprintf (stderr, "Copy target failed.\n"); return 1; } if (restore_trydev (info_r, dest_a, dest_b) < 0) { if (restore_has_error (info_r)) restore_perror (info_r, "Copy target"); else fprintf (stderr, "Copy target failed.\n"); return 1; } if (restore_start (info_r) < 0) { if (restore_has_error (info_r)) restore_perror (info_r, "Copy target"); else fprintf (stderr, "Copy target failed.\n"); return 1; } if (restore_write (info_r, buf + nwrit, nread - nwrit) != nread - nwrit) { if (restore_has_error (info_r)) restore_perror (info_r, "Copy target"); else fprintf (stderr, "Copy target failed.\n"); return 1; } starttime = time (NULL); fprintf (stderr, "Starting copy\nSize: %d megabytes\n", info_r->nsectors / 2048); while ((curcount = backup_read (info_b, buf, BUFSIZE)) > 0) { unsigned int prcnt, compr; if (restore_write (info_r, buf, curcount) != curcount) { if (quiet < 1) fprintf (stderr, "\n"); if (restore_has_error (info_r)) restore_perror (info_r, "Copy source"); else fprintf (stderr, "Copy source failed.\n"); return 1; } prcnt = get_percent (info_r->cursector, info_r->nsectors); if (quiet < 1) { unsigned timedelta = time(NULL) - starttime; fprintf (stderr, "\rCopying %d of %d mb (%d.%02d%%)", info_r->cursector / 2048, info_r->nsectors / 2048, prcnt / 100, prcnt % 100); if (prcnt > 100 && timedelta > 15) { unsigned ETA = timedelta * (10000 - prcnt) / prcnt; fprintf (stderr, " %d mb/sec (ETA %d:%02d:%02d)", info_r->cursector / timedelta / 2048, ETA / 3600, ETA / 60 % 60, ETA % 60); } } } if (quiet < 1) fprintf (stderr, "\n"); if (backup_has_error (info_b)) { backup_perror (info_b, "Copy source"); return 1; } if (restore_has_error (info_r)) { restore_perror (info_r, "Copy target"); return 1; } } if (backup_finish (info_b) < 0) { if (backup_has_error (info_b)) backup_perror (info_b, "Copy source"); else fprintf (stderr, "Copy source failed.\n"); return 1; } if (info_b->back_flags & BF_TRUNCATED) { fprintf (stderr, "***WARNING***\nCopy was made of an incomplete volume. While the copy succeeded,\nit is possible there was some required data missing. Verify your copy.\n"); } if (quiet < 2) fprintf (stderr, "Cleaning up target. Please wait a moment.\n"); if (restore_finish (info_r) < 0) { if (restore_has_error (info_r)) restore_perror (info_r, "Copy target"); else fprintf (stderr, "Copy target failed.\n"); return 1; } if (quiet < 2) fprintf (stderr, "Copy done!\n"); if (expand > 0) { int blocksize = 0x800; struct mfs_handle *mfshnd; expand = 0; mfshnd = mfs_init (dest_a, dest_b, O_RDWR); if (!mfshnd) { fprintf (stderr, "Drive expansion failed.\n"); return 1; } if (mfs_has_error (mfshnd)) { mfs_perror (mfshnd, "Target expand"); return 1; } while (expandscale-- > 0) blocksize *= 2; if (tivo_partition_largest_free (dest_a) > 1024 * 1024 * 2) { if (expand_drive (mfshnd, "/dev/hda", dest_a, blocksize) < 0) { if (mfs_has_error (mfshnd)) mfs_perror (mfshnd, "Expand drive A"); else fprintf (stderr, "Drive A expansion failed.\n"); return 1; } expand++; } if (dest_b[0] && tivo_partition_largest_free (dest_b) > 1024 * 1024 * 2) { if (expand_drive (mfshnd, "/dev/hdb", dest_b, blocksize) < 0) { if (mfs_has_error (mfshnd)) mfs_perror (mfshnd, "Expand drive B"); else fprintf (stderr, "Drive B expansion failed.\n"); return 1; } expand++; } if (!expand) { fprintf (stderr, "Not enough extra space to expand on A drive%s.\n", dest_b[0]? " or B drive": ""); } } return 0; }