Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/coda/coda_linux.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Inode operations for Coda filesystem
4
* Original version: (C) 1996 P. Braam and M. Callahan
5
* Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
6
*
7
* Carnegie Mellon encourages users to contribute improvements to
8
* the Coda project. Contact Peter Braam ([email protected]).
9
*/
10
11
#include <linux/types.h>
12
#include <linux/kernel.h>
13
#include <linux/time.h>
14
#include <linux/fs.h>
15
#include <linux/stat.h>
16
#include <linux/errno.h>
17
#include <linux/uaccess.h>
18
#include <linux/string.h>
19
20
#include <linux/coda.h>
21
#include "coda_psdev.h"
22
#include "coda_linux.h"
23
24
/* initialize the debugging variables */
25
int coda_fake_statfs;
26
27
/* print a fid */
28
char * coda_f2s(struct CodaFid *f)
29
{
30
static char s[60];
31
32
sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
33
34
return s;
35
}
36
37
/* recognize special .CONTROL name */
38
int coda_iscontrol(const char *name, size_t length)
39
{
40
return ((CODA_CONTROLLEN == length) &&
41
(strncmp(name, CODA_CONTROL, CODA_CONTROLLEN) == 0));
42
}
43
44
unsigned short coda_flags_to_cflags(unsigned short flags)
45
{
46
unsigned short coda_flags = 0;
47
48
if ((flags & O_ACCMODE) == O_RDONLY)
49
coda_flags |= C_O_READ;
50
51
if ((flags & O_ACCMODE) == O_RDWR)
52
coda_flags |= C_O_READ | C_O_WRITE;
53
54
if ((flags & O_ACCMODE) == O_WRONLY)
55
coda_flags |= C_O_WRITE;
56
57
if (flags & O_TRUNC)
58
coda_flags |= C_O_TRUNC;
59
60
if (flags & O_CREAT)
61
coda_flags |= C_O_CREAT;
62
63
if (flags & O_EXCL)
64
coda_flags |= C_O_EXCL;
65
66
return coda_flags;
67
}
68
69
static struct timespec64 coda_to_timespec64(struct coda_timespec ts)
70
{
71
struct timespec64 ts64 = {
72
.tv_sec = ts.tv_sec,
73
.tv_nsec = ts.tv_nsec,
74
};
75
76
return ts64;
77
}
78
79
static struct coda_timespec timespec64_to_coda(struct timespec64 ts64)
80
{
81
struct coda_timespec ts = {
82
.tv_sec = ts64.tv_sec,
83
.tv_nsec = ts64.tv_nsec,
84
};
85
86
return ts;
87
}
88
89
/* utility functions below */
90
umode_t coda_inode_type(struct coda_vattr *attr)
91
{
92
switch (attr->va_type) {
93
case C_VREG:
94
return S_IFREG;
95
case C_VDIR:
96
return S_IFDIR;
97
case C_VLNK:
98
return S_IFLNK;
99
case C_VNON:
100
default:
101
return 0;
102
}
103
}
104
105
void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
106
{
107
/* inode's i_flags, i_ino are set by iget
108
* XXX: is this all we need ??
109
*/
110
umode_t inode_type = coda_inode_type(attr);
111
inode->i_mode |= inode_type;
112
113
if (attr->va_mode != (u_short) -1)
114
inode->i_mode = attr->va_mode | inode_type;
115
if (attr->va_uid != -1)
116
inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid);
117
if (attr->va_gid != -1)
118
inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid);
119
if (attr->va_nlink != -1)
120
set_nlink(inode, attr->va_nlink);
121
if (attr->va_size != -1)
122
inode->i_size = attr->va_size;
123
if (attr->va_size != -1)
124
inode->i_blocks = (attr->va_size + 511) >> 9;
125
if (attr->va_atime.tv_sec != -1)
126
inode_set_atime_to_ts(inode,
127
coda_to_timespec64(attr->va_atime));
128
if (attr->va_mtime.tv_sec != -1)
129
inode_set_mtime_to_ts(inode,
130
coda_to_timespec64(attr->va_mtime));
131
if (attr->va_ctime.tv_sec != -1)
132
inode_set_ctime_to_ts(inode,
133
coda_to_timespec64(attr->va_ctime));
134
}
135
136
137
/*
138
* BSD sets attributes that need not be modified to -1.
139
* Linux uses the valid field to indicate what should be
140
* looked at. The BSD type field needs to be deduced from linux
141
* mode.
142
* So we have to do some translations here.
143
*/
144
145
void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
146
{
147
unsigned int valid;
148
149
/* clean out */
150
vattr->va_mode = -1;
151
vattr->va_uid = (vuid_t) -1;
152
vattr->va_gid = (vgid_t) -1;
153
vattr->va_size = (off_t) -1;
154
vattr->va_atime.tv_sec = (int64_t) -1;
155
vattr->va_atime.tv_nsec = (long) -1;
156
vattr->va_mtime.tv_sec = (int64_t) -1;
157
vattr->va_mtime.tv_nsec = (long) -1;
158
vattr->va_ctime.tv_sec = (int64_t) -1;
159
vattr->va_ctime.tv_nsec = (long) -1;
160
vattr->va_type = C_VNON;
161
vattr->va_fileid = -1;
162
vattr->va_gen = -1;
163
vattr->va_bytes = -1;
164
vattr->va_nlink = -1;
165
vattr->va_blocksize = -1;
166
vattr->va_rdev = -1;
167
vattr->va_flags = 0;
168
169
/* determine the type */
170
#if 0
171
mode = iattr->ia_mode;
172
if ( S_ISDIR(mode) ) {
173
vattr->va_type = C_VDIR;
174
} else if ( S_ISREG(mode) ) {
175
vattr->va_type = C_VREG;
176
} else if ( S_ISLNK(mode) ) {
177
vattr->va_type = C_VLNK;
178
} else {
179
/* don't do others */
180
vattr->va_type = C_VNON;
181
}
182
#endif
183
184
/* set those vattrs that need change */
185
valid = iattr->ia_valid;
186
if ( valid & ATTR_MODE ) {
187
vattr->va_mode = iattr->ia_mode;
188
}
189
if ( valid & ATTR_UID ) {
190
vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
191
}
192
if ( valid & ATTR_GID ) {
193
vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
194
}
195
if ( valid & ATTR_SIZE ) {
196
vattr->va_size = iattr->ia_size;
197
}
198
if ( valid & ATTR_ATIME ) {
199
vattr->va_atime = timespec64_to_coda(iattr->ia_atime);
200
}
201
if ( valid & ATTR_MTIME ) {
202
vattr->va_mtime = timespec64_to_coda(iattr->ia_mtime);
203
}
204
if ( valid & ATTR_CTIME ) {
205
vattr->va_ctime = timespec64_to_coda(iattr->ia_ctime);
206
}
207
}
208
209
210