Skip to content

Commit 2bc73d6

Browse files
author
Oleg Girko
committed
Add SBOX_MAP_PATH_ALLOW_NONEXISTENT flag to sbox_map_path().
This flag allows path resolution to succeed even if non-final components in the pathname refer to nonexistent directories. This is needed for emulating bindtextdomain() function which can accept pathname refering to nonexistent directory without returning an error. Signed-off-by: Oleg Girko <[email protected]>
1 parent 52107d2 commit 2bc73d6

File tree

5 files changed

+52
-3
lines changed

5 files changed

+52
-3
lines changed

scratchbox2/include/mapping.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ extern void free_mapping_results(mapping_results_t *res);
7474
extern void force_path_to_mapping_result(mapping_results_t *res, const char *path);
7575

7676
#define SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK 0x01
77+
#define SBOX_MAP_PATH_ALLOW_NONEXISTENT 0x02
7778

7879
extern void sbox_map_path(const char *func_name, const char *path,
7980
uint32_t flags, mapping_results_t *res, uint32_t classmask);

scratchbox2/pathmapping/pathmapping.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef struct path_mapping_context_s {
8888
int pmc_dont_resolve_final_symlink;
8989
int pmc_file_must_exist;
9090
int pmc_must_be_directory;
91+
int pmc_allow_nonexistent;
9192
struct sb2context *pmc_sb2ctx;
9293

9394
/* for paths_ruletree_mapping.c: */

scratchbox2/pathmapping/pathresolution.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,14 @@ static ruletree_object_offset_t sb_path_resolution(
668668
SB_LOG(SB_LOGLEVEL_NOISE2,
669669
"Last component doesn't exist [%d] '%s'",
670670
component_index, virtual_path_work_ptr->pe_path_component);
671+
} else if (errno == ENOENT &&
672+
ctx->pmc_allow_nonexistent) {
673+
/* this is not last component,
674+
* but it's still not required to exist.
675+
*/
676+
SB_LOG(SB_LOGLEVEL_NOISE3,
677+
"Component doesn't exist [%d] '%s'",
678+
component_index, virtual_path_work_ptr->pe_path_component);
671679
} else {
672680
/* any other errno valus is error */
673681
resolved_virtual_path_res->mres_errno = errno;
@@ -1244,6 +1252,7 @@ void sbox_map_path_internal__c_engine(
12441252
ctx.pmc_virtual_orig_path = virtual_orig_path;
12451253
ctx.pmc_dont_resolve_final_symlink =
12461254
flags & SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK;
1255+
ctx.pmc_allow_nonexistent = flags & SBOX_MAP_PATH_ALLOW_NONEXISTENT;
12471256
ctx.pmc_sb2ctx = sb2ctx;
12481257
#if 0 /* see comment at pathmapping_interf.c/custom_map_path() */
12491258
ctx.pmc_rule_list_offset = rule_list_offset;

scratchbox2/preload/gen-interface.pl

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@
6363
# NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS!
6464
# - "resolve_final_symlink" is the opposite of "dont_resolve_final_symlink"
6565
# (and it is on by default)
66+
# - "allow_nonexistent" is used to prefix "map" modifiers where the
67+
# whole pathname (not just the last component) is allowed to refer
68+
# to nonexistent file in nonexistent directory.
69+
# NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS!
70+
# - "allow_nonexistent_if(condition)" conditionally
71+
# allows the pathname to refer to nonexistent file in nonexistent directory
72+
# (see "allow_nonexistent")
73+
# NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS!
6674
# - "postprocess(varname)" can be used to call postprocessor functions for
6775
# mapped variables.
6876
# - "return(expr)" can be used to alter the return value.
@@ -493,6 +501,22 @@ sub expr_to_flagexpr {
493501
return "$expr ? $flag : 0";
494502
}
495503

504+
sub flagexpr_join {
505+
my $result = "0";
506+
foreach my $flagexpr (@_) {
507+
if ($flagexpr eq "0") {
508+
# zero flag, leave result as is
509+
} elsif ($result eq "0") {
510+
# zero result, replace with flag
511+
$result = $flagexpr;
512+
} else {
513+
# non-zero result and flag, join with |
514+
$result .= " | $flagexpr";
515+
}
516+
}
517+
return $result;
518+
}
519+
496520
# Process the modifier section coming from the original input line.
497521
# This returns undef if failed, or a structure containing code fragments
498522
# and other information for the actual code generation phase.
@@ -521,6 +545,7 @@ sub process_wrap_or_gate_modifiers {
521545
'mapped_params_by_orig_name' => {},
522546
'mapping_results_by_orig_name' => {},
523547
'dont_resolve_final_symlink' => 0,
548+
'allow_nonexistent' => 0,
524549

525550
'postprocess_vars' => [],
526551
'return_expr' => undef,
@@ -573,6 +598,9 @@ sub process_wrap_or_gate_modifiers {
573598
my $new_name = "mapped__".$param_to_be_mapped;
574599
my $no_symlink_resolve =
575600
expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK");
601+
my $allow_nonexistent =
602+
expr_to_flagexpr($mods->{'allow_nonexistent'}, "SBOX_MAP_PATH_ALLOW_NONEXISTENT");
603+
my $flags = flagexpr_join($no_symlink_resolve, $allow_nonexistent);
576604

577605
$mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path";
578606
$mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name";
@@ -583,7 +611,7 @@ sub process_wrap_or_gate_modifiers {
583611
"\tclear_mapping_results_struct(&res_$new_name);\n".
584612
"\tsbox_map_path(__func__, ".
585613
"$param_to_be_mapped, ".
586-
"$no_symlink_resolve, ".
614+
"$flags, ".
587615
"&res_$new_name, classmask);\n".
588616
"\tif (res_$new_name.mres_errno) {\n".
589617
"\t\tSB_LOG(SB_LOGLEVEL_DEBUG, \"mapping failed, errno %d\",".
@@ -626,6 +654,9 @@ sub process_wrap_or_gate_modifiers {
626654
my $ro_flag = $param_to_be_mapped."_is_readonly";
627655
my $no_symlink_resolve =
628656
expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK");
657+
my $allow_nonexistent =
658+
expr_to_flagexpr($mods->{'allow_nonexistent'}, "SBOX_MAP_PATH_ALLOW_NONEXISTENT");
659+
my $flags = flagexpr_join($no_symlink_resolve, $allow_nonexistent);
629660

630661
$mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path";
631662
$mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name";
@@ -636,7 +667,7 @@ sub process_wrap_or_gate_modifiers {
636667
"\tsbox_map_path_at(__func__, ".
637668
"$fd_param, ".
638669
"$param_to_be_mapped, ".
639-
"$no_symlink_resolve, ".
670+
"$flags, ".
640671
"&res_$new_name, classmask);\n".
641672
"\tif (res_$new_name.mres_errno) {\n".
642673
"\t\terrno = res_$new_name.mres_errno;\n".
@@ -692,6 +723,11 @@ sub process_wrap_or_gate_modifiers {
692723
} elsif($modifiers[$i] =~ m/^dont_resolve_final_symlink_if\((.*)\)$/) {
693724
my $condition = $1;
694725
$mods->{'dont_resolve_final_symlink'} = "($condition)";
726+
} elsif($modifiers[$i] eq 'allow_nonexistent') {
727+
$mods->{'allow_nonexistent'} = 1;
728+
} elsif($modifiers[$i] =~ m/^allow_nonexistent_if\((.*)\)$/) {
729+
my $condition = $1;
730+
$mods->{'allow_nonexistent'} = "($condition)";
695731
} elsif(($modifiers[$i] =~ m/^optional_arg_is_create_mode\((.*)\)$/) &&
696732
($fn->{'has_varargs'})) {
697733
my $va_list_condition = $1;

scratchbox2/preload/sb_l10n.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ char *bindtextdomain_gate(int *result_errno_ptr,
3737
clear_mapping_results_struct(&res);
3838

3939
if (dirname != NULL) {
40-
sbox_map_path(realfn_name, dirname, 0, &res, SB2_INTERFACE_CLASS_L10N);
40+
sbox_map_path(realfn_name, dirname,
41+
SBOX_MAP_PATH_ALLOW_NONEXISTENT, &res,
42+
SB2_INTERFACE_CLASS_L10N);
4143
assert(res.mres_result_path != NULL);
4244

4345
mapped_dirname = res.mres_result_path;

0 commit comments

Comments
 (0)