209 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Inode operations for Coda filesystem4 * Original version: (C) 1996 P. Braam and M. Callahan5 * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University6 * 7 * Carnegie Mellon encourages users to contribute improvements to8 * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).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 */25int coda_fake_statfs;26 27/* print a fid */28char * 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 */38int coda_iscontrol(const char *name, size_t length)39{40 return ((CODA_CONTROLLEN == length) && 41 (strncmp(name, CODA_CONTROL, CODA_CONTROLLEN) == 0));42}43 44unsigned 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 69static 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 79static 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 */90umode_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 105void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)106{107 /* inode's i_flags, i_ino are set by iget108 * 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 be140 * 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 145void 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 0171 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