| 1 |
|
| 2 |
FIles transferred over SHell protocol (V 0.0.2) |
| 3 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 4 |
|
| 5 |
This protocol was designed for transferring files over a remote shell |
| 6 |
connection (rsh and compatibles). It can be as well used for transfers over |
| 7 |
rsh, and there may be other uses. |
| 8 |
|
| 9 |
Client sends requests of following form: |
| 10 |
|
| 11 |
#FISH_COMMAND |
| 12 |
equivalent shell commands, |
| 13 |
which may be multiline |
| 14 |
|
| 15 |
Only fish commands are defined here, shell equivalents are for your |
| 16 |
information only and will probably vary from implementation to |
| 17 |
implementation. Fish commands always have priority: server is |
| 18 |
expected to execute fish command if it understands it. If it does not, |
| 19 |
however, it can try the luck and execute shell command. |
| 20 |
|
| 21 |
Server's reply is multiline, but always ends with |
| 22 |
|
| 23 |
### 000<optional text> |
| 24 |
|
| 25 |
line. ### is prefix to mark this line, 000 is return code. Return |
| 26 |
codes are superset to those used in ftp. |
| 27 |
|
| 28 |
There are few new exit codes defined: |
| 29 |
|
| 30 |
000 don't know; if there were no previous lines, this marks COMPLETE |
| 31 |
success, if they were, it marks failure. |
| 32 |
|
| 33 |
001 don't know; if there were no previous lines, this marks |
| 34 |
PRELIMinary success, if they were, it marks failure |
| 35 |
|
| 36 |
Connecting |
| 37 |
~~~~~~~~~~ |
| 38 |
Client uses "echo FISH:;/bin/sh" as command executed on remote |
| 39 |
machine. This should make it possible for server to distinguish FISH |
| 40 |
connections from normal rsh/ssh. |
| 41 |
|
| 42 |
Commands |
| 43 |
~~~~~~~~ |
| 44 |
#FISH |
| 45 |
echo; start_fish_server; echo '### 200' |
| 46 |
|
| 47 |
This command is sent at the beginning. It marks that client wishes to |
| 48 |
talk via FISH protocol. #VER command must follow. If server |
| 49 |
understands FISH protocol, it has option to put FISH server somewhere |
| 50 |
on system path and name it start_fish_server. |
| 51 |
|
| 52 |
#VER 0.0.2 <feature1> <feature2> <...> |
| 53 |
echo '### 000' |
| 54 |
|
| 55 |
This command is the second one. It sends client version and extensions |
| 56 |
to the server. Server should reply with protocol version to be used, |
| 57 |
and list of extensions accepted. |
| 58 |
|
| 59 |
VER 0.0.0 <feature2> |
| 60 |
### 200 |
| 61 |
|
| 62 |
#PWD |
| 63 |
pwd; echo '### 200' |
| 64 |
|
| 65 |
Server should reply with current directory (in form /abc/def/ghi) |
| 66 |
followed by line indicating success. |
| 67 |
|
| 68 |
#LIST /directory |
| 69 |
ls -lLa $1 | grep '^[^cbt]' | ( while read p x u g s m d y n; do echo "P$p $u.$g |
| 70 |
S$s |
| 71 |
d$m $d $y |
| 72 |
:$n |
| 73 |
"; done ) |
| 74 |
ls -lLa $1 | grep '^[cb]' | ( while read p x u g a i m d y n; do echo "P$p $u.$g |
| 75 |
E$a$i |
| 76 |
dD$m $d $y |
| 77 |
:$n |
| 78 |
"; done ) |
| 79 |
echo '### 200' |
| 80 |
|
| 81 |
This allows client to list directory or get status information about |
| 82 |
single file. Output is in following form (any line except :<filename> |
| 83 |
may be omitted): |
| 84 |
|
| 85 |
P<unix permissions> <owner>.<group> |
| 86 |
S<size> |
| 87 |
d<3-letters month name> <day> <year or HH:MM> |
| 88 |
D<year> <month> <day> <hour> <minute> <second>[.1234] |
| 89 |
E<major-of-device>,<minor> |
| 90 |
:<filename> |
| 91 |
L<filename symlink points to> |
| 92 |
<blank line to separate items> |
| 93 |
|
| 94 |
Unix permissions are of form X--------- where X is type of |
| 95 |
file. Currently, '-' means regular file, 'd' means directory, 'c', 'b' |
| 96 |
means character and block device, 'l' means symbolic link, 'p' means |
| 97 |
FIFO and 's' means socket. |
| 98 |
|
| 99 |
'd' has three fields: month (one of strings Jan Feb Mar Apr May Jun |
| 100 |
Jul Aug Sep Oct Nov Dec), day of month, and third is either single |
| 101 |
number indicating year, or HH:MM field (assume current year in such |
| 102 |
case). As you've probably noticed, this is pretty broken; it is for |
| 103 |
compatibility with ls listing. |
| 104 |
|
| 105 |
#RETR /some/name |
| 106 |
ls -l /some/name | ( read a b c d x e; echo $x ); echo '### 100'; cat /some/name; echo '### 200' |
| 107 |
|
| 108 |
Server sends line with filesize on it, followed by line with ### 100 |
| 109 |
indicating partial success, then it sends binary data (exactly |
| 110 |
filesize bytes) and follows them with (with no preceding newline) ### |
| 111 |
200. |
| 112 |
|
| 113 |
Note that there's no way to abort running RETR command - except |
| 114 |
closing the connection. |
| 115 |
|
| 116 |
#STOR <size> /file/name |
| 117 |
> /file/name; echo '### 001'; ( dd bs=4096 count=<size/4096>; dd bs=<size%4096> count=1 ) 2>/dev/null | ( cat > %s; cat > /dev/null ); echo '### 200' |
| 118 |
|
| 119 |
This command is for storing /file/name, which is exactly size bytes |
| 120 |
big. You probably think I went crazy. Well, I did not: that strange |
| 121 |
cat > /dev/null has purpose to discard any extra data which was not |
| 122 |
written to disk (due to for example out of space condition). |
| 123 |
|
| 124 |
[Why? Imagine uploading file with "rm -rf /" line in it.] |
| 125 |
|
| 126 |
#CWD /somewhere |
| 127 |
cd /somewhere; echo '### 000' |
| 128 |
|
| 129 |
It is specified here, but I'm not sure how wise idea is to use this |
| 130 |
one: it breaks stateless-ness of the protocol. |
| 131 |
|
| 132 |
Following commands should be rather self-explanatory: |
| 133 |
|
| 134 |
#CHMOD 1234 file |
| 135 |
chmod 1234 file; echo '### 000' |
| 136 |
|
| 137 |
#DELE /some/path |
| 138 |
rm -f /some/path; echo '### 000' |
| 139 |
|
| 140 |
#MKD /some/path |
| 141 |
mkdir /some/path; echo '### 000' |
| 142 |
|
| 143 |
#RMD /some/path |
| 144 |
rmdir /some/path; echo '### 000' |
| 145 |
|
| 146 |
#RENAME /path/a /path/b |
| 147 |
mv /path/a /path/b; echo '### 000' |
| 148 |
|
| 149 |
#LINK /path/a /path/b |
| 150 |
ln /path/a /path/b; echo '### 000' |
| 151 |
|
| 152 |
#SYMLINK /path/a /path/b |
| 153 |
ln -s /path/a /path/b; echo '### 000' |
| 154 |
|
| 155 |
#CHOWN user /file/name |
| 156 |
chown user /file/name; echo '### 000' |
| 157 |
|
| 158 |
#CHGRP group /file/name |
| 159 |
chgrp group /file/name; echo '### 000' |
| 160 |
|
| 161 |
#READ <offset> <size> /path/and/filename |
| 162 |
cat /path/and/filename | ( dd bs=4096 count=<offset/4096> > /dev/null; |
| 163 |
dd bs=<offset%4096> count=1 > /dev/null; |
| 164 |
dd bs=4096 count=<offset/4096>; |
| 165 |
dd bs=<offset%4096> count=1; ) |
| 166 |
|
| 167 |
Returns ### 200 on successful exit, ### 291 on successful exit when |
| 168 |
reading ended at eof, ### 292 on successfull exit when reading did not |
| 169 |
end at eof. |
| 170 |
|
| 171 |
#WRITE <offset> <size> /path/and/filename |
| 172 |
|
| 173 |
Hmm, shall we define these ones if we know our client is not going to |
| 174 |
use them? |
| 175 |
|
| 176 |
|
| 177 |
That's all, folks! |
| 178 |
pavel@ucw.cz |