root/fs/nfs/proc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xdr_encode_fhandle
  2. xdr_decode_fhandle
  3. xdr_encode_string
  4. xdr_decode_string
  5. xdr_encode_data
  6. xdr_decode_data
  7. xdr_decode_fattr
  8. xdr_encode_sattr
  9. xdr_decode_entry
  10. xdr_decode_fsinfo
  11. nfs_proc_getattr
  12. nfs_proc_setattr
  13. nfs_proc_lookup
  14. nfs_proc_readlink
  15. nfs_proc_read
  16. nfs_proc_write
  17. nfs_proc_create
  18. nfs_proc_remove
  19. nfs_proc_rename
  20. nfs_proc_link
  21. nfs_proc_symlink
  22. nfs_proc_mkdir
  23. nfs_proc_rmdir
  24. nfs_proc_readdir
  25. nfs_proc_statfs
  26. nfs_rpc_header
  27. nfs_rpc_verify
  28. nfs_stat_to_errno

   1 /*
   2  *  linux/fs/nfs/proc.c
   3  *
   4  *  Copyright (C) 1992  Rick Sladkey
   5  *
   6  *  OS-independent nfs remote procedure call functions
   7  */
   8 
   9 /*
  10  * Defining NFS_PROC_DEBUG causes a lookup of a file named
  11  * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
  12  * filesystem and type 'ls xyzzy' to turn on debugging.
  13  */
  14 
  15 #if 0
  16 #define NFS_PROC_DEBUG
  17 #endif
  18 
  19 #include <linux/config.h>
  20 #include <linux/param.h>
  21 #include <linux/sched.h>
  22 #include <linux/mm.h>
  23 #include <linux/nfs_fs.h>
  24 #include <linux/utsname.h>
  25 #include <linux/errno.h>
  26 #include <linux/string.h>
  27 #include <linux/in.h>
  28 
  29 #ifdef NFS_PROC_DEBUG
  30 static int proc_debug = 0;
  31 #define PRINTK if (proc_debug) printk
  32 #else
  33 #define PRINTK if (0) printk
  34 #endif
  35 
  36 #define PREP_PAGE_RPC(code)     \
  37   if (!(p0 = (int*)__get_free_page(GFP_KERNEL)))\
  38         return NFSERR_IO;\
  39   p=nfs_rpc_header(p0,code)
  40 
  41 static int *nfs_rpc_header(int *p, int procedure);
  42 static int *nfs_rpc_verify(int *p);
  43 static int nfs_stat_to_errno(int stat);
  44 
  45 /*
  46  * Here are a bunch of xdr encode/decode functions that convert
  47  * between machine dependent and xdr data formats.
  48  */
  49 
  50 static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         *((struct nfs_fh *) p) = *fhandle;
  53         p += (sizeof (*fhandle) + 3) >> 2;
  54         return p;
  55 }
  56 
  57 static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         *fhandle = *((struct nfs_fh *) p);
  60         p += (sizeof (*fhandle) + 3) >> 2;
  61         return p;
  62 }
  63 
  64 static inline int *xdr_encode_string(int *p, const char *string)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         int len, quadlen;
  67         
  68         len = strlen(string);
  69         quadlen = (len + 3) >> 2;
  70         *p++ = htonl(len);
  71         memcpy((char *) p, string, len);
  72         memset(((char *) p) + len, '\0', (quadlen << 2) - len);
  73         p += quadlen;
  74         return p;
  75 }
  76 
  77 static inline int *xdr_decode_string(int *p, char *string, int maxlen)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         unsigned int len;
  80 
  81         len = ntohl(*p++);
  82         if (len > maxlen)
  83                 return NULL;
  84         memcpy(string, (char *) p, len);
  85         string[len] = '\0';
  86         p += (len + 3) >> 2;
  87         return p;
  88 }
  89 
  90 static inline int *xdr_encode_data(int *p, char *data, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         int quadlen;
  93         
  94         quadlen = (len + 3) >> 2;
  95         *p++ = htonl(len);
  96         memcpy((char *) p, data, len);
  97         memset(((char *) p) + len, '\0', (quadlen << 2) - len);
  98         p += quadlen;
  99         return p;
 100 }
 101 
 102 static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104         unsigned int len;
 105 
 106         len = *lenp = ntohl(*p++);
 107         if (len > maxlen)
 108                 return NULL;
 109         memcpy(data, (char *) p, len);
 110         p += (len + 3) >> 2;
 111         return p;
 112 }
 113 
 114 static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         fattr->type = (enum nfs_stat) ntohl(*p++);
 117         fattr->mode = ntohl(*p++);
 118         fattr->nlink = ntohl(*p++);
 119         fattr->uid = ntohl(*p++);
 120         fattr->gid = ntohl(*p++);
 121         fattr->size = ntohl(*p++);
 122         fattr->blocksize = ntohl(*p++);
 123         fattr->rdev = ntohl(*p++);
 124         fattr->blocks = ntohl(*p++);
 125         fattr->fsid = ntohl(*p++);
 126         fattr->fileid = ntohl(*p++);
 127         fattr->atime.seconds = ntohl(*p++);
 128         fattr->atime.useconds = ntohl(*p++);
 129         fattr->mtime.seconds = ntohl(*p++);
 130         fattr->mtime.useconds = ntohl(*p++);
 131         fattr->ctime.seconds = ntohl(*p++);
 132         fattr->ctime.useconds = ntohl(*p++);
 133         return p;
 134 }
 135 
 136 static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         *p++ = htonl(sattr->mode);
 139         *p++ = htonl(sattr->uid);
 140         *p++ = htonl(sattr->gid);
 141         *p++ = htonl(sattr->size);
 142         *p++ = htonl(sattr->atime.seconds);
 143         *p++ = htonl(sattr->atime.useconds);
 144         *p++ = htonl(sattr->mtime.seconds);
 145         *p++ = htonl(sattr->mtime.useconds);
 146         return p;
 147 }
 148 
 149 static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         entry->fileid = ntohl(*p++);
 152         if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))
 153                 return NULL;
 154         entry->cookie = ntohl(*p++);
 155         entry->eof = 0;
 156         return p;
 157 }
 158 
 159 static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         res->tsize = ntohl(*p++);
 162         res->bsize = ntohl(*p++);
 163         res->blocks = ntohl(*p++);
 164         res->bfree = ntohl(*p++);
 165         res->bavail = ntohl(*p++);
 166         return p;
 167 }
 168 
 169 int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 170                      struct nfs_fattr *fattr)
 171 {
 172         int *p, *p0;
 173         int status;
 174 
 175         PRINTK("NFS call  getattr\n");
 176         PREP_PAGE_RPC(NFSPROC_GETATTR);
 177         p = xdr_encode_fhandle(p, fhandle);
 178         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 179                 free_page((long) p0);
 180                 return status;
 181         }
 182         if (!(p = nfs_rpc_verify(p0)))
 183                 status = NFSERR_IO;
 184         else if ((status = ntohl(*p++)) == NFS_OK) {
 185                 p = xdr_decode_fattr(p, fattr);
 186                 PRINTK("NFS reply getattr\n");
 187         }
 188         else
 189                 PRINTK("NFS reply getattr failed = %d\n", status);
 190         free_page((long) p0);
 191         return -nfs_stat_to_errno(status);
 192 }
 193 
 194 int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 195                      struct nfs_sattr *sattr, struct nfs_fattr *fattr)
 196 {
 197         int *p, *p0;
 198         int status;
 199 
 200         PRINTK("NFS call  setattr\n");
 201         PREP_PAGE_RPC(NFSPROC_SETATTR);
 202         p = xdr_encode_fhandle(p, fhandle);
 203         p = xdr_encode_sattr(p, sattr);
 204         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 205                 free_page((long) p0);
 206                 return status;
 207         }
 208         if (!(p = nfs_rpc_verify(p0)))
 209                 status = NFSERR_IO;
 210         else if ((status = ntohl(*p++)) == NFS_OK) {
 211                 p = xdr_decode_fattr(p, fattr);
 212                 PRINTK("NFS reply setattr\n");
 213         }
 214         else
 215                 PRINTK("NFS reply setattr failed = %d\n", status);
 216         free_page((long) p0);
 217         return -nfs_stat_to_errno(status);
 218 }
 219 
 220 int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
     /* [previous][next][first][last][top][bottom][index][help] */
 221                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 222 {
 223         int *p, *p0;
 224         int status;
 225 
 226         PRINTK("NFS call  lookup %s\n", name);
 227 #ifdef NFS_PROC_DEBUG
 228         if (!strcmp(name, "xyzzy"))
 229                 proc_debug = 1 - proc_debug;
 230 #endif
 231         PREP_PAGE_RPC(NFSPROC_LOOKUP);
 232         p = xdr_encode_fhandle(p, dir);
 233         p = xdr_encode_string(p, name);
 234         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 235                 free_page((long) p0);
 236                 return status;
 237         }
 238         if (!(p = nfs_rpc_verify(p0)))
 239                 status = NFSERR_IO;
 240         else if ((status = ntohl(*p++)) == NFS_OK) {
 241                 p = xdr_decode_fhandle(p, fhandle);
 242                 p = xdr_decode_fattr(p, fattr);
 243                 PRINTK("NFS reply lookup\n");
 244         }
 245         else
 246                 PRINTK("NFS reply lookup failed = %d\n", status);
 247         free_page((long) p0);
 248         return -nfs_stat_to_errno(status);
 249 }
 250 
 251 int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 252                       char *res)
 253 {
 254         int *p, *p0;
 255         int status;
 256 
 257         PRINTK("NFS call  readlink\n");
 258         PREP_PAGE_RPC(NFSPROC_READLINK);
 259         p = xdr_encode_fhandle(p, fhandle);
 260         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 261                 free_page((long) p0);
 262                 return status;
 263         }
 264         if (!(p = nfs_rpc_verify(p0)))
 265                 status = NFSERR_IO;
 266         else if ((status = ntohl(*p++)) == NFS_OK) {
 267                 if (!(p = xdr_decode_string(p, res, NFS_MAXPATHLEN))) {
 268                         printk("nfs_proc_readlink: giant pathname\n");
 269                         status = NFSERR_IO;
 270                 }
 271                 else
 272                         PRINTK("NFS reply readlink %s\n", res);
 273         }
 274         else
 275                 PRINTK("NFS reply readlink failed = %d\n", status);
 276         free_page((long) p0);
 277         return -nfs_stat_to_errno(status);
 278 }
 279 
 280 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 281                   int offset, int count, char *data, struct nfs_fattr *fattr)
 282 {
 283         int *p, *p0;
 284         int status;
 285         int len = 0; /* = 0 is for gcc */
 286 
 287         PRINTK("NFS call  read %d @ %d\n", count, offset);
 288         PREP_PAGE_RPC(NFSPROC_READ);
 289         p = xdr_encode_fhandle(p, fhandle);
 290         *p++ = htonl(offset);
 291         *p++ = htonl(count);
 292         *p++ = htonl(count); /* traditional, could be any value */
 293         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 294                 free_page((long) p0);
 295                 return status;
 296         }
 297         if (!(p = nfs_rpc_verify(p0)))
 298                 status = NFSERR_IO;
 299         else if ((status = ntohl(*p++)) == NFS_OK) {
 300                 p = xdr_decode_fattr(p, fattr);
 301                 if (!(p = xdr_decode_data(p, data, &len, count))) {
 302                         printk("nfs_proc_read: giant data size\n"); 
 303                         status = NFSERR_IO;
 304                 }
 305                 else
 306                         PRINTK("NFS reply read %d\n", len);
 307         }
 308         else
 309                 PRINTK("NFS reply read failed = %d\n", status);
 310         free_page((long) p0);
 311         return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
 312 }
 313 
 314 int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 315                    int offset, int count, char *data, struct nfs_fattr *fattr)
 316 {
 317         int *p, *p0;
 318         int status;
 319 
 320         PRINTK("NFS call  write %d @ %d\n", count, offset);
 321         PREP_PAGE_RPC(NFSPROC_WRITE);
 322         p = xdr_encode_fhandle(p, fhandle);
 323         *p++ = htonl(offset); /* traditional, could be any value */
 324         *p++ = htonl(offset);
 325         *p++ = htonl(count); /* traditional, could be any value */
 326         p = xdr_encode_data(p, data, count);
 327         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 328                 free_page((long) p0);
 329                 return status;
 330         }
 331         if (!(p = nfs_rpc_verify(p0)))
 332                 status = NFSERR_IO;
 333         else if ((status = ntohl(*p++)) == NFS_OK) {
 334                 p = xdr_decode_fattr(p, fattr);
 335                 PRINTK("NFS reply write\n");
 336         }
 337         else
 338                 PRINTK("NFS reply write failed = %d\n", status);
 339         free_page((long) p0);
 340         return -nfs_stat_to_errno(status);
 341 }
 342 
 343 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 344                     const char *name, struct nfs_sattr *sattr,
 345                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 346 {
 347         int *p, *p0;
 348         int status;
 349 
 350         PRINTK("NFS call  create %s\n", name);
 351         PREP_PAGE_RPC(NFSPROC_CREATE);
 352         p = xdr_encode_fhandle(p, dir);
 353         p = xdr_encode_string(p, name);
 354         p = xdr_encode_sattr(p, sattr);
 355         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 356                 free_page((long) p0);
 357                 return status;
 358         }
 359         if (!(p = nfs_rpc_verify(p0)))
 360                 status = NFSERR_IO;
 361         else if ((status = ntohl(*p++)) == NFS_OK) {
 362                 p = xdr_decode_fhandle(p, fhandle);
 363                 p = xdr_decode_fattr(p, fattr);
 364                 PRINTK("NFS reply create\n");
 365         }
 366         else
 367                 PRINTK("NFS reply create failed = %d\n", status);
 368         free_page((long) p0);
 369         return -nfs_stat_to_errno(status);
 370 }
 371 
 372 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374         int *p, *p0;
 375         int status;
 376 
 377         PRINTK("NFS call  remove %s\n", name);
 378         PREP_PAGE_RPC(NFSPROC_REMOVE);
 379         p = xdr_encode_fhandle(p, dir);
 380         p = xdr_encode_string(p, name);
 381         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 382                 free_page((long) p0);
 383                 return status;
 384         }
 385         if (!(p = nfs_rpc_verify(p0)))
 386                 status = NFSERR_IO;
 387         else if ((status = ntohl(*p++)) == NFS_OK) {
 388                 PRINTK("NFS reply remove\n");
 389         }
 390         else
 391                 PRINTK("NFS reply remove failed = %d\n", status);
 392         free_page((long) p0);
 393         return -nfs_stat_to_errno(status);
 394 }
 395 
 396 int nfs_proc_rename(struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 397                     struct nfs_fh *old_dir, const char *old_name,
 398                     struct nfs_fh *new_dir, const char *new_name)
 399 {
 400         int *p, *p0;
 401         int status;
 402 
 403         PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 404         PREP_PAGE_RPC(NFSPROC_RENAME);
 405         p = xdr_encode_fhandle(p, old_dir);
 406         p = xdr_encode_string(p, old_name);
 407         p = xdr_encode_fhandle(p, new_dir);
 408         p = xdr_encode_string(p, new_name);
 409         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 410                 free_page((long) p0);
 411                 return status;
 412         }
 413         if (!(p = nfs_rpc_verify(p0)))
 414                 status = NFSERR_IO;
 415         else if ((status = ntohl(*p++)) == NFS_OK) {
 416                 PRINTK("NFS reply rename\n");
 417         }
 418         else
 419                 PRINTK("NFS reply rename failed = %d\n", status);
 420         free_page((long) p0);
 421         return -nfs_stat_to_errno(status);
 422 }
 423 
 424 int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 425                   struct nfs_fh *dir, const char *name)
 426 {
 427         int *p, *p0;
 428         int status;
 429 
 430         PRINTK("NFS call  link %s\n", name);
 431         PREP_PAGE_RPC(NFSPROC_LINK);
 432         p = xdr_encode_fhandle(p, fhandle);
 433         p = xdr_encode_fhandle(p, dir);
 434         p = xdr_encode_string(p, name);
 435         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 436                 free_page((long) p0);
 437                 return status;
 438         }
 439         if (!(p = nfs_rpc_verify(p0)))
 440                 status = NFSERR_IO;
 441         else if ((status = ntohl(*p++)) == NFS_OK) {
 442                 PRINTK("NFS reply link\n");
 443         }
 444         else
 445                 PRINTK("NFS reply link failed = %d\n", status);
 446         free_page((long) p0);
 447         return -nfs_stat_to_errno(status);
 448 }
 449 
 450 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 451                      const char *name, const char *path, struct nfs_sattr *sattr)
 452 {
 453         int *p, *p0;
 454         int status;
 455 
 456         PRINTK("NFS call  symlink %s -> %s\n", name, path);
 457         PREP_PAGE_RPC(NFSPROC_SYMLINK);
 458         p = xdr_encode_fhandle(p, dir);
 459         p = xdr_encode_string(p, name);
 460         p = xdr_encode_string(p, path);
 461         p = xdr_encode_sattr(p, sattr);
 462         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 463                 free_page((long) p0);
 464                 return status;
 465         }
 466         if (!(p = nfs_rpc_verify(p0)))
 467                 status = NFSERR_IO;
 468         else if ((status = ntohl(*p++)) == NFS_OK) {
 469                 PRINTK("NFS reply symlink\n");
 470         }
 471         else
 472                 PRINTK("NFS reply symlink failed = %d\n", status);
 473         free_page((long) p0);
 474         return -nfs_stat_to_errno(status);
 475 }
 476 
 477 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 478                    const char *name, struct nfs_sattr *sattr,
 479                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 480 {
 481         int *p, *p0;
 482         int status;
 483 
 484         PRINTK("NFS call  mkdir %s\n", name);
 485         PREP_PAGE_RPC(NFSPROC_MKDIR);
 486         p = xdr_encode_fhandle(p, dir);
 487         p = xdr_encode_string(p, name);
 488         p = xdr_encode_sattr(p, sattr);
 489         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 490                 free_page((long) p0);
 491                 return status;
 492         }
 493         if (!(p = nfs_rpc_verify(p0)))
 494                 status = NFSERR_IO;
 495         else if ((status = ntohl(*p++)) == NFS_OK) {
 496                 p = xdr_decode_fhandle(p, fhandle);
 497                 p = xdr_decode_fattr(p, fattr);
 498                 PRINTK("NFS reply mkdir\n");
 499         }
 500         else
 501                 PRINTK("NFS reply mkdir failed = %d\n", status);
 502         free_page((long) p0);
 503         return -nfs_stat_to_errno(status);
 504 }
 505 
 506 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 507 {
 508         int *p, *p0;
 509         int status;
 510 
 511         PRINTK("NFS call  rmdir %s\n", name);
 512         PREP_PAGE_RPC(NFSPROC_RMDIR);
 513         p = xdr_encode_fhandle(p, dir);
 514         p = xdr_encode_string(p, name);
 515         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 516                 free_page((long) p0);
 517                 return status;
 518         }
 519         if (!(p = nfs_rpc_verify(p0)))
 520                 status = NFSERR_IO;
 521         else if ((status = ntohl(*p++)) == NFS_OK) {
 522                 PRINTK("NFS reply rmdir\n");
 523         }
 524         else
 525                 PRINTK("NFS reply rmdir failed = %d\n", status);
 526         free_page((long) p0);
 527         return -nfs_stat_to_errno(status);
 528 }
 529 
 530 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 531                      int cookie, int count, struct nfs_entry *entry)
 532 {
 533         int *p, *p0;
 534         int status;
 535         int i = 0; /* = 0 is for gcc */
 536         int size;
 537         int eof;
 538 
 539         PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
 540         size = server->rsize;
 541         PREP_PAGE_RPC(NFSPROC_READDIR);
 542         p = xdr_encode_fhandle(p, fhandle);
 543         *p++ = htonl(cookie);
 544         *p++ = htonl(size);
 545         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 546                 free_page((long) p0);
 547                 return status;
 548         }
 549         if (!(p = nfs_rpc_verify(p0)))
 550                 status = NFSERR_IO;
 551         else if ((status = ntohl(*p++)) == NFS_OK) {
 552                 for (i = 0; i < count && *p++; i++) {
 553                         if (!(p = xdr_decode_entry(p, entry++)))
 554                                 break;
 555                 }
 556                 if (!p) {
 557                         printk("nfs_proc_readdir: giant filename\n");
 558                         status = NFSERR_IO;
 559                 }
 560                 else {
 561                         eof = (i == count && !*p++ && *p++)
 562                               || (i < count && *p++);
 563                         if (eof && i)
 564                                 entry[-1].eof = 1;
 565                         PRINTK("NFS reply readdir %d %s\n", i,
 566                                eof ? "eof" : "");
 567                 }
 568         }
 569         else
 570                 PRINTK("NFS reply readdir failed = %d\n", status);
 571         free_page((long) p0);
 572         return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
 573 }
 574 
 575 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 576                     struct nfs_fsinfo *res)
 577 {
 578         int *p, *p0;
 579         int status;
 580 
 581         PRINTK("NFS call  statfs\n");
 582         PREP_PAGE_RPC(NFSPROC_STATFS);
 583         p = xdr_encode_fhandle(p, fhandle);
 584         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 585                 free_page((long) p0);
 586                 return status;
 587         }
 588         if (!(p = nfs_rpc_verify(p0)))
 589                 status = NFSERR_IO;
 590         else if ((status = ntohl(*p++)) == NFS_OK) {
 591                 p = xdr_decode_fsinfo(p, res);
 592                 PRINTK("NFS reply statfs\n");
 593         }
 594         else
 595                 PRINTK("NFS reply statfs failed = %d\n", status);
 596         free_page((long) p0);
 597         return -nfs_stat_to_errno(status);
 598 }
 599 
 600 /*
 601  * Here are a few RPC-assist functions.
 602  */
 603 
 604 static int *nfs_rpc_header(int *p, int procedure)
     /* [previous][next][first][last][top][bottom][index][help] */
 605 {
 606         int *p1, *p2;
 607         int i;
 608         static int xid = 0;
 609         unsigned char *sys = (unsigned char *) system_utsname.nodename;
 610 
 611         if (xid == 0) {
 612                 xid = CURRENT_TIME;
 613                 xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
 614         }
 615         *p++ = htonl(++xid);
 616         *p++ = htonl(RPC_CALL);
 617         *p++ = htonl(RPC_VERSION);
 618         *p++ = htonl(NFS_PROGRAM);
 619         *p++ = htonl(NFS_VERSION);
 620         *p++ = htonl(procedure);
 621         *p++ = htonl(RPC_AUTH_UNIX);
 622         p1 = p++;
 623         *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 624         p = xdr_encode_string(p, (char *) sys);
 625         *p++ = htonl(current->euid);
 626         *p++ = htonl(current->egid);
 627         p2 = p++;
 628         for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
 629                 *p++ = htonl(current->groups[i]);
 630         *p2 = htonl(i);
 631         *p1 = htonl((p - (p1 + 1)) << 2);
 632         *p++ = htonl(RPC_AUTH_NULL);
 633         *p++ = htonl(0);
 634         return p;
 635 }
 636 
 637 static int *nfs_rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 638 {
 639         unsigned int n;
 640 
 641         p++;
 642         if ((n = ntohl(*p++)) != RPC_REPLY) {
 643                 printk("nfs_rpc_verify: not an RPC reply: %d\n", n);
 644                 return NULL;
 645         }
 646         if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 647                 printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
 648                 return NULL;
 649         }
 650         switch (n = ntohl(*p++)) {
 651         case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
 652                 break;
 653         default:
 654                 printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
 655                 return NULL;
 656         }
 657         if ((n = ntohl(*p++)) > 400) {
 658                 printk("nfs_rpc_verify: giant auth size\n");
 659                 return NULL;
 660         }
 661         p += (n + 3) >> 2;
 662         if ((n = ntohl(*p++)) != RPC_SUCCESS) {
 663                 printk("nfs_rpc_verify: RPC call failed: %d\n", n);
 664                 return NULL;
 665         }
 666         return p;
 667 }
 668         
 669 /*
 670  * We need to translate between nfs status return values and
 671  * the local errno values which may not be the same.
 672  */
 673 
 674 #ifndef EDQUOT
 675 #define EDQUOT  ENOSPC
 676 #endif
 677 
 678 static struct {
 679         int stat;
 680         int errno;
 681 } nfs_errtbl[] = {
 682         { NFS_OK,               0               },
 683         { NFSERR_PERM,          EPERM           },
 684         { NFSERR_NOENT,         ENOENT          },
 685         { NFSERR_IO,            EIO             },
 686         { NFSERR_NXIO,          ENXIO           },
 687         { NFSERR_ACCES,         EACCES          },
 688         { NFSERR_EXIST,         EEXIST          },
 689         { NFSERR_NODEV,         ENODEV          },
 690         { NFSERR_NOTDIR,        ENOTDIR         },
 691         { NFSERR_ISDIR,         EISDIR          },
 692         { NFSERR_INVAL,         EINVAL          },
 693         { NFSERR_FBIG,          EFBIG           },
 694         { NFSERR_NOSPC,         ENOSPC          },
 695         { NFSERR_ROFS,          EROFS           },
 696         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
 697         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
 698         { NFSERR_DQUOT,         EDQUOT          },
 699         { NFSERR_STALE,         ESTALE          },
 700 #ifdef EWFLUSH
 701         { NFSERR_WFLUSH,        EWFLUSH         },
 702 #endif
 703         { -1,                   EIO             }
 704 };
 705 
 706 static int nfs_stat_to_errno(int stat)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         int i;
 709 
 710         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
 711                 if (nfs_errtbl[i].stat == stat)
 712                         return nfs_errtbl[i].errno;
 713         }
 714         printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
 715         return nfs_errtbl[i].errno;
 716 }
 717 

/* [previous][next][first][last][top][bottom][index][help] */