1/* 2 * linux/fs/9p/fcprint.c 3 * 4 * Print 9P call. 5 * 6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 10 * as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to: 19 * Free Software Foundation 20 * 51 Franklin Street, Fifth Floor 21 * Boston, MA 02111-1301 USA 22 * 23 */ 24#include <linux/module.h> 25#include <linux/errno.h> 26#include <linux/fs.h> 27#include <linux/idr.h> 28 29#include "debug.h" 30#include "v9fs.h" 31#include "9p.h" 32#include "mux.h" 33 34static int 35v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q) 36{ 37 int n; 38 char b[10]; 39 40 n = 0; 41 if (q->type & V9FS_QTDIR) 42 b[n++] = 'd'; 43 if (q->type & V9FS_QTAPPEND) 44 b[n++] = 'a'; 45 if (q->type & V9FS_QTAUTH) 46 b[n++] = 'A'; 47 if (q->type & V9FS_QTEXCL) 48 b[n++] = 'l'; 49 if (q->type & V9FS_QTTMP) 50 b[n++] = 't'; 51 if (q->type & V9FS_QTSYMLINK) 52 b[n++] = 'L'; 53 b[n] = '\0'; 54 55 return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path, 56 q->version, b); 57} 58 59static int 60v9fs_printperm(char *buf, int buflen, int perm) 61{ 62 int n; 63 char b[15]; 64 65 n = 0; 66 if (perm & V9FS_DMDIR) 67 b[n++] = 'd'; 68 if (perm & V9FS_DMAPPEND) 69 b[n++] = 'a'; 70 if (perm & V9FS_DMAUTH) 71 b[n++] = 'A'; 72 if (perm & V9FS_DMEXCL) 73 b[n++] = 'l'; 74 if (perm & V9FS_DMTMP) 75 b[n++] = 't'; 76 if (perm & V9FS_DMDEVICE) 77 b[n++] = 'D'; 78 if (perm & V9FS_DMSOCKET) 79 b[n++] = 'S'; 80 if (perm & V9FS_DMNAMEDPIPE) 81 b[n++] = 'P'; 82 if (perm & V9FS_DMSYMLINK) 83 b[n++] = 'L'; 84 b[n] = '\0'; 85 86 return scnprintf(buf, buflen, "%s%03o", b, perm&077); 87} 88 89static int 90v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended) 91{ 92 int n; 93 94 n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len, 95 st->name.str, st->uid.len, st->uid.str); 96 if (extended) 97 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid); 98 99 n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str); 100 if (extended) 101 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid); 102 103 n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str); 104 if (extended) 105 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); 106 107 n += scnprintf(buf+n, buflen-n, " q "); 108 n += v9fs_printqid(buf+n, buflen-n, &st->qid); 109 n += scnprintf(buf+n, buflen-n, " m "); 110 n += v9fs_printperm(buf+n, buflen-n, st->mode); 111 n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", 112 st->atime, st->mtime, (long long int) st->length); 113 114 if (extended) 115 n += scnprintf(buf+n, buflen-n, " ext '%.*s'", 116 st->extension.len, st->extension.str); 117 118 return n; 119} 120 121static int 122v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen) 123{ 124 int i, n; 125 126 i = n = 0; 127 while (i < datalen) { 128 n += scnprintf(buf + n, buflen - n, "%02x", data[i]); 129 if (i%4 == 3) 130 n += scnprintf(buf + n, buflen - n, " "); 131 if (i%32 == 31) 132 n += scnprintf(buf + n, buflen - n, "\n"); 133 134 i++; 135 } 136 n += scnprintf(buf + n, buflen - n, "\n"); 137 138 return n; 139} 140 141static int 142v9fs_printdata(char *buf, int buflen, u8 *data, int datalen) 143{ 144 return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16); 145} 146 147int 148v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended) 149{ 150 int i, ret, type, tag; 151 152 if (!fc) 153 return scnprintf(buf, buflen, "<NULL>"); 154 155 type = fc->id; 156 tag = fc->tag; 157 158 ret = 0; 159 switch (type) { 160 case TVERSION: 161 ret += scnprintf(buf+ret, buflen-ret, 162 "Tversion tag %u msize %u version '%.*s'", tag, 163 fc->params.tversion.msize, fc->params.tversion.version.len, 164 fc->params.tversion.version.str); 165 break; 166 167 case RVERSION: 168 ret += scnprintf(buf+ret, buflen-ret, 169 "Rversion tag %u msize %u version '%.*s'", tag, 170 fc->params.rversion.msize, fc->params.rversion.version.len, 171 fc->params.rversion.version.str); 172 break; 173 174 case TAUTH: 175 ret += scnprintf(buf+ret, buflen-ret, 176 "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, 177 fc->params.tauth.afid, fc->params.tauth.uname.len, 178 fc->params.tauth.uname.str, fc->params.tauth.aname.len, 179 fc->params.tauth.aname.str); 180 break; 181 182 case RAUTH: 183 ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); 184 v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); 185 break; 186 187 case TATTACH: 188 ret += scnprintf(buf+ret, buflen-ret, 189 "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", 190 tag, fc->params.tattach.fid, fc->params.tattach.afid, 191 fc->params.tattach.uname.len, fc->params.tattach.uname.str, 192 fc->params.tattach.aname.len, fc->params.tattach.aname.str); 193 break; 194 195 case RATTACH: 196 ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag); 197 v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); 198 break; 199 200 case RERROR: 201 ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'", 202 tag, fc->params.rerror.error.len, 203 fc->params.rerror.error.str); 204 if (extended) 205 ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", 206 fc->params.rerror.errno); 207 break; 208 209 case TFLUSH: 210 ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", 211 tag, fc->params.tflush.oldtag); 212 break; 213 214 case RFLUSH: 215 ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); 216 break; 217 218 case TWALK: 219 ret += scnprintf(buf+ret, buflen-ret, 220 "Twalk tag %u fid %d newfid %d nwname %d", tag, 221 fc->params.twalk.fid, fc->params.twalk.newfid, 222 fc->params.twalk.nwname); 223 for(i = 0; i < fc->params.twalk.nwname; i++) 224 ret += scnprintf(buf+ret, buflen-ret," '%.*s'", 225 fc->params.twalk.wnames[i].len, 226 fc->params.twalk.wnames[i].str); 227 break; 228 229 case RWALK: 230 ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", 231 tag, fc->params.rwalk.nwqid); 232 for(i = 0; i < fc->params.rwalk.nwqid; i++) 233 ret += v9fs_printqid(buf+ret, buflen-ret, 234 &fc->params.rwalk.wqids[i]); 235 break; 236 237 case TOPEN: 238 ret += scnprintf(buf+ret, buflen-ret, 239 "Topen tag %u fid %d mode %d", tag, 240 fc->params.topen.fid, fc->params.topen.mode); 241 break; 242 243 case ROPEN: 244 ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); 245 ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); 246 ret += scnprintf(buf+ret, buflen-ret," iounit %d", 247 fc->params.ropen.iounit); 248 break; 249 250 case TCREATE: 251 ret += scnprintf(buf+ret, buflen-ret, 252 "Tcreate tag %u fid %d name '%.*s' perm ", tag, 253 fc->params.tcreate.fid, fc->params.tcreate.name.len, 254 fc->params.tcreate.name.str); 255 256 ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm); 257 ret += scnprintf(buf+ret, buflen-ret, " mode %d", 258 fc->params.tcreate.mode); 259 break; 260 261 case RCREATE: 262 ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); 263 ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid); 264 ret += scnprintf(buf+ret, buflen-ret, " iounit %d", 265 fc->params.rcreate.iounit); 266 break; 267 268 case TREAD: 269 ret += scnprintf(buf+ret, buflen-ret, 270 "Tread tag %u fid %d offset %lld count %u", tag, 271 fc->params.tread.fid, 272 (long long int) fc->params.tread.offset, 273 fc->params.tread.count); 274 break; 275 276 case RREAD: 277 ret += scnprintf(buf+ret, buflen-ret, 278 "Rread tag %u count %u data ", tag, 279 fc->params.rread.count); 280 ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data, 281 fc->params.rread.count); 282 break; 283 284 case TWRITE: 285 ret += scnprintf(buf+ret, buflen-ret, 286 "Twrite tag %u fid %d offset %lld count %u data ", 287 tag, fc->params.twrite.fid, 288 (long long int) fc->params.twrite.offset, 289 fc->params.twrite.count); 290 ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data, 291 fc->params.twrite.count); 292 break; 293 294 case RWRITE: 295 ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", 296 tag, fc->params.rwrite.count); 297 break; 298 299 case TCLUNK: 300 ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", 301 tag, fc->params.tclunk.fid); 302 break; 303 304 case RCLUNK: 305 ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); 306 break; 307 308 case TREMOVE: 309 ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", 310 tag, fc->params.tremove.fid); 311 break; 312 313 case RREMOVE: 314 ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); 315 break; 316 317 case TSTAT: 318 ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", 319 tag, fc->params.tstat.fid); 320 break; 321 322 case RSTAT: 323 ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); 324 ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, 325 extended); 326 break; 327 328 case TWSTAT: 329 ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", 330 tag, fc->params.twstat.fid); 331 ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat, 332 extended); 333 break; 334 335 case RWSTAT: 336 ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); 337 break; 338 339 default: 340 ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type); 341 break; 342 } 343 344 return ret; 345} 346