Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
alpine
mkinitfs
Commits
7673ee7d
Commit
7673ee7d
authored
Nov 23, 2016
by
Timo Teräs
Browse files
nlplug-findfs: speed up and simplify boot media finding
parent
4ff7f921
Changes
1
Hide whitespace changes
Inline
Side-by-side
nlplug-findfs.c
View file @
7673ee7d
/*
* Copy me if you can.
* by 20h
...
...
@@ -14,9 +13,9 @@
#include
<dirent.h>
#include
<err.h>
#include
<errno.h>
#include
<glob.h>
#include
<limits.h>
#include
<poll.h>
#include
<fnmatch.h>
#include
<pthread.h>
#include
<stdio.h>
#include
<stdlib.h>
...
...
@@ -619,71 +618,85 @@ static int is_mounted(const char *devnode) {
}
struct
recurse_opts
{
const
char
*
searchname
;
int
matchdirs
,
matchdepth
;
size_t
pathlen
;
char
path
[
PATH_MAX
],
*
filename
;
int
is_dir
;
int
matchdepth
;
int
curdepth
,
maxdepth
;
void
(
*
callback
)(
char
*
pathbuf
,
size_t
pathlen
,
void
*
userdata
);
void
(
*
callback
)(
struct
recurse_opts
*
opts
,
void
*
userdata
);
void
*
userdata
;
};
/* pathbuf needs hold PATH_MAX chars */
static
void
do_recurse_dir
(
char
*
pathbuf
,
struct
recurse_opts
*
opts
)
static
int
recurse_push
(
struct
recurse_opts
*
opts
,
size_t
*
oldlen
,
const
char
*
path
)
{
size_t
pathlen
=
strlen
(
path
);
if
(
opts
->
pathlen
+
1
+
pathlen
+
1
>=
sizeof
opts
->
path
)
return
0
;
*
oldlen
=
opts
->
pathlen
;
opts
->
path
[
opts
->
pathlen
++
]
=
'/'
;
strcpy
(
&
opts
->
path
[
opts
->
pathlen
],
path
);
opts
->
pathlen
+=
strlen
(
path
);
return
1
;
}
static
void
recurse_pop
(
struct
recurse_opts
*
opts
,
size_t
len
)
{
opts
->
pathlen
=
len
;
opts
->
path
[
len
]
=
0
;
}
static
void
do_recurse_dir
(
struct
recurse_opts
*
opts
)
{
size_t
pathlen
,
name
len
;
size_t
old
len
;
struct
dirent
*
entry
;
DIR
*
d
;
int
is_dir
;
d
=
opendir
(
path
buf
);
d
=
opendir
(
opts
->
path
);
if
(
!
d
)
return
;
pathlen
=
strlen
(
pathbuf
);
while
((
entry
=
readdir
(
d
))
!=
NULL
)
{
if
(
strcmp
(
entry
->
d_name
,
"."
)
==
0
||
strcmp
(
entry
->
d_name
,
".."
)
==
0
)
continue
;
namelen
=
strlen
(
entry
->
d_name
);
if
(
pathlen
+
2
+
namelen
>
PATH_MAX
)
{
dbg
(
"path length overflow"
);
if
(
!
recurse_push
(
opts
,
&
oldlen
,
entry
->
d_name
))
continue
;
}
pathbuf
[
pathlen
]
=
'/'
;
strcpy
(
&
pathbuf
[
pathlen
+
1
],
entry
->
d_name
);
if
(
entry
->
d_type
==
DT_UNKNOWN
)
{
/* some filesystems like iso9660 does not support
the d_type so we use lstat */
struct
stat
st
;
if
(
lstat
(
path
buf
,
&
st
)
<
0
)
{
dbg
(
"%s: %s"
,
path
buf
,
strerror
(
errno
));
if
(
lstat
(
opts
->
path
,
&
st
)
<
0
)
{
dbg
(
"%s: %s"
,
opts
->
path
,
strerror
(
errno
));
goto
next
;
}
is_dir
=
S_ISDIR
(
st
.
st_mode
);
}
else
is_dir
=
entry
->
d_type
&
DT_DIR
;
if
((
opts
->
matchdirs
||
!
is_dir
)
&&
(
opts
->
matchdepth
==
0
||
opts
->
matchdepth
==
opts
->
curdepth
)
&&
(
!
opts
->
searchname
||
strcmp
(
entry
->
d_name
,
opts
->
searchname
)
==
0
))
opts
->
callback
(
pathbuf
,
pathlen
+
1
+
namelen
,
opts
->
userdata
);
if
(
opts
->
matchdepth
==
0
||
opts
->
matchdepth
==
opts
->
curdepth
)
{
opts
->
filename
=
&
opts
->
path
[
oldlen
+
1
];
opts
->
is_dir
=
is_dir
;
opts
->
callback
(
opts
,
opts
->
userdata
);
}
if
(
is_dir
&&
opts
->
curdepth
<
opts
->
maxdepth
)
{
opts
->
curdepth
++
;
do_recurse_dir
(
pathbuf
,
opts
);
do_recurse_dir
(
opts
);
opts
->
curdepth
--
;
}
next:
pathbuf
[
pathlen
]
=
'\0'
;
recurse_pop
(
opts
,
oldlen
)
;
}
closedir
(
d
);
}
static
void
recurse_dir
(
char
*
pathbuf
,
struct
recurse_opts
*
opts
)
static
void
recurse_dir
(
struct
recurse_opts
*
opts
)
{
opts
->
pathlen
=
strlen
(
opts
->
path
);
opts
->
curdepth
=
1
;
do_recurse_dir
(
pathbuf
,
opts
);
do_recurse_dir
(
opts
);
}
struct
trigger_entry
{
...
...
@@ -692,22 +705,20 @@ struct trigger_entry {
char
pathname
[];
};
static
void
trigger_uevent_cb
(
char
*
path
,
size_t
pathlen
,
void
*
data
)
static
void
trigger_uevent_cb
(
struct
recurse_opts
*
opts
,
void
*
data
)
{
size_t
oldlen
;
int
fd
;
if
(
pathlen
+
1
+
strlen
(
"/uevent"
)
>
PATH_MAX
)
{
dbg
(
"path length overflow"
);
if
(
!
recurse_push
(
opts
,
&
oldlen
,
"uevent"
))
return
;
}
strcpy
(
&
path
[
pathlen
],
"/uevent"
);
fd
=
open
(
path
,
O_WRONLY
);
fd
=
open
(
opts
->
path
,
O_WRONLY
);
if
(
fd
>=
0
)
{
write
(
fd
,
"add"
,
3
);
close
(
fd
);
}
path
[
pathlen
]
=
0
;
recurse_pop
(
opts
,
oldlen
)
;
}
static
void
trigger_path
(
struct
ueventconf
*
conf
,
char
*
path
,
char
*
subdir
,
int
max_depth
)
...
...
@@ -735,8 +746,6 @@ static void *trigger_thread(void *data)
struct
ueventconf
*
conf
=
data
;
struct
recurse_opts
opts
;
struct
trigger_entry
*
entry
=
NULL
;
char
path
[
PATH_MAX
]
=
"/sys"
;
size_t
prefixlen
=
strlen
(
path
);
while
(
1
)
{
pthread_mutex_lock
(
&
conf
->
trigger_mutex
);
...
...
@@ -752,88 +761,74 @@ static void *trigger_thread(void *data)
}
pthread_mutex_unlock
(
&
conf
->
trigger_mutex
);
/* scan list */
strcpy
(
&
path
[
prefixlen
],
entry
->
pathname
);
dbg
(
"trigger_thread: scanning %s"
,
path
);
opts
=
(
struct
recurse_opts
)
{
.
callback
=
trigger_uevent_cb
,
.
matchdirs
=
1
,
.
userdata
=
entry
,
.
maxdepth
=
entry
->
max_depth
,
.
matchdepth
=
entry
->
max_depth
,
};
recurse_dir
(
path
,
&
opts
);
snprintf
(
opts
.
path
,
sizeof
opts
.
path
,
"/sys%s"
,
entry
->
pathname
);
dbg
(
"trigger_thread: scanning %s"
,
opts
.
path
);
recurse_dir
(
&
opts
);
}
return
NULL
;
}
struct
bootrepos
{
char
*
outfile
;
int
count
;
};
static
void
bootrepo_cb
(
char
*
path
,
size_t
pathlen
,
void
*
data
)
static
void
append_line
(
const
char
*
outfile
,
const
char
*
data
)
{
struct
bootrepos
*
repos
=
data
;
int
fd
=
open
(
repos
->
outfile
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
int
fd
;
if
(
outfile
==
0
)
return
;
fd
=
open
(
outfile
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
if
(
fd
==
-
1
)
err
(
1
,
"%s"
,
repos
->
outfile
);
write
(
fd
,
path
,
strlen
(
path
)
-
strlen
(
"/.boot_repository"
));
err
(
1
,
"%s"
,
outfile
);
write
(
fd
,
data
,
strlen
(
data
));
write
(
fd
,
"
\n
"
,
1
);
close
(
fd
);
dbg
(
"added boot repository %s to %s
\n
"
,
path
,
repos
->
outfile
);
repos
->
count
++
;
}
static
int
find_apkovl
(
const
char
*
dir
,
const
char
*
outfile
)
{
char
pattern
[
PATH_MAX
];
glob_t
gl
;
int
r
,
fd
;
if
(
outfile
==
NULL
)
return
0
;
snprintf
(
pattern
,
sizeof
(
pattern
),
"%s/*.apkovl.tar.gz*"
,
dir
);
r
=
glob
(
pattern
,
0
,
NULL
,
&
gl
);
if
(
r
!=
0
)
return
0
;
fd
=
open
(
outfile
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
if
(
fd
==
-
1
)
err
(
1
,
"%s"
,
outfile
);
struct
scandevctx
{
struct
ueventconf
*
conf
;
int
found
;
};
for
(
r
=
0
;
r
<
gl
.
gl_pathc
;
r
++
)
{
dbg
(
"Found apkovl: %s"
,
gl
.
gl_pathv
[
r
]);
write
(
fd
,
gl
.
gl_pathv
[
r
],
strlen
(
gl
.
gl_pathv
[
r
]));
write
(
fd
,
"
\n
"
,
1
);
static
void
scandev_cb
(
struct
recurse_opts
*
opts
,
void
*
data
)
{
struct
scandevctx
*
ctx
=
data
;
struct
ueventconf
*
conf
=
ctx
->
conf
;
if
(
opts
->
is_dir
)
{
size_t
oldlen
;
int
ok
=
0
;
if
(
recurse_push
(
opts
,
&
oldlen
,
".boot_repository"
))
{
ok
=
access
(
opts
->
path
,
F_OK
)
==
0
;
recurse_pop
(
opts
,
oldlen
);
}
if
(
ok
)
{
dbg
(
"added boot repository %s to %s"
,
opts
->
path
,
conf
->
bootrepos
);
append_line
(
conf
->
bootrepos
,
opts
->
path
);
ctx
->
found
|=
FOUND_BOOTREPO
;
}
}
else
if
(
fnmatch
(
"*.apkovl.tar.gz*"
,
opts
->
filename
,
0
)
==
0
)
{
dbg
(
"found apkovl %s"
,
opts
->
path
);
append_line
(
conf
->
apkovls
,
opts
->
path
);
ctx
->
found
|=
FOUND_APKOVL
;
}
close
(
fd
);
globfree
(
&
gl
);
return
FOUND_APKOVL
;
}
static
int
find_bootrepos
(
const
char
*
devnode
,
const
char
*
type
,
char
*
bootrepos
,
const
char
*
apkovls
)
static
int
scandev
(
struct
ueventconf
*
conf
,
const
char
*
devnode
,
const
char
*
type
)
{
char
mountdir
[
PATH_MAX
]
=
""
;
char
*
devname
;
int
r
,
rc
=
0
;
struct
bootrepos
repos
=
{
.
outfile
=
bootrepos
,
.
count
=
0
,
struct
scandevctx
ctx
=
{
.
conf
=
conf
,
};
struct
recurse_opts
opts
=
{
.
maxdepth
=
2
,
.
searchname
=
".boot_repository"
,
.
callback
=
bootrepo_cb
,
.
userdata
=
&
repos
,
.
maxdepth
=
1
,
.
callback
=
scandev_cb
,
.
userdata
=
&
ctx
,
};
char
*
devname
;
int
r
;
/* skip already mounted devices */
if
(
is_mounted
(
devnode
))
{
...
...
@@ -841,31 +836,26 @@ static int find_bootrepos(const char *devnode, const char *type,
return
0
;
}
devname
=
strrchr
(
devnode
,
'/'
);
if
(
!
devname
)
return
0
;
if
(
devname
)
snprintf
(
mountdir
,
sizeof
(
mountdir
),
"/media%s"
,
devname
);
dbg
(
"mounting %s on %s. (%s)"
,
devnode
,
mountdir
,
type
);
mkdir
(
mountdir
,
0755
);
snprintf
(
opts
.
path
,
sizeof
opts
.
path
,
"/media%s"
,
devname
);
dbg
(
"mounting %s on %s (%s)"
,
devnode
,
opts
.
path
,
type
);
mkdir
(
opts
.
path
,
0755
);
r
=
mount
(
devnode
,
mountdir
,
type
,
MS_RDONLY
,
NULL
);
r
=
mount
(
devnode
,
opts
.
path
,
type
,
MS_RDONLY
,
NULL
);
if
(
r
<
0
)
{
dbg
(
"Failed to mount %s on %s: %s"
,
devnode
,
mountdir
,
strerror
(
errno
));
devnode
,
opts
.
path
,
strerror
(
errno
));
return
0
;
}
recurse_dir
(
mountdir
,
&
opts
);
if
(
repos
.
count
>
0
)
rc
|=
FOUND_BOOTREPO
;
recurse_dir
(
&
opts
);
if
(
find_apkovl
(
mountdir
,
apkovls
)
)
rc
|=
FOUND_APKOVL
;
if
(
ctx
.
found
==
0
)
umount
(
opts
.
path
)
;
if
(
rc
==
0
)
umount
(
mountdir
);
return
rc
;
return
ctx
.
found
;
}
static
int
is_same_device
(
const
struct
uevent
*
ev
,
const
char
*
nodepath
)
...
...
@@ -904,14 +894,13 @@ static void founddev(struct ueventconf *conf, int found)
}
}
static
int
searchdev
(
struct
uevent
*
ev
,
const
char
*
searchdev
,
char
*
bootrepos
,
const
char
*
apkovls
)
static
int
searchdev
(
struct
uevent
*
ev
,
const
char
*
searchdev
,
int
scanbootmedia
)
{
struct
ueventconf
*
conf
=
ev
->
conf
;
char
*
type
=
NULL
,
*
label
=
NULL
,
*
uuid
=
NULL
;
int
rc
=
0
;
if
(
searchdev
==
NULL
&&
bootrepos
==
NULL
&&
apkovls
==
NULL
)
if
(
searchdev
==
NULL
&&
!
scanbootmedia
)
return
0
;
if
(
searchdev
&&
(
strcmp
(
ev
->
devname
,
searchdev
)
==
0
...
...
@@ -945,8 +934,8 @@ static int searchdev(struct uevent *ev, const char *searchdev, char *bootrepos,
start_mdadm
(
ev
->
devnode
);
}
else
if
(
strcmp
(
"LVM2_member"
,
type
)
==
0
)
{
start_lvm2
(
ev
->
devnode
);
}
else
if
(
bootrepos
)
{
rc
=
find_bootrepos
(
ev
->
devnode
,
type
,
bootrepos
,
apkovls
);
}
else
if
(
scanbootmedia
)
{
rc
=
scandev
(
conf
,
ev
->
devnode
,
type
);
}
}
...
...
@@ -974,12 +963,12 @@ static void uevent_handle(struct uevent *ev)
snprintf
(
ev
->
devnode
,
sizeof
(
ev
->
devnode
),
"/dev/%s"
,
ev
->
devname
);
pthread_mutex_lock
(
&
conf
->
cryptsetup_mutex
);
found
=
searchdev
(
ev
,
conf
->
search_device
,
conf
->
bootrepos
,
conf
->
apkovls
);
found
=
searchdev
(
ev
,
conf
->
search_device
,
1
);
pthread_mutex_unlock
(
&
conf
->
cryptsetup_mutex
);
if
(
found
)
{
founddev
(
conf
,
found
);
}
else
if
(
conf
->
crypt
.
devnode
[
0
]
==
'\0'
&&
searchdev
(
ev
,
conf
->
crypt
.
device
,
NULL
,
NULL
))
{
searchdev
(
ev
,
conf
->
crypt
.
device
,
0
))
{
strncpy
(
conf
->
crypt
.
devnode
,
conf
->
crypt
.
device
[
0
]
==
'/'
?
conf
->
crypt
.
device
:
ev
->
devnode
,
sizeof
(
conf
->
crypt
.
devnode
));
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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