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

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