summaryrefslogtreecommitdiff
path: root/nfsd/xdr.c
blob: 8b17559598763da94d6facec712c66ef1a33839f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* xdr.c - XDR packing and unpacking in nfsd.

   Copyright (C) 1996, 2002, 2007 Free Software Foundation, Inc.

   Written by Michael I. Bushnell, p/BSG.

   This file is part of the GNU Hurd.

   The GNU Hurd is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   The GNU Hurd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */

#include <sys/stat.h>
#include <sys/statfs.h>
#include <string.h>
#include "nfsd.h"

/* Any better ideas?  */
static int
hurd_mode_to_nfs_mode (mode_t m)
{
  return m & 0177777;
}

static int
hurd_mode_to_nfs_type (mode_t m, int version)
{
  switch (m & S_IFMT)
    {
    case S_IFDIR:
      return NFDIR;

    case S_IFCHR:
      return NFCHR;
      
    case S_IFBLK:
      return NFBLK;
      
    case S_IFREG:
      return NFREG;
      
    case S_IFLNK:
      return NFLNK;
      
    case S_IFSOCK:
      return NFSOCK;
      
    case S_IFIFO:
      return (version == 2 ? NF2FIFO : NF3FIFO);
      
    default:
      return (version == 2 ? NF2NON : NFREG);
    }
}

/* Encode ST into P and return the next thing to come after it.  */
int *
encode_fattr (int *p, struct stat *st, int version)
{
  *(p++) = htonl (hurd_mode_to_nfs_type (st->st_mode, version));
  *(p++) = htonl (hurd_mode_to_nfs_mode (st->st_mode));
  *(p++) = htonl (st->st_nlink);
  *(p++) = htonl (st->st_uid);
  *(p++) = htonl (st->st_gid);
  *(p++) = htonl (st->st_size);
  *(p++) = htonl (st->st_blksize);
  *(p++) = htonl (st->st_rdev);
  *(p++) = htonl (st->st_blocks);
  *(p++) = htonl (st->st_fsid);
  *(p++) = htonl (st->st_ino);
  *(p++) = htonl (st->st_atim.tv_sec);
  *(p++) = htonl (st->st_atim.tv_nsec / 1000);
  *(p++) = htonl (st->st_mtim.tv_sec);
  *(p++) = htonl (st->st_mtim.tv_nsec / 1000);
  *(p++) = htonl (st->st_ctim.tv_sec);
  *(p++) = htonl (st->st_ctim.tv_nsec / 1000);
  return p;
}

/* Decode P into NAME and return the next thing to come after it.  */
int *
decode_name (int *p, char **name)
{
  int len;
  
  len = ntohl (*p);
  p++;
  *name = malloc (len + 1);
  memcpy (*name, p, len);
  (*name)[len] = '\0';
  return p + INTSIZE (len);
}

/* Encode HANDLE into P and return the next thing to come after it.  */
int *
encode_fhandle (int *p, char *handle)
{
  memcpy (p, handle, NFS2_FHSIZE);
  return p + INTSIZE (NFS2_FHSIZE);
}

/* Encode STRING into P and return the next thing to come after it.  */
int *
encode_string (int *p, char *string)
{
  return encode_data (p, string, strlen (string));
}

/* Encode DATA into P and return the next thing to come after it.  */
int *
encode_data (int *p, char *data, size_t len)
{
  int nints = INTSIZE (len);
  
  p[nints] = 0;
  *(p++) = htonl (len);
  memcpy (p, data, len);
  return p + nints;
}

/* Encode ST into P and return the next thing to come after it.  */
int *
encode_statfs (int *p, struct statfs *st)
{
  *(p++) = st->f_bsize;
  *(p++) = st->f_bsize;
  *(p++) = st->f_blocks;
  *(p++) = st->f_bfree;
  *(p++) = st->f_bavail;
  return p;
}

/* Return an NFS error corresponding to Hurd error ERR.  */
int
nfs_error_trans (error_t err, int version)
{
  switch (err)
    {
    case 0:
      return NFS_OK;
      
    case EPERM:
      return NFSERR_PERM;
      
    case ENOENT:
      return NFSERR_NOENT;
      
    case EIO:
      return NFSERR_IO;
      
    case ENXIO:
      return NFSERR_NXIO;
      
    case EACCES:
      return NFSERR_ACCES;
      
    case EEXIST:
      return NFSERR_EXIST;
      
    case ENODEV:
      return NFSERR_NODEV;
      
    case ENOTDIR:
      return NFSERR_NOTDIR;
      
    case EISDIR:
      return NFSERR_ISDIR;
      
    case E2BIG:
      return NFSERR_FBIG;
      
    case ENOSPC:
      return NFSERR_NOSPC;
      
    case EROFS:
      return NFSERR_ROFS;
      
    case ENAMETOOLONG:
      return NFSERR_NAMETOOLONG;
      
    case ENOTEMPTY:
      return NFSERR_NOTEMPTY;
      
    case EDQUOT:
      return NFSERR_DQUOT;
      
    case ESTALE:
      return NFSERR_STALE;

    default:
      if (version == 2)
	return NFSERR_IO;
      else switch (err)
	{
	case EXDEV:
	  return NFSERR_XDEV;
	  
	case EINVAL:
	  return NFSERR_INVAL;
	  
	case EOPNOTSUPP:
	  return NFSERR_NOTSUPP;	/* Are we sure here?  */
	  
	default:
	  return NFSERR_IO;
	}
    }
}