Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
651ef4ef
Commit
651ef4ef
authored
Sep 16, 2016
by
Stéphane Graber
Committed by
GitHub
Sep 16, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1194 from tych0/cgroup-root-on-dump
Cgroup root on dump
parents
127a74d7
09e80d0c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
167 additions
and
75 deletions
+167
-75
cgfs.c
src/lxc/cgroups/cgfs.c
+14
-23
cgfsng.c
src/lxc/cgroups/cgfsng.c
+29
-21
cgmanager.c
src/lxc/cgroups/cgmanager.c
+14
-10
cgroup.c
src/lxc/cgroups/cgroup.c
+11
-8
cgroup.h
src/lxc/cgroups/cgroup.h
+4
-6
criu.c
src/lxc/criu.c
+75
-7
utils.c
src/lxc/utils.c
+18
-0
utils.h
src/lxc/utils.h
+2
-0
No files found.
src/lxc/cgroups/cgfs.c
View file @
651ef4ef
...
@@ -2363,28 +2363,6 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
...
@@ -2363,28 +2363,6 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
return
lxc_cgroup_get_hierarchy_path_data
(
subsystem
,
d
);
return
lxc_cgroup_get_hierarchy_path_data
(
subsystem
,
d
);
}
}
static
const
char
*
cgfs_canonical_path
(
void
*
hdata
)
{
struct
cgfs_data
*
d
=
hdata
;
struct
cgroup_process_info
*
info_ptr
;
char
*
path
=
NULL
;
if
(
!
d
)
return
NULL
;
for
(
info_ptr
=
d
->
info
;
info_ptr
;
info_ptr
=
info_ptr
->
next
)
{
if
(
!
path
)
path
=
info_ptr
->
cgroup_path
;
else
if
(
strcmp
(
path
,
info_ptr
->
cgroup_path
)
!=
0
)
{
ERROR
(
"not all paths match %s, %s has path %s"
,
path
,
info_ptr
->
hierarchy
->
subsystems
[
0
],
info_ptr
->
cgroup_path
);
return
NULL
;
}
}
return
path
;
}
static
bool
cgfs_escape
(
void
*
hdata
)
static
bool
cgfs_escape
(
void
*
hdata
)
{
{
struct
cgroup_meta_data
*
md
;
struct
cgroup_meta_data
*
md
;
...
@@ -2434,6 +2412,18 @@ out:
...
@@ -2434,6 +2412,18 @@ out:
return
ret
;
return
ret
;
}
}
static
int
cgfs_num_hierarchies
(
void
)
{
/* not implemented */
return
-
1
;
}
static
bool
cgfs_get_hierarchies
(
int
i
,
char
***
out
)
{
/* not implemented */
return
false
;
}
static
bool
cgfs_unfreeze
(
void
*
hdata
)
static
bool
cgfs_unfreeze
(
void
*
hdata
)
{
{
struct
cgfs_data
*
d
=
hdata
;
struct
cgfs_data
*
d
=
hdata
;
...
@@ -2625,8 +2615,9 @@ static struct cgroup_ops cgfs_ops = {
...
@@ -2625,8 +2615,9 @@ static struct cgroup_ops cgfs_ops = {
.
enter
=
cgfs_enter
,
.
enter
=
cgfs_enter
,
.
create_legacy
=
cgfs_create_legacy
,
.
create_legacy
=
cgfs_create_legacy
,
.
get_cgroup
=
cgfs_get_cgroup
,
.
get_cgroup
=
cgfs_get_cgroup
,
.
canonical_path
=
cgfs_canonical_path
,
.
escape
=
cgfs_escape
,
.
escape
=
cgfs_escape
,
.
num_hierarchies
=
cgfs_num_hierarchies
,
.
get_hierarchies
=
cgfs_get_hierarchies
,
.
get
=
lxc_cgroupfs_get
,
.
get
=
lxc_cgroupfs_get
,
.
set
=
lxc_cgroupfs_set
,
.
set
=
lxc_cgroupfs_set
,
.
unfreeze
=
cgfs_unfreeze
,
.
unfreeze
=
cgfs_unfreeze
,
...
...
src/lxc/cgroups/cgfsng.c
View file @
651ef4ef
...
@@ -1087,13 +1087,6 @@ out_free:
...
@@ -1087,13 +1087,6 @@ out_free:
return
false
;
return
false
;
}
}
static
const
char
*
cgfsng_canonical_path
(
void
*
hdata
)
{
struct
cgfsng_handler_data
*
d
=
hdata
;
return
d
->
container_cgroup
;
}
static
bool
cgfsng_enter
(
void
*
hdata
,
pid_t
pid
)
static
bool
cgfsng_enter
(
void
*
hdata
,
pid_t
pid
)
{
{
char
pidstr
[
25
];
char
pidstr
[
25
];
...
@@ -1426,19 +1419,11 @@ static int cgfsng_nrtasks(void *hdata) {
...
@@ -1426,19 +1419,11 @@ static int cgfsng_nrtasks(void *hdata) {
/* Only root needs to escape to the cgroup of its init */
/* Only root needs to escape to the cgroup of its init */
static
bool
cgfsng_escape
()
static
bool
cgfsng_escape
()
{
{
struct
cgfsng_handler_data
*
d
;
int
i
;
int
i
;
bool
ret
=
false
;
if
(
geteuid
())
if
(
geteuid
())
return
true
;
return
true
;
d
=
cgfsng_init
(
"criu-temp-cgfsng"
);
if
(
!
d
)
{
ERROR
(
"cgfsng_init failed"
);
return
false
;
}
for
(
i
=
0
;
hierarchies
[
i
];
i
++
)
{
for
(
i
=
0
;
hierarchies
[
i
];
i
++
)
{
char
*
fullpath
=
must_make_path
(
hierarchies
[
i
]
->
mountpoint
,
char
*
fullpath
=
must_make_path
(
hierarchies
[
i
]
->
mountpoint
,
hierarchies
[
i
]
->
base_cgroup
,
hierarchies
[
i
]
->
base_cgroup
,
...
@@ -1446,15 +1431,37 @@ static bool cgfsng_escape()
...
@@ -1446,15 +1431,37 @@ static bool cgfsng_escape()
if
(
lxc_write_to_file
(
fullpath
,
"0"
,
2
,
false
)
!=
0
)
{
if
(
lxc_write_to_file
(
fullpath
,
"0"
,
2
,
false
)
!=
0
)
{
SYSERROR
(
"Failed to escape to %s"
,
fullpath
);
SYSERROR
(
"Failed to escape to %s"
,
fullpath
);
free
(
fullpath
);
free
(
fullpath
);
goto
out
;
return
false
;
}
}
free
(
fullpath
);
free
(
fullpath
);
}
}
ret
=
true
;
return
true
;
out:
}
free_handler_data
(
d
);
return
ret
;
static
int
cgfsng_num_hierarchies
(
void
)
{
int
i
;
for
(
i
=
0
;
hierarchies
[
i
];
i
++
)
;
return
i
;
}
static
bool
cgfsng_get_hierarchies
(
int
n
,
char
***
out
)
{
int
i
;
/* sanity check n */
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
!
hierarchies
[
i
])
return
false
;
}
*
out
=
hierarchies
[
i
]
->
controllers
;
return
true
;
}
}
#define THAWED "THAWED"
#define THAWED "THAWED"
...
@@ -1672,8 +1679,9 @@ static struct cgroup_ops cgfsng_ops = {
...
@@ -1672,8 +1679,9 @@ static struct cgroup_ops cgfsng_ops = {
.
destroy
=
cgfsng_destroy
,
.
destroy
=
cgfsng_destroy
,
.
create
=
cgfsng_create
,
.
create
=
cgfsng_create
,
.
enter
=
cgfsng_enter
,
.
enter
=
cgfsng_enter
,
.
canonical_path
=
cgfsng_canonical_path
,
.
escape
=
cgfsng_escape
,
.
escape
=
cgfsng_escape
,
.
num_hierarchies
=
cgfsng_num_hierarchies
,
.
get_hierarchies
=
cgfsng_get_hierarchies
,
.
get_cgroup
=
cgfsng_get_cgroup
,
.
get_cgroup
=
cgfsng_get_cgroup
,
.
get
=
cgfsng_get
,
.
get
=
cgfsng_get
,
.
set
=
cgfsng_set
,
.
set
=
cgfsng_set
,
...
...
src/lxc/cgroups/cgmanager.c
View file @
651ef4ef
...
@@ -337,6 +337,18 @@ static bool cgm_escape(void *hdata)
...
@@ -337,6 +337,18 @@ static bool cgm_escape(void *hdata)
return
ret
;
return
ret
;
}
}
static
int
cgm_num_hierarchies
(
void
)
{
/* not implemented */
return
-
1
;
}
static
bool
cgm_get_hierarchies
(
int
i
,
char
***
out
)
{
/* not implemented */
return
false
;
}
struct
chown_data
{
struct
chown_data
{
const
char
*
cgroup_path
;
const
char
*
cgroup_path
;
uid_t
origuid
;
uid_t
origuid
;
...
@@ -734,15 +746,6 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
...
@@ -734,15 +746,6 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
return
d
->
cgroup_path
;
return
d
->
cgroup_path
;
}
}
static
const
char
*
cgm_canonical_path
(
void
*
hdata
)
{
struct
cgm_data
*
d
=
hdata
;
if
(
!
d
||
!
d
->
cgroup_path
)
return
NULL
;
return
d
->
cgroup_path
;
}
#if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
#if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
static
inline
bool
abs_cgroup_supported
(
void
)
{
static
inline
bool
abs_cgroup_supported
(
void
)
{
return
api_version
>=
CGM_SUPPORTS_GET_ABS
;
return
api_version
>=
CGM_SUPPORTS_GET_ABS
;
...
@@ -1655,8 +1658,9 @@ static struct cgroup_ops cgmanager_ops = {
...
@@ -1655,8 +1658,9 @@ static struct cgroup_ops cgmanager_ops = {
.
enter
=
cgm_enter
,
.
enter
=
cgm_enter
,
.
create_legacy
=
NULL
,
.
create_legacy
=
NULL
,
.
get_cgroup
=
cgm_get_cgroup
,
.
get_cgroup
=
cgm_get_cgroup
,
.
canonical_path
=
cgm_canonical_path
,
.
escape
=
cgm_escape
,
.
escape
=
cgm_escape
,
.
num_hierarchies
=
cgm_num_hierarchies
,
.
get_hierarchies
=
cgm_get_hierarchies
,
.
get
=
cgm_get
,
.
get
=
cgm_get
,
.
set
=
cgm_set
,
.
set
=
cgm_set
,
.
unfreeze
=
cgm_unfreeze
,
.
unfreeze
=
cgm_unfreeze
,
...
...
src/lxc/cgroups/cgroup.c
View file @
651ef4ef
...
@@ -119,17 +119,20 @@ bool cgroup_escape(struct lxc_handler *handler)
...
@@ -119,17 +119,20 @@ bool cgroup_escape(struct lxc_handler *handler)
return
false
;
return
false
;
}
}
const
char
*
cgroup_canonical_path
(
struct
lxc_handler
*
handler
)
int
cgroup_num_hierarchies
(
void
)
{
{
if
(
geteuid
())
{
if
(
!
ops
)
WARN
(
"cgroup_canonical_path only makes sense for privileged containers.
\n
"
);
return
-
1
;
return
NULL
;
}
if
(
ops
)
return
ops
->
num_hierarchies
();
return
ops
->
canonical_path
(
handler
->
cgroup_data
);
}
return
NULL
;
bool
cgroup_get_hierarchies
(
int
n
,
char
***
out
)
{
if
(
!
ops
)
return
false
;
return
ops
->
get_hierarchies
(
n
,
out
);
}
}
bool
cgroup_unfreeze
(
struct
lxc_handler
*
handler
)
bool
cgroup_unfreeze
(
struct
lxc_handler
*
handler
)
...
...
src/lxc/cgroups/cgroup.h
View file @
651ef4ef
...
@@ -47,8 +47,9 @@ struct cgroup_ops {
...
@@ -47,8 +47,9 @@ struct cgroup_ops {
bool
(
*
enter
)(
void
*
hdata
,
pid_t
pid
);
bool
(
*
enter
)(
void
*
hdata
,
pid_t
pid
);
bool
(
*
create_legacy
)(
void
*
hdata
,
pid_t
pid
);
bool
(
*
create_legacy
)(
void
*
hdata
,
pid_t
pid
);
const
char
*
(
*
get_cgroup
)(
void
*
hdata
,
const
char
*
subsystem
);
const
char
*
(
*
get_cgroup
)(
void
*
hdata
,
const
char
*
subsystem
);
const
char
*
(
*
canonical_path
)(
void
*
hdata
);
bool
(
*
escape
)();
bool
(
*
escape
)();
int
(
*
num_hierarchies
)();
bool
(
*
get_hierarchies
)(
int
n
,
char
***
out
);
int
(
*
set
)(
const
char
*
filename
,
const
char
*
value
,
const
char
*
name
,
const
char
*
lxcpath
);
int
(
*
set
)(
const
char
*
filename
,
const
char
*
value
,
const
char
*
name
,
const
char
*
lxcpath
);
int
(
*
get
)(
const
char
*
filename
,
char
*
value
,
size_t
len
,
const
char
*
name
,
const
char
*
lxcpath
);
int
(
*
get
)(
const
char
*
filename
,
char
*
value
,
size_t
len
,
const
char
*
name
,
const
char
*
lxcpath
);
bool
(
*
unfreeze
)(
void
*
hdata
);
bool
(
*
unfreeze
)(
void
*
hdata
);
...
@@ -74,11 +75,8 @@ extern bool cgroup_create_legacy(struct lxc_handler *handler);
...
@@ -74,11 +75,8 @@ extern bool cgroup_create_legacy(struct lxc_handler *handler);
extern
int
cgroup_nrtasks
(
struct
lxc_handler
*
handler
);
extern
int
cgroup_nrtasks
(
struct
lxc_handler
*
handler
);
extern
const
char
*
cgroup_get_cgroup
(
struct
lxc_handler
*
handler
,
const
char
*
subsystem
);
extern
const
char
*
cgroup_get_cgroup
(
struct
lxc_handler
*
handler
,
const
char
*
subsystem
);
extern
bool
cgroup_escape
();
extern
bool
cgroup_escape
();
extern
int
cgroup_num_hierarchies
();
/*
extern
bool
cgroup_get_hierarchies
(
int
i
,
char
***
out
);
* Currently, this call only makes sense for privileged containers.
*/
extern
const
char
*
cgroup_canonical_path
(
struct
lxc_handler
*
handler
);
extern
bool
cgroup_unfreeze
(
struct
lxc_handler
*
handler
);
extern
bool
cgroup_unfreeze
(
struct
lxc_handler
*
handler
);
extern
void
cgroup_disconnect
(
void
);
extern
void
cgroup_disconnect
(
void
);
extern
cgroup_driver_t
cgroup_driver
(
void
);
extern
cgroup_driver_t
cgroup_driver
(
void
);
...
...
src/lxc/criu.c
View file @
651ef4ef
...
@@ -69,7 +69,7 @@ struct criu_opts {
...
@@ -69,7 +69,7 @@ struct criu_opts {
char
tty_id
[
32
];
/* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
char
tty_id
[
32
];
/* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
/* restore: the file to write the init process' pid into */
/* restore: the file to write the init process' pid into */
const
char
*
cgroup_path
;
struct
lxc_handler
*
handler
;
int
console_fd
;
int
console_fd
;
/* The path that is bind mounted from /dev/console, if any. We don't
/* The path that is bind mounted from /dev/console, if any. We don't
* want to use `--ext-mount-map auto`'s result here because the pts
* want to use `--ext-mount-map auto`'s result here because the pts
...
@@ -140,7 +140,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -140,7 +140,7 @@ static void exec_criu(struct criu_opts *opts)
/* The command line always looks like:
/* The command line always looks like:
* criu $(action) --tcp-established --file-locks --link-remap \
* criu $(action) --tcp-established --file-locks --link-remap \
* --manage-cgroups=full action-script foo.sh -D $(directory) \
* --manage-cgroups=full
--
action-script foo.sh -D $(directory) \
* -o $(directory)/$(action).log --ext-mount-map auto
* -o $(directory)/$(action).log --ext-mount-map auto
* --enable-external-sharing --enable-external-masters
* --enable-external-sharing --enable-external-masters
* --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n
* --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n
...
@@ -175,10 +175,10 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -175,10 +175,10 @@ static void exec_criu(struct criu_opts *opts)
static_args
+=
2
;
static_args
+=
2
;
}
else
if
(
strcmp
(
opts
->
action
,
"restore"
)
==
0
)
{
}
else
if
(
strcmp
(
opts
->
action
,
"restore"
)
==
0
)
{
/* --root $(lxc_mount_point) --restore-detached
/* --root $(lxc_mount_point) --restore-detached
* --restore-sibling
--cgroup-root $foo
* --restore-sibling
* --lsm-profile apparmor:whatever
* --lsm-profile apparmor:whatever
*/
*/
static_args
+=
8
;
static_args
+=
6
;
tty_info
[
0
]
=
0
;
tty_info
[
0
]
=
0
;
if
(
load_tty_major_minor
(
opts
->
user
->
directory
,
tty_info
,
sizeof
(
tty_info
)))
if
(
load_tty_major_minor
(
opts
->
user
->
directory
,
tty_info
,
sizeof
(
tty_info
)))
...
@@ -191,6 +191,9 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -191,6 +191,9 @@ static void exec_criu(struct criu_opts *opts)
return
;
return
;
}
}
if
(
cgroup_num_hierarchies
()
>
0
)
static_args
+=
2
*
cgroup_num_hierarchies
();
if
(
opts
->
user
->
verbose
)
if
(
opts
->
user
->
verbose
)
static_args
++
;
static_args
++
;
...
@@ -244,6 +247,66 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -244,6 +247,66 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG
(
"-o"
);
DECLARE_ARG
(
"-o"
);
DECLARE_ARG
(
log
);
DECLARE_ARG
(
log
);
for
(
i
=
0
;
i
<
cgroup_num_hierarchies
();
i
++
)
{
char
**
controllers
=
NULL
,
*
fullname
;
char
*
path
;
if
(
!
cgroup_get_hierarchies
(
i
,
&
controllers
))
{
ERROR
(
"failed to get hierarchy %d"
,
i
);
goto
err
;
}
/* if we are in a dump, we have to ask the monitor process what
* the right cgroup is. if this is a restore, we can just use
* the handler the restore task created.
*/
if
(
!
strcmp
(
opts
->
action
,
"dump"
)
||
!
strcmp
(
opts
->
action
,
"pre-dump"
))
{
path
=
lxc_cmd_get_cgroup_path
(
opts
->
c
->
name
,
opts
->
c
->
config_path
,
controllers
[
0
]);
if
(
!
path
)
{
ERROR
(
"failed to get cgroup path for %s"
,
controllers
[
0
]);
goto
err
;
}
}
else
{
const
char
*
p
;
p
=
cgroup_get_cgroup
(
opts
->
handler
,
controllers
[
0
]);
if
(
!
p
)
{
ERROR
(
"failed to get cgroup path for %s"
,
controllers
[
0
]);
goto
err
;
}
path
=
strdup
(
p
);
if
(
!
path
)
{
ERROR
(
"strdup failed"
);
goto
err
;
}
}
if
(
!
lxc_deslashify
(
path
))
{
ERROR
(
"failed to deslashify %s"
,
path
);
free
(
path
);
goto
err
;
}
fullname
=
lxc_string_join
(
","
,
(
const
char
**
)
controllers
,
false
);
if
(
!
fullname
)
{
ERROR
(
"failed to join controllers"
);
free
(
path
);
goto
err
;
}
ret
=
sprintf
(
buf
,
"%s:%s"
,
fullname
,
path
);
free
(
path
);
free
(
fullname
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
{
ERROR
(
"sprintf of cgroup root arg failed"
);
goto
err
;
}
DECLARE_ARG
(
"--cgroup-root"
);
DECLARE_ARG
(
buf
);
}
if
(
opts
->
user
->
verbose
)
if
(
opts
->
user
->
verbose
)
DECLARE_ARG
(
"-vvvvvv"
);
DECLARE_ARG
(
"-vvvvvv"
);
...
@@ -329,8 +392,6 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -329,8 +392,6 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG
(
opts
->
c
->
lxc_conf
->
rootfs
.
mount
);
DECLARE_ARG
(
opts
->
c
->
lxc_conf
->
rootfs
.
mount
);
DECLARE_ARG
(
"--restore-detached"
);
DECLARE_ARG
(
"--restore-detached"
);
DECLARE_ARG
(
"--restore-sibling"
);
DECLARE_ARG
(
"--restore-sibling"
);
DECLARE_ARG
(
"--cgroup-root"
);
DECLARE_ARG
(
opts
->
cgroup_path
);
if
(
tty_info
[
0
])
{
if
(
tty_info
[
0
])
{
if
(
opts
->
console_fd
<
0
)
{
if
(
opts
->
console_fd
<
0
)
{
...
@@ -682,9 +743,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -682,9 +743,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
os
.
action
=
"restore"
;
os
.
action
=
"restore"
;
os
.
user
=
opts
;
os
.
user
=
opts
;
os
.
c
=
c
;
os
.
c
=
c
;
os
.
cgroup_path
=
cgroup_canonical_path
(
handler
);
os
.
console_fd
=
c
->
lxc_conf
->
console
.
slave
;
os
.
console_fd
=
c
->
lxc_conf
->
console
.
slave
;
os
.
criu_version
=
criu_version
;
os
.
criu_version
=
criu_version
;
os
.
handler
=
handler
;
if
(
os
.
console_fd
>=
0
)
{
if
(
os
.
console_fd
>=
0
)
{
/* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu
/* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu
...
@@ -891,6 +952,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
...
@@ -891,6 +952,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
if
(
pid
==
0
)
{
if
(
pid
==
0
)
{
struct
criu_opts
os
;
struct
criu_opts
os
;
struct
lxc_handler
h
;
h
.
name
=
c
->
name
;
if
(
!
cgroup_init
(
&
h
))
{
ERROR
(
"failed to cgroup_init()"
);
exit
(
1
);
}
os
.
action
=
mode
;
os
.
action
=
mode
;
os
.
user
=
opts
;
os
.
user
=
opts
;
...
...
src/lxc/utils.c
View file @
651ef4ef
...
@@ -716,6 +716,24 @@ char **lxc_normalize_path(const char *path)
...
@@ -716,6 +716,24 @@ char **lxc_normalize_path(const char *path)
return
components
;
return
components
;
}
}
bool
lxc_deslashify
(
char
*
path
)
{
char
**
parts
=
NULL
,
*
path2
;
parts
=
lxc_normalize_path
(
path
);
if
(
!
parts
)
return
false
;
path2
=
lxc_string_join
(
"/"
,
(
const
char
**
)
parts
,
*
path
==
'/'
);
lxc_free_array
((
void
**
)
parts
,
free
);
if
(
!
path2
)
return
false
;
strncpy
(
path
,
path2
,
strlen
(
path
));
free
(
path2
);
return
true
;
}
char
*
lxc_append_paths
(
const
char
*
first
,
const
char
*
second
)
char
*
lxc_append_paths
(
const
char
*
first
,
const
char
*
second
)
{
{
size_t
len
=
strlen
(
first
)
+
strlen
(
second
)
+
1
;
size_t
len
=
strlen
(
first
)
+
strlen
(
second
)
+
1
;
...
...
src/lxc/utils.h
View file @
651ef4ef
...
@@ -248,6 +248,8 @@ extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_pr
...
@@ -248,6 +248,8 @@ extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_pr
* foo//bar -> { foo, bar, NULL }
* foo//bar -> { foo, bar, NULL }
*/
*/
extern
char
**
lxc_normalize_path
(
const
char
*
path
);
extern
char
**
lxc_normalize_path
(
const
char
*
path
);
/* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */
extern
bool
lxc_deslashify
(
char
*
path
);
extern
char
*
lxc_append_paths
(
const
char
*
first
,
const
char
*
second
);
extern
char
*
lxc_append_paths
(
const
char
*
first
,
const
char
*
second
);
/* Note: the following two functions use strtok(), so they will never
/* Note: the following two functions use strtok(), so they will never
* consider an empty element, even if two delimiters are next to
* consider an empty element, even if two delimiters are next to
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment