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

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