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