mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-26 07:43:01 +00:00
133 lines
3.5 KiB
C
133 lines
3.5 KiB
C
/*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* In addition to the permissions in the GNU General Public License,
|
|
* the authors give you unlimited permission to link the compiled
|
|
* version of this file into combinations with other programs,
|
|
* and to distribute those combinations without any restriction
|
|
* coming from the use of this file. (The General Public License
|
|
* restrictions do apply in other respects; for example, they cover
|
|
* modification of the file, and distribution when not linked into
|
|
* a combined executable.)
|
|
*
|
|
* This file is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "filelock.h"
|
|
#include "fileops.h"
|
|
|
|
static const char *GIT_FILELOCK_EXTENSION = ".lock\0";
|
|
static const size_t GIT_FILELOCK_EXTLENGTH = 6;
|
|
|
|
#define BUILD_PATH_LOCK(_lock, _path) { \
|
|
memcpy(_path, _lock->path, _lock->path_length); \
|
|
memcpy(_path + _lock->path_length, GIT_FILELOCK_EXTENSION,\
|
|
GIT_FILELOCK_EXTLENGTH);\
|
|
}
|
|
|
|
int git_filelock_init(git_filelock *lock, const char *path)
|
|
{
|
|
if (lock == NULL || path == NULL)
|
|
return GIT_ERROR;
|
|
|
|
memset(lock, 0x0, sizeof(git_filelock));
|
|
|
|
lock->path_length = strlen(path);
|
|
|
|
if (lock->path_length + GIT_FILELOCK_EXTLENGTH >= GIT_PATH_MAX)
|
|
return GIT_ERROR;
|
|
|
|
memcpy(lock->path, path, lock->path_length);
|
|
return GIT_SUCCESS;
|
|
}
|
|
|
|
int git_filelock_lock(git_filelock *lock, int append)
|
|
{
|
|
char path_lock[GIT_PATH_MAX];
|
|
BUILD_PATH_LOCK(lock, path_lock);
|
|
|
|
/* If file already exists, we cannot create a lock */
|
|
if (gitfo_exists(path_lock) == 0)
|
|
return GIT_EOSERR;
|
|
|
|
lock->file_lock = gitfo_creat(path_lock, 0666);
|
|
|
|
if (lock->file_lock < 0)
|
|
return GIT_EOSERR;
|
|
|
|
lock->is_locked = 1;
|
|
|
|
/* TODO: do a flock() in the descriptor file_lock */
|
|
|
|
if (append && gitfo_exists(lock->path) == 0) {
|
|
git_file source;
|
|
char buffer[2048];
|
|
size_t read_bytes;
|
|
|
|
source = gitfo_open(lock->path, O_RDONLY);
|
|
if (source < 0)
|
|
return GIT_EOSERR;
|
|
|
|
while ((read_bytes = gitfo_read(source, buffer, 2048)) > 0)
|
|
gitfo_write(lock->file_lock, buffer, read_bytes);
|
|
|
|
gitfo_close(source);
|
|
}
|
|
|
|
return GIT_SUCCESS;
|
|
}
|
|
|
|
void git_filelock_unlock(git_filelock *lock)
|
|
{
|
|
char path_lock[GIT_PATH_MAX];
|
|
BUILD_PATH_LOCK(lock, path_lock);
|
|
|
|
if (lock->is_locked) {
|
|
/* The flock() in lock->file_lock is removed
|
|
* automatically when closing the descriptor */
|
|
gitfo_close(lock->file_lock);
|
|
gitfo_unlink(path_lock);
|
|
lock->is_locked = 0;
|
|
}
|
|
}
|
|
|
|
int git_filelock_commit(git_filelock *lock)
|
|
{
|
|
int error;
|
|
char path_lock[GIT_PATH_MAX];
|
|
BUILD_PATH_LOCK(lock, path_lock);
|
|
|
|
if (!lock->is_locked || lock->file_lock < 0)
|
|
return GIT_ERROR;
|
|
|
|
/* FIXME: flush the descriptor? */
|
|
gitfo_close(lock->file_lock);
|
|
|
|
error = gitfo_move_file(path_lock, lock->path);
|
|
|
|
if (error < GIT_SUCCESS)
|
|
gitfo_unlink(path_lock);
|
|
|
|
lock->is_locked = 0;
|
|
return error;
|
|
}
|
|
|
|
int git_filelock_write(git_filelock *lock, const void *buffer, size_t length)
|
|
{
|
|
if (!lock->is_locked || lock->file_lock < 0)
|
|
return GIT_ERROR;
|
|
|
|
return gitfo_write(lock->file_lock, (void *)buffer, length);
|
|
}
|