return NT_STATUS_OK;
}
-static const char *previous_slash(const char *name_in, const char *slash)
-{
- const char *prev = NULL;
-
- SMB_ASSERT((name_in <= slash) && (slash[0] == '/'));
-
- prev = strchr_m(name_in, '/');
-
- if (prev == slash) {
- /* No previous slash */
- return NULL;
- }
-
- while (true) {
- const char *next = strchr_m(prev + 1, '/');
-
- if (next == slash) {
- return prev;
- }
- prev = next;
- }
-
- return NULL; /* unreachable */
-}
-
-static char *_symlink_target_path(TALLOC_CTX *mem_ctx,
- const char *name_in,
- const char *substitute,
- size_t unparsed)
-{
- size_t name_in_len = strlen(name_in);
- const char *p_unparsed = NULL;
- const char *parent = NULL;
- char *ret;
-
- SMB_ASSERT(unparsed <= name_in_len);
-
- p_unparsed = name_in + (name_in_len - unparsed);
-
- if (substitute[0] == '/') {
- ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
- return ret;
- }
-
- if (unparsed == 0) {
- parent = strrchr_m(name_in, '/');
- } else {
- parent = previous_slash(name_in, p_unparsed);
- }
-
- if (parent == NULL) {
- ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
- } else {
- ret = talloc_asprintf(mem_ctx,
- "%.*s/%s%s",
- (int)(parent - name_in),
- name_in,
- substitute,
- p_unparsed);
- }
-
- return ret;
-}
-
NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
const char *connectpath,
const char *dir,
char *target = NULL;
char *safe_target = NULL;
size_t symlink_redirects = 0;
+ int ret;
next:
if (symlink_redirects > 40) {
* resolve all symlinks locally.
*/
- target = _symlink_target_path(mem_ctx,
- name_in,
- lnk->substitute_name,
- lnk->unparsed_path_length);
- if (target == NULL) {
- return NT_STATUS_NO_MEMORY;
+ ret = symlink_target_path(mem_ctx,
+ name_in,
+ lnk->unparsed_path_length,
+ lnk->substitute_name,
+ lnk->substitute_name[0] != '/',
+ '/',
+ &target);
+ if (ret != 0) {
+ return map_nt_error_from_unix(ret);
}
status = safe_symlink_target_path(mem_ctx,