File: setattr.c

package info (click to toggle)
netstd 3.07-7slink.3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 6,312 kB
  • ctags: 9,027
  • sloc: ansic: 72,107; cpp: 6,144; makefile: 1,650; yacc: 1,614; sh: 1,164; perl: 308; awk: 46
file content (128 lines) | stat: -rw-r--r-- 3,061 bytes parent folder | download | duplicates (2)
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
/*
 * getattr	This module handles the NFS attributes.
 *
 * Authors:	Mark A. Shand, May 1988
 *		Donald J. Becker, <becker@super.org>
 *		Rick Sladkey, <jrs@world.std.com>
 *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *		Olaf Kirch, <okir@monad.swb.de>
 *
 *		Copyright 1988 Mark A. Shand
 *		This software maybe be used for any purpose provided
 *		the above copyright notice is retained.  It is supplied
 *		as is, with no warranty expressed or implied.
 */

#include "nfsd.h"

/*
 * Set file attributes based on file handle
 */
nfsstat fh_setattr(fh, attr, s, rqstp, flags)
nfs_fh		*fh;
sattr		*attr;
struct stat	*s;
struct svc_req	*rqstp;
int		flags;
{
	char *path;
	nfsstat status;

	if ((path = fh_path(fh, &status)) == NULL) {
		Dprintf(D_CALL, "setattr failed: No such file.\n");
		return (NFSERR_STALE);
	}
	return setattr(path, attr, s, rqstp, flags);
}

/*
 * Set file attributes given the path. The flags argument
 * determines if we have to stat the file or if the stat buf
 * passed in s contains valid data.
 * As we go along and modify the file attributes, we update the
 * fields of this stat structure.
 */
nfsstat setattr(path, attr, s, rqstp, flags)
char		*path;
sattr		*attr;
struct stat	*s;
struct svc_req	*rqstp;
int		flags;
{
	struct stat	sbuf;

	if (s == NULL) {
		s = &sbuf;
		flags |= SATTR_STAT;
	}

	if ((flags & SATTR_STAT) && lstat(path, (s = &sbuf)) < 0) {
		Dprintf(D_CALL, "setattr: couldn't stat %s! errno=%d\n",
				path, errno);
		return nfs_errno();
	}

	if (flags & SATTR_SIZE) {
		unsigned int	size = attr->size;

		if (S_ISREG(s->st_mode) && size != -1) {
			if (truncate(path, size) < 0)
				goto failure;
			s->st_size = size;
		}
	}

	if (flags & SATTR_UTIMES) {
		unsigned int	a_secs = attr->atime.seconds;
		unsigned int	m_secs = attr->mtime.seconds;

		if ((a_secs != -1 && a_secs != s->st_atime)
		 || (m_secs != -1 && m_secs != s->st_mtime)) {
			struct timeval tvp[2];
			tvp[0].tv_sec = attr->atime.seconds;
			tvp[0].tv_usec = attr->atime.useconds;
			tvp[1].tv_sec = attr->mtime.seconds;
			tvp[1].tv_usec = attr->mtime.useconds;
			if (utimes(path, tvp) < 0)
				goto failure;
			if (attr->mtime.seconds != -1)
				s->st_atime = attr->atime.seconds;
			if (attr->mtime.seconds != -1)
				s->st_mtime = attr->mtime.seconds;
		}
	}

	if (flags & SATTR_CHMOD) {
		unsigned int	mode = attr->mode;

		if (mode != -1 && mode != 0xFFFF /* ultrix bug */
		 && (mode & 07777) != (s->st_mode & 07777)) {
			if (chmod(path, mode) < 0)
				goto failure;
			s->st_mode = (s->st_mode & ~07777) | (mode & 07777);
		}
	}

	if (flags & SATTR_CHOWN) {
		uid_t		uid = attr->uid;
		gid_t		gid = attr->gid;

		if (uid != (uid_t)-1)
			uid = luid(uid, nfsmount, rqstp);
		if (gid != (gid_t)-1)
			gid = lgid(gid, nfsmount, rqstp);

		if ((uid != (uid_t)-1 && uid != s->st_uid)
		 || (gid != (gid_t)-1 && gid != s->st_gid)) {
			if (lchown(path, uid, gid) < 0)
				goto failure;
			if (uid != (uid_t)-1) s->st_uid = uid;
			if (gid != (gid_t)-1) s->st_gid = gid;
		}
	}

	return (NFS_OK);

failure:
	return nfs_errno();
}