root/fs/nfs/proc.c

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

DEFINITIONS

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

   1 /*
   2  *  linux/fs/nfs/proc.c
   3  *
   4  *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
   5  *
   6  *  OS-independent nfs remote procedure call functions
   7  *
   8  *  Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers
   9  *  so at last we can have decent(ish) throughput off a 
  10  *  Sun server.
  11  *
  12  *  Coding optimized and cleaned up by Florian La Roche.
  13  *  Note: Error returns are optimized for NFS_OK, which isn't translated via
  14  *  nfs_stat_to_errno(), but happens to be already the right return code.
  15  *
  16  *  FixMe: We ought to define a sensible small max size for
  17  *  things like getattr that are tiny packets and use the
  18  *  old get_free_page stuff with it.
  19  *
  20  *  Also, the code currently doesn't check the size of the packet, when
  21  *  it decodes the packet.
  22  *
  23  *  Feel free to fix it and mail me the diffs if it worries you.
  24  */
  25 
  26 /*
  27  * Defining NFS_PROC_DEBUG causes a lookup of a file named
  28  * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
  29  * filesystem and type 'ls xyzzy' to turn on debugging.
  30  */
  31 
  32 #if 0
  33 #define NFS_PROC_DEBUG
  34 #endif
  35 
  36 #include <linux/config.h>
  37 #include <linux/param.h>
  38 #include <linux/sched.h>
  39 #include <linux/mm.h>
  40 #include <linux/malloc.h>
  41 #include <linux/nfs_fs.h>
  42 #include <linux/utsname.h>
  43 #include <linux/errno.h>
  44 #include <linux/string.h>
  45 #include <linux/in.h>
  46 #include <asm/segment.h>
  47 
  48 #ifdef NFS_PROC_DEBUG
  49 
  50 static int proc_debug = 0;
  51 #define PRINTK(format, args...) \
  52         do {                                            \
  53                 if (proc_debug)                         \
  54                         printk(format , ## args);       \
  55         } while (0)
  56 
  57 #else /* !NFS_PROC_DEBUG */
  58 
  59 #define PRINTK(format, args...) do ; while (0)
  60 
  61 #endif /* !NFS_PROC_DEBUG */
  62 
  63 /* Mapping from NFS error code to "errno" error code. */
  64 #define errno_NFSERR_IO EIO
  65 
  66 static int *nfs_rpc_header(int *p, int procedure, int ruid);
  67 static int *nfs_rpc_verify(int *p);
  68 static int nfs_stat_to_errno(int stat);
  69 
  70 /*
  71  * Our memory allocation and release functions.
  72  */
  73  
  74 #define NFS_SLACK_SPACE         1024    /* Total overkill */ 
  75 /* !!! Be careful, this constant is now also used in sock.c...
  76    We should easily convert to not using it anymore for most cases... */
  77 
  78 static inline int *nfs_rpc_alloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         int *i;
  81 
  82         while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {
  83                 schedule();
  84         }
  85         return i;
  86 }
  87 
  88 static inline void nfs_rpc_free(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90         kfree((void *)p);
  91 }
  92 
  93 /*
  94  * Here are a bunch of xdr encode/decode functions that convert
  95  * between machine dependent and xdr data formats.
  96  */
  97 
  98 #define QUADLEN(len) (((len) + 3) >> 2)
  99 
 100 static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         *((struct nfs_fh *) p) = *fhandle;
 103         return p + QUADLEN(sizeof(*fhandle));
 104 }
 105 
 106 static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         *fhandle = *((struct nfs_fh *) p);
 109         return p + QUADLEN(sizeof(*fhandle));
 110 }
 111 
 112 static inline int *xdr_encode_string(int *p, const char *string)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         int len = strlen(string);
 115         int quadlen = QUADLEN(len);
 116 
 117         p[quadlen] = 0;
 118         *p++ = htonl(len);
 119         memcpy(p, string, len);
 120         return p + quadlen;
 121 }
 122 
 123 static inline int *xdr_decode_string(int *p, char *string, unsigned int maxlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         unsigned int len = ntohl(*p++);
 126         if (len > maxlen)
 127                 return NULL;
 128         memcpy(string, p, len);
 129         string[len] = '\0';
 130         return p + QUADLEN(len);
 131 }
 132 
 133 static inline int *xdr_decode_string2(int *p, char **string, unsigned int *len,
     /* [previous][next][first][last][top][bottom][index][help] */
 134                         unsigned int maxlen)
 135 {
 136         *len = ntohl(*p++);
 137         if (*len > maxlen)
 138                 return NULL;
 139         *string = (char *) p;
 140         return p + QUADLEN(*len);
 141 }
 142 
 143 
 144 static inline int *xdr_encode_data(int *p, char *data, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         int quadlen = QUADLEN(len);
 147         
 148         p[quadlen] = 0;
 149         *p++ = htonl(len);
 150         memcpy_fromfs(p, data, len);
 151         return p + quadlen;
 152 }
 153 
 154 static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen,
     /* [previous][next][first][last][top][bottom][index][help] */
 155                         int fs)
 156 {
 157         unsigned len = *lenp = ntohl(*p++);
 158         if (len > maxlen)
 159                 return NULL;
 160         if (fs)
 161                 memcpy_tofs(data, p, len);
 162         else
 163                 memcpy(data, p, len);
 164         return p + QUADLEN(len);
 165 }
 166 
 167 static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         fattr->type = (enum nfs_ftype) ntohl(*p++);
 170         fattr->mode = ntohl(*p++);
 171         fattr->nlink = ntohl(*p++);
 172         fattr->uid = ntohl(*p++);
 173         fattr->gid = ntohl(*p++);
 174         fattr->size = ntohl(*p++);
 175         fattr->blocksize = ntohl(*p++);
 176         fattr->rdev = ntohl(*p++);
 177         fattr->blocks = ntohl(*p++);
 178         fattr->fsid = ntohl(*p++);
 179         fattr->fileid = ntohl(*p++);
 180         fattr->atime.seconds = ntohl(*p++);
 181         fattr->atime.useconds = ntohl(*p++);
 182         fattr->mtime.seconds = ntohl(*p++);
 183         fattr->mtime.useconds = ntohl(*p++);
 184         fattr->ctime.seconds = ntohl(*p++);
 185         fattr->ctime.useconds = ntohl(*p++);
 186         return p;
 187 }
 188 
 189 static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         *p++ = htonl(sattr->mode);
 192         *p++ = htonl(sattr->uid);
 193         *p++ = htonl(sattr->gid);
 194         *p++ = htonl(sattr->size);
 195         *p++ = htonl(sattr->atime.seconds);
 196         *p++ = htonl(sattr->atime.useconds);
 197         *p++ = htonl(sattr->mtime.seconds);
 198         *p++ = htonl(sattr->mtime.useconds);
 199         return p;
 200 }
 201 
 202 static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         entry->fileid = ntohl(*p++);
 205         if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))
 206                 return NULL;
 207         entry->cookie = ntohl(*p++);
 208         entry->eof = 0;
 209         return p;
 210 }
 211 
 212 static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         res->tsize = ntohl(*p++);
 215         res->bsize = ntohl(*p++);
 216         res->blocks = ntohl(*p++);
 217         res->bfree = ntohl(*p++);
 218         res->bavail = ntohl(*p++);
 219         return p;
 220 }
 221 
 222 /*
 223  * One function for each procedure in the NFS protocol.
 224  */
 225 
 226 int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 227                      struct nfs_fattr *fattr)
 228 {
 229         int *p, *p0;
 230         int status;
 231         int ruid = 0;
 232 
 233         PRINTK("NFS call  getattr\n");
 234         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 235                 return -EIO;
 236 retry:
 237         p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
 238         p = xdr_encode_fhandle(p, fhandle);
 239         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 240                 nfs_rpc_free(p0);
 241                 return status;
 242         }
 243         if (!(p = nfs_rpc_verify(p0)))
 244                 status = -errno_NFSERR_IO;
 245         else if ((status = ntohl(*p++)) == NFS_OK) {
 246                 p = xdr_decode_fattr(p, fattr);
 247                 PRINTK("NFS reply getattr\n");
 248                 /* status = 0; */
 249         }
 250         else {
 251                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 252                         ruid = 1;
 253                         goto retry;
 254                 }
 255                 PRINTK("NFS reply getattr failed = %d\n", status);
 256                 status = -nfs_stat_to_errno(status);
 257         }
 258         nfs_rpc_free(p0);
 259         return status;
 260 }
 261 
 262 int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 263                      struct nfs_sattr *sattr, struct nfs_fattr *fattr)
 264 {
 265         int *p, *p0;
 266         int status;
 267         int ruid = 0;
 268 
 269         PRINTK("NFS call  setattr\n");
 270         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 271                 return -EIO;
 272 retry:
 273         p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
 274         p = xdr_encode_fhandle(p, fhandle);
 275         p = xdr_encode_sattr(p, sattr);
 276         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 277                 nfs_rpc_free(p0);
 278                 return status;
 279         }
 280         if (!(p = nfs_rpc_verify(p0)))
 281                 status = -errno_NFSERR_IO;
 282         else if ((status = ntohl(*p++)) == NFS_OK) {
 283                 p = xdr_decode_fattr(p, fattr);
 284                 PRINTK("NFS reply setattr\n");
 285                 /* status = 0; */
 286         }
 287         else {
 288                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 289                         ruid = 1;
 290                         goto retry;
 291                 }
 292                 PRINTK("NFS reply setattr failed = %d\n", status);
 293                 status = -nfs_stat_to_errno(status);
 294         }
 295         nfs_rpc_free(p0);
 296         return status;
 297 }
 298 
 299 int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
     /* [previous][next][first][last][top][bottom][index][help] */
 300                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 301 {
 302         int *p, *p0;
 303         int status;
 304         int ruid = 0;
 305 
 306         PRINTK("NFS call  lookup %s\n", name);
 307 #ifdef NFS_PROC_DEBUG
 308         if (!strcmp(name, "xyzzy"))
 309                 proc_debug = 1 - proc_debug;
 310 #endif
 311         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 312                 return -EIO;
 313 retry:
 314         p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
 315         p = xdr_encode_fhandle(p, dir);
 316         p = xdr_encode_string(p, name);
 317         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 318                 nfs_rpc_free(p0);
 319                 return status;
 320         }
 321         if (!(p = nfs_rpc_verify(p0)))
 322                 status = -errno_NFSERR_IO;
 323         else if ((status = ntohl(*p++)) == NFS_OK) {
 324                 p = xdr_decode_fhandle(p, fhandle);
 325                 p = xdr_decode_fattr(p, fattr);
 326                 PRINTK("NFS reply lookup\n");
 327                 /* status = 0; */
 328         }
 329         else {
 330                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 331                         ruid = 1;
 332                         goto retry;
 333                 }
 334                 PRINTK("NFS reply lookup failed = %d\n", status);
 335                 status = -nfs_stat_to_errno(status);
 336         }
 337         nfs_rpc_free(p0);
 338         return status;
 339 }
 340 
 341 int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 342                 int **p0, char **string, unsigned int *len, unsigned int maxlen)
 343 {
 344         int *p;
 345         int status, ruid = 0;
 346 
 347         PRINTK("NFS call  readlink\n");
 348         if (!(*p0 = nfs_rpc_alloc(server->rsize)))
 349                 return -EIO;
 350 retry:
 351         p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid);
 352         p = xdr_encode_fhandle(p, fhandle);
 353         if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0)
 354                 return status;
 355         if (!(p = nfs_rpc_verify(*p0)))
 356                 status = -errno_NFSERR_IO;
 357         else if ((status = ntohl(*p++)) == NFS_OK) {
 358                 if (!(p = xdr_decode_string2(p, string, len, maxlen))) {
 359                         printk("nfs_proc_readlink: giant pathname\n");
 360                         status = -errno_NFSERR_IO;
 361                 }
 362                 else    /* status = 0, */
 363                         PRINTK("NFS reply readlink\n");
 364         }
 365         else {
 366                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 367                         ruid = 1;
 368                         goto retry;
 369                 }
 370                 PRINTK("NFS reply readlink failed = %d\n", status);
 371                 status = -nfs_stat_to_errno(status);
 372         }
 373         return status;
 374 }
 375 
 376 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 377           int offset, int count, char *data, struct nfs_fattr *fattr, int fs)
 378 {
 379         int *p, *p0;
 380         int status;
 381         int ruid = 0;
 382         int len;
 383 
 384         PRINTK("NFS call  read %d @ %d\n", count, offset);
 385         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 386                 return -EIO;
 387 retry:
 388         p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
 389         p = xdr_encode_fhandle(p, fhandle);
 390         *p++ = htonl(offset);
 391         *p++ = htonl(count);
 392         *p++ = htonl(count); /* traditional, could be any value */
 393         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 394                 nfs_rpc_free(p0);
 395                 return status;
 396         }
 397         if (!(p = nfs_rpc_verify(p0)))
 398                 status = -errno_NFSERR_IO;
 399         else if ((status = ntohl(*p++)) == NFS_OK) {
 400                 p = xdr_decode_fattr(p, fattr);
 401                 if (!(p = xdr_decode_data(p, data, &len, count, fs))) {
 402                         printk("nfs_proc_read: giant data size\n"); 
 403                         status = -errno_NFSERR_IO;
 404                 }
 405                 else {
 406                         status = len;
 407                         PRINTK("NFS reply read %d\n", len);
 408                 }
 409         }
 410         else {
 411                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 412                         ruid = 1;
 413                         goto retry;
 414                 }
 415                 PRINTK("NFS reply read failed = %d\n", status);
 416                 status = -nfs_stat_to_errno(status);
 417         }
 418         nfs_rpc_free(p0);
 419         return status;
 420 }
 421 
 422 int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 423                    int offset, int count, char *data, struct nfs_fattr *fattr)
 424 {
 425         int *p, *p0;
 426         int status;
 427         int ruid = 0;
 428 
 429         PRINTK("NFS call  write %d @ %d\n", count, offset);
 430         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 431                 return -EIO;
 432 retry:
 433         p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
 434         p = xdr_encode_fhandle(p, fhandle);
 435         *p++ = htonl(offset); /* traditional, could be any value */
 436         *p++ = htonl(offset);
 437         *p++ = htonl(count); /* traditional, could be any value */
 438         p = xdr_encode_data(p, data, count);
 439         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 440                 nfs_rpc_free(p0);
 441                 return status;
 442         }
 443         if (!(p = nfs_rpc_verify(p0)))
 444                 status = -errno_NFSERR_IO;
 445         else if ((status = ntohl(*p++)) == NFS_OK) {
 446                 p = xdr_decode_fattr(p, fattr);
 447                 PRINTK("NFS reply write\n");
 448                 /* status = 0; */
 449         }
 450         else {
 451                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 452                         ruid = 1;
 453                         goto retry;
 454                 }
 455                 PRINTK("NFS reply write failed = %d\n", status);
 456                 status = -nfs_stat_to_errno(status);
 457         }
 458         nfs_rpc_free(p0);
 459         return status;
 460 }
 461 
 462 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 463                     const char *name, struct nfs_sattr *sattr,
 464                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 465 {
 466         int *p, *p0;
 467         int status;
 468         int ruid = 0;
 469 
 470         PRINTK("NFS call  create %s\n", name);
 471         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 472                 return -EIO;
 473 retry:
 474         p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
 475         p = xdr_encode_fhandle(p, dir);
 476         p = xdr_encode_string(p, name);
 477         p = xdr_encode_sattr(p, sattr);
 478         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 479                 nfs_rpc_free(p0);
 480                 return status;
 481         }
 482         if (!(p = nfs_rpc_verify(p0)))
 483                 status = -errno_NFSERR_IO;
 484         else if ((status = ntohl(*p++)) == NFS_OK) {
 485                 p = xdr_decode_fhandle(p, fhandle);
 486                 p = xdr_decode_fattr(p, fattr);
 487                 PRINTK("NFS reply create\n");
 488                 /* status = 0; */
 489         }
 490         else {
 491                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 492                         ruid = 1;
 493                         goto retry;
 494                 }
 495                 PRINTK("NFS reply create failed = %d\n", status);
 496                 status = -nfs_stat_to_errno(status);
 497         }
 498         nfs_rpc_free(p0);
 499         return status;
 500 }
 501 
 502 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 503 {
 504         int *p, *p0;
 505         int status;
 506         int ruid = 0;
 507 
 508         PRINTK("NFS call  remove %s\n", name);
 509         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 510                 return -EIO;
 511 retry:
 512         p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
 513         p = xdr_encode_fhandle(p, dir);
 514         p = xdr_encode_string(p, name);
 515         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 516                 nfs_rpc_free(p0);
 517                 return status;
 518         }
 519         if (!(p = nfs_rpc_verify(p0)))
 520                 status = -errno_NFSERR_IO;
 521         else if ((status = ntohl(*p++)) == NFS_OK) {
 522                 PRINTK("NFS reply remove\n");
 523                 /* status = 0; */
 524         }
 525         else {
 526                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 527                         ruid = 1;
 528                         goto retry;
 529                 }
 530                 PRINTK("NFS reply remove failed = %d\n", status);
 531                 status = -nfs_stat_to_errno(status);
 532         }
 533         nfs_rpc_free(p0);
 534         return status;
 535 }
 536 
 537 int nfs_proc_rename(struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 538                     struct nfs_fh *old_dir, const char *old_name,
 539                     struct nfs_fh *new_dir, const char *new_name)
 540 {
 541         int *p, *p0;
 542         int status;
 543         int ruid = 0;
 544 
 545         PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 546         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 547                 return -EIO;
 548 retry:
 549         p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
 550         p = xdr_encode_fhandle(p, old_dir);
 551         p = xdr_encode_string(p, old_name);
 552         p = xdr_encode_fhandle(p, new_dir);
 553         p = xdr_encode_string(p, new_name);
 554         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 555                 nfs_rpc_free(p0);
 556                 return status;
 557         }
 558         if (!(p = nfs_rpc_verify(p0)))
 559                 status = -errno_NFSERR_IO;
 560         else if ((status = ntohl(*p++)) == NFS_OK) {
 561                 PRINTK("NFS reply rename\n");
 562                 /* status = 0; */
 563         }
 564         else {
 565                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 566                         ruid = 1;
 567                         goto retry;
 568                 }
 569                 PRINTK("NFS reply rename failed = %d\n", status);
 570                 status = -nfs_stat_to_errno(status);
 571         }
 572         nfs_rpc_free(p0);
 573         return status;
 574 }
 575 
 576 int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 577                   struct nfs_fh *dir, const char *name)
 578 {
 579         int *p, *p0;
 580         int status;
 581         int ruid = 0;
 582 
 583         PRINTK("NFS call  link %s\n", name);
 584         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 585                 return -EIO;
 586 retry:
 587         p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
 588         p = xdr_encode_fhandle(p, fhandle);
 589         p = xdr_encode_fhandle(p, dir);
 590         p = xdr_encode_string(p, name);
 591         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 592                 nfs_rpc_free(p0);
 593                 return status;
 594         }
 595         if (!(p = nfs_rpc_verify(p0)))
 596                 status = -errno_NFSERR_IO;
 597         else if ((status = ntohl(*p++)) == NFS_OK) {
 598                 PRINTK("NFS reply link\n");
 599                 /* status = 0; */
 600         }
 601         else {
 602                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 603                         ruid = 1;
 604                         goto retry;
 605                 }
 606                 PRINTK("NFS reply link failed = %d\n", status);
 607                 status = -nfs_stat_to_errno(status);
 608         }
 609         nfs_rpc_free(p0);
 610         return status;
 611 }
 612 
 613 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 614                      const char *name, const char *path, struct nfs_sattr *sattr)
 615 {
 616         int *p, *p0;
 617         int status;
 618         int ruid = 0;
 619 
 620         PRINTK("NFS call  symlink %s -> %s\n", name, path);
 621         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 622                 return -EIO;
 623 retry:
 624         p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
 625         p = xdr_encode_fhandle(p, dir);
 626         p = xdr_encode_string(p, name);
 627         p = xdr_encode_string(p, path);
 628         p = xdr_encode_sattr(p, sattr);
 629         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 630                 nfs_rpc_free(p0);
 631                 return status;
 632         }
 633         if (!(p = nfs_rpc_verify(p0)))
 634                 status = -errno_NFSERR_IO;
 635         else if ((status = ntohl(*p++)) == NFS_OK) {
 636                 PRINTK("NFS reply symlink\n");
 637                 /* status = 0; */
 638         }
 639         else {
 640                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 641                         ruid = 1;
 642                         goto retry;
 643                 }
 644                 PRINTK("NFS reply symlink failed = %d\n", status);
 645                 status = -nfs_stat_to_errno(status);
 646         }
 647         nfs_rpc_free(p0);
 648         return status;
 649 }
 650 
 651 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 652                    const char *name, struct nfs_sattr *sattr,
 653                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 654 {
 655         int *p, *p0;
 656         int status;
 657         int ruid = 0;
 658 
 659         PRINTK("NFS call  mkdir %s\n", name);
 660         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 661                 return -EIO;
 662 retry:
 663         p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
 664         p = xdr_encode_fhandle(p, dir);
 665         p = xdr_encode_string(p, name);
 666         p = xdr_encode_sattr(p, sattr);
 667         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 668                 nfs_rpc_free(p0);
 669                 return status;
 670         }
 671         if (!(p = nfs_rpc_verify(p0)))
 672                 status = -errno_NFSERR_IO;
 673         else if ((status = ntohl(*p++)) == NFS_OK) {
 674                 p = xdr_decode_fhandle(p, fhandle);
 675                 p = xdr_decode_fattr(p, fattr);
 676                 PRINTK("NFS reply mkdir\n");
 677                 /* status = 0; */
 678         }
 679         else {
 680                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 681                         ruid = 1;
 682                         goto retry;
 683                 }
 684                 PRINTK("NFS reply mkdir failed = %d\n", status);
 685                 status = -nfs_stat_to_errno(status);
 686         }
 687         nfs_rpc_free(p0);
 688         return status;
 689 }
 690 
 691 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 692 {
 693         int *p, *p0;
 694         int status;
 695         int ruid = 0;
 696 
 697         PRINTK("NFS call  rmdir %s\n", name);
 698         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 699                 return -EIO;
 700 retry:
 701         p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
 702         p = xdr_encode_fhandle(p, dir);
 703         p = xdr_encode_string(p, name);
 704         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 705                 nfs_rpc_free(p0);
 706                 return status;
 707         }
 708         if (!(p = nfs_rpc_verify(p0)))
 709                 status = -errno_NFSERR_IO;
 710         else if ((status = ntohl(*p++)) == NFS_OK) {
 711                 PRINTK("NFS reply rmdir\n");
 712                 /* status = 0; */
 713         }
 714         else {
 715                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 716                         ruid = 1;
 717                         goto retry;
 718                 }
 719                 PRINTK("NFS reply rmdir failed = %d\n", status);
 720                 status = -nfs_stat_to_errno(status);
 721         }
 722         nfs_rpc_free(p0);
 723         return status;
 724 }
 725 
 726 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 727                      int cookie, int count, struct nfs_entry *entry)
 728 {
 729         int *p, *p0;
 730         int status;
 731         int ruid = 0;
 732         int i;
 733         int size;
 734         int eof;
 735 
 736         PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
 737         size = server->rsize;
 738         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 739                 return -EIO;
 740 retry:
 741         p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
 742         p = xdr_encode_fhandle(p, fhandle);
 743         *p++ = htonl(cookie);
 744         *p++ = htonl(size);
 745         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 746                 nfs_rpc_free(p0);
 747                 return status;
 748         }
 749         if (!(p = nfs_rpc_verify(p0)))
 750                 status = -errno_NFSERR_IO;
 751         else if ((status = ntohl(*p++)) == NFS_OK) {
 752                 for (i = 0; i < count && *p++; i++) {
 753                         if (!(p = xdr_decode_entry(p, entry++)))
 754                                 break;
 755                 }
 756                 if (!p) {
 757                         printk("nfs_proc_readdir: giant filename\n");
 758                         status = -errno_NFSERR_IO;
 759                 }
 760                 else {
 761                         eof = (i == count && !*p++ && *p++)
 762                               || (i < count && *p++);
 763                         if (eof && i)
 764                                 entry[-1].eof = 1;
 765                         PRINTK("NFS reply readdir %d %s\n", i,
 766                                eof ? "eof" : "");
 767                         status = i;
 768                 }
 769         }
 770         else {
 771                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 772                         ruid = 1;
 773                         goto retry;
 774                 }
 775                 PRINTK("NFS reply readdir failed = %d\n", status);
 776                 status = -nfs_stat_to_errno(status);
 777         }
 778         nfs_rpc_free(p0);
 779         return status;
 780 }
 781 
 782 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 783                     struct nfs_fsinfo *res)
 784 {
 785         int *p, *p0;
 786         int status;
 787         int ruid = 0;
 788 
 789         PRINTK("NFS call  statfs\n");
 790         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 791                 return -EIO;
 792 retry:
 793         p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
 794         p = xdr_encode_fhandle(p, fhandle);
 795         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 796                 nfs_rpc_free(p0);
 797                 return status;
 798         }
 799         if (!(p = nfs_rpc_verify(p0)))
 800                 status = -errno_NFSERR_IO;
 801         else if ((status = ntohl(*p++)) == NFS_OK) {
 802                 p = xdr_decode_fsinfo(p, res);
 803                 PRINTK("NFS reply statfs\n");
 804                 /* status = 0; */
 805         }
 806         else {
 807                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 808                         ruid = 1;
 809                         goto retry;
 810                 }
 811                 PRINTK("NFS reply statfs failed = %d\n", status);
 812                 status = -nfs_stat_to_errno(status);
 813         }
 814         nfs_rpc_free(p0);
 815         return status;
 816 }
 817 
 818 /*
 819  * Here are a few RPC-assist functions.
 820  */
 821 
 822 static int *nfs_rpc_header(int *p, int procedure, int ruid)
     /* [previous][next][first][last][top][bottom][index][help] */
 823 {
 824         int *p1, *p2;
 825         int i;
 826         static int xid = 0;
 827         unsigned char *sys = (unsigned char *) system_utsname.nodename;
 828 
 829         if (xid == 0) {
 830                 xid = CURRENT_TIME;
 831                 xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
 832         }
 833         *p++ = htonl(++xid);
 834         *p++ = htonl(RPC_CALL);
 835         *p++ = htonl(RPC_VERSION);
 836         *p++ = htonl(NFS_PROGRAM);
 837         *p++ = htonl(NFS_VERSION);
 838         *p++ = htonl(procedure);
 839         *p++ = htonl(RPC_AUTH_UNIX);
 840         p1 = p++;
 841         *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 842         p = xdr_encode_string(p, (char *) sys);
 843         *p++ = htonl(ruid ? current->uid : current->fsuid);
 844         *p++ = htonl(current->egid);
 845         p2 = p++;
 846         for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
 847                 *p++ = htonl(current->groups[i]);
 848         *p2 = htonl(i);
 849         *p1 = htonl((p - (p1 + 1)) << 2);
 850         *p++ = htonl(RPC_AUTH_NULL);
 851         *p++ = htonl(0);
 852         return p;
 853 }
 854 
 855 static int *nfs_rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857         unsigned int n;
 858 
 859         p++;
 860         if ((n = ntohl(*p++)) != RPC_REPLY) {
 861                 printk("nfs_rpc_verify: not an RPC reply: %d\n", n);
 862                 return NULL;
 863         }
 864         if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 865                 printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
 866                 return NULL;
 867         }
 868         switch (n = ntohl(*p++)) {
 869         case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
 870                 break;
 871         default:
 872                 printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
 873                 return NULL;
 874         }
 875         if ((n = ntohl(*p++)) > 400) {
 876                 printk("nfs_rpc_verify: giant auth size\n");
 877                 return NULL;
 878         }
 879         p += QUADLEN(n);
 880         if ((n = ntohl(*p++)) != RPC_SUCCESS) {
 881                 printk("nfs_rpc_verify: RPC call failed: %d\n", n);
 882                 return NULL;
 883         }
 884         return p;
 885 }
 886         
 887 /*
 888  * We need to translate between nfs status return values and
 889  * the local errno values which may not be the same.
 890  */
 891 
 892 static struct {
 893         int stat;
 894         int errno;
 895 } nfs_errtbl[] = {
 896         { NFS_OK,               0               },
 897         { NFSERR_PERM,          EPERM           },
 898         { NFSERR_NOENT,         ENOENT          },
 899         { NFSERR_IO,            errno_NFSERR_IO },
 900         { NFSERR_NXIO,          ENXIO           },
 901         { NFSERR_ACCES,         EACCES          },
 902         { NFSERR_EXIST,         EEXIST          },
 903         { NFSERR_NODEV,         ENODEV          },
 904         { NFSERR_NOTDIR,        ENOTDIR         },
 905         { NFSERR_ISDIR,         EISDIR          },
 906         { NFSERR_INVAL,         EINVAL          },
 907         { NFSERR_FBIG,          EFBIG           },
 908         { NFSERR_NOSPC,         ENOSPC          },
 909         { NFSERR_ROFS,          EROFS           },
 910         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
 911         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
 912         { NFSERR_DQUOT,         EDQUOT          },
 913         { NFSERR_STALE,         ESTALE          },
 914 #ifdef EWFLUSH
 915         { NFSERR_WFLUSH,        EWFLUSH         },
 916 #endif
 917         { -1,                   EIO             }
 918 };
 919 
 920 static int nfs_stat_to_errno(int stat)
     /* [previous][next][first][last][top][bottom][index][help] */
 921 {
 922         int i;
 923 
 924         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
 925                 if (nfs_errtbl[i].stat == stat)
 926                         return nfs_errtbl[i].errno;
 927         }
 928         printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
 929         return nfs_errtbl[i].errno;
 930 }
 931 

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