xref: /dflybsd-src/lib/libc/gen/fdevname.c (revision 45e80934a8afa3af2f45a285cb65e23cd1f7e931)
1*45e80934SMatthew Dillon /*
2*45e80934SMatthew Dillon  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3*45e80934SMatthew Dillon  *
4*45e80934SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5*45e80934SMatthew Dillon  * by Alex Hornung <ahornung@gmail.com>
6*45e80934SMatthew Dillon  *
7*45e80934SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8*45e80934SMatthew Dillon  * modification, are permitted provided that the following conditions
9*45e80934SMatthew Dillon  * are met:
10*45e80934SMatthew Dillon  *
11*45e80934SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12*45e80934SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13*45e80934SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14*45e80934SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15*45e80934SMatthew Dillon  *    the documentation and/or other materials provided with the
16*45e80934SMatthew Dillon  *    distribution.
17*45e80934SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18*45e80934SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19*45e80934SMatthew Dillon  *    from this software without specific, prior written permission.
20*45e80934SMatthew Dillon  *
21*45e80934SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*45e80934SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*45e80934SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*45e80934SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*45e80934SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*45e80934SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*45e80934SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*45e80934SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*45e80934SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*45e80934SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*45e80934SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*45e80934SMatthew Dillon  * SUCH DAMAGE.
33*45e80934SMatthew Dillon  */
34*45e80934SMatthew Dillon #include "namespace.h"
35*45e80934SMatthew Dillon #include <sys/types.h>
36*45e80934SMatthew Dillon #include <fcntl.h>
37*45e80934SMatthew Dillon #include <dirent.h>
38*45e80934SMatthew Dillon #include <stdlib.h>
39*45e80934SMatthew Dillon #include <termios.h>
40*45e80934SMatthew Dillon #include <unistd.h>
41*45e80934SMatthew Dillon #include <string.h>
42*45e80934SMatthew Dillon #include <paths.h>
43*45e80934SMatthew Dillon #include <errno.h>
44*45e80934SMatthew Dillon #include <machine/stdint.h>
45*45e80934SMatthew Dillon #include <sys/stat.h>
46*45e80934SMatthew Dillon #include <sys/ioctl.h>
47*45e80934SMatthew Dillon #include "reentrant.h"
48*45e80934SMatthew Dillon #include "un-namespace.h"
49*45e80934SMatthew Dillon 
50*45e80934SMatthew Dillon #include "libc_private.h"
51*45e80934SMatthew Dillon 
52*45e80934SMatthew Dillon static char fdevname_buf[sizeof(_PATH_DEV) + NAME_MAX];
53*45e80934SMatthew Dillon 
54*45e80934SMatthew Dillon static once_t		fdevname_init_once = ONCE_INITIALIZER;
55*45e80934SMatthew Dillon static thread_key_t	fdevname_key;
56*45e80934SMatthew Dillon static int			fdevname_keycreated = 0;
57*45e80934SMatthew Dillon 
58*45e80934SMatthew Dillon int
59*45e80934SMatthew Dillon fdevname_r(int fd, char *buf, size_t len)
60*45e80934SMatthew Dillon {
61*45e80934SMatthew Dillon 	struct stat	sb;
62*45e80934SMatthew Dillon 	struct fiodname_args fa;
63*45e80934SMatthew Dillon 	size_t used;
64*45e80934SMatthew Dillon 
65*45e80934SMatthew Dillon 	*buf = '\0';
66*45e80934SMatthew Dillon 
67*45e80934SMatthew Dillon 	/* Must be a character device. */
68*45e80934SMatthew Dillon 	if (_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
69*45e80934SMatthew Dillon 		return (ENOTTY);
70*45e80934SMatthew Dillon 
71*45e80934SMatthew Dillon 	/* Must have enough room */
72*45e80934SMatthew Dillon 	if (len <= sizeof(_PATH_DEV))
73*45e80934SMatthew Dillon 		return (ERANGE);
74*45e80934SMatthew Dillon 
75*45e80934SMatthew Dillon 	strcpy(buf, _PATH_DEV);
76*45e80934SMatthew Dillon 	used = strlen(buf);
77*45e80934SMatthew Dillon 	fa.len = len - used;
78*45e80934SMatthew Dillon 	fa.name = buf + used;
79*45e80934SMatthew Dillon 	if (_ioctl(fd, FIODNAME, &fa) == -1) {
80*45e80934SMatthew Dillon 		return ERANGE;
81*45e80934SMatthew Dillon 	}
82*45e80934SMatthew Dillon 	return (0);
83*45e80934SMatthew Dillon }
84*45e80934SMatthew Dillon 
85*45e80934SMatthew Dillon static void
86*45e80934SMatthew Dillon fdevname_keycreate(void)
87*45e80934SMatthew Dillon {
88*45e80934SMatthew Dillon 	fdevname_keycreated = (thr_keycreate(&fdevname_key, free) == 0);
89*45e80934SMatthew Dillon }
90*45e80934SMatthew Dillon 
91*45e80934SMatthew Dillon char *
92*45e80934SMatthew Dillon fdevname(int fd)
93*45e80934SMatthew Dillon {
94*45e80934SMatthew Dillon 	char	*buf;
95*45e80934SMatthew Dillon 
96*45e80934SMatthew Dillon 	if (thr_main() != 0)
97*45e80934SMatthew Dillon 		buf = fdevname_buf;
98*45e80934SMatthew Dillon 	else {
99*45e80934SMatthew Dillon 		if (thr_once(&fdevname_init_once, fdevname_keycreate) != 0 ||
100*45e80934SMatthew Dillon 		    !fdevname_keycreated)
101*45e80934SMatthew Dillon 			return (NULL);
102*45e80934SMatthew Dillon 		if ((buf = thr_getspecific(fdevname_key)) == NULL) {
103*45e80934SMatthew Dillon 			if ((buf = malloc(sizeof fdevname_buf)) == NULL)
104*45e80934SMatthew Dillon 				return (NULL);
105*45e80934SMatthew Dillon 			if (thr_setspecific(fdevname_key, buf) != 0) {
106*45e80934SMatthew Dillon 				free(buf);
107*45e80934SMatthew Dillon 				return (NULL);
108*45e80934SMatthew Dillon 			}
109*45e80934SMatthew Dillon 		}
110*45e80934SMatthew Dillon 	}
111*45e80934SMatthew Dillon 
112*45e80934SMatthew Dillon 	if (fdevname_r(fd, buf, sizeof fdevname_buf) != 0)
113*45e80934SMatthew Dillon 		return (NULL);
114*45e80934SMatthew Dillon 	return (buf);
115*45e80934SMatthew Dillon }
116