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

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