home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / nfs / proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-29  |  22.5 KB  |  936 lines

  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)
  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)
  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)
  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)
  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)
  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)
  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,
  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)
  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,
  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)
  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)
  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)
  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)
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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)
  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,
  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,
  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,
  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,
  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)
  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,
  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,
  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)
  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)
  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)
  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.  
  936.