2013-06-27 06:14:27 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2013 Lennart Poettering
systemd 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 .
systemd 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2013-11-20 00:12:59 +04:00
# include "bus-util.h"
2013-06-28 01:13:17 +04:00
# include "path-util.h"
2013-11-20 00:12:59 +04:00
# include "cgroup-util.h"
# include "cgroup.h"
2013-06-27 06:14:27 +04:00
# include "dbus-cgroup.h"
2013-11-20 00:12:59 +04:00
static BUS_DEFINE_PROPERTY_GET_ENUM ( property_get_cgroup_device_policy , cgroup_device_policy , CGroupDevicePolicy ) ;
static int property_get_blockio_device_weight (
sd_bus * bus ,
const char * path ,
const char * interface ,
const char * property ,
sd_bus_message * reply ,
2013-11-21 22:34:37 +04:00
void * userdata ,
sd_bus_error * error ) {
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
CGroupContext * c = userdata ;
2013-06-27 06:14:27 +04:00
CGroupBlockIODeviceWeight * w ;
2013-11-20 00:12:59 +04:00
int r ;
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
assert ( bus ) ;
assert ( reply ) ;
2013-06-27 06:14:27 +04:00
assert ( c ) ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_open_container ( reply , ' a ' , " (st) " ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
LIST_FOREACH ( device_weights , w , c - > blockio_device_weights ) {
2013-11-20 00:12:59 +04:00
r = sd_bus_message_append ( reply , " (st) " , w - > path , w - > weight ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
return sd_bus_message_close_container ( reply ) ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
static int property_get_blockio_device_bandwidths (
sd_bus * bus ,
const char * path ,
const char * interface ,
const char * property ,
sd_bus_message * reply ,
2013-11-21 22:34:37 +04:00
void * userdata ,
sd_bus_error * error ) {
2013-11-20 00:12:59 +04:00
CGroupContext * c = userdata ;
2013-06-27 06:14:27 +04:00
CGroupBlockIODeviceBandwidth * b ;
2013-11-20 00:12:59 +04:00
int r ;
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
assert ( bus ) ;
assert ( reply ) ;
2013-06-27 06:14:27 +04:00
assert ( c ) ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_open_container ( reply , ' a ' , " (st) " ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
LIST_FOREACH ( device_bandwidths , b , c - > blockio_device_bandwidths ) {
if ( streq ( property , " BlockIOReadBandwidth " ) ! = b - > read )
continue ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_append ( reply , " (st) " , b - > path , b - > bandwidth ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
return sd_bus_message_close_container ( reply ) ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
static int property_get_device_allow (
sd_bus * bus ,
const char * path ,
const char * interface ,
const char * property ,
sd_bus_message * reply ,
2013-11-21 22:34:37 +04:00
void * userdata ,
sd_bus_error * error ) {
2013-11-20 00:12:59 +04:00
CGroupContext * c = userdata ;
2013-06-27 06:14:27 +04:00
CGroupDeviceAllow * a ;
2013-11-20 00:12:59 +04:00
int r ;
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
assert ( bus ) ;
assert ( reply ) ;
2013-06-27 06:14:27 +04:00
assert ( c ) ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_open_container ( reply , ' a ' , " (ss) " ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
LIST_FOREACH ( device_allow , a , c - > device_allow ) {
unsigned k = 0 ;
2013-11-20 00:12:59 +04:00
char rwm [ 4 ] ;
2013-06-27 06:14:27 +04:00
if ( a - > r )
2013-11-20 00:12:59 +04:00
rwm [ k + + ] = ' r ' ;
2013-06-27 06:14:27 +04:00
if ( a - > w )
2013-11-20 00:12:59 +04:00
rwm [ k + + ] = ' w ' ;
2013-06-27 06:14:27 +04:00
if ( a - > m )
2013-11-20 00:12:59 +04:00
rwm [ k + + ] = ' m ' ;
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
rwm [ k ] = 0 ;
2013-06-27 06:14:27 +04:00
2013-11-20 00:12:59 +04:00
r = sd_bus_message_append ( reply , " (ss) " , a - > path , rwm ) ;
if ( r < 0 )
return r ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
return sd_bus_message_close_container ( reply ) ;
2013-06-27 06:14:27 +04:00
}
2013-11-20 00:12:59 +04:00
const sd_bus_vtable bus_cgroup_vtable [ ] = {
SD_BUS_VTABLE_START ( 0 ) ,
2013-12-22 22:44:04 +04:00
SD_BUS_PROPERTY ( " CPUAccounting " , " b " , bus_property_get_bool , offsetof ( CGroupContext , cpu_accounting ) , 0 ) ,
SD_BUS_PROPERTY ( " CPUShares " , " t " , bus_property_get_ulong , offsetof ( CGroupContext , cpu_shares ) , 0 ) ,
SD_BUS_PROPERTY ( " BlockIOAccounting " , " b " , bus_property_get_bool , offsetof ( CGroupContext , blockio_accounting ) , 0 ) ,
SD_BUS_PROPERTY ( " BlockIOWeight " , " t " , bus_property_get_ulong , offsetof ( CGroupContext , blockio_weight ) , 0 ) ,
SD_BUS_PROPERTY ( " BlockIODeviceWeight " , " a(st) " , property_get_blockio_device_weight , 0 , 0 ) ,
SD_BUS_PROPERTY ( " BlockIOReadBandwidth " , " a(st) " , property_get_blockio_device_bandwidths , 0 , 0 ) ,
SD_BUS_PROPERTY ( " BlockIOWriteBandwidth " , " a(st) " , property_get_blockio_device_bandwidths , 0 , 0 ) ,
SD_BUS_PROPERTY ( " MemoryAccounting " , " b " , bus_property_get_bool , offsetof ( CGroupContext , memory_accounting ) , 0 ) ,
SD_BUS_PROPERTY ( " MemoryLimit " , " t " , NULL , offsetof ( CGroupContext , memory_limit ) , 0 ) ,
SD_BUS_PROPERTY ( " DevicePolicy " , " s " , property_get_cgroup_device_policy , offsetof ( CGroupContext , device_policy ) , 0 ) ,
SD_BUS_PROPERTY ( " DeviceAllow " , " a(ss) " , property_get_device_allow , 0 , 0 ) ,
2013-11-20 00:12:59 +04:00
SD_BUS_VTABLE_END
2013-06-27 06:14:27 +04:00
} ;
2013-06-27 23:14:56 +04:00
int bus_cgroup_set_property (
Unit * u ,
CGroupContext * c ,
const char * name ,
2013-11-20 00:12:59 +04:00
sd_bus_message * message ,
2013-06-27 23:14:56 +04:00
UnitSetPropertiesMode mode ,
2013-11-20 00:12:59 +04:00
sd_bus_error * error ) {
int r ;
2013-06-27 23:14:56 +04:00
assert ( u ) ;
assert ( c ) ;
2013-11-20 00:12:59 +04:00
assert ( name ) ;
assert ( message ) ;
2013-06-27 23:14:56 +04:00
if ( streq ( name , " CPUAccounting " ) ) {
2013-11-20 00:12:59 +04:00
int b ;
2013-06-27 23:14:56 +04:00
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " b " , & b ) ;
if ( r < 0 )
return r ;
2013-06-27 23:14:56 +04:00
if ( mode ! = UNIT_CHECK ) {
c - > cpu_accounting = b ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private ( u , mode , name , b ? " CPUAccounting=yes " : " CPUAccounting=no " ) ;
2013-06-27 23:50:35 +04:00
}
return 1 ;
} else if ( streq ( name , " CPUShares " ) ) {
uint64_t u64 ;
unsigned long ul ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " t " , & u64 ) ;
if ( r < 0 )
return r ;
2013-06-27 23:50:35 +04:00
ul = ( unsigned long ) u64 ;
2013-11-20 00:12:59 +04:00
if ( ul < = 0 | | ( uint64_t ) ul ! = u64 )
return sd_bus_error_set_errnof ( error , EINVAL , " CPUShares value out of range " ) ;
2013-06-27 23:50:35 +04:00
if ( mode ! = UNIT_CHECK ) {
c - > cpu_shares = ul ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private_format ( u , mode , name , " CPUShares=%lu " , ul ) ;
2013-06-27 23:14:56 +04:00
}
return 1 ;
} else if ( streq ( name , " BlockIOAccounting " ) ) {
2013-11-20 00:12:59 +04:00
int b ;
2013-06-27 23:14:56 +04:00
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " b " , & b ) ;
if ( r < 0 )
return r ;
2013-06-27 23:14:56 +04:00
if ( mode ! = UNIT_CHECK ) {
c - > blockio_accounting = b ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private ( u , mode , name , b ? " BlockIOAccounting=yes " : " BlockIOAccounting=no " ) ;
2013-06-27 23:14:56 +04:00
}
return 1 ;
2013-06-27 23:50:35 +04:00
} else if ( streq ( name , " BlockIOWeight " ) ) {
uint64_t u64 ;
unsigned long ul ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " t " , & u64 ) ;
if ( r < 0 )
return r ;
2013-06-27 23:50:35 +04:00
ul = ( unsigned long ) u64 ;
2013-11-20 00:12:59 +04:00
if ( ul < 10 | | ul > 1000 )
return sd_bus_error_set_errnof ( error , EINVAL , " BlockIOWeight value out of range " ) ;
2013-06-27 23:50:35 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-08-23 13:53:23 +04:00
c - > blockio_weight = ul ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private_format ( u , mode , name , " BlockIOWeight=%lu " , ul ) ;
2013-06-27 23:50:35 +04:00
}
return 1 ;
2013-09-10 19:23:07 +04:00
} else if ( streq ( name , " BlockIOReadBandwidth " ) | | streq ( name , " BlockIOWriteBandwidth " ) ) {
2013-11-20 00:12:59 +04:00
const char * path ;
2013-09-10 19:23:07 +04:00
bool read = true ;
2013-11-20 00:12:59 +04:00
unsigned n = 0 ;
uint64_t u64 ;
2013-09-10 19:23:07 +04:00
if ( streq ( name , " BlockIOWriteBandwidth " ) )
read = false ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_enter_container ( message , ' a ' , " (st) " ) ;
if ( r < 0 )
return r ;
2013-09-10 19:23:07 +04:00
2013-11-20 00:12:59 +04:00
while ( ( r = sd_bus_message_read ( message , " (st) " , & path , & u64 ) ) > 0 ) {
2013-09-10 19:23:07 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-11-20 00:12:59 +04:00
CGroupBlockIODeviceBandwidth * a = NULL , * b ;
2013-09-10 19:23:07 +04:00
LIST_FOREACH ( device_bandwidths , b , c - > blockio_device_bandwidths ) {
if ( path_equal ( path , b - > path ) & & read = = b - > read ) {
a = b ;
break ;
}
}
2013-11-20 00:12:59 +04:00
if ( ! a ) {
2013-09-10 19:23:07 +04:00
a = new0 ( CGroupBlockIODeviceBandwidth , 1 ) ;
if ( ! a )
return - ENOMEM ;
a - > read = read ;
a - > path = strdup ( path ) ;
if ( ! a - > path ) {
free ( a ) ;
return - ENOMEM ;
}
2013-11-20 00:12:59 +04:00
LIST_PREPEND ( device_bandwidths , c - > blockio_device_bandwidths , a ) ;
2013-09-10 19:23:07 +04:00
}
a - > bandwidth = u64 ;
}
n + + ;
}
2013-11-20 00:12:59 +04:00
if ( r < 0 )
return r ;
2013-09-10 19:23:07 +04:00
2014-02-24 05:59:57 +04:00
r = sd_bus_message_exit_container ( message ) ;
if ( r < 0 )
return r ;
2013-09-10 19:23:07 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-11-20 00:12:59 +04:00
CGroupBlockIODeviceBandwidth * a , * next ;
2013-09-10 19:23:07 +04:00
_cleanup_free_ char * buf = NULL ;
_cleanup_fclose_ FILE * f = NULL ;
size_t size = 0 ;
if ( n = = 0 ) {
LIST_FOREACH_SAFE ( device_bandwidths , a , next , c - > blockio_device_bandwidths )
if ( a - > read = = read )
cgroup_context_free_blockio_device_bandwidth ( c , a ) ;
}
f = open_memstream ( & buf , & size ) ;
if ( ! f )
return - ENOMEM ;
if ( read ) {
fputs ( " BlockIOReadBandwidth= \n " , f ) ;
LIST_FOREACH ( device_bandwidths , a , c - > blockio_device_bandwidths )
if ( a - > read )
fprintf ( f , " BlockIOReadBandwidth=%s % " PRIu64 " \n " , a - > path , a - > bandwidth ) ;
} else {
fputs ( " BlockIOWriteBandwidth= \n " , f ) ;
LIST_FOREACH ( device_bandwidths , a , c - > blockio_device_bandwidths )
if ( ! a - > read )
fprintf ( f , " BlockIOWriteBandwidth=%s % " PRIu64 " \n " , a - > path , a - > bandwidth ) ;
}
2013-08-27 09:36:53 +04:00
fflush ( f ) ;
unit_write_drop_in_private ( u , mode , name , buf ) ;
}
return 1 ;
} else if ( streq ( name , " BlockIODeviceWeight " ) ) {
2013-11-20 00:12:59 +04:00
const char * path ;
uint64_t u64 ;
2013-08-27 09:36:53 +04:00
unsigned n = 0 ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_enter_container ( message , ' a ' , " (st) " ) ;
if ( r < 0 )
return r ;
2013-08-27 09:36:53 +04:00
2013-12-31 02:22:26 +04:00
while ( ( r = sd_bus_message_read ( message , " (st) " , & path , & u64 ) ) > 0 ) {
unsigned long ul = u64 ;
2013-08-27 09:36:53 +04:00
if ( ul < 10 | | ul > 1000 )
2013-11-20 00:12:59 +04:00
return sd_bus_error_set_errnof ( error , EINVAL , " BlockIODeviceWeight out of range " ) ;
2013-08-27 09:36:53 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-11-20 00:12:59 +04:00
CGroupBlockIODeviceWeight * a = NULL , * b ;
2013-08-27 09:36:53 +04:00
LIST_FOREACH ( device_weights , b , c - > blockio_device_weights ) {
if ( path_equal ( b - > path , path ) ) {
a = b ;
break ;
}
}
2013-11-20 00:12:59 +04:00
if ( ! a ) {
2013-08-27 09:36:53 +04:00
a = new0 ( CGroupBlockIODeviceWeight , 1 ) ;
if ( ! a )
return - ENOMEM ;
a - > path = strdup ( path ) ;
if ( ! a - > path ) {
free ( a ) ;
return - ENOMEM ;
}
2013-11-20 00:12:59 +04:00
LIST_PREPEND ( device_weights , c - > blockio_device_weights , a ) ;
2013-08-27 09:36:53 +04:00
}
a - > weight = ul ;
}
n + + ;
}
2014-02-24 05:59:57 +04:00
r = sd_bus_message_exit_container ( message ) ;
if ( r < 0 )
return r ;
2013-08-27 09:36:53 +04:00
if ( mode ! = UNIT_CHECK ) {
_cleanup_free_ char * buf = NULL ;
_cleanup_fclose_ FILE * f = NULL ;
CGroupBlockIODeviceWeight * a ;
size_t size = 0 ;
if ( n = = 0 ) {
while ( c - > blockio_device_weights )
cgroup_context_free_blockio_device_weight ( c , c - > blockio_device_weights ) ;
}
f = open_memstream ( & buf , & size ) ;
if ( ! f )
return - ENOMEM ;
fputs ( " BlockIODeviceWeight= \n " , f ) ;
LIST_FOREACH ( device_weights , a , c - > blockio_device_weights )
fprintf ( f , " BlockIODeviceWeight=%s %lu \n " , a - > path , a - > weight ) ;
2013-09-10 19:23:07 +04:00
fflush ( f ) ;
unit_write_drop_in_private ( u , mode , name , buf ) ;
}
return 1 ;
2013-06-27 23:14:56 +04:00
} else if ( streq ( name , " MemoryAccounting " ) ) {
2013-11-20 00:12:59 +04:00
int b ;
2013-06-27 23:14:56 +04:00
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " b " , & b ) ;
if ( r < 0 )
return r ;
2013-06-27 23:14:56 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-06-27 23:50:35 +04:00
c - > memory_accounting = b ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private ( u , mode , name , b ? " MemoryAccounting=yes " : " MemoryAccounting=no " ) ;
2013-06-27 23:14:56 +04:00
}
return 1 ;
2013-09-17 23:58:00 +04:00
} else if ( streq ( name , " MemoryLimit " ) ) {
2013-11-20 00:12:59 +04:00
uint64_t limit ;
2013-06-27 23:50:35 +04:00
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " t " , & limit ) ;
if ( r < 0 )
return r ;
2013-06-27 23:50:35 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-09-17 23:58:00 +04:00
c - > memory_limit = limit ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private_format ( u , mode , name , " %s=% " PRIu64 , name , limit ) ;
2013-06-27 23:50:35 +04:00
}
2013-06-28 01:13:17 +04:00
return 1 ;
} else if ( streq ( name , " DevicePolicy " ) ) {
const char * policy ;
CGroupDevicePolicy p ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_read ( message , " s " , & policy ) ;
if ( r < 0 )
return r ;
2013-06-28 01:13:17 +04:00
p = cgroup_device_policy_from_string ( policy ) ;
if ( p < 0 )
return - EINVAL ;
if ( mode ! = UNIT_CHECK ) {
char * buf ;
c - > device_policy = p ;
buf = strappenda ( " DevicePolicy= " , policy ) ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private ( u , mode , name , buf ) ;
2013-06-28 01:13:17 +04:00
}
return 1 ;
} else if ( streq ( name , " DeviceAllow " ) ) {
2013-11-20 00:12:59 +04:00
const char * path , * rwm ;
2013-06-28 01:13:17 +04:00
unsigned n = 0 ;
2013-11-20 00:12:59 +04:00
r = sd_bus_message_enter_container ( message , ' a ' , " (ss) " ) ;
if ( r < 0 )
return r ;
2013-06-28 01:13:17 +04:00
2013-11-20 00:12:59 +04:00
while ( ( r = sd_bus_message_read ( message , " (ss) " , & path , & rwm ) ) > 0 ) {
2013-06-28 01:13:17 +04:00
2014-02-22 05:47:29 +04:00
if ( ( ! startswith ( path , " /dev/ " ) & &
! startswith ( path , " block- " ) & &
! startswith ( path , " char- " ) ) | |
strpbrk ( path , WHITESPACE ) )
return sd_bus_error_set_errnof ( error , EINVAL , " DeviceAllow= requires device node " ) ;
2013-06-28 01:13:17 +04:00
if ( isempty ( rwm ) )
rwm = " rwm " ;
2013-11-20 00:12:59 +04:00
if ( ! in_charset ( rwm , " rwm " ) )
return sd_bus_error_set_errnof ( error , EINVAL , " DeviceAllow= requires combination of rwm flags " ) ;
2013-06-28 01:13:17 +04:00
if ( mode ! = UNIT_CHECK ) {
2013-11-20 00:12:59 +04:00
CGroupDeviceAllow * a = NULL , * b ;
2013-08-28 05:49:11 +04:00
LIST_FOREACH ( device_allow , b , c - > device_allow ) {
2013-09-10 20:21:10 +04:00
if ( path_equal ( b - > path , path ) ) {
2013-08-28 05:49:11 +04:00
a = b ;
break ;
}
}
2013-11-20 00:12:59 +04:00
if ( ! a ) {
2013-08-28 05:49:11 +04:00
a = new0 ( CGroupDeviceAllow , 1 ) ;
if ( ! a )
return - ENOMEM ;
a - > path = strdup ( path ) ;
if ( ! a - > path ) {
free ( a ) ;
return - ENOMEM ;
}
2013-11-20 00:12:59 +04:00
LIST_PREPEND ( device_allow , c - > device_allow , a ) ;
2013-06-28 01:13:17 +04:00
}
a - > r = ! ! strchr ( rwm , ' r ' ) ;
a - > w = ! ! strchr ( rwm , ' w ' ) ;
a - > m = ! ! strchr ( rwm , ' m ' ) ;
}
2013-06-28 06:12:58 +04:00
n + + ;
2013-06-28 01:13:17 +04:00
}
2013-12-25 22:00:12 +04:00
if ( r < 0 )
return r ;
2013-06-28 01:13:17 +04:00
2014-02-24 05:59:57 +04:00
r = sd_bus_message_exit_container ( message ) ;
if ( r < 0 )
return r ;
2013-06-28 01:13:17 +04:00
if ( mode ! = UNIT_CHECK ) {
_cleanup_free_ char * buf = NULL ;
_cleanup_fclose_ FILE * f = NULL ;
CGroupDeviceAllow * a ;
size_t size = 0 ;
if ( n = = 0 ) {
while ( c - > device_allow )
cgroup_context_free_device_allow ( c , c - > device_allow ) ;
}
f = open_memstream ( & buf , & size ) ;
if ( ! f )
return - ENOMEM ;
fputs ( " DeviceAllow= \n " , f ) ;
LIST_FOREACH ( device_allow , a , c - > device_allow )
fprintf ( f , " DeviceAllow=%s %s%s%s \n " , a - > path , a - > r ? " r " : " " , a - > w ? " w " : " " , a - > m ? " m " : " " ) ;
fflush ( f ) ;
2013-07-11 23:29:33 +04:00
unit_write_drop_in_private ( u , mode , name , buf ) ;
2013-06-28 01:13:17 +04:00
}
2013-06-27 23:50:35 +04:00
return 1 ;
}
2013-06-27 23:14:56 +04:00
return 0 ;
}