xref: /openbmc/linux/fs/coda/coda_linux.c (revision ea9b53d4)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Inode operations for Coda filesystem
41da177e4SLinus Torvalds  * Original version: (C) 1996 P. Braam and M. Callahan
51da177e4SLinus Torvalds  * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Carnegie Mellon encourages users to contribute improvements to
81da177e4SLinus Torvalds  * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/types.h>
121da177e4SLinus Torvalds #include <linux/kernel.h>
131da177e4SLinus Torvalds #include <linux/time.h>
141da177e4SLinus Torvalds #include <linux/fs.h>
151da177e4SLinus Torvalds #include <linux/stat.h>
161da177e4SLinus Torvalds #include <linux/errno.h>
17834b46c3SFabian Frederick #include <linux/uaccess.h>
181da177e4SLinus Torvalds #include <linux/string.h>
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include <linux/coda.h>
218fc8b9dfSDavid Howells #include "coda_psdev.h"
2231a203dfSAl Viro #include "coda_linux.h"
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds /* initialize the debugging variables */
251da177e4SLinus Torvalds int coda_fake_statfs;
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds /* print a fid */
coda_f2s(struct CodaFid * f)281da177e4SLinus Torvalds char * coda_f2s(struct CodaFid *f)
291da177e4SLinus Torvalds {
301da177e4SLinus Torvalds 	static char s[60];
31de0ca06aSAdrian Bunk 
321da177e4SLinus Torvalds  	sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
33de0ca06aSAdrian Bunk 
341da177e4SLinus Torvalds 	return s;
351da177e4SLinus Torvalds }
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds /* recognize special .CONTROL name */
coda_iscontrol(const char * name,size_t length)381da177e4SLinus Torvalds int coda_iscontrol(const char *name, size_t length)
391da177e4SLinus Torvalds {
401da177e4SLinus Torvalds 	return ((CODA_CONTROLLEN == length) &&
411da177e4SLinus Torvalds                 (strncmp(name, CODA_CONTROL, CODA_CONTROLLEN) == 0));
421da177e4SLinus Torvalds }
431da177e4SLinus Torvalds 
coda_flags_to_cflags(unsigned short flags)441da177e4SLinus Torvalds unsigned short coda_flags_to_cflags(unsigned short flags)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	unsigned short coda_flags = 0;
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	if ((flags & O_ACCMODE) == O_RDONLY)
491da177e4SLinus Torvalds 		coda_flags |= C_O_READ;
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds 	if ((flags & O_ACCMODE) == O_RDWR)
521da177e4SLinus Torvalds 		coda_flags |= C_O_READ | C_O_WRITE;
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds 	if ((flags & O_ACCMODE) == O_WRONLY)
551da177e4SLinus Torvalds 		coda_flags |= C_O_WRITE;
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds 	if (flags & O_TRUNC)
581da177e4SLinus Torvalds 		coda_flags |= C_O_TRUNC;
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds 	if (flags & O_CREAT)
611da177e4SLinus Torvalds 		coda_flags |= C_O_CREAT;
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds 	if (flags & O_EXCL)
641da177e4SLinus Torvalds 		coda_flags |= C_O_EXCL;
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds 	return coda_flags;
671da177e4SLinus Torvalds }
681da177e4SLinus Torvalds 
coda_to_timespec64(struct coda_timespec ts)695e7c31dfSJan Harkes static struct timespec64 coda_to_timespec64(struct coda_timespec ts)
706ced9aa7SArnd Bergmann {
716ced9aa7SArnd Bergmann 	struct timespec64 ts64 = {
726ced9aa7SArnd Bergmann 		.tv_sec = ts.tv_sec,
736ced9aa7SArnd Bergmann 		.tv_nsec = ts.tv_nsec,
746ced9aa7SArnd Bergmann 	};
756ced9aa7SArnd Bergmann 
766ced9aa7SArnd Bergmann 	return ts64;
776ced9aa7SArnd Bergmann }
786ced9aa7SArnd Bergmann 
timespec64_to_coda(struct timespec64 ts64)795e7c31dfSJan Harkes static struct coda_timespec timespec64_to_coda(struct timespec64 ts64)
806ced9aa7SArnd Bergmann {
815e7c31dfSJan Harkes 	struct coda_timespec ts = {
825e7c31dfSJan Harkes 		.tv_sec = ts64.tv_sec,
836ced9aa7SArnd Bergmann 		.tv_nsec = ts64.tv_nsec,
846ced9aa7SArnd Bergmann 	};
856ced9aa7SArnd Bergmann 
866ced9aa7SArnd Bergmann 	return ts;
876ced9aa7SArnd Bergmann }
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds /* utility functions below */
coda_inode_type(struct coda_vattr * attr)905a646fb3SJan Harkes umode_t coda_inode_type(struct coda_vattr *attr)
915a646fb3SJan Harkes {
925a646fb3SJan Harkes 	switch (attr->va_type) {
935a646fb3SJan Harkes 	case C_VREG:
945a646fb3SJan Harkes 		return S_IFREG;
955a646fb3SJan Harkes 	case C_VDIR:
965a646fb3SJan Harkes 		return S_IFDIR;
975a646fb3SJan Harkes 	case C_VLNK:
985a646fb3SJan Harkes 		return S_IFLNK;
995a646fb3SJan Harkes 	case C_VNON:
1005a646fb3SJan Harkes 	default:
1015a646fb3SJan Harkes 		return 0;
1025a646fb3SJan Harkes 	}
1035a646fb3SJan Harkes }
1045a646fb3SJan Harkes 
coda_vattr_to_iattr(struct inode * inode,struct coda_vattr * attr)1051da177e4SLinus Torvalds void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
1061da177e4SLinus Torvalds {
1071da177e4SLinus Torvalds 	/* inode's i_flags, i_ino are set by iget
1085a646fb3SJan Harkes 	 * XXX: is this all we need ??
1091da177e4SLinus Torvalds 	 */
1105a646fb3SJan Harkes 	umode_t inode_type = coda_inode_type(attr);
1111da177e4SLinus Torvalds 	inode->i_mode |= inode_type;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	if (attr->va_mode != (u_short) -1)
1141da177e4SLinus Torvalds 	        inode->i_mode = attr->va_mode | inode_type;
1151da177e4SLinus Torvalds         if (attr->va_uid != -1)
116d83f5901SEric W. Biederman 	        inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid);
1171da177e4SLinus Torvalds         if (attr->va_gid != -1)
118d83f5901SEric W. Biederman 	        inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid);
1191da177e4SLinus Torvalds 	if (attr->va_nlink != -1)
120bfe86848SMiklos Szeredi 		set_nlink(inode, attr->va_nlink);
1211da177e4SLinus Torvalds 	if (attr->va_size != -1)
1221da177e4SLinus Torvalds 	        inode->i_size = attr->va_size;
1231da177e4SLinus Torvalds 	if (attr->va_size != -1)
1241da177e4SLinus Torvalds 		inode->i_blocks = (attr->va_size + 511) >> 9;
1251da177e4SLinus Torvalds 	if (attr->va_atime.tv_sec != -1)
1266ced9aa7SArnd Bergmann 		inode->i_atime = coda_to_timespec64(attr->va_atime);
1271da177e4SLinus Torvalds 	if (attr->va_mtime.tv_sec != -1)
1286ced9aa7SArnd Bergmann 		inode->i_mtime = coda_to_timespec64(attr->va_mtime);
1291da177e4SLinus Torvalds         if (attr->va_ctime.tv_sec != -1)
130*ea9b53d4SJeff Layton 		inode_set_ctime_to_ts(inode,
131*ea9b53d4SJeff Layton 				      coda_to_timespec64(attr->va_ctime));
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds  * BSD sets attributes that need not be modified to -1.
1371da177e4SLinus Torvalds  * Linux uses the valid field to indicate what should be
1381da177e4SLinus Torvalds  * looked at.  The BSD type field needs to be deduced from linux
1391da177e4SLinus Torvalds  * mode.
1401da177e4SLinus Torvalds  * So we have to do some translations here.
1411da177e4SLinus Torvalds  */
1421da177e4SLinus Torvalds 
coda_iattr_to_vattr(struct iattr * iattr,struct coda_vattr * vattr)1431da177e4SLinus Torvalds void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
1441da177e4SLinus Torvalds {
1451da177e4SLinus Torvalds         unsigned int valid;
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds         /* clean out */
148a2d416dcSAndrew Morton 	vattr->va_mode = -1;
1491da177e4SLinus Torvalds         vattr->va_uid = (vuid_t) -1;
1501da177e4SLinus Torvalds         vattr->va_gid = (vgid_t) -1;
1511da177e4SLinus Torvalds         vattr->va_size = (off_t) -1;
1525e7c31dfSJan Harkes 	vattr->va_atime.tv_sec = (int64_t) -1;
1536ced9aa7SArnd Bergmann 	vattr->va_atime.tv_nsec = (long) -1;
1545e7c31dfSJan Harkes 	vattr->va_mtime.tv_sec = (int64_t) -1;
1556ced9aa7SArnd Bergmann 	vattr->va_mtime.tv_nsec = (long) -1;
1565e7c31dfSJan Harkes 	vattr->va_ctime.tv_sec = (int64_t) -1;
1576ced9aa7SArnd Bergmann 	vattr->va_ctime.tv_nsec = (long) -1;
1581da177e4SLinus Torvalds         vattr->va_type = C_VNON;
1591da177e4SLinus Torvalds 	vattr->va_fileid = -1;
1601da177e4SLinus Torvalds 	vattr->va_gen = -1;
1611da177e4SLinus Torvalds 	vattr->va_bytes = -1;
1621da177e4SLinus Torvalds 	vattr->va_nlink = -1;
1631da177e4SLinus Torvalds 	vattr->va_blocksize = -1;
1641da177e4SLinus Torvalds 	vattr->va_rdev = -1;
1651da177e4SLinus Torvalds         vattr->va_flags = 0;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds         /* determine the type */
1681da177e4SLinus Torvalds #if 0
1691da177e4SLinus Torvalds         mode = iattr->ia_mode;
1701da177e4SLinus Torvalds                 if ( S_ISDIR(mode) ) {
1711da177e4SLinus Torvalds                 vattr->va_type = C_VDIR;
1721da177e4SLinus Torvalds         } else if ( S_ISREG(mode) ) {
1731da177e4SLinus Torvalds                 vattr->va_type = C_VREG;
1741da177e4SLinus Torvalds         } else if ( S_ISLNK(mode) ) {
1751da177e4SLinus Torvalds                 vattr->va_type = C_VLNK;
1761da177e4SLinus Torvalds         } else {
1771da177e4SLinus Torvalds                 /* don't do others */
1781da177e4SLinus Torvalds                 vattr->va_type = C_VNON;
1791da177e4SLinus Torvalds         }
1801da177e4SLinus Torvalds #endif
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds         /* set those vattrs that need change */
1831da177e4SLinus Torvalds         valid = iattr->ia_valid;
1841da177e4SLinus Torvalds         if ( valid & ATTR_MODE ) {
1851da177e4SLinus Torvalds                 vattr->va_mode = iattr->ia_mode;
1861da177e4SLinus Torvalds 	}
1871da177e4SLinus Torvalds         if ( valid & ATTR_UID ) {
188d83f5901SEric W. Biederman                 vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
1891da177e4SLinus Torvalds 	}
1901da177e4SLinus Torvalds         if ( valid & ATTR_GID ) {
191d83f5901SEric W. Biederman                 vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
1921da177e4SLinus Torvalds 	}
1931da177e4SLinus Torvalds         if ( valid & ATTR_SIZE ) {
1941da177e4SLinus Torvalds                 vattr->va_size = iattr->ia_size;
1951da177e4SLinus Torvalds 	}
1961da177e4SLinus Torvalds         if ( valid & ATTR_ATIME ) {
1976ced9aa7SArnd Bergmann 		vattr->va_atime = timespec64_to_coda(iattr->ia_atime);
1981da177e4SLinus Torvalds 	}
1991da177e4SLinus Torvalds         if ( valid & ATTR_MTIME ) {
2006ced9aa7SArnd Bergmann 		vattr->va_mtime = timespec64_to_coda(iattr->ia_mtime);
2011da177e4SLinus Torvalds 	}
2021da177e4SLinus Torvalds         if ( valid & ATTR_CTIME ) {
2036ced9aa7SArnd Bergmann 		vattr->va_ctime = timespec64_to_coda(iattr->ia_ctime);
2041da177e4SLinus Torvalds 	}
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds 
207