o *pa@sdZddlmZddlmZeddlmZddlmZddl m Z ddl Z ddl Z ddl Z ddl Z ddlZddlZzddlmZWneySdd lmZYnwdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZgagadada da!da"da#da$gdZ%ddZ&ddZ'ddZ(ddZ)ddZ*ddZ+dd Z,d!d"Z-d#d$Z.d%d&Z/Gd'd(d(e j0Z1d)d*Z2d+d,Z3d-d.Z4d/d0Z5d1d2Z6d3d4Z7d5d6Z8d7d8Z9d9d:Z:d;d<Z;d=d>Zr$r?er%r%r& check_times  rFcCsd}|}|dvrtj}n<|dvrtj}n4|dvrtj}n,|dvr&tj}n$|dvr.tj}nzt|}|dks;|dkr=d }Wn tyId }Ynw|rQt d |S) NF)rEerror)wwarning)nnotice)iinfo)ddebugr TzVerbosity must be one of: digit [0-9], character [ewnid], or word ['error', 'warning', 'notice', 'info', 'debug']. The default is 4 (Notice). It is strongly recommended that verbosity level is set at 2 (Warning) or higher.) lowerr r"WARNINGNOTICEINFODEBUGint ValueErrorrCrD)r>r$r?failverbr%r%r&check_verbositys.  rZc@steZdZejjdZeejjZeed<e ed<e ed<ejj dZ ejj dZ ejj dZ ejjdZddZdS) DupOption)filetime verbosityr\r]r^)extendc Csn|dkr)|sdSt||r!t||r!t||t||d|dSt|||dStj|||||||dS)Nr_ )hasattrgetattrsetattrrCOption take_action)selfactiondestr$r?valuesparserr%r%r&reszDupOption.take_actionN)__name__ __module__ __qualname__rCrdTYPESr TYPE_CHECKERr@rFrZACTIONS STORE_ACTIONS TYPED_ACTIONSALWAYS_TYPED_ACTIONSrer%r%r%r&r[s       r[c s\ dddddd}ddd d }d d }tjttd }|jddd|jddtdd|jddddd|jddd|jddtdtjd|jddd|jddd tjd!|jd"dd|jd#d$td%d&d'd(d)d*|jd+d$tdd|jd,d$td%d&d'd-d)d*|jd.d'td/d&d$|d0|jd1d'd&|d2|jd3dtd4d&d'd*|jd5d'd&d6d)tjd7|jd8dtd4d&d'fd9d)tjd:|jd;td4d&dd'|d<|jd=d'd&|d2|jd>td?d&d$d'|d<|jd@dAtdAd&d'|d*|jdBdtjdC|jdDd$dEdFdG|jdHd$dIdFdG|jdJd$dKdFdG|jdLd$dMdFdG|jdNdtjdC|jdOdPd'dtddQdRd)dS|jdTdd|jdUddVdWd|jdXddYdWd|jdZdAd[tdAd\|jd]d'd^d_d)d2|jd`dtdd|jdadbtdcdd|jded$td%d&d'dfd)d*|jdgdhdtddi|jdjd'dkdld)d2|jdmdd|jdntdodp|jdqd'td/d&d$|d0|jdrdtd4d&d'd*|jdsd'd&dtd)tjd7|jdudtd4d&d'fdvd)tjd:|jdwtd?d&d$d'|d<|jdxdtdyd&d'fdzd)d*|jd{dtd4d&d'd|d)d*|jd}d'd~d)d|jddtdd|jddtdd|jdddd|jdddd|jdddd|jddd|jddtdd|jddd|jddd|jdd'ddd)d2|jdddd|jddtdd|jddbtdcdd|jddtdd|jddd|jddtdd|jddd|jddd'd|d|jddddAtdAd|jddbtdcdd|jddd|jddd|jddd|jddd|jddd|jddd|jddd|jddd|jddd'tddd)d|jddtdd|jddtdd|jddd|jdddd|jdddd|jddFdd|jddFdd|jdd$ddFdG|jdd$ddFdG|jdd$tdd|jddtdd|jddtdd|jddtdd|jdd$tdƃd|jdtdȃdp|jdtdȃdp|jdtd˃dp|jddd|jdd'ddd)d2|jdd$td%d&d'dd)d*|jddd|jddbtdcdd|jdtdՃdp|jdtd׃dp|jddd|jdddtddi|jddtd܃d|jdd$tdރd'fdd)d|jddd|jddddd&d'dd)d*|jddd'|d|jddddd}|jddd'td|ddd}|jddd'td|d|jdd'dtdddd)dS|jddtd܃d||\}}ddt|DD]} t || } | durt t | | qt j jdkrtt jtrtt jdt _tt jtrtt jdt _tt jtrtt jdt _tt jtrtt jdt _tt jd&d} |r4|dfddtD} t| dkrtd| fnt| dkr+| dn | s4|ddkr>dad} ndkrHdad} ndkrRda d} ndkr^dt _!d} ndkrida"d} ndkrz|d} Wnt#ytdYnwt$%| t _&d} n_dksdkrۈdkrdt _'dkrdt _(z|d} Wnt#ytdYnwt)| t _*t j*dkstdd} ndkrda+n d krda,d} t|| krtd | t|ft-t|D]%}t||tr||.d ||<d ||vr*t/||||<qt|dkr9td nFt|dkrE|d}n:t|dkrzt,rnt01|dr_t01|dsdtd|d|d}}nt2|d|d\}}ntdt j3durt4|t _3t5t6t j7t j3t89tdt j:j;ft89tdt j3f|S(zParse argument listcSs |dkr tdt|dS)Nz!log-fd must be greater than zero.)rCrDr add_fd)fdr%r%r& set_log_fds z)parse_cmdline_options..set_log_fdcSs$|dkr td|t_t|dS)N-z(Dash ('-') not valid for time-separator.)rCrDr time_separatorr')sepr$r%r%r& set_time_seps  z+parse_cmdline_options..set_time_sepcSs2|jdvr t|}n|}tt||fdS)N)stringr\)typerfsdecode select_optsappend)or>additional_argpaddargr%r%r& add_selections  z,parse_cmdline_options..add_selectioncSsdtt|t|fzttj|dddWdSty1t t d|tj j YdSw)NrtzUTF-8)encodingzError opening file %s) rrrr~ select_filesioopenIOErrorr FatalErrorr! ErrorCodecant_open_filelist)rsr0rr%r%r& add_filelists  z+parse_cmdline_options..add_filelistcSstdtjtddS)Nz duplicity %sr)printr versionsysexitrrvrr%r%r& print_versz(parse_cmdline_options..print_vercSs6ttjtj|d}t|dtj|<dS)Nrrt)rfsencoder-rnormcasenormpathr rename)rrrrkeyr%r%r& add_renamesz)parse_cmdline_options..add_rename) option_classusagez--allow-source-mismatch store_true)rgz --archive-dirr\r)r}metavarz--asynchronous-upload store_constrtasync_concurrency)rgconstrhz--compare-dataz --config-dir)r}rhelpz --copy-linksz--current-timerV current_time)r}rhrz --dry-runz --encrypt-keyr| gpg-key-idcallbackcStjj|Sr+)r gpg_profile recipientsrrr%r%r&"z'parse_cmdline_options..)r}rrhrgrz--encrypt-secret-keyringz--encrypt-sign-keycSstjj|t|fSr+)r rrr set_sign_keyrr%r%r&r)z --exclude shell_pattern)rgrrhr}rz--exclude-device-files)rgrhr--exclude-filelistr0z--exclude-filelist-stdincStdttjt|fS)N)rstandard inputrrrrstdinr*rr%r%r&r9 )rgrhrrz--exclude-globbing-filelistc||||t|fSr+r)rrr%r&r? )r}rrhrgrrz--exclude-if-present)rrhr}rgrz--exclude-other-filesystemsz--exclude-regexpregular_expressionz--exclude-older-thanr]z--fail-on-volume)r}rz --file-prefix file_prefixstore)r}rhrgz--file-prefix-manifestfile_prefix_manifestz--file-prefix-archivefile_prefix_archivez--file-prefix-signaturefile_prefix_signaturez --skip-volumez--file-to-restorez-r restore_dircSst|jdt|dS)Nr/)rcrirrstriprr%r%r&rm)rgr}rrhrz--forcez --ftp-passivepassiveftp_connectionz --ftp-regularregularz--full-if-older-thanfull_force_time)r}rhrz--giouse_giocSt|j|jdt|fSNTrcrirhr'rr%r%r&r{z --gpg-binaryz --gpg-optionsr_options)rgrz--hidden-encrypt-keycSrr+)r rhidden_recipientsrrr%r%r&rrz--idr-fakerootfakeroot)rhr}rz--ignore-errors ignore_errorscSs ttd|t|jddfS)NzVRunning in 'ignore errors' mode due to %s; please re-consider if this was not intendedrT)r Warnr!rcrirr%r%r&rs z--imap-full-addressz--imap-mailbox imap_mailbox)rz --include--include-filelistz--include-filelist-stdincSr)N)rrrrr%r%r&rrz--include-globbing-filelistcrr+rrrr%r&rrz--include-regexpz--log-fdfile_descriptorcs|Sr+r%r)rwr%r&rz --log-filecS t|Sr+)r add_filerr%r%r&r z--log-timestampcSstSr+)r,rr%r%r&rs)rgrz--max-blocksizenumberz--namer2z backup name)rhrz--no-encryption store_false encryption)rgrhz--no-compression compressionz--no-print-statisticsprint_statisticsz--null-separatorz --num-retriesz--numeric-ownerz--do-not-restore-ownershipz--old-filenames old_filenamescSrrrrr%r%r&rrz--metadata-sync-modepartial)rr)defaultchoicesz--par2-redundancyz--par2-optionsz--par2-volumesz --progressz--progress-ratez--pydevdz--rename)r}rgnargsrz--restore-timez--timez-tz--rsync-optionsz--s3-european-bucketsz --s3-use-rrsz --s3-use-iaz--s3-use-glacierz--s3-use-deep-archivez--s3-use-onezone-iaz--s3-use-new-stylez--s3-unencrypted-connectionz--s3-multipart-chunk-sizecSst|jd|ddS)Ns3_multipart_chunk_sizercrirr%r%r&r)r)r}rgrrz--s3-multipart-max-procsz--s3-multipart-max-timeoutz--s3-use-multiprocessingz--s3-use-server-side-encryption s3_use_ssez#--s3-use-server-side-kms-encryptions3_use_sse_kmsz--s3-kms-key-id s3_kms_key_idz--s3-kms-grant s3_kms_grantz--s3-region-names3_region_namez--s3-endpoint-urls3_endpoint_urlz--swift-storage-policypolicyz--azure-max-single-put-sizez--azure-max-block-sizez--azure-max-connectionsz--azure-blob-tierzHot|Cool|Archivez --scp-commandcommandz--sftp-commandz --cf-backendzpyrax|cloudfilesz--b2-hide-filesz--short-filenamesshort_filenamescSrrrrr%r%r&rfrz --sign-keycSr=r+)rrr%r%r&rmrz --ssh-askpassz --ssh-optionsz--ssl-cacert-filez/pem formatted bundle of certificate authoritiesz--ssl-cacert-pathz1path to a folder with certificate authority filesz--ssl-no-check-certificatez --tempdirtemprootz --timeoutsecondsz--time-separatorcharcs ||Sr+r%r)r{r%r&rr)r}rrgrz --use-agentz --verbosityz-vr^z[0-9]cSrr+)r setverbosityrr%r%r&rrz-Vz --versionz --mf-purgecSs(t|jd|ddt|jdddS)Nmp_segment_sizermp_setTrrr%r%r& set_mpsizesz)parse_cmdline_options..set_mpsizez--mp-segment-sizecSsHt|jd|ddt|jdds"t|jdttj|jjdSdS)NvolsizerrFr)rcrirbrVr mp_factorrrr%r%r& set_volsizes z*parse_cmdline_options..set_volsizez --volsizez--file-changed file_changedcSst|jd|dS)Nrr)rcrirstriprr%r%r&rsz--backend-retry-delaycSsg|] }|r|ds|qSr! startswith).0xr%r%r& sz)parse_cmdline_options..Nzutf-8rcsg|] }|r|qSr%r)rc)cmdr%r&rrz$command '%s' not unique, could be %srTrrrrrz)Missing time string for remove-older-thanrrzMissing count for z count must be > 0rrzExpected %d args, got %dutf8z://Too few argumentsz Two URLs expected for replicate.zToo many argumentszUsing archive dir: %szUsing backup name: %s) like the following is required @.iam.gserviceaccount.com gdrive:///target-folder/?driveID= (for GOOGLE Shared Drive) gdrive:///target-folder/?myDriveFolderID= (for GOOGLE MyDrive) hsi://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s imap://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s mega://%(user)s[:%(password)s]@%(other_host)s/%(some_dir)s megav2://%(user)s[:%(password)s]@%(other_host)s/%(some_dir)s mf://%(user)s[:%(password)s]@%(other_host)s/%(some_dir)s onedrive://%(some_dir)s pca://%(container_name)s pydrive://%(user)s@%(other_host)s/%(some_dir)s rclone://%(remote)s:/%(some_dir)s rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(relative_path)s rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]//%(absolute_path)s rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]::/%(module)s/%(some_dir)s s3+http://%(bucket_name)s[/%(prefix)s] s3://%(other_host)s[:%(port)s]/%(bucket_name)s[/%(prefix)s] scp://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s ssh://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s swift://%(container_name)s tahoe://%(alias)s/%(directory)s webdav://%(user)s[:%(password)s]@%(other_host)s/%(some_dir)s webdavs://%(user)s[:%(password)s]@%(other_host)s/%(some_dir)s z Commands:a cleanup <%(target_url)s> collection-status <%(target_url)s> full <%(source_dir)s> <%(target_url)s> incr <%(source_dir)s> <%(target_url)s> list-current-files <%(target_url)s> remove-all-but-n-full <%(count)s> <%(target_url)s> remove-all-inc-of-but-n-full <%(count)s> <%(target_url)s> remove-older-than <%(time)s> <%(target_url)s> replicate <%(source_url)s> <%(target_url)s> restore <%(source_url)s> <%(target_dir)s> verify <%(target_url)s> <%(source_dir)s> r)transmsgr%r%r&r:s| !%*/48<@DI   # & rcCsftj|szt|Wn tyYnwt|}|s.tt d|j ftj j |t _dS)z Check archive dir and set globalzFSpecified archive directory '%s' does not exist, or is not a directoryN)r-rexistsmakedirsrPathisdirr rr!r)rbad_archive_dirr r() dirstringr(r%r%r&r%s     r%cCs2td|sttd|ftjj|tj_ dS)z-Set config.sign_key assuming proper key givenz7^(0x)?([0-9A-Fa-f]{8}|[0-9A-Fa-f]{16}|[0-9A-Fa-f]{40})$zaSign key should be an 8, 16 alt. 40 character hex string, like 'AA0E73D2'. Received '%s' instead.N) researchr rr!r bad_sign_keyr rsign_key)rXr%r%r&r!s   rcCs&ttj}|tt|t_dS)zAReturn selection iter starting at filename with arguments appliedN) rSelectr local_path ParseArgsrrset_iterselect)selr%r%r& set_selection*s  r_cCsVt|t|}}|s|std|r|rtd|r!||fS|r'||fStd)z Given exactly two arguments, arg1 and arg2, figure out which one is the backend URL and which one is a local path, and return (local, backend). zOne of the arguments must be an URL. Examples of URL strings are "scp://user@host.net:1234/path" and "file:///usr/local". See the man page for more information.z3Two URLs specified. One argument should be a path.zshould not be reached)r r#rAssertionError)arg1arg2arg1_is_backendarg2_is_backendr%r%r&r$2sr$cCs2t||\}}t|t_||krd|fSd|fS)zFigure out which arg is url, set backend Return value is pair (path_first, path) where is_first is true iff path made from arg1. Nrt)r$r get_backendr )rarbrbendr%r%r& set_backendJs  rgcCstt|}|dkr(|r'|s'tjs'tt d|j ftj j n3|dkr?|s>tt d|j ftj j n|dksI|dksIJ|s[tt d|j ftj j|t_dS) z,Check local directory, set config.local_pathrzDRestore destination directory %s already exists. Will not overwrite.rz"Verify directory %s does not existrincz*Backup source directory %s does not exist.N)rrQ get_canonicalrO isemptydirr forcer rr!r)rrestore_dir_existsverify_dir_doesnt_existbackup_dir_doesnt_existrZ)rglocal_pathnamerZr%r%r&process_local_dir[s2    rpcCsdd}|dvr|tttttjdugdS|dks|dkrCtr%tdntjr,tdt r?|dkrAt t d t d dSdSdS|d ksM|d ksMJt rStd tjr]td|fttjtjtjgdkrotddSdS)zAFinal consistency check, see if something wrong with command linecSs.d}|D]}|r |d7}q|dksJddS)z?Raises error if two or more of the elements of arglist are truerrtz/Invalid syntax, two conflicting modes specifiedNr%)r*rJmr%r%r&assert_only_onevs z*check_consistency..assert_only_one) list-currentrr remove-oldrrrNrrz6full option cannot be used when restoring or verifyingz=incremental option cannot be used when restoring or verifyingzCommand line warning: %szXSelection options --exclude/--include currently work only when backing up,not restoring.rhrz,verify option cannot be used when backing upz*restore option incompatible with %s backuprzJonly one of --s3-use-rrs, --s3-use-ia, and --s3-use-onezone-ia may be used)rrrrr rrrrrr rr!rrsum s3_use_rrs s3_use_ias3_use_onezone_ia)rgrrr%r%r&check_consistencyrs.     rycCstt_t|}tjdurtj}tj|j|j|j|j dt_t t dtjp(dtjj ftt|dkr?t|dksCJdt|dkrtrNd}n"trSd }ntrXd }ntjdur`d }ntjrfd }n tjrld }ntdt|dt_tjst t d|dft jjnNt|dkrtrt|dt_t|dt_d}n3t|d|d\}}|rtrd}n d}nt rd}nd}t!|||dvrt"n t|dkrt#dt$|t %t d||S)zProcess command line, set config, return action action will be "list-current", "collection-status", "cleanup", "remove-old", "restore", "verify", "full", or "inc". N) passphraserXrrzGPG binary is %s, version %sr rtrz*arg count should have been checked alreadyrsrrrtrrrrzBad URL '%s'. Examples of URL strings are "scp://user@host.net:1234/path" and "file:///usr/local". See the man page for more information.rrrhrr)rrhrz!this code should not be reachablez Main action: )&r GPGProfiler rr3 gpg_binaryrzrXrrr Debugr! gpg_versionr import_backendsrrrrrrr rrerrbad_urlr src_backendrgrrrpr_r`ryr') cmdline_listr+srcrgbackupror%r%r&ProcessCommandLinesv          r)=__doc__ __future__rfuturerinstall_aliasesbuiltinsrrrrCr-rUrrrhashlibr ImportErrorr duplicityr r r r r rrrrrrrrrrrrr'r)r*r,r1r6r<r@rFrZrdr[r3rrr%rr_r$rgrpryrr%r%r%r&s|                "cY  '