/usr/share/doc/libssh-doc/html/libssh_tutor_scp.html is in libssh-doc 0.6.1-0ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.6"/>
<title>libssh: Chapter 6: The SCP subsystem</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">libssh
 <span id="projectnumber">0.6.1</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.6 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li class="current"><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Data Structures</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="index.html">index</a></li><li class="navelem"><a class="el" href="libssh_tutorial.html">The Tutorial</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Chapter 6: The SCP subsystem </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="scp_subsystem"></a>
The SCP subsystem</h1>
<p>The SCP subsystem has far less functionnality than the SFTP subsystem. However, if you only need to copy files from and to the remote system, it does its job.</p>
<h2><a class="anchor" id="scp_session"></a>
Opening and closing a SCP session</h2>
<p>Like in the SFTP subsystem, you don't handle the SSH channels directly. Instead, you open a "SCP session".</p>
<p>When you open your SCP session, you have to choose between read or write mode. You can't do both in the same session. So you specify either SSH_SCP_READ or SSH_SCP_WRITE as the second parameter of function <a class="el" href="group__libssh__scp.html#ga9fcd39a2bb6438e39cf19ff859dc2f2e" title="Create a new scp session. ">ssh_scp_new()</a>.</p>
<p>Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE. When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate the behaviour of "scp -r" command in your program, no matter it is for reading or for writing.</p>
<p>Once your session is created, you initialize it with <a class="el" href="group__libssh__scp.html#ga1db56dcb9dee01dd0b679b3b11151110" title="Initialize the scp channel. ">ssh_scp_init()</a>. When you have finished transferring files, you terminate the SCP connection with <a class="el" href="group__libssh__scp.html#ga14d31059dcf6fb2325fb960da8e4474e" title="Close the scp channel. ">ssh_scp_close()</a>. Finally, you can dispose the SCP connection with <a class="el" href="group__libssh__scp.html#gac29000cdb07c74d54251fbd838c0c661" title="Free a scp context. ">ssh_scp_free()</a>.</p>
<p>The example below does the maintenance work to open a SCP connection for writing in recursive mode:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> scp_write(ssh_session session)</div>
<div class="line">{</div>
<div class="line"> ssh_scp scp;</div>
<div class="line"> <span class="keywordtype">int</span> rc;</div>
<div class="line"></div>
<div class="line"> scp = <a class="code" href="group__libssh__scp.html#ga9fcd39a2bb6438e39cf19ff859dc2f2e">ssh_scp_new</a></div>
<div class="line"> (session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, <span class="stringliteral">"."</span>);</div>
<div class="line"> <span class="keywordflow">if</span> (scp == NULL)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error allocating scp session: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> SSH_ERROR;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#ga1db56dcb9dee01dd0b679b3b11151110">ssh_scp_init</a>(scp);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_OK)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error initializing scp session: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <a class="code" href="group__libssh__scp.html#gac29000cdb07c74d54251fbd838c0c661">ssh_scp_free</a>(scp);</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> ...</div>
<div class="line"></div>
<div class="line"> <a class="code" href="group__libssh__scp.html#ga14d31059dcf6fb2325fb960da8e4474e">ssh_scp_close</a>(scp);</div>
<div class="line"> <a class="code" href="group__libssh__scp.html#gac29000cdb07c74d54251fbd838c0c661">ssh_scp_free</a>(scp);</div>
<div class="line"> <span class="keywordflow">return</span> SSH_OK;</div>
<div class="line">}</div>
</div><!-- fragment --><p>The example below shows how to open a connection to read a single file:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> scp_read(ssh_session session)</div>
<div class="line">{</div>
<div class="line"> ssh_scp scp;</div>
<div class="line"> <span class="keywordtype">int</span> rc;</div>
<div class="line"></div>
<div class="line"> scp = <a class="code" href="group__libssh__scp.html#ga9fcd39a2bb6438e39cf19ff859dc2f2e">ssh_scp_new</a></div>
<div class="line"> (session, SSH_SCP_READ, <span class="stringliteral">"helloworld/helloworld.txt"</span>);</div>
<div class="line"> <span class="keywordflow">if</span> (scp == NULL)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error allocating scp session: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> SSH_ERROR;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#ga1db56dcb9dee01dd0b679b3b11151110">ssh_scp_init</a>(scp);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_OK)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error initializing scp session: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <a class="code" href="group__libssh__scp.html#gac29000cdb07c74d54251fbd838c0c661">ssh_scp_free</a>(scp);</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> ...</div>
<div class="line"></div>
<div class="line"> <a class="code" href="group__libssh__scp.html#ga14d31059dcf6fb2325fb960da8e4474e">ssh_scp_close</a>(scp);</div>
<div class="line"> <a class="code" href="group__libssh__scp.html#gac29000cdb07c74d54251fbd838c0c661">ssh_scp_free</a>(scp);</div>
<div class="line"> <span class="keywordflow">return</span> SSH_OK;</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="scp_write"></a>
Creating files and directories</h2>
<p>You create directories with <a class="el" href="group__libssh__scp.html#gaa584f03d4e3d582ac10a3a19818ec56d" title="Create a directory in a scp in sink mode. ">ssh_scp_push_directory()</a>. In recursive mode, you are placed in this directory once it is created. If the directory already exists and if you are in recursive mode, you simply enter that directory.</p>
<p>Creating files is done in two steps. First, you prepare the writing with <a class="el" href="group__libssh__scp.html#ga544f4b9c525071910110ada94148adc6" title="Initialize the sending of a file to a scp in sink mode. ">ssh_scp_push_file()</a>. Then, you write the data with <a class="el" href="group__libssh__scp.html#ga11f48e2cf62bcec20d9232ed3ca41752" title="Write into a remote scp file. ">ssh_scp_write()</a>. The length of the data to write must be identical between both function calls. There's no need to "open" nor "close" the file, this is done automatically on the remote end. If the file already exists, it is overwritten and truncated.</p>
<p>The following example creates a new directory named "helloworld/", then creates a file named "helloworld.txt" in that directory:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> scp_helloworld(ssh_session session, ssh_scp scp)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">int</span> rc;</div>
<div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *helloworld = <span class="stringliteral">"Hello, world!\n"</span>;</div>
<div class="line"> <span class="keywordtype">int</span> length = strlen(helloworld);</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#gaa584f03d4e3d582ac10a3a19818ec56d">ssh_scp_push_directory</a>(scp, <span class="stringliteral">"helloworld"</span>, S_IRWXU);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_OK)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Can't create remote directory: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#ga544f4b9c525071910110ada94148adc6">ssh_scp_push_file</a></div>
<div class="line"> (scp, <span class="stringliteral">"helloworld.txt"</span>, length, S_IRUSR | S_IWUSR);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_OK)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Can't open remote file: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#ga11f48e2cf62bcec20d9232ed3ca41752">ssh_scp_write</a>(scp, helloworld, length);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_OK)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Can't write to remote file: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> <span class="keywordflow">return</span> SSH_OK;</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="scp_recursive_write"></a>
Copying full directory trees to the remote server</h2>
<p>Let's say you want to copy the following tree of files to the remote site:</p>
<pre class="fragment"> +-- file1
+-- B --+
| +-- file2
-- A --+
| +-- file3
+-- C --+
+-- file4
</pre><p>You would do it that way:</p>
<ul>
<li>open the session in recursive mode</li>
<li>enter directory A</li>
<li>enter its subdirectory B</li>
<li>create file1 in B</li>
<li>create file2 in B</li>
<li>leave directory B</li>
<li>enter subdirectory C</li>
<li>create file3 in C</li>
<li>create file4 in C</li>
<li>leave directory C</li>
<li>leave directory A</li>
</ul>
<p>To leave a directory, call <a class="el" href="group__libssh__scp.html#ga2ca698c1e49612c083d9f8a72df52188" title="Leave a directory. ">ssh_scp_leave_directory()</a>.</p>
<h2><a class="anchor" id="scp_read"></a>
Reading files and directories</h2>
<p>To receive files, you pull requests from the other side with <a class="el" href="group__libssh__scp.html#gaba59cd8cc77d219cac93f865445c6e47" title="Wait for a scp request (file, directory). ">ssh_scp_pull_request()</a>. If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for the reception. You can get the size of the data to receive with <a class="el" href="group__libssh__scp.html#ga8b6f736a5b5af73cf59c7825d7e61966" title="Get the size of the file being pushed from the other party. ">ssh_scp_request_get_size()</a> and allocate a buffer accordingly. When you are ready, you accept the request with <a class="el" href="group__libssh__scp.html#gad3bb38b15f02597cc1e155c526a51e51" title="Accepts transfer of a file or creation of a directory coming from the remote party. ">ssh_scp_accept_request()</a>, then read the data with <a class="el" href="group__libssh__scp.html#ga10bf627407959b51a7c39b37e8d46460" title="Read from a remote scp file. ">ssh_scp_read()</a>.</p>
<p>The following example receives a single file. The name of the file to receive has been given earlier, when the scp session was opened:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> scp_receive(ssh_session session, ssh_scp scp)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">int</span> rc;</div>
<div class="line"> <span class="keywordtype">int</span> size, mode;</div>
<div class="line"> <span class="keywordtype">char</span> *filename, *buffer;</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#gaba59cd8cc77d219cac93f865445c6e47">ssh_scp_pull_request</a>(scp);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_SCP_REQUEST_NEWFILE)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error receiving information about file: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> SSH_ERROR;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> size = <a class="code" href="group__libssh__scp.html#ga8b6f736a5b5af73cf59c7825d7e61966">ssh_scp_request_get_size</a>(scp);</div>
<div class="line"> filename = strdup(<a class="code" href="group__libssh__scp.html#gab41ede14208dea4bbd3600077008ccf3">ssh_scp_request_get_filename</a>(scp));</div>
<div class="line"> mode = <a class="code" href="group__libssh__scp.html#ga3386eb6df0cc620e74a039974c6280d4">ssh_scp_request_get_permissions</a>(scp);</div>
<div class="line"> printf(<span class="stringliteral">"Receiving file %s, size %d, permisssions 0%o\n"</span>,</div>
<div class="line"> filename, size, mode);</div>
<div class="line"> free(filename);</div>
<div class="line"></div>
<div class="line"> buffer = malloc(size);</div>
<div class="line"> <span class="keywordflow">if</span> (buffer == NULL)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Memory allocation error\n"</span>);</div>
<div class="line"> <span class="keywordflow">return</span> SSH_ERROR;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> <a class="code" href="group__libssh__scp.html#gad3bb38b15f02597cc1e155c526a51e51">ssh_scp_accept_request</a>(scp);</div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#ga10bf627407959b51a7c39b37e8d46460">ssh_scp_read</a>(scp, buffer, size);</div>
<div class="line"> <span class="keywordflow">if</span> (rc == SSH_ERROR)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Error receiving file data: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> free(buffer);</div>
<div class="line"> <span class="keywordflow">return</span> rc;</div>
<div class="line"> }</div>
<div class="line"> printf(<span class="stringliteral">"Done\n"</span>);</div>
<div class="line"></div>
<div class="line"> write(1, buffer, size);</div>
<div class="line"> free(buffer);</div>
<div class="line"></div>
<div class="line"> rc = <a class="code" href="group__libssh__scp.html#gaba59cd8cc77d219cac93f865445c6e47">ssh_scp_pull_request</a>(scp);</div>
<div class="line"> <span class="keywordflow">if</span> (rc != SSH_SCP_REQUEST_EOF)</div>
<div class="line"> {</div>
<div class="line"> fprintf(stderr, <span class="stringliteral">"Unexpected request: %s\n"</span>,</div>
<div class="line"> <a class="code" href="group__libssh__error.html#ga9241586665bf21f823806473fc386258">ssh_get_error</a>(session));</div>
<div class="line"> <span class="keywordflow">return</span> SSH_ERROR;</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> <span class="keywordflow">return</span> SSH_OK;</div>
<div class="line">}</div>
</div><!-- fragment --><p>In this example, since we just requested a single file, we expect ssh_scp_request() to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a naive approach; for example, the remote server might send a warning as well (return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive reception program would receive the requests in a loop and analyze them carefully until SSH_SCP_REQUEST_EOF has been received.</p>
<h2><a class="anchor" id="scp_recursive_read"></a>
Receiving full directory trees from the remote server</h2>
<p>If you opened the SCP session in recursive mode, the remote end will be telling you when to change directory.</p>
<p>In that case, when <a class="el" href="group__libssh__scp.html#gaba59cd8cc77d219cac93f865445c6e47" title="Wait for a scp request (file, directory). ">ssh_scp_pull_request()</a> answers SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if it does not exist yet) and enter it. When <a class="el" href="group__libssh__scp.html#gaba59cd8cc77d219cac93f865445c6e47" title="Wait for a scp request (file, directory). ">ssh_scp_pull_request()</a> answers SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory. </p>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.6
</small></address>
</body>
</html>
|