From 7fd9194d8130bebe74285c796040f0b5e8e99d1d Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Mon, 30 Jan 2017 19:08:37 +0000 Subject: [PATCH] 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. --- bochs/iodev/hdimage/hdimage.cc | 92 +++++++++++++++++++++++++++------- bochs/iodev/hdimage/hdimage.h | 4 +- bochs/iodev/hdimage/vbox.cc | 4 +- bochs/iodev/hdimage/vmware3.cc | 4 +- bochs/iodev/hdimage/vmware4.cc | 4 +- bochs/iodev/hdimage/vpc-img.cc | 12 ++--- 6 files changed, 88 insertions(+), 32 deletions(-) diff --git a/bochs/iodev/hdimage/hdimage.cc b/bochs/iodev/hdimage/hdimage.cc index 814c1adef..ec984281f 100644 --- a/bochs/iodev/hdimage/hdimage.cc +++ b/bochs/iodev/hdimage/hdimage.cc @@ -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 -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); diff --git a/bochs/iodev/hdimage/hdimage.h b/bochs/iodev/hdimage/hdimage.h index f483ac64f..3753ac586 100644 --- a/bochs/iodev/hdimage/hdimage.h +++ b/bochs/iodev/hdimage/hdimage.h @@ -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; diff --git a/bochs/iodev/hdimage/vbox.cc b/bochs/iodev/hdimage/vbox.cc index b7686def4..4a26e3ee5 100644 --- a/bochs/iodev/hdimage/vbox.cc +++ b/bochs/iodev/hdimage/vbox.cc @@ -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; } diff --git a/bochs/iodev/hdimage/vmware3.cc b/bochs/iodev/hdimage/vmware3.cc index fffc446d9..df7e3ee5e 100644 --- a/bochs/iodev/hdimage/vmware3.cc +++ b/bochs/iodev/hdimage/vmware3.cc @@ -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; diff --git a/bochs/iodev/hdimage/vmware4.cc b/bochs/iodev/hdimage/vmware4.cc index bc16508be..832ebc810 100644 --- a/bochs/iodev/hdimage/vmware4.cc +++ b/bochs/iodev/hdimage/vmware4.cc @@ -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; } diff --git a/bochs/iodev/hdimage/vpc-img.cc b/bochs/iodev/hdimage/vpc-img.cc index 133d99b12..49254fabe 100644 --- a/bochs/iodev/hdimage/vpc-img.cc +++ b/bochs/iodev/hdimage/vpc-img.cc @@ -6,7 +6,7 @@ // // Copyright (c) 2005 Alex Beregszaszi // Copyright (c) 2009 Kevin Wolf -// 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); } }