before overlay
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
e92a04af 1/* lfs_vnops.c 4.12 81/11/08 */
d67a03eb
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mount.h"
6#include "../h/ino.h"
7#include "../h/reg.h"
8#include "../h/buf.h"
9#include "../h/filsys.h"
10#include "../h/dir.h"
11#include "../h/user.h"
12#include "../h/inode.h"
13#include "../h/file.h"
14#include "../h/conf.h"
15#include "../h/stat.h"
0737b714 16#include "../h/inline.h"
d67a03eb
BJ
17
18/*
19 * the fstat system call.
20 */
21fstat()
22{
23 register struct file *fp;
24 register struct a {
25 int fdes;
26 struct stat *sb;
27 } *uap;
28
29 uap = (struct a *)u.u_ap;
30 fp = getf(uap->fdes);
e92a04af 31 if (fp == NULL)
d67a03eb 32 return;
e92a04af
BJ
33 if (fp->f_flag & FSOCKET)
34 sostat(fp->f_socket);
35 else
36 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
37}
38
39/*
e92a04af 40 * Stat system call.
d67a03eb
BJ
41 */
42stat()
43{
44 register struct inode *ip;
45 register struct a {
46 char *fname;
47 struct stat *sb;
48 } *uap;
49
50 uap = (struct a *)u.u_ap;
51 ip = namei(uchar, 0);
e92a04af 52 if (ip == NULL)
d67a03eb 53 return;
a3aa7f92 54 stat1(ip, uap->sb);
d67a03eb
BJ
55 iput(ip);
56}
57
58/*
59 * The basic routine for fstat and stat:
60 * get the inode and pass appropriate parts back.
61 */
a3aa7f92 62stat1(ip, ub)
e92a04af
BJ
63 register struct inode *ip;
64 struct stat *ub;
d67a03eb
BJ
65{
66 register struct dinode *dp;
67 register struct buf *bp;
68 struct stat ds;
69
c0bb1685 70 IUPDAT(ip, &time, &time, 0);
d67a03eb 71 /*
e92a04af 72 * First copy from inode table
d67a03eb
BJ
73 */
74 ds.st_dev = ip->i_dev;
75 ds.st_ino = ip->i_number;
76 ds.st_mode = ip->i_mode;
77 ds.st_nlink = ip->i_nlink;
78 ds.st_uid = ip->i_uid;
79 ds.st_gid = ip->i_gid;
80 ds.st_rdev = (dev_t)ip->i_un.i_rdev;
a3aa7f92 81 ds.st_size = ip->i_size;
d67a03eb 82 /*
e92a04af 83 * Next the dates in the disk
d67a03eb
BJ
84 */
85 bp = bread(ip->i_dev, itod(ip->i_number));
86 dp = bp->b_un.b_dino;
87 dp += itoo(ip->i_number);
88 ds.st_atime = dp->di_atime;
89 ds.st_mtime = dp->di_mtime;
90 ds.st_ctime = dp->di_ctime;
91 brelse(bp);
92 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
93 u.u_error = EFAULT;
94}
95
96/*
e92a04af 97 * Dup system call.
d67a03eb
BJ
98 */
99dup()
100{
101 register struct file *fp;
102 register struct a {
103 int fdes;
104 int fdes2;
105 } *uap;
106 register i, m;
107
108 uap = (struct a *)u.u_ap;
109 m = uap->fdes & ~077;
110 uap->fdes &= 077;
111 fp = getf(uap->fdes);
e92a04af 112 if (fp == NULL)
d67a03eb
BJ
113 return;
114 if ((m&0100) == 0) {
115 if ((i = ufalloc()) < 0)
116 return;
117 } else {
118 i = uap->fdes2;
119 if (i<0 || i>=NOFILE) {
120 u.u_error = EBADF;
121 return;
122 }
d67a03eb
BJ
123 u.u_r.r_val1 = i;
124 }
e92a04af 125 if (i != uap->fdes) {
d67a03eb
BJ
126 if (u.u_ofile[i]!=NULL)
127 closef(u.u_ofile[i]);
128 u.u_ofile[i] = fp;
129 fp->f_count++;
130 }
131}
132
133/*
e92a04af 134 * Mount system call.
d67a03eb 135 */
e92a04af
BJ
136smount()
137{
d67a03eb
BJ
138 dev_t dev;
139 register struct inode *ip;
140 register struct mount *mp;
141 struct mount *smp;
142 register struct filsys *fp;
143 struct buf *bp;
144 register struct a {
145 char *fspec;
146 char *freg;
147 int ronly;
148 } *uap;
1e608f17 149 register char *cp;
d67a03eb
BJ
150
151 uap = (struct a *)u.u_ap;
152 dev = getmdev();
e92a04af 153 if (u.u_error)
d67a03eb
BJ
154 return;
155 u.u_dirp = (caddr_t)uap->freg;
156 ip = namei(uchar, 0);
e92a04af 157 if (ip == NULL)
d67a03eb 158 return;
e92a04af 159 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
d67a03eb
BJ
160 goto out;
161 smp = NULL;
e92a04af
BJ
162 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
163 if (mp->m_bufp != NULL) {
164 if (dev == mp->m_dev)
d67a03eb
BJ
165 goto out;
166 } else
e92a04af 167 if (smp == NULL)
d67a03eb
BJ
168 smp = mp;
169 }
170 mp = smp;
e92a04af 171 if (mp == NULL)
d67a03eb
BJ
172 goto out;
173 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
e92a04af 174 if (u.u_error)
d67a03eb
BJ
175 goto out;
176 bp = bread(dev, SUPERB);
e92a04af 177 if (u.u_error) {
d67a03eb
BJ
178 brelse(bp);
179 goto out1;
180 }
181 mp->m_inodp = ip;
182 mp->m_dev = dev;
2c3059b1
BJ
183 bp->b_flags |= B_LOCKED;
184 mp->m_bufp = bp;
185 fp = bp->b_un.b_filsys;
d67a03eb
BJ
186 fp->s_ilock = 0;
187 fp->s_flock = 0;
188 fp->s_ronly = uap->ronly & 1;
189 fp->s_nbehind = 0;
190 fp->s_lasti = 1;
1e608f17
BJ
191 u.u_dirp = uap->freg;
192 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
193 if ((*cp++ = uchar()) == 0)
194 u.u_dirp--; /* get 0 again */
195 *cp = 0;
d67a03eb
BJ
196 brelse(bp);
197 ip->i_flag |= IMOUNT;
e92a04af 198 irele(ip);
d67a03eb
BJ
199 return;
200
201out:
202 u.u_error = EBUSY;
203out1:
204 iput(ip);
205}
206
207/*
208 * the umount system call.
209 */
210sumount()
211{
212 dev_t dev;
213 register struct inode *ip;
214 register struct mount *mp;
215 struct buf *bp;
2c3059b1 216 int stillopen, flag;
d67a03eb
BJ
217 register struct a {
218 char *fspec;
219 };
220
221 dev = getmdev();
e92a04af 222 if (u.u_error)
d67a03eb
BJ
223 return;
224 xumount(dev); /* remove unused sticky files from text table */
225 update();
e92a04af
BJ
226 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
227 if (mp->m_bufp != NULL && dev == mp->m_dev)
d67a03eb
BJ
228 goto found;
229 u.u_error = EINVAL;
230 return;
231
232found:
9491f93d 233 stillopen = 0;
e92a04af 234 for (ip = inode; ip < inodeNINODE; ip++)
2c3059b1 235 if (ip->i_number != 0 && dev == ip->i_dev) {
d67a03eb
BJ
236 u.u_error = EBUSY;
237 return;
2c3059b1
BJ
238 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
239 ip->i_un.i_rdev == dev)
240 stillopen++;
d67a03eb
BJ
241 ip = mp->m_inodp;
242 ip->i_flag &= ~IMOUNT;
e92a04af 243 ilock(ip);
d67a03eb 244 iput(ip);
2c3059b1
BJ
245 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
246 panic("umount");
247 bp->b_flags &= ~B_LOCKED;
4a18fb8e 248 flag = !bp->b_un.b_filsys->s_ronly;
d67a03eb
BJ
249 mp->m_bufp = NULL;
250 brelse(bp);
aa250f32 251 mpurge(mp - &mount[0]);
4a18fb8e 252 if (!stillopen) {
4a18fb8e
RE
253 (*bdevsw[major(dev)].d_close)(dev, flag);
254 binval(dev);
255 }
d67a03eb
BJ
256}
257
258/*
259 * Common code for mount and umount.
260 * Check that the user's argument is a reasonable
261 * thing on which to mount, and return the device number if so.
262 */
263dev_t
264getmdev()
265{
266 dev_t dev;
267 register struct inode *ip;
268
d67a03eb
BJ
269 if (!suser())
270 return(NODEV);
d67a03eb 271 ip = namei(uchar, 0);
e92a04af 272 if (ip == NULL)
d67a03eb 273 return(NODEV);
e92a04af 274 if ((ip->i_mode&IFMT) != IFBLK)
d67a03eb
BJ
275 u.u_error = ENOTBLK;
276 dev = (dev_t)ip->i_un.i_rdev;
e92a04af 277 if (major(dev) >= nblkdev)
d67a03eb
BJ
278 u.u_error = ENXIO;
279 iput(ip);
280 return(dev);
281}