* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)kern_descrip.c 7.7 (Berkeley) %G%
* System calls on descriptors.
} *uap
= (struct a
*) u
.u_ap
;
if (uap
->i
&~ 077) { uap
->i
&= 077; dup2(); return; } /* XXX */
if ((unsigned)uap
->i
>= NOFILE
|| (fp
= u
.u_ofile
[uap
->i
]) == NULL
)
if (u
.u_error
= ufalloc(0, &j
))
dupit(j
, fp
, u
.u_pofile
[uap
->i
] &~ UF_EXCLOSE
);
} *uap
= (struct a
*) u
.u_ap
;
register struct file
*fp
;
if ((unsigned)uap
->i
>= NOFILE
|| (fp
= u
.u_ofile
[uap
->i
]) == NULL
)
if (uap
->j
< 0 || uap
->j
>= NOFILE
)
if (u
.u_pofile
[uap
->j
] & UF_MAPPED
)
error
= closef(u
.u_ofile
[uap
->j
]);
dupit(uap
->j
, fp
, u
.u_pofile
[uap
->i
] &~ UF_EXCLOSE
);
* dup2() must succeed even though the close had an error.
register struct file
*fp
;
* The file control system call.
register struct file
*fp
;
} *uap
= (struct a
*)u
.u_ap
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
)
pop
= &u
.u_pofile
[uap
->fdes
];
if (uap
->arg
< 0 || uap
->arg
>= NOFILE
) {
if (u
.u_error
= ufalloc(uap
->arg
, &i
))
dupit(i
, fp
, *pop
&~ UF_EXCLOSE
);
*pop
= (*pop
&~ 1) | (uap
->arg
& 1);
u
.u_r
.r_val1
= fp
->f_flag
+FOPEN
;
fp
->f_flag
|= (uap
->arg
-FOPEN
) &~ FCNTLCANT
;
u
.u_error
= fset(fp
, FNDELAY
, fp
->f_flag
& FNDELAY
);
u
.u_error
= fset(fp
, FASYNC
, fp
->f_flag
& FASYNC
);
(void) fset(fp
, FNDELAY
, 0);
u
.u_error
= fgetown(fp
, &u
.u_r
.r_val1
);
u
.u_error
= fsetown(fp
, uap
->arg
);
return (fioctl(fp
, (int)(bit
== FNDELAY
? FIONBIO
: FIOASYNC
),
*valuep
= ((struct socket
*)fp
->f_data
)->so_pgid
;
error
= fioctl(fp
, (int)TIOCGPGRP
, (caddr_t
)valuep
);
if (fp
->f_type
== DTYPE_SOCKET
) {
((struct socket
*)fp
->f_data
)->so_pgid
= value
;
struct proc
*p
= pfind(value
);
value
= p
->p_pgrp
->pg_id
;
return (fioctl(fp
, (int)TIOCSPGRP
, (caddr_t
)&value
));
return ((*fp
->f_ops
->fo_ioctl
)(fp
, cmd
, value
));
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
)
pf
= (u_char
*)&u
.u_pofile
[uap
->fdes
];
u
.u_ofile
[uap
->fdes
] = NULL
;
while (u
.u_lastfile
>= 0 && u
.u_ofile
[u
.u_lastfile
] == NULL
)
register struct file
*fp
;
} *uap
= (struct a
*)u
.u_ap
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
)
u
.u_error
= vn_stat((struct vnode
*)fp
->f_data
, &ub
);
u
.u_error
= soo_stat((struct socket
*)fp
->f_data
, &ub
);
u
.u_error
= copyout((caddr_t
)&ub
, (caddr_t
)uap
->sb
,
* Allocate a user file descriptor.
for (; want
< NOFILE
; want
++)
if (u
.u_ofile
[want
] == NULL
) {
register int i
, avail
= 0;
for (i
= 0; i
< NOFILE
; i
++)
if (u
.u_ofile
[i
] == NULL
)
* Allocate a user file descriptor
* Initialize the descriptor
* to point at the file structure.
falloc(resultfp
, resultfd
)
register struct file
*fp
;
if (error
= ufalloc(0, &i
))
for (fp
= lastf
; fp
< fileNFILE
; fp
++)
for (fp
= file
; fp
< lastf
; fp
++)
* Internal form of close.
* Decrement reference count on file structure.
register struct file
*fp
;
panic("closef: count < 1");
error
= (*fp
->f_ops
->fo_close
)(fp
);
* Apply an advisory lock on a file descriptor.
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
)
if (fp
->f_type
!= DTYPE_VNODE
) {
if (uap
->how
& LOCK_UN
) {
vn_unlock(fp
, FSHLOCK
|FEXLOCK
);
if ((uap
->how
& (LOCK_SH
| LOCK_EX
)) == 0)
if ((fp
->f_flag
& FEXLOCK
) && (uap
->how
& LOCK_EX
) ||
(fp
->f_flag
& FSHLOCK
) && (uap
->how
& LOCK_SH
))
u
.u_error
= vn_lock(fp
, uap
->how
);
* File Descriptor pseudo-device driver (/dev/fd/).
* Fred Blonder - U of Maryland 11-Sep-1984
* Opening minor device N dup()s the file (if any) connected to file
* descriptor N belonging to the calling process. Note that this driver
* consists of only the ``open()'' routine, because all subsequent
* references to this file will be direct to the other driver.
* Note the horrid kludge here: u.u_r.r_val1 contains the value
* of the new file descriptor, which was set before the call to
* vn_open() by copen() in vfs_syscalls.c
indx
= u
.u_r
.r_val1
; /* XXX from copen */
if ((unsigned)indx
>= NOFILE
|| (fp
= u
.u_ofile
[indx
]) == NULL
)
if ((unsigned)dfd
>= NOFILE
|| (wfp
= u
.u_ofile
[dfd
]) == NULL
)
* We must explicitly test for this case because ufalloc() may
* have allocated us the same file desriptor we are referring
* to, if the proccess referred to an invalid (closed) descriptor.
* Ordinarily this would be caught by the check for NULL above,
* but by the time we reach this routine u_pofile[minor(dev)]
* could already be set to point to our file struct.
* Fake a ``dup()'' sys call.
* Check that the mode the file is being opened
* for is consistent with the mode of the existing
* descriptor. This isn't as clean as it should be,
* but this entire driver is a real kludge anyway.
rwmode
= mode
& (FREAD
|FWRITE
);
if ((wfp
->f_flag
& rwmode
) != rwmode
)
* Dup the file descriptor.
dupit(indx
, wfp
, u
.u_pofile
[dfd
]);
* Delete references to this pseudo-device by returning
* a special error (-1) that will cause all resources to
* be freed, then detected and cleared by copen.