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