Back to index

glibc  2.9
xmknodat.c
Go to the documentation of this file.
00001 /* Create a device file relative to an open directory.  Hurd version.
00002    Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <sys/stat.h>
00023 #include <hurd.h>
00024 #include <hurd/fd.h>
00025 #include <hurd/paths.h>
00026 #include <fcntl.h>
00027 #include "stdio-common/_itoa.h"
00028 #include <string.h>
00029 #include <sys/types.h>
00030 
00031 /* Create a device file named PATH relative to FD, with permission and
00032    special bits MODE and device number DEV (which can be constructed
00033    from major and minor device numbers with the `makedev' macro
00034    above).  */
00035 int
00036 __xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev)
00037 {
00038   error_t err;
00039   file_t dir, node;
00040   char *name;
00041   char buf[100], *bp;
00042   const char *translator;
00043   size_t len;
00044 
00045   if (vers != _MKNOD_VER)
00046     return __hurd_fail (EINVAL);
00047 
00048   if (S_ISCHR (mode))
00049     {
00050       translator = _HURD_CHRDEV;
00051       len = sizeof (_HURD_CHRDEV);
00052     }
00053   else if (S_ISBLK (mode))
00054     {
00055       translator = _HURD_BLKDEV;
00056       len = sizeof (_HURD_BLKDEV);
00057     }
00058   else if (S_ISFIFO (mode))
00059     {
00060       translator = _HURD_FIFO;
00061       len = sizeof (_HURD_FIFO);
00062     }
00063   else if (S_ISREG (mode))
00064     {
00065       translator = NULL;
00066       len = 0;
00067     }
00068   else
00069     {
00070       errno = EINVAL;
00071       return -1;
00072     }
00073 
00074   if (translator != NULL && ! S_ISFIFO (mode))
00075     {
00076       /* We set the translator to "ifmt\0major\0minor\0", where IFMT
00077         depends on the S_IFMT bits of our MODE argument, and MAJOR and
00078         MINOR are ASCII decimal (octal or hex would do as well)
00079         representations of our arguments.  Thus the convention is that
00080         CHRDEV and BLKDEV translators are invoked with two non-switch
00081         arguments, giving the major and minor device numbers in %i format. */
00082 
00083       bp = buf + sizeof (buf);
00084       *--bp = '\0';
00085       bp = _itoa (minor (*dev), bp, 10, 0);
00086       *--bp = '\0';
00087       bp = _itoa (major (*dev), bp, 10, 0);
00088       memcpy (bp - len, translator, len);
00089       translator = bp - len;
00090       len = buf + sizeof (buf) - translator;
00091     }
00092 
00093   dir = __file_name_split_at (fd, path, &name);
00094   if (dir == MACH_PORT_NULL)
00095     return -1;
00096 
00097   /* Create a new, unlinked node in the target directory.  */
00098   err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node);
00099 
00100   if (! err && translator != NULL)
00101     /* Set the node's translator to make it a device.  */
00102     err = __file_set_translator (node,
00103                              FS_TRANS_EXCL | FS_TRANS_SET,
00104                              FS_TRANS_EXCL | FS_TRANS_SET, 0,
00105                              translator, len,
00106                              MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
00107 
00108   if (! err)
00109     /* Link the node, now a valid device, into the target directory.  */
00110     err = __dir_link (dir, node, name, 1);
00111 
00112   __mach_port_deallocate (__mach_task_self (), dir);
00113   __mach_port_deallocate (__mach_task_self (), node);
00114 
00115   if (err)
00116     return __hurd_fail (err);
00117   return 0;
00118 }