s3: Plumb smb_filename through SMB_VFS_STAT and SMB_VFS_LSTAT
[ira/wip.git] / source3 / smbd / notify.c
index fdab2ca848537b6fc38a6fcb5ea364f1810fc22f..a242fc3ac03d3517cc28c6108347769d86740285 100644 (file)
@@ -81,7 +81,7 @@ static bool notify_marshall_changes(int num_changes,
 
                c = &changes[i];
 
-               if (!convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE,
+               if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE,
                        c->name, strlen(c->name)+1, &uni_name.buffer,
                        &namelen, True) || (uni_name.buffer == NULL)) {
                        goto fail;
@@ -109,7 +109,7 @@ static bool notify_marshall_changes(int num_changes,
                 */
                prs_set_offset(ps, prs_offset(ps)-2);
 
-               SAFE_FREE(uni_name.buffer);
+               TALLOC_FREE(uni_name.buffer);
 
                if (prs_offset(ps) > max_offset) {
                        /* Too much data for client. */
@@ -123,7 +123,7 @@ static bool notify_marshall_changes(int num_changes,
        return True;
 
  fail:
-       SAFE_FREE(uni_name.buffer);
+       TALLOC_FREE(uni_name.buffer);
        return False;
 }
 
@@ -211,6 +211,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
        if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath,
                     fsp->fsp_name) == -1) {
                DEBUG(0, ("asprintf failed\n"));
+               TALLOC_FREE(fsp->notify);
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -338,17 +339,37 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
                  const char *path)
 {
        char *fullpath;
+       char *parent;
+       const char *name;
 
        if (path[0] == '.' && path[1] == '/') {
                path += 2;
        }
-       if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
+       if (parent_dirname(talloc_tos(), path, &parent, &name)) {
+               struct smb_filename *smb_fname_parent = NULL;
+               NTSTATUS status;
+
+               status = create_synthetic_smb_fname(talloc_tos(), parent, NULL,
+                                                   NULL, &smb_fname_parent);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return;
+               }
+               if (SMB_VFS_STAT(conn, smb_fname_parent) != -1) {
+                       notify_onelevel(conn->notify_ctx, action, filter,
+                           SMB_VFS_FILE_ID_CREATE(conn, &smb_fname_parent->st),
+                           name);
+               }
+               TALLOC_FREE(smb_fname_parent);
+       }
+
+       fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
+                                  path);
+       if (fullpath == NULL) {
                DEBUG(0, ("asprintf failed\n"));
                return;
        }
-
        notify_trigger(conn->notify_ctx, action, filter, fullpath);
-       SAFE_FREE(fullpath);
+       TALLOC_FREE(fullpath);
 }
 
 static void notify_fsp(files_struct *fsp, uint32 action, const char *name)