udev-add.c revision 4763256c65859b94ac7a309cbb8f772d5426a08d
/*
*
* Userspace devfs
*
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
*
*
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <grp.h>
#ifndef __KLIBC__
#include <pwd.h>
#endif
#include "udev.h"
#include "udev_version.h"
#include "udev_dbus.h"
#include "namedev.h"
#include "udevdb.h"
#include "libsysfs/libsysfs.h"
#include "klibc_fixups.h"
/*
* "dev" in sysfs.
* The number is stored as:
* MM:mm
* MM is the major
* mm is the minor
* The value is in decimal.
*/
{
char *dev;
goto exit;
goto exit;
retval = 0;
exit:
return retval;
}
static int create_path(char *file)
{
char p[NAME_SIZE];
char *pos;
int retval;
while (1) {
break;
*pos = 0x00;
if (retval) {
dbg("mkdir(%s) failed with error '%s'",
return retval;
}
dbg("created '%s'", p);
}
*pos = '/';
}
return 0;
}
{
char filename[255];
char linktarget[255];
char *linkname;
char *symlinks;
int retval = 0;
int i;
int tail;
#ifdef __KLIBC__
#else
#endif
case 'b':
break;
case 'c':
case 'u':
break;
case 'p':
break;
default:
return -EINVAL;
}
/* create parent directories if needed */
if (retval)
dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
if (retval)
dbg("chmod(%s, %#o) failed with error '%s'",
char *endptr;
if (*endptr == 0x00)
else {
if (!pw)
else
}
}
char *endptr;
if (*endptr == 0x00)
else {
if (!gr)
else
}
}
if (retval)
dbg("chown(%s, %u, %u) failed with error '%s'",
}
/* create symlink if requested */
while (1) {
break;
/* optimize relative link */
linktarget[0] = '\0';
i = 0;
tail = 0;
tail = i+1;
i++;
}
while (linkname[i]) {
if (linkname[i] == '/')
i++;
}
if (*linktarget == '\0')
if (retval)
dbg("symlink(%s, %s) failed with error '%s'",
}
}
return retval;
}
{
char dev_path[SYSFS_PATH_MAX];
/* open up the sysfs class device for this thing... */
dbg ("sysfs_open_class_device failed");
goto exit;
}
exit:
return class_dev;
}
/* wait for the "dev" file to show up in the directory in sysfs.
* If it doesn't happen in about 10 seconds, give up.
*/
#define SECONDS_TO_WAIT_FOR_DEV 10
static int sleep_for_dev(char *path)
{
int loop = SECONDS_TO_WAIT_FOR_DEV;
int retval;
while (loop--) {
if (!retval)
goto exit;
/* sleep to give the kernel a chance to create the dev file */
sleep(1);
}
exit:
return retval;
}
{
/* for now, the block layer is the only place where block devices are */
else
if (retval)
goto exit;
goto exit;
if (retval) {
dbg("get_major_minor failed");
goto exit;
}
if (retval)
goto exit;
if (retval != 0)
dbg("udevdb_add_dev failed, but we are going to try to create the node anyway. "
"But remove might not work properly for this device.");
if (retval == 0)
exit:
if (class_dev)
return retval;
}