xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/bb/fetch2/sftp.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun"""
2*4882a593SmuzhiyunBitBake SFTP Fetch implementation
3*4882a593Smuzhiyun
4*4882a593SmuzhiyunClass for fetching files via SFTP. It tries to adhere to the (now
5*4882a593Smuzhiyunexpired) IETF Internet Draft for "Uniform Resource Identifier (URI)
6*4882a593SmuzhiyunScheme for Secure File Transfer Protocol (SFTP) and Secure Shell
7*4882a593Smuzhiyun(SSH)" (SECSH URI).
8*4882a593Smuzhiyun
9*4882a593SmuzhiyunIt uses SFTP (as to adhere to the SECSH URI specification). It only
10*4882a593Smuzhiyunsupports key based authentication, not password. This class, unlike
11*4882a593Smuzhiyunthe SSH fetcher, does not support fetching a directory tree from the
12*4882a593Smuzhiyunremote.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun  http://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04
15*4882a593Smuzhiyun  https://www.iana.org/assignments/uri-schemes/prov/sftp
16*4882a593Smuzhiyun  https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13
17*4882a593Smuzhiyun
18*4882a593SmuzhiyunPlease note that '/' is used as host path seperator, and not ":"
19*4882a593Smuzhiyunas you may be used to from the scp/sftp commands. You can use a
20*4882a593Smuzhiyun~ (tilde) to specify a path relative to your home directory.
21*4882a593Smuzhiyun(The /~user/ syntax, for specyfing a path relative to another
22*4882a593Smuzhiyunuser's home directory is not supported.) Note that the tilde must
23*4882a593Smuzhiyunstill follow the host path seperator ("/"). See exampels below.
24*4882a593Smuzhiyun
25*4882a593SmuzhiyunExample SRC_URIs:
26*4882a593Smuzhiyun
27*4882a593SmuzhiyunSRC_URI = "sftp://host.example.com/dir/path.file.txt"
28*4882a593Smuzhiyun
29*4882a593SmuzhiyunA path relative to your home directory.
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunSRC_URI = "sftp://host.example.com/~/dir/path.file.txt"
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunYou can also specify a username (specyfing password in the
34*4882a593SmuzhiyunURI is not supported, use SSH keys to authenticate):
35*4882a593Smuzhiyun
36*4882a593SmuzhiyunSRC_URI = "sftp://user@host.example.com/dir/path.file.txt"
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun"""
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun# Copyright (C) 2013, Olof Johansson <olof.johansson@axis.com>
41*4882a593Smuzhiyun#
42*4882a593Smuzhiyun# Based in part on bb.fetch2.wget:
43*4882a593Smuzhiyun#    Copyright (C) 2003, 2004  Chris Larson
44*4882a593Smuzhiyun#
45*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
46*4882a593Smuzhiyun#
47*4882a593Smuzhiyun# Based on functions from the base bb module, Copyright 2003 Holger Schurig
48*4882a593Smuzhiyun
49*4882a593Smuzhiyunimport os
50*4882a593Smuzhiyunimport bb
51*4882a593Smuzhiyunimport urllib.request, urllib.parse, urllib.error
52*4882a593Smuzhiyunfrom bb.fetch2 import URI
53*4882a593Smuzhiyunfrom bb.fetch2 import FetchMethod
54*4882a593Smuzhiyunfrom bb.fetch2 import runfetchcmd
55*4882a593Smuzhiyun
56*4882a593Smuzhiyunclass SFTP(FetchMethod):
57*4882a593Smuzhiyun    """Class to fetch urls via 'sftp'"""
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun    def supports(self, ud, d):
60*4882a593Smuzhiyun        """
61*4882a593Smuzhiyun        Check to see if a given url can be fetched with sftp.
62*4882a593Smuzhiyun        """
63*4882a593Smuzhiyun        return ud.type in ['sftp']
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun    def recommends_checksum(self, urldata):
66*4882a593Smuzhiyun        return True
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun    def urldata_init(self, ud, d):
69*4882a593Smuzhiyun        if 'protocol' in ud.parm and ud.parm['protocol'] == 'git':
70*4882a593Smuzhiyun            raise bb.fetch2.ParameterError(
71*4882a593Smuzhiyun                "Invalid protocol - if you wish to fetch from a " +
72*4882a593Smuzhiyun                "git repository using ssh, you need to use the " +
73*4882a593Smuzhiyun                "git:// prefix with protocol=ssh", ud.url)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun        if 'downloadfilename' in ud.parm:
76*4882a593Smuzhiyun            ud.basename = ud.parm['downloadfilename']
77*4882a593Smuzhiyun        else:
78*4882a593Smuzhiyun            ud.basename = os.path.basename(ud.path)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun        ud.localfile = d.expand(urllib.parse.unquote(ud.basename))
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun    def download(self, ud, d):
83*4882a593Smuzhiyun        """Fetch urls"""
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun        urlo = URI(ud.url)
86*4882a593Smuzhiyun        basecmd = 'sftp -oBatchMode=yes'
87*4882a593Smuzhiyun        port = ''
88*4882a593Smuzhiyun        if urlo.port:
89*4882a593Smuzhiyun            port = '-P %d' % urlo.port
90*4882a593Smuzhiyun            urlo.port = None
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun        dldir = d.getVar('DL_DIR')
93*4882a593Smuzhiyun        lpath = os.path.join(dldir, ud.localfile)
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun        user = ''
96*4882a593Smuzhiyun        if urlo.userinfo:
97*4882a593Smuzhiyun            user = urlo.userinfo + '@'
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun        path = urlo.path
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun        # Supoprt URIs relative to the user's home directory, with
102*4882a593Smuzhiyun        # the tilde syntax. (E.g. <sftp://example.com/~/foo.diff>).
103*4882a593Smuzhiyun        if path[:3] == '/~/':
104*4882a593Smuzhiyun            path = path[3:]
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun        remote = '%s%s:%s' % (user, urlo.hostname, path)
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun        cmd = '%s %s %s %s' % (basecmd, port, remote, lpath)
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun        bb.fetch2.check_network_access(d, cmd, ud.url)
111*4882a593Smuzhiyun        runfetchcmd(cmd, d)
112*4882a593Smuzhiyun        return True
113