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