1''' 2BitBake 'Fetch' implementations 3 4This implementation is for Secure Shell (SSH), and attempts to comply with the 5IETF secsh internet draft: 6 http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/ 7 8 Currently does not support the sftp parameters, as this uses scp 9 Also does not support the 'fingerprint' connection parameter. 10 11 Please note that '/' is used as host, path separator not ':' as you may 12 be used to, also '~' can be used to specify user HOME, but again after '/' 13 14 Example SRC_URI: 15 SRC_URI = "ssh://user@host.example.com/dir/path/file.txt" 16 SRC_URI = "ssh://user@host.example.com/~/file.txt" 17''' 18 19# Copyright (C) 2006 OpenedHand Ltd. 20# 21# 22# Based in part on svk.py: 23# Copyright (C) 2006 Holger Hans Peter Freyther 24# Based on svn.py: 25# Copyright (C) 2003, 2004 Chris Larson 26# Based on functions from the base bb module: 27# Copyright 2003 Holger Schurig 28# 29# 30# SPDX-License-Identifier: GPL-2.0-only 31# 32 33import re, os 34from bb.fetch2 import check_network_access, FetchMethod, ParameterError, runfetchcmd 35 36 37__pattern__ = re.compile(r''' 38 \s* # Skip leading whitespace 39 ssh:// # scheme 40 ( # Optional username/password block 41 (?P<user>\S+) # username 42 (:(?P<pass>\S+))? # colon followed by the password (optional) 43 )? 44 (?P<cparam>(;[^;]+)*)? # connection parameters block (optional) 45 @ 46 (?P<host>\S+?) # non-greedy match of the host 47 (:(?P<port>[0-9]+))? # colon followed by the port (optional) 48 / 49 (?P<path>[^;]+) # path on the remote system, may be absolute or relative, 50 # and may include the use of '~' to reference the remote home 51 # directory 52 (?P<sparam>(;[^;]+)*)? # parameters block (optional) 53 $ 54''', re.VERBOSE) 55 56class SSH(FetchMethod): 57 '''Class to fetch a module or modules via Secure Shell''' 58 59 def supports(self, urldata, d): 60 return __pattern__.match(urldata.url) is not None 61 62 def supports_checksum(self, urldata): 63 return False 64 65 def urldata_init(self, urldata, d): 66 if 'protocol' in urldata.parm and urldata.parm['protocol'] == 'git': 67 raise ParameterError( 68 "Invalid protocol - if you wish to fetch from a git " + 69 "repository using ssh, you need to use " + 70 "git:// prefix with protocol=ssh", urldata.url) 71 m = __pattern__.match(urldata.url) 72 path = m.group('path') 73 host = m.group('host') 74 urldata.localpath = os.path.join(d.getVar('DL_DIR'), 75 os.path.basename(os.path.normpath(path))) 76 77 def download(self, urldata, d): 78 dldir = d.getVar('DL_DIR') 79 80 m = __pattern__.match(urldata.url) 81 path = m.group('path') 82 host = m.group('host') 83 port = m.group('port') 84 user = m.group('user') 85 password = m.group('pass') 86 87 if port: 88 portarg = '-P %s' % port 89 else: 90 portarg = '' 91 92 if user: 93 fr = user 94 if password: 95 fr += ':%s' % password 96 fr += '@%s' % host 97 else: 98 fr = host 99 fr += ':%s' % path 100 101 cmd = 'scp -B -r %s %s %s/' % ( 102 portarg, 103 fr, 104 dldir 105 ) 106 107 check_network_access(d, cmd, urldata.url) 108 109 runfetchcmd(cmd, d) 110 111