2003-10-17 12:40:02 +04:00
/*
2009-03-26 21:29:36 +03:00
* libudev - interface to udev device information
2003-10-17 12:40:02 +04:00
*
2010-04-22 20:12:36 +04:00
* Copyright ( C ) 2008 - 2010 Kay Sievers < kay . sievers @ vrfy . org >
2008-09-10 04:40:42 +04:00
*
2009-03-26 21:29:36 +03:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
2003-10-17 12:40:02 +04:00
*/
2003-08-06 10:57:23 +04:00
# include <stdlib.h>
# include <stdio.h>
2004-03-02 10:47:59 +03:00
# include <string.h>
2004-03-23 09:22:20 +03:00
# include <stddef.h>
2010-04-22 20:12:36 +04:00
# include <stdbool.h>
2005-03-06 14:16:32 +03:00
# include <unistd.h>
2003-08-06 10:57:23 +04:00
# include <fcntl.h>
# include <string.h>
2006-08-24 02:13:07 +04:00
# include <sys/stat.h>
2003-08-06 10:57:23 +04:00
2009-06-10 01:05:25 +04:00
# include "libudev.h"
# include "libudev-private.h"
2004-11-06 16:28:01 +03:00
2010-04-23 11:01:56 +04:00
static void udev_device_tag ( struct udev_device * dev , const char * tag , bool add )
2010-04-22 20:12:36 +04:00
{
2010-12-10 03:13:35 +03:00
const char * id ;
2010-04-23 11:01:56 +04:00
struct udev * udev = udev_device_get_udev ( dev ) ;
char filename [ UTIL_PATH_SIZE ] ;
2010-04-22 20:12:36 +04:00
2010-12-10 03:13:35 +03:00
id = udev_device_get_id_filename ( dev ) ;
if ( id = = NULL )
return ;
2011-03-23 04:31:09 +03:00
util_strscpyl ( filename , sizeof ( filename ) , udev_get_run_path ( udev ) , " /tags/ " , tag , " / " , id , NULL ) ;
2010-04-22 20:12:36 +04:00
2010-04-23 11:01:56 +04:00
if ( add ) {
2010-12-12 22:07:15 +03:00
int fd ;
2010-04-23 11:01:56 +04:00
util_create_path ( udev , filename ) ;
2010-12-12 22:07:15 +03:00
fd = open ( filename , O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC | O_NOFOLLOW , 0444 ) ;
if ( fd > = 0 )
close ( fd ) ;
2010-04-23 11:01:56 +04:00
} else {
unlink ( filename ) ;
}
}
2010-04-22 20:12:36 +04:00
2010-04-23 11:01:56 +04:00
int udev_device_tag_index ( struct udev_device * dev , struct udev_device * dev_old , bool add )
{
struct udev_list_entry * list_entry ;
bool found ;
2010-04-23 11:22:42 +04:00
if ( add & & dev_old ! = NULL ) {
2010-04-23 11:01:56 +04:00
/* delete possible left-over tags */
udev_list_entry_foreach ( list_entry , udev_device_get_tags_list_entry ( dev_old ) ) {
const char * tag_old = udev_list_entry_get_name ( list_entry ) ;
struct udev_list_entry * list_entry_current ;
found = false ;
udev_list_entry_foreach ( list_entry_current , udev_device_get_tags_list_entry ( dev ) ) {
const char * tag = udev_list_entry_get_name ( list_entry_current ) ;
if ( strcmp ( tag , tag_old ) = = 0 ) {
found = true ;
break ;
}
2010-04-22 20:12:36 +04:00
}
2010-04-23 11:01:56 +04:00
if ( ! found )
udev_device_tag ( dev_old , tag_old , false ) ;
2010-04-22 20:12:36 +04:00
}
}
2010-04-23 11:01:56 +04:00
udev_list_entry_foreach ( list_entry , udev_device_get_tags_list_entry ( dev ) )
udev_device_tag ( dev , udev_list_entry_get_name ( list_entry ) , add ) ;
2010-04-22 20:12:36 +04:00
return 0 ;
}
2010-12-11 16:00:46 +03:00
static bool device_has_info ( struct udev_device * udev_device )
{
2010-12-14 23:26:12 +03:00
struct udev * udev = udev_device_get_udev ( udev_device ) ;
2010-12-11 16:00:46 +03:00
struct udev_list_entry * list_entry ;
if ( udev_device_get_devlinks_list_entry ( udev_device ) ! = NULL )
return true ;
if ( udev_device_get_devlink_priority ( udev_device ) ! = 0 )
return true ;
udev_list_entry_foreach ( list_entry , udev_device_get_properties_list_entry ( udev_device ) )
if ( udev_list_entry_get_flags ( list_entry ) )
return true ;
if ( udev_device_get_tags_list_entry ( udev_device ) ! = NULL )
return true ;
2010-12-14 23:26:12 +03:00
if ( udev_device_get_devnode ( udev_device ) ! = NULL & & udev_device_get_knodename ( udev_device ) ! = NULL ) {
size_t devlen = strlen ( udev_get_dev_path ( udev ) ) + 1 ;
if ( strcmp ( & udev_device_get_devnode ( udev_device ) [ devlen ] , udev_device_get_knodename ( udev_device ) ) ! = 0 )
2010-12-14 04:30:36 +03:00
return true ;
2010-12-14 23:26:12 +03:00
}
2010-12-11 16:00:46 +03:00
if ( udev_device_get_watch_handle ( udev_device ) > = 0 )
return true ;
return false ;
}
2008-10-16 19:16:58 +04:00
int udev_device_update_db ( struct udev_device * udev_device )
2003-10-18 10:32:17 +04:00
{
2010-12-11 16:00:46 +03:00
bool has_info ;
2010-12-10 03:13:35 +03:00
const char * id ;
2008-10-16 19:16:58 +04:00
struct udev * udev = udev_device_get_udev ( udev_device ) ;
2008-09-10 23:50:21 +04:00
char filename [ UTIL_PATH_SIZE ] ;
2010-01-13 15:26:56 +03:00
char filename_tmp [ UTIL_PATH_SIZE ] ;
2008-10-06 15:52:43 +04:00
FILE * f ;
2003-10-18 10:32:17 +04:00
2010-12-10 03:13:35 +03:00
id = udev_device_get_id_filename ( udev_device ) ;
if ( id = = NULL )
return - 1 ;
2010-12-11 16:00:46 +03:00
has_info = device_has_info ( udev_device ) ;
2011-03-23 04:31:09 +03:00
util_strscpyl ( filename , sizeof ( filename ) , udev_get_run_path ( udev ) , " /data/ " , id , NULL ) ;
2006-08-18 04:27:16 +04:00
2010-12-11 16:00:46 +03:00
/* do not store anything for otherwise empty devices */
2010-12-14 16:18:32 +03:00
if ( ! has_info & &
major ( udev_device_get_devnum ( udev_device ) ) = = 0 & &
udev_device_get_ifindex ( udev_device ) = = 0 ) {
2010-12-11 16:00:46 +03:00
unlink ( filename ) ;
return 0 ;
2004-11-06 16:28:01 +03:00
}
2010-12-11 16:00:46 +03:00
/* write a database file */
util_strscpyl ( filename_tmp , sizeof ( filename_tmp ) , filename , " .tmp " , NULL ) ;
2010-01-13 15:26:56 +03:00
util_create_path ( udev , filename_tmp ) ;
2010-12-11 16:00:46 +03:00
f = fopen ( filename_tmp , " we " ) ;
2008-10-06 15:52:43 +04:00
if ( f = = NULL ) {
2010-01-13 15:26:56 +03:00
err ( udev , " unable to create temporary db file '%s': %m \n " , filename_tmp ) ;
2008-10-06 15:52:43 +04:00
return - 1 ;
2010-04-22 20:12:36 +04:00
}
2008-10-16 19:16:58 +04:00
2010-12-11 16:00:46 +03:00
if ( has_info ) {
2010-12-14 04:30:36 +03:00
size_t devlen = strlen ( udev_get_dev_path ( udev ) ) + 1 ;
2010-12-11 16:00:46 +03:00
struct udev_list_entry * list_entry ;
if ( udev_device_get_devnode ( udev_device ) ! = NULL ) {
fprintf ( f , " N:%s \n " , & udev_device_get_devnode ( udev_device ) [ devlen ] ) ;
udev_list_entry_foreach ( list_entry , udev_device_get_devlinks_list_entry ( udev_device ) )
fprintf ( f , " S:%s \n " , & udev_list_entry_get_name ( list_entry ) [ devlen ] ) ;
}
if ( udev_device_get_devlink_priority ( udev_device ) ! = 0 )
fprintf ( f , " L:%i \n " , udev_device_get_devlink_priority ( udev_device ) ) ;
if ( udev_device_get_watch_handle ( udev_device ) > = 0 )
fprintf ( f , " W:%i \n " , udev_device_get_watch_handle ( udev_device ) ) ;
2010-12-15 10:57:46 +03:00
if ( udev_device_get_usec_initialized ( udev_device ) > 0 )
fprintf ( f , " I:%llu \n " , udev_device_get_usec_initialized ( udev_device ) ) ;
2010-12-11 16:00:46 +03:00
udev_list_entry_foreach ( list_entry , udev_device_get_properties_list_entry ( udev_device ) ) {
if ( ! udev_list_entry_get_flags ( list_entry ) )
continue ;
fprintf ( f , " E:%s=%s \n " ,
udev_list_entry_get_name ( list_entry ) ,
udev_list_entry_get_value ( list_entry ) ) ;
}
udev_list_entry_foreach ( list_entry , udev_device_get_tags_list_entry ( udev_device ) )
fprintf ( f , " G:%s \n " , udev_list_entry_get_name ( list_entry ) ) ;
2008-10-06 15:52:43 +04:00
}
2010-12-11 16:00:46 +03:00
2008-10-06 15:52:43 +04:00
fclose ( f ) ;
2010-01-13 15:26:56 +03:00
rename ( filename_tmp , filename ) ;
2010-12-11 16:00:46 +03:00
info ( udev , " created %s file '%s' for '%s' \n " , has_info ? " db " : " empty " ,
filename , udev_device_get_devpath ( udev_device ) ) ;
2004-11-06 16:28:01 +03:00
return 0 ;
2003-10-18 10:32:17 +04:00
}
2008-10-16 19:16:58 +04:00
int udev_device_delete_db ( struct udev_device * udev_device )
2003-08-06 10:57:23 +04:00
{
2010-12-10 03:13:35 +03:00
const char * id ;
2009-05-20 19:57:52 +04:00
struct udev * udev = udev_device_get_udev ( udev_device ) ;
2008-09-10 23:50:21 +04:00
char filename [ UTIL_PATH_SIZE ] ;
2004-10-19 06:11:51 +04:00
2010-12-10 03:13:35 +03:00
id = udev_device_get_id_filename ( udev_device ) ;
if ( id = = NULL )
return - 1 ;
2011-03-23 04:31:09 +03:00
util_strscpyl ( filename , sizeof ( filename ) , udev_get_run_path ( udev ) , " /data/ " , id , NULL ) ;
2008-10-16 19:16:58 +04:00
unlink ( filename ) ;
2003-12-20 05:29:01 +03:00
return 0 ;
2003-08-06 10:57:23 +04:00
}