mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-22 08:48:55 +00:00
Fixed a bug that regular files could not be created by mknod
This commit is contained in:
parent
4bec68713a
commit
73b49c1038
1
.gitignore
vendored
1
.gitignore
vendored
@ -85,6 +85,7 @@ test/chaos-http-proxy-*
|
|||||||
test/junk_data
|
test/junk_data
|
||||||
test/s3proxy-*
|
test/s3proxy-*
|
||||||
test/write_multiblock
|
test/write_multiblock
|
||||||
|
test/mknod_test
|
||||||
|
|
||||||
#
|
#
|
||||||
# Windows ports
|
# Windows ports
|
||||||
|
@ -86,16 +86,16 @@ int AutoFdEntity::Detach()
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AutoFdEntity::Attach(const char* path, int existfd)
|
FdEntity* AutoFdEntity::Attach(const char* path, int existfd)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
if(NULL == (pFdEntity = FdManager::get()->GetFdEntity(path, existfd, false))){
|
if(NULL == (pFdEntity = FdManager::get()->GetFdEntity(path, existfd, false))){
|
||||||
S3FS_PRN_DBG("Could not find fd entity object(file=%s, pseudo_fd=%d)", path, existfd);
|
S3FS_PRN_DBG("Could not find fd entity object(file=%s, pseudo_fd=%d)", path, existfd);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
pseudo_fd = existfd;
|
pseudo_fd = existfd;
|
||||||
return true;
|
return pFdEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
FdEntity* AutoFdEntity::Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
FdEntity* AutoFdEntity::Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
||||||
|
@ -48,7 +48,7 @@ class AutoFdEntity
|
|||||||
|
|
||||||
bool Close();
|
bool Close();
|
||||||
int Detach();
|
int Detach();
|
||||||
bool Attach(const char* path, int existfd);
|
FdEntity* Attach(const char* path, int existfd);
|
||||||
int GetPseudoFd() const { return pseudo_fd; }
|
int GetPseudoFd() const { return pseudo_fd; }
|
||||||
|
|
||||||
FdEntity* Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
FdEntity* Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
||||||
|
@ -96,7 +96,7 @@ ino_t FdEntity::GetInode(int fd)
|
|||||||
FdEntity::FdEntity(const char* tpath, const char* cpath) :
|
FdEntity::FdEntity(const char* tpath, const char* cpath) :
|
||||||
is_lock_init(false), path(SAFESTRPTR(tpath)),
|
is_lock_init(false), path(SAFESTRPTR(tpath)),
|
||||||
physical_fd(-1), pfile(NULL), inode(0), size_orgmeta(0),
|
physical_fd(-1), pfile(NULL), inode(0), size_orgmeta(0),
|
||||||
cachepath(SAFESTRPTR(cpath)), is_meta_pending(false)
|
cachepath(SAFESTRPTR(cpath)), pending_status(NO_UPDATE_PENDING)
|
||||||
{
|
{
|
||||||
holding_mtime.tv_sec = -1;
|
holding_mtime.tv_sec = -1;
|
||||||
holding_mtime.tv_nsec = 0;
|
holding_mtime.tv_nsec = 0;
|
||||||
@ -1255,7 +1255,7 @@ int FdEntity::NoCachePreMultipartPost(PseudoFdInfo* pseudo_obj)
|
|||||||
s3fscurl.DestroyCurlHandle();
|
s3fscurl.DestroyCurlHandle();
|
||||||
|
|
||||||
// Clear the dirty flag, because the meta data is updated.
|
// Clear the dirty flag, because the meta data is updated.
|
||||||
is_meta_pending = false;
|
pending_status = NO_UPDATE_PENDING;
|
||||||
|
|
||||||
// reset upload_id
|
// reset upload_id
|
||||||
if(!pseudo_obj->InitialUploadInfo(upload_id)){
|
if(!pseudo_obj->InitialUploadInfo(upload_id)){
|
||||||
@ -1544,15 +1544,15 @@ int FdEntity::RowFlushMultipart(PseudoFdInfo* pseudo_obj, const char* tpath)
|
|||||||
// So the file has already been removed, skip error.
|
// So the file has already been removed, skip error.
|
||||||
S3FS_PRN_ERR("failed to truncate file(physical_fd=%d) to zero, but continue...", physical_fd);
|
S3FS_PRN_ERR("failed to truncate file(physical_fd=%d) to zero, but continue...", physical_fd);
|
||||||
}
|
}
|
||||||
// put pending headers
|
// put pending headers or create new file
|
||||||
if(0 != (result = UploadPendingMeta())){
|
if(0 != (result = UploadPending())){
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 == result){
|
if(0 == result){
|
||||||
pagelist.ClearAllModified();
|
pagelist.ClearAllModified();
|
||||||
is_meta_pending = false;
|
pending_status = NO_UPDATE_PENDING;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1672,15 +1672,15 @@ int FdEntity::RowFlushMixMultipart(PseudoFdInfo* pseudo_obj, const char* tpath)
|
|||||||
// So the file has already been removed, skip error.
|
// So the file has already been removed, skip error.
|
||||||
S3FS_PRN_ERR("failed to truncate file(physical_fd=%d) to zero, but continue...", physical_fd);
|
S3FS_PRN_ERR("failed to truncate file(physical_fd=%d) to zero, but continue...", physical_fd);
|
||||||
}
|
}
|
||||||
// put pending headers
|
// put pending headers or create new file
|
||||||
if(0 != (result = UploadPendingMeta())){
|
if(0 != (result = UploadPending())){
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 == result){
|
if(0 == result){
|
||||||
pagelist.ClearAllModified();
|
pagelist.ClearAllModified();
|
||||||
is_meta_pending = false;
|
pending_status = NO_UPDATE_PENDING;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2089,29 +2089,51 @@ bool FdEntity::MergeOrgMeta(headers_t& updatemeta)
|
|||||||
if(0 <= atime.tv_sec){
|
if(0 <= atime.tv_sec){
|
||||||
SetAtime(atime, true);
|
SetAtime(atime, true);
|
||||||
}
|
}
|
||||||
is_meta_pending |= (IsUploading(true) || pagelist.IsModified());
|
|
||||||
|
|
||||||
return is_meta_pending;
|
if(NO_UPDATE_PENDING == pending_status && (IsUploading(true) || pagelist.IsModified())){
|
||||||
|
pending_status = UPDATE_META_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NO_UPDATE_PENDING != pending_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// global function in s3fs.cpp
|
// global function in s3fs.cpp
|
||||||
int put_headers(const char* path, headers_t& meta, bool is_copy, bool use_st_size = true);
|
int put_headers(const char* path, headers_t& meta, bool is_copy, bool use_st_size = true);
|
||||||
|
|
||||||
int FdEntity::UploadPendingMeta()
|
int FdEntity::UploadPending(int fd)
|
||||||
{
|
{
|
||||||
if(!is_meta_pending) {
|
int result;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
headers_t updatemeta = orgmeta;
|
if(NO_UPDATE_PENDING == pending_status){
|
||||||
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(path.c_str()));
|
// nothing to do
|
||||||
updatemeta["x-amz-metadata-directive"] = "REPLACE";
|
result = 0;
|
||||||
// put headers, no need to update mtime to avoid dead lock
|
|
||||||
int result = put_headers(path.c_str(), updatemeta, true);
|
}else if(UPDATE_META_PENDING == pending_status){
|
||||||
if(0 != result){
|
headers_t updatemeta = orgmeta;
|
||||||
S3FS_PRN_ERR("failed to put header after flushing file(%s) by(%d).", path.c_str(), result);
|
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(path.c_str()));
|
||||||
|
updatemeta["x-amz-metadata-directive"] = "REPLACE";
|
||||||
|
|
||||||
|
// put headers, no need to update mtime to avoid dead lock
|
||||||
|
result = put_headers(path.c_str(), updatemeta, true);
|
||||||
|
if(0 != result){
|
||||||
|
S3FS_PRN_ERR("failed to put header after flushing file(%s) by(%d).", path.c_str(), result);
|
||||||
|
}else{
|
||||||
|
pending_status = NO_UPDATE_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{ // CREATE_FILE_PENDING == pending_status
|
||||||
|
if(-1 == fd){
|
||||||
|
S3FS_PRN_ERR("could not create a new file(%s), because fd is not specified.", path.c_str());
|
||||||
|
result = -EBADF;
|
||||||
|
}else{
|
||||||
|
result = Flush(fd, true);
|
||||||
|
if(0 != result){
|
||||||
|
S3FS_PRN_ERR("failed to flush for file(%s) by(%d).", path.c_str(), result);
|
||||||
|
}else{
|
||||||
|
pending_status = NO_UPDATE_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is_meta_pending = false;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2194,7 +2216,7 @@ bool FdEntity::PunchHole(off_t start, size_t size)
|
|||||||
void FdEntity::MarkDirtyNewFile()
|
void FdEntity::MarkDirtyNewFile()
|
||||||
{
|
{
|
||||||
pagelist.Init(0, false, true);
|
pagelist.Init(0, false, true);
|
||||||
is_meta_pending = true;
|
pending_status = CREATE_FILE_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,6 +32,17 @@
|
|||||||
class FdEntity
|
class FdEntity
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
// [NOTE]
|
||||||
|
// Distinguish between meta pending and new file creation pending,
|
||||||
|
// because the processing(request) at these updates is different.
|
||||||
|
// Therefore, the pending state is expressed by this enum type.
|
||||||
|
//
|
||||||
|
enum pending_status_t {
|
||||||
|
NO_UPDATE_PENDING = 0,
|
||||||
|
UPDATE_META_PENDING, // pending meta header
|
||||||
|
CREATE_FILE_PENDING // pending file creation and meta header
|
||||||
|
};
|
||||||
|
|
||||||
static bool mixmultipart; // whether multipart uploading can use copy api.
|
static bool mixmultipart; // whether multipart uploading can use copy api.
|
||||||
|
|
||||||
pthread_mutex_t fdent_lock;
|
pthread_mutex_t fdent_lock;
|
||||||
@ -49,7 +60,7 @@ class FdEntity
|
|||||||
std::string cachepath; // local cache file path
|
std::string cachepath; // local cache file path
|
||||||
// (if this is empty, does not load/save pagelist.)
|
// (if this is empty, does not load/save pagelist.)
|
||||||
std::string mirrorpath; // mirror file path to local cache file path
|
std::string mirrorpath; // mirror file path to local cache file path
|
||||||
bool is_meta_pending;
|
pending_status_t pending_status;// status for new file creation and meta update
|
||||||
struct timespec holding_mtime; // if mtime is updated while the file is open, it is set time_t value
|
struct timespec holding_mtime; // if mtime is updated while the file is open, it is set time_t value
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -73,7 +84,6 @@ class FdEntity
|
|||||||
ssize_t WriteNoMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
ssize_t WriteNoMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
||||||
ssize_t WriteMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
ssize_t WriteMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
||||||
ssize_t WriteMixMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
ssize_t WriteMixMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
|
||||||
int UploadPendingMeta();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool GetNoMixMultipart() { return mixmultipart; }
|
static bool GetNoMixMultipart() { return mixmultipart; }
|
||||||
@ -95,6 +105,7 @@ class FdEntity
|
|||||||
int GetPhysicalFd() const { return physical_fd; }
|
int GetPhysicalFd() const { return physical_fd; }
|
||||||
bool IsModified() const;
|
bool IsModified() const;
|
||||||
bool MergeOrgMeta(headers_t& updatemeta);
|
bool MergeOrgMeta(headers_t& updatemeta);
|
||||||
|
int UploadPending(int fd = -1);
|
||||||
|
|
||||||
bool GetStats(struct stat& st, bool lock_already_held = false);
|
bool GetStats(struct stat& st, bool lock_already_held = false);
|
||||||
int SetCtime(struct timespec time, bool lock_already_held = false);
|
int SetCtime(struct timespec time, bool lock_already_held = false);
|
||||||
|
@ -2488,10 +2488,17 @@ static int s3fs_release(const char* _path, struct fuse_file_info* fi)
|
|||||||
// The pseudo fd stored in fi->fh is attached to AutoFdEntry so that it can be
|
// The pseudo fd stored in fi->fh is attached to AutoFdEntry so that it can be
|
||||||
// destroyed here.
|
// destroyed here.
|
||||||
//
|
//
|
||||||
if(!autoent.Attach(path, static_cast<int>(fi->fh))){
|
FdEntity* ent;
|
||||||
|
if(NULL == (ent = autoent.Attach(path, static_cast<int>(fi->fh)))){
|
||||||
S3FS_PRN_ERR("could not find pseudo_fd(%llu) for path(%s)", (unsigned long long)(fi->fh), path);
|
S3FS_PRN_ERR("could not find pseudo_fd(%llu) for path(%s)", (unsigned long long)(fi->fh), path);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int result = ent->UploadPending(static_cast<int>(fi->fh));
|
||||||
|
if(0 != result){
|
||||||
|
S3FS_PRN_ERR("could not upload pending data(meta, etc) for pseudo_fd(%llu) / path(%s)", (unsigned long long)(fi->fh), path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check - for debug
|
// check - for debug
|
||||||
|
@ -31,10 +31,12 @@ testdir = test
|
|||||||
|
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
junk_data \
|
junk_data \
|
||||||
write_multiblock
|
write_multiblock \
|
||||||
|
mknod_test
|
||||||
|
|
||||||
junk_data_SOURCES = junk_data.c
|
junk_data_SOURCES = junk_data.c
|
||||||
write_multiblock_SOURCES = write_multiblock.cc
|
write_multiblock_SOURCES = write_multiblock.cc
|
||||||
|
mknod_test_SOURCES = mknod_test.c
|
||||||
|
|
||||||
#
|
#
|
||||||
# Local variables:
|
# Local variables:
|
||||||
|
@ -749,6 +749,16 @@ function test_hardlink {
|
|||||||
rm_test_file "${ALT_TEST_TEXT_FILE}"
|
rm_test_file "${ALT_TEST_TEXT_FILE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_mknod {
|
||||||
|
describe "Testing mknod system call function ..."
|
||||||
|
|
||||||
|
local MKNOD_TEST_FILE_BASENAME="mknod_testfile"
|
||||||
|
|
||||||
|
rm -f "${MKNOD_TEST_FILE_BASENAME}*"
|
||||||
|
|
||||||
|
../../mknod_test "${MKNOD_TEST_FILE_BASENAME}"
|
||||||
|
}
|
||||||
|
|
||||||
function test_symlink {
|
function test_symlink {
|
||||||
describe "Testing symlinks ..."
|
describe "Testing symlinks ..."
|
||||||
|
|
||||||
@ -1894,6 +1904,9 @@ function add_all_tests {
|
|||||||
add_tests test_special_characters
|
add_tests test_special_characters
|
||||||
add_tests test_hardlink
|
add_tests test_hardlink
|
||||||
add_tests test_symlink
|
add_tests test_symlink
|
||||||
|
if ! uname | grep -q Darwin; then
|
||||||
|
add_tests test_mknod
|
||||||
|
fi
|
||||||
add_tests test_extended_attributes
|
add_tests test_extended_attributes
|
||||||
add_tests test_mtime_file
|
add_tests test_mtime_file
|
||||||
|
|
||||||
|
177
test/mknod_test.c
Normal file
177
test/mknod_test.c
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* s3fs - FUSE-based file system backed by Amazon S3
|
||||||
|
*
|
||||||
|
* Copyright(C) 2021 Andrew Gaul <andrew@gaul.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Const
|
||||||
|
//---------------------------------------------------------
|
||||||
|
const char usage_string[] = "Usage : \"mknod_test <base file path>\"";
|
||||||
|
|
||||||
|
const char str_mode_reg[] = "REGULAR";
|
||||||
|
const char str_mode_chr[] = "CHARACTER";
|
||||||
|
const char str_mode_blk[] = "BLOCK";
|
||||||
|
const char str_mode_fifo[] = "FIFO";
|
||||||
|
const char str_mode_sock[] = "SOCK";
|
||||||
|
|
||||||
|
const char str_ext_reg[] = "reg";
|
||||||
|
const char str_ext_chr[] = "chr";
|
||||||
|
const char str_ext_blk[] = "blk";
|
||||||
|
const char str_ext_fifo[] = "fifo";
|
||||||
|
const char str_ext_sock[] = "sock";
|
||||||
|
|
||||||
|
// [NOTE]
|
||||||
|
// It would be nice if PATH_MAX could be used as is, but since there are
|
||||||
|
// issues using on Linux and we also must support for macos, this simple
|
||||||
|
// test program defines a fixed value for simplicity.
|
||||||
|
//
|
||||||
|
#define S3FS_TEST_PATH_MAX 255
|
||||||
|
int max_base_path_length = S3FS_TEST_PATH_MAX - 5;
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Test function
|
||||||
|
//---------------------------------------------------------
|
||||||
|
bool TestMknod(const char* basepath, mode_t mode)
|
||||||
|
{
|
||||||
|
if(!basepath){
|
||||||
|
fprintf(stderr, "[ERROR] Called function with wrong basepath argument.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* str_mode;
|
||||||
|
dev_t dev;
|
||||||
|
char filepath[S3FS_TEST_PATH_MAX];
|
||||||
|
switch(mode){
|
||||||
|
case S_IFREG:
|
||||||
|
str_mode = str_mode_reg;
|
||||||
|
dev = 0;
|
||||||
|
sprintf(filepath, "%s.%s", basepath, str_ext_reg);
|
||||||
|
break;
|
||||||
|
case S_IFCHR:
|
||||||
|
str_mode = str_mode_chr;
|
||||||
|
dev = makedev(0, 0);
|
||||||
|
sprintf(filepath, "%s.%s", basepath, str_ext_chr);
|
||||||
|
break;
|
||||||
|
case S_IFBLK:
|
||||||
|
str_mode = str_mode_blk;
|
||||||
|
dev = makedev((long long)(259), 0); // temporary value
|
||||||
|
sprintf(filepath, "%s.%s", basepath, str_ext_blk);
|
||||||
|
break;
|
||||||
|
case S_IFIFO:
|
||||||
|
str_mode = str_mode_fifo;
|
||||||
|
dev = 0;
|
||||||
|
sprintf(filepath, "%s.%s", basepath, str_ext_fifo);
|
||||||
|
break;
|
||||||
|
case S_IFSOCK:
|
||||||
|
str_mode = str_mode_sock;
|
||||||
|
dev = 0;
|
||||||
|
sprintf(filepath, "%s.%s", basepath, str_ext_sock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "[ERROR] Called function with wrong mode argument.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create
|
||||||
|
//
|
||||||
|
if(0 != mknod(filepath, mode | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, dev)){
|
||||||
|
fprintf(stderr, "[ERROR] Could not create %s file(%s) : errno = %d\n", str_mode, filepath, errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check
|
||||||
|
//
|
||||||
|
struct stat st;
|
||||||
|
if(0 != stat(filepath, &st)){
|
||||||
|
fprintf(stderr, "[ERROR] Could not get stat from %s file(%s) : errno = %d\n", str_mode, filepath, errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(mode != (st.st_mode & S_IFMT)){
|
||||||
|
fprintf(stderr, "[ERROR] Created %s file(%s) does not have 0%o stat\n", str_mode, filepath, mode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove
|
||||||
|
//
|
||||||
|
if(0 != unlink(filepath)){
|
||||||
|
fprintf(stderr, "[WARNING] Could not remove %s file(%s) : errno = %d\n", str_mode, filepath, mode);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Main
|
||||||
|
//---------------------------------------------------------
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// Parse parameters
|
||||||
|
if(2 != argc){
|
||||||
|
fprintf(stderr, "[ERROR] No paraemter is specified.\n");
|
||||||
|
fprintf(stderr, "%s\n", usage_string);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if(0 == strcasecmp("-h", argv[1]) || 0 == strcasecmp("--help", argv[1])){
|
||||||
|
fprintf(stdout, "%s\n", usage_string);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
if(max_base_path_length < strlen(argv[1])){
|
||||||
|
fprintf(stderr, "[ERROR] Base file path is too long, it must be less than %d\n", max_base_path_length);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test
|
||||||
|
//
|
||||||
|
// [NOTE]
|
||||||
|
// Privilege is required to execute S_IFBLK.
|
||||||
|
//
|
||||||
|
if(!TestMknod(argv[1], S_IFREG) ||
|
||||||
|
!TestMknod(argv[1], S_IFCHR) ||
|
||||||
|
!TestMknod(argv[1], S_IFIFO) ||
|
||||||
|
!TestMknod(argv[1], S_IFSOCK) ||
|
||||||
|
(0 == geteuid() && !TestMknod(argv[1], S_IFBLK)))
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* End:
|
||||||
|
* vim600: expandtab sw=4 ts=4 fdm=marker
|
||||||
|
* vim<600: expandtab sw=4 ts=4
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user