%H%->%G%
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
f86df66c 1/* lfs_vnops.c 3.3 %G% */
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);
31 if(fp == NULL)
32 return;
33 stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
34}
35
36/*
37 * the stat system call.
38 */
39stat()
40{
41 register struct inode *ip;
42 register struct a {
43 char *fname;
44 struct stat *sb;
45 } *uap;
46
47 uap = (struct a *)u.u_ap;
48 ip = namei(uchar, 0);
49 if(ip == NULL)
50 return;
51 stat1(ip, uap->sb, (off_t)0);
52 iput(ip);
53}
54
55/*
56 * The basic routine for fstat and stat:
57 * get the inode and pass appropriate parts back.
58 */
59stat1(ip, ub, pipeadj)
60register struct inode *ip;
61struct stat *ub;
62off_t pipeadj;
63{
64 register struct dinode *dp;
65 register struct buf *bp;
66 struct stat ds;
67
0737b714 68 IUPDAT(ip, &time, &time);
d67a03eb
BJ
69 /*
70 * first copy from inode table
71 */
72 ds.st_dev = ip->i_dev;
73 ds.st_ino = ip->i_number;
74 ds.st_mode = ip->i_mode;
75 ds.st_nlink = ip->i_nlink;
76 ds.st_uid = ip->i_uid;
77 ds.st_gid = ip->i_gid;
78 ds.st_rdev = (dev_t)ip->i_un.i_rdev;
79 ds.st_size = ip->i_size - pipeadj;
80 /*
81 * next the dates in the disk
82 */
83 bp = bread(ip->i_dev, itod(ip->i_number));
84 dp = bp->b_un.b_dino;
85 dp += itoo(ip->i_number);
86 ds.st_atime = dp->di_atime;
87 ds.st_mtime = dp->di_mtime;
88 ds.st_ctime = dp->di_ctime;
89 brelse(bp);
90 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
91 u.u_error = EFAULT;
92}
93
94/*
95 * the dup system call.
96 */
97dup()
98{
99 register struct file *fp;
100 register struct a {
101 int fdes;
102 int fdes2;
103 } *uap;
104 register i, m;
105
106 uap = (struct a *)u.u_ap;
107 m = uap->fdes & ~077;
108 uap->fdes &= 077;
109 fp = getf(uap->fdes);
110 if(fp == NULL)
111 return;
112 if ((m&0100) == 0) {
113 if ((i = ufalloc()) < 0)
114 return;
115 } else {
116 i = uap->fdes2;
117 if (i<0 || i>=NOFILE) {
118 u.u_error = EBADF;
119 return;
120 }
121 if (u.u_vrpages[i]) {
122 u.u_error = ETXTBSY;
123 return;
124 }
125 u.u_r.r_val1 = i;
126 }
127 if (i!=uap->fdes) {
128 if (u.u_ofile[i]!=NULL)
129 closef(u.u_ofile[i]);
130 u.u_ofile[i] = fp;
131 fp->f_count++;
132 }
133}
134
135/*
136 * the mount system call.
137 */
138smount()
139{
140 dev_t dev;
141 register struct inode *ip;
142 register struct mount *mp;
143 struct mount *smp;
144 register struct filsys *fp;
145 struct buf *bp;
146 register struct a {
147 char *fspec;
148 char *freg;
149 int ronly;
150 } *uap;
151
152 uap = (struct a *)u.u_ap;
153 dev = getmdev();
154 if(u.u_error)
155 return;
156 u.u_dirp = (caddr_t)uap->freg;
157 ip = namei(uchar, 0);
158 if(ip == NULL)
159 return;
160 if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
161 goto out;
162 smp = NULL;
163 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
164 if(mp->m_bufp != NULL) {
165 if(dev == mp->m_dev)
166 goto out;
167 } else
168 if(smp == NULL)
169 smp = mp;
170 }
171 mp = smp;
172 if(mp == NULL)
173 goto out;
174 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
175 if(u.u_error)
176 goto out;
177 bp = bread(dev, SUPERB);
178 if(u.u_error) {
179 brelse(bp);
180 goto out1;
181 }
182 mp->m_inodp = ip;
183 mp->m_dev = dev;
184 mp->m_bufp = geteblk();
185 bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
186 fp = mp->m_bufp->b_un.b_filsys;
187 fp->s_ilock = 0;
188 fp->s_flock = 0;
189 fp->s_ronly = uap->ronly & 1;
190 fp->s_nbehind = 0;
191 fp->s_lasti = 1;
192 brelse(bp);
193 ip->i_flag |= IMOUNT;
194 prele(ip);
195 return;
196
197out:
198 u.u_error = EBUSY;
199out1:
200 iput(ip);
201}
202
203/*
204 * the umount system call.
205 */
206sumount()
207{
208 dev_t dev;
209 register struct inode *ip;
210 register struct mount *mp;
211 struct buf *bp;
212 register struct a {
213 char *fspec;
214 };
215
216 dev = getmdev();
217 if(u.u_error)
218 return;
219 xumount(dev); /* remove unused sticky files from text table */
220 update();
221 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
222 if(mp->m_bufp != NULL && dev == mp->m_dev)
223 goto found;
224 u.u_error = EINVAL;
225 return;
226
227found:
228 for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
229 if(ip->i_number != 0 && dev == ip->i_dev) {
230 u.u_error = EBUSY;
231 return;
232 }
233 (*bdevsw[major(dev)].d_close)(dev, 0);
234 ip = mp->m_inodp;
235 ip->i_flag &= ~IMOUNT;
236 plock(ip);
237 iput(ip);
238 bp = mp->m_bufp;
239 mp->m_bufp = NULL;
240 brelse(bp);
241}
242
243/*
244 * Common code for mount and umount.
245 * Check that the user's argument is a reasonable
246 * thing on which to mount, and return the device number if so.
247 */
248dev_t
249getmdev()
250{
251 dev_t dev;
252 register struct inode *ip;
253
254#ifdef UCB
255 if (!suser())
256 return(NODEV);
257#endif
258 ip = namei(uchar, 0);
259 if(ip == NULL)
260 return(NODEV);
261 if((ip->i_mode&IFMT) != IFBLK)
262 u.u_error = ENOTBLK;
263 dev = (dev_t)ip->i_un.i_rdev;
264 if(major(dev) >= nblkdev)
265 u.u_error = ENXIO;
266 iput(ip);
267 return(dev);
268}