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

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