home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / nfs / proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-14  |  20.3 KB  |  874 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.  
  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)
  53. {
  54.     return (int *) __get_free_page(GFP_KERNEL);
  55. }
  56.  
  57. static inline void nfs_rpc_free(int *p)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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)
  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,
  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,
  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,
  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,
  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)
  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,
  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,
  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)
  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)
  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)
  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.  
  874.