Implemented lock mechanism for hard disk images (fixes SF bug #605).
- Create a file with image name plus extension ".lock" if an image is opened in read/write mode. This file will be deleted after closing the image. - Check for a lock file before opening an image and fail if it exists. - Check for a lock file before creating a undoable/volatile redolog file and fail if it exists.
This commit is contained in:
parent
124f521797
commit
7fd9194d81
@ -178,12 +178,30 @@ int bx_write_image(int fd, Bit64s offset, void *buf, int count)
|
||||
return write(fd, buf, count);
|
||||
}
|
||||
|
||||
int bx_close_image(int fd, const char *pathname)
|
||||
{
|
||||
#ifndef BXIMAGE
|
||||
char lockfn[BX_PATHNAME_LEN];
|
||||
|
||||
sprintf(lockfn, "%s.lock", pathname);
|
||||
if (access(lockfn, F_OK) == 0) {
|
||||
unlink(lockfn);
|
||||
}
|
||||
#endif
|
||||
return ::close(fd);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime)
|
||||
#else
|
||||
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *mtime)
|
||||
#endif
|
||||
{
|
||||
#ifndef BXIMAGE
|
||||
char lockfn[BX_PATHNAME_LEN];
|
||||
int lockfd;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
if (fsize != NULL) {
|
||||
HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
|
||||
@ -205,6 +223,17 @@ int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BXIMAGE
|
||||
sprintf(lockfn, "%s.lock", pathname);
|
||||
lockfd = ::open(lockfn, O_RDONLY);
|
||||
if (lockfd >= 0) {
|
||||
// Opening image must fail if lock file exists.
|
||||
::close(lockfd);
|
||||
BX_ERROR(("image locked: '%s'", pathname));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int fd = ::open(pathname, flags
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY
|
||||
@ -235,6 +264,19 @@ int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *
|
||||
*mtime = stat_buf.st_mtime;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef BXIMAGE
|
||||
if ((flags & O_ACCMODE) != O_RDONLY) {
|
||||
lockfd = ::open(lockfn, O_CREAT | O_RDWR
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY
|
||||
#endif
|
||||
, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
|
||||
if (lockfd >= 0) {
|
||||
// lock this image
|
||||
::close(lockfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
@ -488,7 +530,7 @@ int flat_image_t::open(const char* _pathname, int flags)
|
||||
void flat_image_t::close()
|
||||
{
|
||||
if (fd > -1) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,11 +611,11 @@ int concat_image_t::open(const char* _pathname0, int flags)
|
||||
{
|
||||
UNUSED(flags);
|
||||
pathname0 = _pathname0;
|
||||
char *pathname = strdup(pathname0);
|
||||
char *pathname1 = strdup(pathname0);
|
||||
BX_DEBUG(("concat_image_t::open"));
|
||||
Bit64s start_offset = 0;
|
||||
for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) {
|
||||
fd_table[i] = hdimage_open_file(pathname, flags, &length_table[i], NULL);
|
||||
fd_table[i] = hdimage_open_file(pathname1, flags, &length_table[i], NULL);
|
||||
if (fd_table[i] < 0) {
|
||||
// open failed.
|
||||
// if no FD was opened successfully, return -1 (fail).
|
||||
@ -583,7 +625,7 @@ int concat_image_t::open(const char* _pathname0, int flags)
|
||||
maxfd = i;
|
||||
break;
|
||||
}
|
||||
BX_INFO(("concat_image: open image #%d: '%s', (" FMT_LL "u bytes)", i, pathname, length_table[i]));
|
||||
BX_INFO(("concat_image: open image #%d: '%s', (" FMT_LL "u bytes)", i, pathname1, length_table[i]));
|
||||
struct stat stat_buf;
|
||||
int ret = fstat(fd_table[i], &stat_buf);
|
||||
if (ret) {
|
||||
@ -599,9 +641,9 @@ int concat_image_t::open(const char* _pathname0, int flags)
|
||||
}
|
||||
start_offset_table[i] = start_offset;
|
||||
start_offset += length_table[i];
|
||||
increment_string(pathname);
|
||||
increment_string(pathname1);
|
||||
}
|
||||
free(pathname);
|
||||
free(pathname1);
|
||||
// start up with first image selected
|
||||
total_offset = 0;
|
||||
index = 0;
|
||||
@ -616,11 +658,14 @@ int concat_image_t::open(const char* _pathname0, int flags)
|
||||
void concat_image_t::close()
|
||||
{
|
||||
BX_DEBUG(("concat_image_t.close"));
|
||||
char *pathname1 = strdup(pathname0);
|
||||
for (int index = 0; index < maxfd; index++) {
|
||||
if (fd_table[index] > -1) {
|
||||
::close(fd_table[index]);
|
||||
bx_close_image(fd_table[index], pathname1);
|
||||
}
|
||||
increment_string(pathname1);
|
||||
}
|
||||
free(pathname1);
|
||||
}
|
||||
|
||||
Bit64s concat_image_t::lseek(Bit64s offset, int whence)
|
||||
@ -914,13 +959,8 @@ int sparse_image_t::open(const char* pathname0, int flags)
|
||||
void sparse_image_t::close()
|
||||
{
|
||||
BX_DEBUG(("concat_image_t.close"));
|
||||
if (pathname != NULL)
|
||||
{
|
||||
free(pathname);
|
||||
}
|
||||
#ifdef _POSIX_MAPPED_FILES
|
||||
if (mmap_header != NULL)
|
||||
{
|
||||
if (mmap_header != NULL) {
|
||||
int ret = munmap(mmap_header, mmap_length);
|
||||
if (ret != 0)
|
||||
BX_INFO(("failed to un-memory map sparse disk file"));
|
||||
@ -928,14 +968,15 @@ void sparse_image_t::close()
|
||||
pagetable = NULL; // We didn't malloc it
|
||||
#endif
|
||||
if (fd > -1) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
}
|
||||
if (pagetable != NULL)
|
||||
{
|
||||
if (pathname != NULL) {
|
||||
free(pathname);
|
||||
}
|
||||
if (pagetable != NULL) {
|
||||
delete [] pagetable;
|
||||
}
|
||||
if (parent_image != NULL)
|
||||
{
|
||||
if (parent_image != NULL) {
|
||||
delete parent_image;
|
||||
}
|
||||
}
|
||||
@ -1492,6 +1533,15 @@ int redolog_t::make_header(const char* type, Bit64u size)
|
||||
|
||||
int redolog_t::create(const char* filename, const char* type, Bit64u size)
|
||||
{
|
||||
#ifndef BXIMAGE
|
||||
char lockfn[BX_PATHNAME_LEN];
|
||||
|
||||
sprintf(lockfn, "%s.lock", filename);
|
||||
if (access(lockfn, F_OK) == 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
BX_INFO(("redolog : creating redolog %s", filename));
|
||||
|
||||
int filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC
|
||||
@ -1541,6 +1591,7 @@ int redolog_t::open(const char* filename, const char *type, int flags)
|
||||
FILETIME mtime;
|
||||
#endif
|
||||
|
||||
pathname = strdup(filename);
|
||||
fd = hdimage_open_file(filename, flags, &imgsize, &mtime);
|
||||
if (fd < 0) {
|
||||
BX_INFO(("redolog : could not open image %s", filename));
|
||||
@ -1624,7 +1675,10 @@ int redolog_t::open(const char* filename, const char *type, int flags)
|
||||
void redolog_t::close()
|
||||
{
|
||||
if (fd >= 0)
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
|
||||
if (pathname != NULL)
|
||||
free(pathname);
|
||||
|
||||
if (catalog != NULL)
|
||||
free(catalog);
|
||||
|
@ -2,7 +2,7 @@
|
||||
// $Id$
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2005-2015 The Bochs Project
|
||||
// Copyright (C) 2005-2017 The Bochs Project
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@ -143,6 +143,7 @@ class redolog_t;
|
||||
|
||||
int bx_read_image(int fd, Bit64s offset, void *buf, int count);
|
||||
int bx_write_image(int fd, Bit64s offset, void *buf, int count);
|
||||
int bx_close_image(int fd, const char *pathname);
|
||||
#ifndef WIN32
|
||||
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime);
|
||||
#else
|
||||
@ -452,6 +453,7 @@ class redolog_t
|
||||
|
||||
private:
|
||||
void print_header();
|
||||
char *pathname;
|
||||
int fd;
|
||||
redolog_header_t header; // Header is kept in x86 (little) endianness
|
||||
Bit32u *catalog;
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Contact: fys [at] fysnet [dot] net
|
||||
*
|
||||
* Copyright (C) 2015 Benjamin D Lunt.
|
||||
* Copyright (C) 2006-2016 The Bochs Project
|
||||
* Copyright (C) 2006-2017 The Bochs Project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -167,7 +167,7 @@ void vbox_image_t::close()
|
||||
delete [] mtlb; mtlb = 0;
|
||||
delete [] block_data; block_data = 0;
|
||||
|
||||
::close(file_descriptor);
|
||||
bx_close_image(file_descriptor, pathname);
|
||||
file_descriptor = -1;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Contact: snrrrub@yahoo.com
|
||||
*
|
||||
* Copyright (C) 2003 Net Integration Technologies, Inc.
|
||||
* Copyright (C) 2003-2015 The Bochs Project
|
||||
* Copyright (C) 2003-2017 The Bochs Project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -224,7 +224,7 @@ int vmware3_image_t::open(const char* _pathname, int flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
::close(file);
|
||||
bx_close_image(file, pathname);
|
||||
|
||||
tlb_size = header.tlb_size_sectors * 512;
|
||||
slb_count = (1 << FL_SHIFT) / tlb_size;
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Contact: snrrrub@gmail.com
|
||||
*
|
||||
* Copyright (C) 2006 Sharvil Nanavati.
|
||||
* Copyright (C) 2006-2016 The Bochs Project
|
||||
* Copyright (C) 2006-2017 The Bochs Project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -112,7 +112,7 @@ void vmware4_image_t::close()
|
||||
flush();
|
||||
delete [] tlb; tlb = 0;
|
||||
|
||||
::close(file_descriptor);
|
||||
bx_close_image(file_descriptor, pathname);
|
||||
file_descriptor = -1;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
// Copyright (c) 2005 Alex Beregszaszi
|
||||
// Copyright (c) 2009 Kevin Wolf <kwolf@suse.de>
|
||||
// Copyright (C) 2012-2013 The Bochs Project
|
||||
// Copyright (C) 2012-2017 The Bochs Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -138,20 +138,20 @@ int vpc_image_t::open(const char* _pathname, int flags)
|
||||
hd_size = sector_count * 512;
|
||||
|
||||
if (sector_count >= 65535 * 16 * 255) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
if (disk_type == VHD_DYNAMIC) {
|
||||
if (bx_read_image(fd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE) != HEADER_SIZE) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dyndisk_header = (vhd_dyndisk_header_t*)buf;
|
||||
|
||||
if (strncmp((char*)dyndisk_header->magic, "cxsparse", 8)) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ int vpc_image_t::open(const char* _pathname, int flags)
|
||||
|
||||
bat_offset = be64_to_cpu(dyndisk_header->table_offset);
|
||||
if (bx_read_image(fd, bat_offset, (void*)pagetable, max_table_entries * 4) != (max_table_entries * 4)) {
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ void vpc_image_t::close(void)
|
||||
{
|
||||
if (fd > -1) {
|
||||
delete [] pagetable;
|
||||
::close(fd);
|
||||
bx_close_image(fd, pathname);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user