-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfuse_fd_write.c
126 lines (105 loc) · 3.98 KB
/
fuse_fd_write.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
This file is part of ESFS, a FUSE-based filesystem that supports snapshots.
ESFS is Copyright (C) 2013, 2014 Elod Csirmaz
<http://www.epcsirmaz.com/> <https://github.com/csirmaz>.
ESFS is based on Big Brother File System (fuse-tutorial)
Copyright (C) 2012 Joseph J. Pfeiffer, Jr., Ph.D. <[email protected]>,
and was forked from it on 21 August 2013.
Big Brother File System can be distributed under the terms of
the GNU GPLv3. See the file COPYING.
See also <http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial/>.
Big Brother File System was derived from function prototypes found in
/usr/include/fuse/fuse.h
Copyright (C) 2001-2007 Miklos Szeredi <[email protected]>
fuse.h is licensed under the LGPLv2.
ESFS 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 3 of the License, or (at your option) any later
version.
ESFS 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, see <http://www.gnu.org/licenses/>.
*/
/*
* NOTE: A Perl script is used to replace $ with esfs_ and $$ with ESFS_
* in this file. To write $, use \$.
*/
/** Write data to an open file
*
* FUSE: Write should return exactly the number of bytes requested
* except on error. An exception to this is when the 'direct_io'
* mount option is specified (see read operation).
*
* Changed in version 2.2
*
* BBFS: "As with read(), the documentation above is inconsistent
* with the documentation for the write() system call."
*/
int $write(
const char *path,
const char *buf,
size_t size,
off_t offset,
struct fuse_file_info *fi
)
{
int ret;
$$DFSDATA_MFD
// Only allow writes on main FDs
if(mfd->is_main != $$mfd_main) { return -EACCES; }
$dlogdbg("* write(path=\"%s\", size=%d, offset=%lld, main fd=%d)\n", path, (int)size, (long long int)offset, mfd->mainfd);
// Verify that we're writing into the latest snapshot
if(unlikely((ret = $mfd_validate(mfd, fsdata)) != 0)) {
$dlogi("ERROR write(%s): mfd_validate failed with %d = %s\n", path, -ret, strerror(-ret));
return ret;
}
// Save blocks into snapshot
if(unlikely((ret = $b_write(fsdata, mfd, size, offset, $$B_WRITE_DEFAULTS)) != 0)) {
$dlogi("ERROR write(%s): b_write failed with %d = %s\n", path, -ret, strerror(-ret));
return ret;
}
ret = pwrite(mfd->mainfd, buf, size, offset);
if(ret >= 0) {
$dlogdbg("pwrite wrote %d bytes\n", ret);
return ret;
}
#if $$DEBUG > 1
ret = errno;
$dlogdbg("WARNING pwrite failed with %d = %s\n", ret, strerror(ret));
return -ret;
#else
return -errno;
#endif
}
/**
* Change the size of an open file
*
* This method is called instead of the truncate() method if the
* truncation was invoked from an ftruncate() system call.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the truncate() method will be
* called instead.
*
* Introduced in version 2.5
*/
int $ftruncate(const char *path, off_t newsize, struct fuse_file_info *fi)
{
int ret;
$$DFSDATA_MFD
$dlogdbg("* ftruncate(path=\"%s\", newsize=%zu, FD = %d)\n", path, newsize, mfd->mainfd);
// Verify that we're writing into the latest snapshot
if(unlikely((ret = $mfd_validate(mfd, fsdata)) != 0)) {
$dlogi("ERROR ftruncate(%s): mfd_validate failed with %d = %s\n", path, -ret, strerror(-ret));
return ret;
}
if(unlikely((ret = $b_truncate(fsdata, mfd, newsize, $$B_WRITE_DEFAULTS)) != 0)) {
$dlogi("ERROR ftruncate(%s): b_truncate failed with %d = %s\n", path, -ret, strerror(-ret));
return ret;
}
if(unlikely(ftruncate(mfd->mainfd, newsize) != 0)) { return -errno; }
return 0;
}