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

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