|
9 | 9 | #include <linux/init.h> |
10 | 10 | #include <linux/slab.h> |
11 | 11 | #include <linux/fs.h> |
| 12 | +#include <linux/stat.h> |
12 | 13 | #include <linux/namei.h> |
13 | 14 | #include <linux/mount.h> |
14 | 15 | #include <linux/path.h> |
|
50 | 51 | DEEPIN_ERR_NOTIFY_ATTR_UID = 7, /* User ID (u32) */ |
51 | 52 | DEEPIN_ERR_NOTIFY_ATTR_GID = 8, /* Group ID (u32) */ |
52 | 53 | DEEPIN_ERR_NOTIFY_ATTR_STATUS = 9, /* Enable/Disable Status (u8) */ |
53 | | - DEEPIN_ERR_NOTIFY_ATTR_FUNC_NAME = 10, /* Function Name (string) */ |
54 | 54 | __DEEPIN_ERR_NOTIFY_ATTR_MAX, |
55 | 55 | }; |
56 | 56 |
|
@@ -139,11 +139,56 @@ int deepin_err_notify_should_send(void) |
139 | 139 | return __ratelimit(&deepin_err_notify_ratelimit); |
140 | 140 | } |
141 | 141 |
|
| 142 | +/** |
| 143 | + * combine_path_and_last - Combine base path with last component |
| 144 | + * @buffer: Pre-allocated buffer to store the combined path (size PATH_MAX) |
| 145 | + * @path: The base path to combine |
| 146 | + * @last: The last component to append |
| 147 | + * |
| 148 | + * This function combines a base path with a last component, constructing |
| 149 | + * the full path: base_path + "/" + last. The result is stored in buffer. |
| 150 | + * |
| 151 | + * Returns: Pointer to the combined path string on success, NULL on failure |
| 152 | + */ |
142 | 153 | static char *combine_path_and_last(char *buffer, const struct path *path, |
143 | 154 | const char *last) |
144 | 155 | { |
145 | | - /* TODO: Implement in next commit */ |
146 | | - return NULL; |
| 156 | + char *base_path; |
| 157 | + size_t base_len, last_len, total_len; |
| 158 | + |
| 159 | + base_path = d_absolute_path(path, buffer, PATH_MAX); |
| 160 | + if (IS_ERR(base_path)) |
| 161 | + return NULL; |
| 162 | + |
| 163 | + /* Construct full path: base_path + "/" + last */ |
| 164 | + base_len = strlen(base_path); |
| 165 | + last_len = strlen(last); |
| 166 | + total_len = base_len + 1 + last_len + 1; |
| 167 | + |
| 168 | + if (total_len > PATH_MAX) |
| 169 | + return NULL; |
| 170 | + |
| 171 | + /* |
| 172 | + * Move base_path to start of buffer if needed. |
| 173 | + * d_absolute_path() may return a pointer to the middle of the buffer, |
| 174 | + * not the start. We need the path at the beginning so we can |
| 175 | + * append "/" + last to it. |
| 176 | + */ |
| 177 | + if (base_path != buffer) |
| 178 | + memmove(buffer, base_path, base_len); |
| 179 | + |
| 180 | + /* Avoid appending an extra "/" after root directory "/" which would |
| 181 | + * result in "//filename". |
| 182 | + */ |
| 183 | + if (base_len > 0 && buffer[base_len - 1] != '/') { |
| 184 | + buffer[base_len] = '/'; |
| 185 | + memcpy(buffer + base_len + 1, last, last_len + 1); |
| 186 | + } else { |
| 187 | + /* base_path is already "/" or ends with "/" (rare case) */ |
| 188 | + memcpy(buffer + base_len, last, last_len + 1); |
| 189 | + } |
| 190 | + |
| 191 | + return buffer; |
147 | 192 | } |
148 | 193 |
|
149 | 194 | /* Check if overlay filesystem is mounted on /usr and send read only error notification */ |
@@ -673,13 +718,26 @@ static int __init deepin_err_notify_init(void) |
673 | 718 | * @new_path: path of new parent directory |
674 | 719 | * |
675 | 720 | * This function is called when a rename operation fails with EROFS error. |
| 721 | + * It attempts to look up the old and new paths and send error notification |
| 722 | + * if both paths are valid. |
676 | 723 | */ |
677 | 724 | void deepin_notify_rename_ro_fs_err(const struct qstr *old_last, |
678 | 725 | const struct qstr *new_last, |
679 | 726 | const struct path *old_path, |
680 | 727 | const struct path *new_path) |
681 | 728 | { |
682 | | - /* Simplified implementation - will be enhanced in next commit */ |
| 729 | + const struct deepin_path_last path_lasts[2] = { |
| 730 | + { .path = *old_path, .last = old_last->name }, |
| 731 | + { .path = *new_path, .last = new_last->name } |
| 732 | + }; |
| 733 | + int ret; |
| 734 | + |
| 735 | + ret = prepare_and_notify_fs_error(path_lasts, 2); |
| 736 | + if (ret < 0) { |
| 737 | + pr_debug( |
| 738 | + "deepin_err_notify: Failed to send notification to userspace: %d\n", |
| 739 | + ret); |
| 740 | + } |
683 | 741 | } |
684 | 742 |
|
685 | 743 | /* Use fs_initcall to ensure initialization before file system operations */ |
|
0 commit comments