예제 #1
0
파일: dirops.c 프로젝트: ailispaw/vboxguest
/**
 * Rename a regular file / directory.
 *
 * @param old_parent    inode of the old parent directory
 * @param old_dentry    old directory cache entry
 * @param new_parent    inode of the new parent directory
 * @param new_dentry    new directory cache entry
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_rename(struct inode *old_parent, struct dentry *old_dentry,
                     struct inode *new_parent, struct dentry *new_dentry)
{
    int err = 0, rc = VINF_SUCCESS;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(old_parent->i_sb);

    TRACE();

    if (sf_g != GET_GLOB_INFO(new_parent->i_sb))
    {
        LogFunc(("rename with different roots\n"));
        err = -EINVAL;
    }
    else
    {
        struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent);
        struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent);
        /* As we save the relative path inside the inode structure, we need to change
           this if the rename is successful. */
        struct sf_inode_info *sf_file_i = GET_INODE_INFO(old_dentry->d_inode);
        SHFLSTRING *old_path;
        SHFLSTRING *new_path;

        BUG_ON(!sf_old_i);
        BUG_ON(!sf_new_i);
        BUG_ON(!sf_file_i);

        old_path = sf_file_i->path;
        err = sf_path_from_dentry(__func__, sf_g, sf_new_i,
                                  new_dentry, &new_path);
        if (err)
            LogFunc(("failed to create new path\n"));
        else
        {
            int fDir = ((old_dentry->d_inode->i_mode & S_IFDIR) != 0);

            rc = vboxCallRename(&client_handle, &sf_g->map, old_path,
                                new_path, fDir ? 0 : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS);
            if (RT_SUCCESS(rc))
            {
                kfree(old_path);
                sf_new_i->force_restat = 1;
                sf_old_i->force_restat = 1; /* XXX: needed? */
                /* Set the new relative path in the inode. */
                sf_file_i->path = new_path;
            }
            else
            {
                LogFunc(("vboxCallRename failed rc=%Rrc\n", rc));
                err = -RTErrConvertToErrno(rc);
                kfree(new_path);
            }
        }
    }
    return err;
}
예제 #2
0
NTSTATUS vbsfRename(IN PRX_CONTEXT RxContext,
                       IN FILE_INFORMATION_CLASS FileInformationClass,
                       IN PVOID pBuffer,
                       IN ULONG BufferLength)
{
    NTSTATUS Status = STATUS_SUCCESS;

    RxCaptureFcb;
    RxCaptureFobx;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;

    PFILE_RENAME_INFORMATION RenameInformation = (PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
    PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(pSrvOpen, capFcb);

    int vboxRC;
    PSHFLSTRING SrcPath = 0, DestPath = 0;
    ULONG ParsedPathSize, flags;

    Assert(FileInformationClass == FileRenameInformation);

    Log(("VBOXSF: vbsfRename: FileName = %.*ls\n",
         RenameInformation->FileNameLength / sizeof(WCHAR), &RenameInformation->FileName[0]));

    /* Must close the file before renaming it! */
    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
    {
        vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
    }

    /* Mark it as renamed, so we do nothing during close */
    SetFlag(pSrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED);

    /* Calculate length required for destination path. */
    ParsedPathSize = sizeof(*DestPath) + (RenameInformation->FileNameLength + sizeof(WCHAR));

    Log(("VBOXSF: vbsfRename: ParsedPathSize = %d\n",
         ParsedPathSize));

    DestPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);

    if (NULL == DestPath)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(DestPath, ParsedPathSize);
    ShflStringInitBuffer(DestPath, ParsedPathSize - sizeof(SHFLSTRING));

    Log(("VBOXSF: vbsfRename: Setting up destination path\n"));

    DestPath->u16Size = (USHORT)(RenameInformation->FileNameLength + sizeof(WCHAR));
    DestPath->u16Length = DestPath->u16Size - sizeof(WCHAR); /* without terminating null */
    RtlCopyMemory(DestPath->String.ucs2, RenameInformation->FileName, DestPath->u16Length);

    Log(("VBOXSF: vbsfRename: Destination path = %.*ls\n",
         DestPath->u16Length / sizeof(WCHAR), &DestPath->String.ucs2[0]));

    /* Calculate length required for source path */
    ParsedPathSize = sizeof(*DestPath) + (RemainingName->Length + sizeof(WCHAR));

    Log(("VBOXSF: vbsfRename: ParsedPathSize = %d\n", ParsedPathSize));

    SrcPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);

    if (NULL == SrcPath)
    {
        vbsfFreeNonPagedMem(DestPath);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(SrcPath, ParsedPathSize);
    ShflStringInitBuffer(SrcPath, ParsedPathSize - sizeof(SHFLSTRING));

    Log(("VBOXSF: vbsfRename: Setting up source path\n"));

    SrcPath->u16Size = RemainingName->Length + sizeof(WCHAR);
    SrcPath->u16Length = SrcPath->u16Size - sizeof(WCHAR); /* without terminating null */
    RtlCopyMemory(SrcPath->String.ucs2, RemainingName->Buffer, SrcPath->u16Length);

    Log(("VBOXSF: vbsfRename: Source path = %.*ls\n",
         SrcPath->u16Length / sizeof(WCHAR), &SrcPath->String.ucs2[0]));

    /* Call host. */
    flags = pVBoxFobx->FileStandardInfo.Directory? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
    if (RenameInformation->ReplaceIfExists)
    {
        flags |= SHFL_RENAME_REPLACE_IF_EXISTS;
    }

    Log(("VBOXSF: vbsfRename: Calling vboxCallRename\n"));
    vboxRC = vboxCallRename(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, SrcPath, DestPath, flags);

    vbsfFreeNonPagedMem(SrcPath);
    vbsfFreeNonPagedMem(DestPath);

    Status = VBoxErrorToNTStatus(vboxRC);
    if (vboxRC != VINF_SUCCESS)
    {
        Log(("VBOXSF: vbsfRename: vboxCallRename failed with %Rrc\n",
             vboxRC));
    }

    Log(("VBOXSF: vbsfRename: Returned 0x%08X\n",
         Status));
    return Status;
}